blob: 31309b34427eb27b0b381cedcd28ad22b2f90e3f [file] [log] [blame]
Guy Schalnate5a37791996-06-05 15:50:50 -05001
2/* pngwio.c - functions for data output
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003 *
Glenn Randers-Pehrson363f96e2010-08-11 09:00:26 -05004 * Last changed in libpng 1.5.0 [August 11, 2010]
Glenn Randers-Pehrsone69b55d2010-01-01 10:29:06 -06005 * Copyright (c) 1998-2010 Glenn Randers-Pehrson
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05006 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06008 *
Glenn Randers-Pehrsonbfbf8652009-06-26 21:46:52 -05009 * This code is released under the libpng license.
Glenn Randers-Pehrsonc332bbc2009-06-25 13:43:50 -050010 * For conditions of distribution and use, see the disclaimer
Glenn Randers-Pehrson037023b2009-06-24 10:27:36 -050011 * and license in png.h
Glenn Randers-Pehrson3e61d792009-06-24 09:31:28 -050012 *
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050013 * This file provides a location for all output. Users who need
14 * special handling are expected to write functions that have the same
15 * arguments as these and perform similar functions, but that possibly
16 * use different output methods. Note that you shouldn't change these
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060017 * functions, but rather write replacement functions and then change
18 * them at run time with png_set_write_fn(...).
19 */
Guy Schalnate5a37791996-06-05 15:50:50 -050020
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -050021#include "pngpriv.h"
Guy Schalnate5a37791996-06-05 15:50:50 -050022
Glenn Randers-Pehrsonc3cd22b2010-03-08 21:10:25 -060023#ifdef PNG_WRITE_SUPPORTED
24
Guy Schalnate5a37791996-06-05 15:50:50 -050025/* Write the data to whatever output you are using. The default routine
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050026 * writes to a file pointer. Note that this routine sometimes gets called
27 * with very small lengths, so you should implement some kind of simple
28 * buffering if you are using unbuffered writes. This should never be asked
29 * to write more than 64K on a 16 bit machine.
30 */
Guy Schalnate5a37791996-06-05 15:50:50 -050031
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050032void /* PRIVATE */
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -050033png_write_data(png_structp png_ptr, png_const_bytep data, png_size_t length)
Guy Schalnate5a37791996-06-05 15:50:50 -050034{
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -050035 /* NOTE: write_data_fn must not change the buffer! */
Andreas Dilger47a0c421997-05-16 02:46:07 -050036 if (png_ptr->write_data_fn != NULL )
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -050037 (*(png_ptr->write_data_fn))(png_ptr, (png_bytep)data, length);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050038
Guy Schalnate5a37791996-06-05 15:50:50 -050039 else
40 png_error(png_ptr, "Call to NULL write function");
41}
42
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -050043#ifdef PNG_STDIO_SUPPORTED
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050044/* This is the function that does the actual writing of data. If you are
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050045 * not writing to a standard C stream, you should create a replacement
46 * write_data function and use it at run time with png_set_write_fn(), rather
47 * than changing the library.
48 */
Guy Schalnate5a37791996-06-05 15:50:50 -050049#ifndef USE_FAR_KEYWORD
Glenn Randers-Pehrsoneae8e362010-03-12 17:36:53 -060050void PNGCBAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -050051png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
Guy Schalnate5a37791996-06-05 15:50:50 -050052{
53 png_uint_32 check;
54
Glenn Randers-Pehrsond8eb62f2009-05-30 20:19:20 -050055 if (png_ptr == NULL)
56 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050057
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -050058 check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050059
Guy Schalnate5a37791996-06-05 15:50:50 -050060 if (check != length)
Guy Schalnate5a37791996-06-05 15:50:50 -050061 png_error(png_ptr, "Write Error");
Guy Schalnate5a37791996-06-05 15:50:50 -050062}
63#else
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050064/* This is the model-independent version. Since the standard I/O library
65 * can't handle far buffers in the medium and small models, we have to copy
66 * the data.
67 */
Guy Schalnate5a37791996-06-05 15:50:50 -050068
69#define NEAR_BUF_SIZE 1024
70#define MIN(a,b) (a <= b ? a : b)
71
Glenn Randers-Pehrsoneae8e362010-03-12 17:36:53 -060072void PNGCBAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -050073png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
Guy Schalnate5a37791996-06-05 15:50:50 -050074{
75 png_uint_32 check;
Andreas Dilger47a0c421997-05-16 02:46:07 -050076 png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -050077 png_FILE_p io_ptr;
Guy Schalnate5a37791996-06-05 15:50:50 -050078
Glenn Randers-Pehrsond8eb62f2009-05-30 20:19:20 -050079 if (png_ptr == NULL)
80 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050081
Guy Schalnate5a37791996-06-05 15:50:50 -050082 /* Check if data really is near. If so, use usual code. */
Andreas Dilger47a0c421997-05-16 02:46:07 -050083 near_data = (png_byte *)CVT_PTR_NOCHECK(data);
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -050084 io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050085
Andreas Dilger47a0c421997-05-16 02:46:07 -050086 if ((png_bytep)near_data == data)
Guy Schalnate5a37791996-06-05 15:50:50 -050087 {
Andreas Dilger47a0c421997-05-16 02:46:07 -050088 check = fwrite(near_data, 1, length, io_ptr);
Guy Schalnate5a37791996-06-05 15:50:50 -050089 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050090
Guy Schalnate5a37791996-06-05 15:50:50 -050091 else
92 {
93 png_byte buf[NEAR_BUF_SIZE];
94 png_size_t written, remaining, err;
95 check = 0;
Andreas Dilger47a0c421997-05-16 02:46:07 -050096 remaining = length;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050097
Guy Schalnate5a37791996-06-05 15:50:50 -050098 do
99 {
100 written = MIN(NEAR_BUF_SIZE, remaining);
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500101 png_memcpy(buf, data, written); /* Copy far buffer to near buffer */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600102 err = fwrite(buf, 1, written, io_ptr);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500103
Guy Schalnate5a37791996-06-05 15:50:50 -0500104 if (err != written)
105 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500106
Guy Schalnate5a37791996-06-05 15:50:50 -0500107 else
108 check += err;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500109
Guy Schalnate5a37791996-06-05 15:50:50 -0500110 data += written;
111 remaining -= written;
112 }
113 while (remaining != 0);
114 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500115
Guy Schalnate5a37791996-06-05 15:50:50 -0500116 if (check != length)
Guy Schalnate5a37791996-06-05 15:50:50 -0500117 png_error(png_ptr, "Write Error");
Guy Schalnate5a37791996-06-05 15:50:50 -0500118}
119
120#endif
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600121#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500122
123/* This function is called to output any data pending writing (normally
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500124 * to disk). After png_flush is called, there should be no data pending
125 * writing in any buffers.
126 */
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500127#ifdef PNG_WRITE_FLUSH_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500128void /* PRIVATE */
Guy Schalnate5a37791996-06-05 15:50:50 -0500129png_flush(png_structp png_ptr)
130{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500131 if (png_ptr->output_flush_fn != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500132 (*(png_ptr->output_flush_fn))(png_ptr);
133}
134
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600135# ifdef PNG_STDIO_SUPPORTED
Glenn Randers-Pehrsoneae8e362010-03-12 17:36:53 -0600136void PNGCBAPI
Guy Schalnate5a37791996-06-05 15:50:50 -0500137png_default_flush(png_structp png_ptr)
138{
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500139 png_FILE_p io_ptr;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500140
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500141 if (png_ptr == NULL)
142 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500143
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500144 io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
Glenn Randers-Pehrson8fb550c2009-03-21 08:15:32 -0500145 fflush(io_ptr);
Guy Schalnate5a37791996-06-05 15:50:50 -0500146}
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600147# endif
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600148#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500149
150/* This function allows the application to supply new output functions for
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500151 * libpng if standard C streams aren't being used.
152 *
153 * This function takes as its arguments:
154 * png_ptr - pointer to a png output data structure
155 * io_ptr - pointer to user supplied structure containing info about
156 * the output functions. May be NULL.
157 * write_data_fn - pointer to a new output function that takes as its
158 * arguments a pointer to a png_struct, a pointer to
159 * data to be written, and a 32-bit unsigned int that is
160 * the number of bytes to be written. The new write
161 * function should call png_error(png_ptr, "Error msg")
162 * to exit and output any fatal error messages. May be
163 * NULL, in which case libpng's default function will
164 * be used.
165 * flush_data_fn - pointer to a new flush function that takes as its
166 * arguments a pointer to a png_struct. After a call to
167 * the flush function, there should be no data in any buffers
168 * or pending transmission. If the output method doesn't do
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500169 * any buffering of output, a function prototype must still be
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500170 * supplied although it doesn't have to do anything. If
171 * PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
172 * time, output_flush_fn will be ignored, although it must be
173 * supplied for compatibility. May be NULL, in which case
174 * libpng's default function will be used, if
175 * PNG_WRITE_FLUSH_SUPPORTED is defined. This is not
176 * a good idea if io_ptr does not point to a standard
177 * *FILE structure.
178 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500179void PNGAPI
Guy Schalnate5a37791996-06-05 15:50:50 -0500180png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600181 png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
Guy Schalnate5a37791996-06-05 15:50:50 -0500182{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500183 if (png_ptr == NULL)
184 return;
185
Guy Schalnate5a37791996-06-05 15:50:50 -0500186 png_ptr->io_ptr = io_ptr;
187
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500188#ifdef PNG_STDIO_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500189 if (write_data_fn != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500190 png_ptr->write_data_fn = write_data_fn;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500191
Guy Schalnate5a37791996-06-05 15:50:50 -0500192 else
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -0500193 png_ptr->write_data_fn = png_default_write_data;
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600194#else
195 png_ptr->write_data_fn = write_data_fn;
196#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500197
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500198#ifdef PNG_WRITE_FLUSH_SUPPORTED
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600199# ifdef PNG_STDIO_SUPPORTED
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500200
Andreas Dilger47a0c421997-05-16 02:46:07 -0500201 if (output_flush_fn != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500202 png_ptr->output_flush_fn = output_flush_fn;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500203
Guy Schalnate5a37791996-06-05 15:50:50 -0500204 else
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -0500205 png_ptr->output_flush_fn = png_default_flush;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500206
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600207# else
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600208 png_ptr->output_flush_fn = output_flush_fn;
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600209# endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500210#endif /* PNG_WRITE_FLUSH_SUPPORTED */
211
212 /* It is an error to read while writing a png file */
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500213 if (png_ptr->read_data_fn != NULL)
214 {
215 png_ptr->read_data_fn = NULL;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500216
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500217 png_warning(png_ptr,
Glenn Randers-Pehrson92a3ef42010-03-31 21:50:21 -0500218 "Can't set both read_data_fn and write_data_fn in the"
219 " same structure");
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500220 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500221}
222
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500223#ifdef USE_FAR_KEYWORD
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600224# ifdef _MSC_VER
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500225void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600226{
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600227 void *near_ptr;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600228 void FAR *far_ptr;
229 FP_OFF(near_ptr) = FP_OFF(ptr);
230 far_ptr = (void FAR *)near_ptr;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500231
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500232 if (check != 0)
233 if (FP_SEG(ptr) != FP_SEG(far_ptr))
234 png_error(png_ptr, "segment lost in conversion");
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500235
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600236 return(near_ptr);
237}
238# else
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500239void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600240{
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600241 void *near_ptr;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600242 void FAR *far_ptr;
243 near_ptr = (void FAR *)ptr;
244 far_ptr = (void FAR *)near_ptr;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500245
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500246 if (check != 0)
247 if (far_ptr != ptr)
248 png_error(png_ptr, "segment lost in conversion");
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500249
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600250 return(near_ptr);
251}
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600252# endif
253#endif
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500254#endif /* PNG_WRITE_SUPPORTED */