17dd7cddfSDavid du Colombier
27dd7cddfSDavid du Colombier /* pngwio.c - functions for data output
37dd7cddfSDavid du Colombier *
4*593dc095SDavid du Colombier * libpng 1.2.8 - December 3, 2004
57dd7cddfSDavid du Colombier * For conditions of distribution and use, see copyright notice in png.h
6*593dc095SDavid du Colombier * Copyright (c) 1998-2004 Glenn Randers-Pehrson
7*593dc095SDavid du Colombier * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8*593dc095SDavid du Colombier * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
97dd7cddfSDavid du Colombier *
10*593dc095SDavid du Colombier * This file provides a location for all output. Users who need
11*593dc095SDavid du Colombier * special handling are expected to write functions that have the same
12*593dc095SDavid du Colombier * arguments as these and perform similar functions, but that possibly
13*593dc095SDavid du Colombier * use different output methods. Note that you shouldn't change these
147dd7cddfSDavid du Colombier * functions, but rather write replacement functions and then change
157dd7cddfSDavid du Colombier * them at run time with png_set_write_fn(...).
167dd7cddfSDavid du Colombier */
177dd7cddfSDavid du Colombier
187dd7cddfSDavid du Colombier #define PNG_INTERNAL
197dd7cddfSDavid du Colombier #include "png.h"
20*593dc095SDavid du Colombier #ifdef PNG_WRITE_SUPPORTED
217dd7cddfSDavid du Colombier
227dd7cddfSDavid du Colombier /* Write the data to whatever output you are using. The default routine
237dd7cddfSDavid du Colombier writes to a file pointer. Note that this routine sometimes gets called
247dd7cddfSDavid du Colombier with very small lengths, so you should implement some kind of simple
257dd7cddfSDavid du Colombier buffering if you are using unbuffered writes. This should never be asked
26*593dc095SDavid du Colombier to write more than 64K on a 16 bit machine. */
277dd7cddfSDavid du Colombier
28*593dc095SDavid du Colombier void /* PRIVATE */
png_write_data(png_structp png_ptr,png_bytep data,png_size_t length)297dd7cddfSDavid du Colombier png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
307dd7cddfSDavid du Colombier {
317dd7cddfSDavid du Colombier if (png_ptr->write_data_fn != NULL )
327dd7cddfSDavid du Colombier (*(png_ptr->write_data_fn))(png_ptr, data, length);
337dd7cddfSDavid du Colombier else
347dd7cddfSDavid du Colombier png_error(png_ptr, "Call to NULL write function");
357dd7cddfSDavid du Colombier }
367dd7cddfSDavid du Colombier
377dd7cddfSDavid du Colombier #if !defined(PNG_NO_STDIO)
38*593dc095SDavid du Colombier /* This is the function that does the actual writing of data. If you are
397dd7cddfSDavid du Colombier not writing to a standard C stream, you should create a replacement
407dd7cddfSDavid du Colombier write_data function and use it at run time with png_set_write_fn(), rather
417dd7cddfSDavid du Colombier than changing the library. */
427dd7cddfSDavid du Colombier #ifndef USE_FAR_KEYWORD
43*593dc095SDavid du Colombier void PNGAPI
png_default_write_data(png_structp png_ptr,png_bytep data,png_size_t length)447dd7cddfSDavid du Colombier png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
457dd7cddfSDavid du Colombier {
467dd7cddfSDavid du Colombier png_uint_32 check;
477dd7cddfSDavid du Colombier
48*593dc095SDavid du Colombier #if defined(_WIN32_WCE)
49*593dc095SDavid du Colombier if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
50*593dc095SDavid du Colombier check = 0;
51*593dc095SDavid du Colombier #else
52*593dc095SDavid du Colombier check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
53*593dc095SDavid du Colombier #endif
547dd7cddfSDavid du Colombier if (check != length)
557dd7cddfSDavid du Colombier png_error(png_ptr, "Write Error");
567dd7cddfSDavid du Colombier }
577dd7cddfSDavid du Colombier #else
587dd7cddfSDavid du Colombier /* this is the model-independent version. Since the standard I/O library
597dd7cddfSDavid du Colombier can't handle far buffers in the medium and small models, we have to copy
607dd7cddfSDavid du Colombier the data.
617dd7cddfSDavid du Colombier */
627dd7cddfSDavid du Colombier
637dd7cddfSDavid du Colombier #define NEAR_BUF_SIZE 1024
647dd7cddfSDavid du Colombier #define MIN(a,b) (a <= b ? a : b)
657dd7cddfSDavid du Colombier
66*593dc095SDavid du Colombier void PNGAPI
png_default_write_data(png_structp png_ptr,png_bytep data,png_size_t length)677dd7cddfSDavid du Colombier png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
687dd7cddfSDavid du Colombier {
697dd7cddfSDavid du Colombier png_uint_32 check;
707dd7cddfSDavid du Colombier png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */
71*593dc095SDavid du Colombier png_FILE_p io_ptr;
727dd7cddfSDavid du Colombier
737dd7cddfSDavid du Colombier /* Check if data really is near. If so, use usual code. */
747dd7cddfSDavid du Colombier near_data = (png_byte *)CVT_PTR_NOCHECK(data);
75*593dc095SDavid du Colombier io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
767dd7cddfSDavid du Colombier if ((png_bytep)near_data == data)
777dd7cddfSDavid du Colombier {
78*593dc095SDavid du Colombier #if defined(_WIN32_WCE)
79*593dc095SDavid du Colombier if ( !WriteFile(io_ptr, near_data, length, &check, NULL) )
80*593dc095SDavid du Colombier check = 0;
81*593dc095SDavid du Colombier #else
827dd7cddfSDavid du Colombier check = fwrite(near_data, 1, length, io_ptr);
83*593dc095SDavid du Colombier #endif
847dd7cddfSDavid du Colombier }
857dd7cddfSDavid du Colombier else
867dd7cddfSDavid du Colombier {
877dd7cddfSDavid du Colombier png_byte buf[NEAR_BUF_SIZE];
887dd7cddfSDavid du Colombier png_size_t written, remaining, err;
897dd7cddfSDavid du Colombier check = 0;
907dd7cddfSDavid du Colombier remaining = length;
917dd7cddfSDavid du Colombier do
927dd7cddfSDavid du Colombier {
937dd7cddfSDavid du Colombier written = MIN(NEAR_BUF_SIZE, remaining);
947dd7cddfSDavid du Colombier png_memcpy(buf, data, written); /* copy far buffer to near buffer */
95*593dc095SDavid du Colombier #if defined(_WIN32_WCE)
96*593dc095SDavid du Colombier if ( !WriteFile(io_ptr, buf, written, &err, NULL) )
97*593dc095SDavid du Colombier err = 0;
98*593dc095SDavid du Colombier #else
997dd7cddfSDavid du Colombier err = fwrite(buf, 1, written, io_ptr);
100*593dc095SDavid du Colombier #endif
1017dd7cddfSDavid du Colombier if (err != written)
1027dd7cddfSDavid du Colombier break;
1037dd7cddfSDavid du Colombier else
1047dd7cddfSDavid du Colombier check += err;
1057dd7cddfSDavid du Colombier data += written;
1067dd7cddfSDavid du Colombier remaining -= written;
1077dd7cddfSDavid du Colombier }
1087dd7cddfSDavid du Colombier while (remaining != 0);
1097dd7cddfSDavid du Colombier }
1107dd7cddfSDavid du Colombier if (check != length)
1117dd7cddfSDavid du Colombier png_error(png_ptr, "Write Error");
1127dd7cddfSDavid du Colombier }
1137dd7cddfSDavid du Colombier
1147dd7cddfSDavid du Colombier #endif
1157dd7cddfSDavid du Colombier #endif
1167dd7cddfSDavid du Colombier
1177dd7cddfSDavid du Colombier /* This function is called to output any data pending writing (normally
1187dd7cddfSDavid du Colombier to disk). After png_flush is called, there should be no data pending
1197dd7cddfSDavid du Colombier writing in any buffers. */
1207dd7cddfSDavid du Colombier #if defined(PNG_WRITE_FLUSH_SUPPORTED)
121*593dc095SDavid du Colombier void /* PRIVATE */
png_flush(png_structp png_ptr)1227dd7cddfSDavid du Colombier png_flush(png_structp png_ptr)
1237dd7cddfSDavid du Colombier {
1247dd7cddfSDavid du Colombier if (png_ptr->output_flush_fn != NULL)
1257dd7cddfSDavid du Colombier (*(png_ptr->output_flush_fn))(png_ptr);
1267dd7cddfSDavid du Colombier }
1277dd7cddfSDavid du Colombier
1287dd7cddfSDavid du Colombier #if !defined(PNG_NO_STDIO)
129*593dc095SDavid du Colombier void PNGAPI
png_default_flush(png_structp png_ptr)1307dd7cddfSDavid du Colombier png_default_flush(png_structp png_ptr)
1317dd7cddfSDavid du Colombier {
132*593dc095SDavid du Colombier #if !defined(_WIN32_WCE)
133*593dc095SDavid du Colombier png_FILE_p io_ptr;
134*593dc095SDavid du Colombier io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
1357dd7cddfSDavid du Colombier if (io_ptr != NULL)
1367dd7cddfSDavid du Colombier fflush(io_ptr);
137*593dc095SDavid du Colombier #endif
1387dd7cddfSDavid du Colombier }
1397dd7cddfSDavid du Colombier #endif
1407dd7cddfSDavid du Colombier #endif
1417dd7cddfSDavid du Colombier
1427dd7cddfSDavid du Colombier /* This function allows the application to supply new output functions for
1437dd7cddfSDavid du Colombier libpng if standard C streams aren't being used.
1447dd7cddfSDavid du Colombier
1457dd7cddfSDavid du Colombier This function takes as its arguments:
1467dd7cddfSDavid du Colombier png_ptr - pointer to a png output data structure
1477dd7cddfSDavid du Colombier io_ptr - pointer to user supplied structure containing info about
1487dd7cddfSDavid du Colombier the output functions. May be NULL.
149*593dc095SDavid du Colombier write_data_fn - pointer to a new output function that takes as its
1507dd7cddfSDavid du Colombier arguments a pointer to a png_struct, a pointer to
151*593dc095SDavid du Colombier data to be written, and a 32-bit unsigned int that is
1527dd7cddfSDavid du Colombier the number of bytes to be written. The new write
1537dd7cddfSDavid du Colombier function should call png_error(png_ptr, "Error msg")
1547dd7cddfSDavid du Colombier to exit and output any fatal error messages.
155*593dc095SDavid du Colombier flush_data_fn - pointer to a new flush function that takes as its
1567dd7cddfSDavid du Colombier arguments a pointer to a png_struct. After a call to
1577dd7cddfSDavid du Colombier the flush function, there should be no data in any buffers
1587dd7cddfSDavid du Colombier or pending transmission. If the output method doesn't do
1597dd7cddfSDavid du Colombier any buffering of ouput, a function prototype must still be
1607dd7cddfSDavid du Colombier supplied although it doesn't have to do anything. If
1617dd7cddfSDavid du Colombier PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
1627dd7cddfSDavid du Colombier time, output_flush_fn will be ignored, although it must be
1637dd7cddfSDavid du Colombier supplied for compatibility. */
164*593dc095SDavid du Colombier void PNGAPI
png_set_write_fn(png_structp png_ptr,png_voidp io_ptr,png_rw_ptr write_data_fn,png_flush_ptr output_flush_fn)1657dd7cddfSDavid du Colombier png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
1667dd7cddfSDavid du Colombier png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
1677dd7cddfSDavid du Colombier {
1687dd7cddfSDavid du Colombier png_ptr->io_ptr = io_ptr;
1697dd7cddfSDavid du Colombier
1707dd7cddfSDavid du Colombier #if !defined(PNG_NO_STDIO)
1717dd7cddfSDavid du Colombier if (write_data_fn != NULL)
1727dd7cddfSDavid du Colombier png_ptr->write_data_fn = write_data_fn;
1737dd7cddfSDavid du Colombier else
1747dd7cddfSDavid du Colombier png_ptr->write_data_fn = png_default_write_data;
1757dd7cddfSDavid du Colombier #else
1767dd7cddfSDavid du Colombier png_ptr->write_data_fn = write_data_fn;
1777dd7cddfSDavid du Colombier #endif
1787dd7cddfSDavid du Colombier
1797dd7cddfSDavid du Colombier #if defined(PNG_WRITE_FLUSH_SUPPORTED)
1807dd7cddfSDavid du Colombier #if !defined(PNG_NO_STDIO)
1817dd7cddfSDavid du Colombier if (output_flush_fn != NULL)
1827dd7cddfSDavid du Colombier png_ptr->output_flush_fn = output_flush_fn;
1837dd7cddfSDavid du Colombier else
1847dd7cddfSDavid du Colombier png_ptr->output_flush_fn = png_default_flush;
1857dd7cddfSDavid du Colombier #else
1867dd7cddfSDavid du Colombier png_ptr->output_flush_fn = output_flush_fn;
1877dd7cddfSDavid du Colombier #endif
1887dd7cddfSDavid du Colombier #endif /* PNG_WRITE_FLUSH_SUPPORTED */
1897dd7cddfSDavid du Colombier
1907dd7cddfSDavid du Colombier /* It is an error to read while writing a png file */
191*593dc095SDavid du Colombier if (png_ptr->read_data_fn != NULL)
192*593dc095SDavid du Colombier {
1937dd7cddfSDavid du Colombier png_ptr->read_data_fn = NULL;
194*593dc095SDavid du Colombier png_warning(png_ptr,
195*593dc095SDavid du Colombier "Attempted to set both read_data_fn and write_data_fn in");
196*593dc095SDavid du Colombier png_warning(png_ptr,
197*593dc095SDavid du Colombier "the same structure. Resetting read_data_fn to NULL.");
198*593dc095SDavid du Colombier }
1997dd7cddfSDavid du Colombier }
2007dd7cddfSDavid du Colombier
2017dd7cddfSDavid du Colombier #if defined(USE_FAR_KEYWORD)
2027dd7cddfSDavid du Colombier #if defined(_MSC_VER)
png_far_to_near(png_structp png_ptr,png_voidp ptr,int check)203*593dc095SDavid du Colombier void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
2047dd7cddfSDavid du Colombier {
2057dd7cddfSDavid du Colombier void *near_ptr;
2067dd7cddfSDavid du Colombier void FAR *far_ptr;
2077dd7cddfSDavid du Colombier FP_OFF(near_ptr) = FP_OFF(ptr);
2087dd7cddfSDavid du Colombier far_ptr = (void FAR *)near_ptr;
2097dd7cddfSDavid du Colombier if(check != 0)
2107dd7cddfSDavid du Colombier if(FP_SEG(ptr) != FP_SEG(far_ptr))
2117dd7cddfSDavid du Colombier png_error(png_ptr,"segment lost in conversion");
2127dd7cddfSDavid du Colombier return(near_ptr);
2137dd7cddfSDavid du Colombier }
2147dd7cddfSDavid du Colombier # else
png_far_to_near(png_structp png_ptr,png_voidp ptr,int check)215*593dc095SDavid du Colombier void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
2167dd7cddfSDavid du Colombier {
2177dd7cddfSDavid du Colombier void *near_ptr;
2187dd7cddfSDavid du Colombier void FAR *far_ptr;
2197dd7cddfSDavid du Colombier near_ptr = (void FAR *)ptr;
2207dd7cddfSDavid du Colombier far_ptr = (void FAR *)near_ptr;
2217dd7cddfSDavid du Colombier if(check != 0)
2227dd7cddfSDavid du Colombier if(far_ptr != ptr)
2237dd7cddfSDavid du Colombier png_error(png_ptr,"segment lost in conversion");
2247dd7cddfSDavid du Colombier return(near_ptr);
2257dd7cddfSDavid du Colombier }
2267dd7cddfSDavid du Colombier # endif
2277dd7cddfSDavid du Colombier # endif
228*593dc095SDavid du Colombier #endif /* PNG_WRITE_SUPPORTED */
229