blob: f8842feddb35132d5057541a166fbccc38433111 [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-Pehrsonf24daf22010-05-06 09:44:04 -05004 * Last changed in libpng 1.5.0 [May 6, 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 */
Andreas Dilger47a0c421997-05-16 02:46:07 -050033png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
Guy Schalnate5a37791996-06-05 15:50:50 -050034{
Andreas Dilger47a0c421997-05-16 02:46:07 -050035 if (png_ptr->write_data_fn != NULL )
Guy Schalnate5a37791996-06-05 15:50:50 -050036 (*(png_ptr->write_data_fn))(png_ptr, data, length);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050037
Guy Schalnate5a37791996-06-05 15:50:50 -050038 else
39 png_error(png_ptr, "Call to NULL write function");
40}
41
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -050042#ifdef PNG_STDIO_SUPPORTED
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050043/* 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 -050044 * not writing to a standard C stream, you should create a replacement
45 * write_data function and use it at run time with png_set_write_fn(), rather
46 * than changing the library.
47 */
Guy Schalnate5a37791996-06-05 15:50:50 -050048#ifndef USE_FAR_KEYWORD
Glenn Randers-Pehrsoneae8e362010-03-12 17:36:53 -060049void PNGCBAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -050050png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
Guy Schalnate5a37791996-06-05 15:50:50 -050051{
52 png_uint_32 check;
53
Glenn Randers-Pehrsond8eb62f2009-05-30 20:19:20 -050054 if (png_ptr == NULL)
55 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050056
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -050057 check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050058
Guy Schalnate5a37791996-06-05 15:50:50 -050059 if (check != length)
Guy Schalnate5a37791996-06-05 15:50:50 -050060 png_error(png_ptr, "Write Error");
Guy Schalnate5a37791996-06-05 15:50:50 -050061}
62#else
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050063/* This is the model-independent version. Since the standard I/O library
64 * can't handle far buffers in the medium and small models, we have to copy
65 * the data.
66 */
Guy Schalnate5a37791996-06-05 15:50:50 -050067
68#define NEAR_BUF_SIZE 1024
69#define MIN(a,b) (a <= b ? a : b)
70
Glenn Randers-Pehrsoneae8e362010-03-12 17:36:53 -060071void PNGCBAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -050072png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
Guy Schalnate5a37791996-06-05 15:50:50 -050073{
74 png_uint_32 check;
Andreas Dilger47a0c421997-05-16 02:46:07 -050075 png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -050076 png_FILE_p io_ptr;
Guy Schalnate5a37791996-06-05 15:50:50 -050077
Glenn Randers-Pehrsond8eb62f2009-05-30 20:19:20 -050078 if (png_ptr == NULL)
79 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050080
Guy Schalnate5a37791996-06-05 15:50:50 -050081 /* Check if data really is near. If so, use usual code. */
Andreas Dilger47a0c421997-05-16 02:46:07 -050082 near_data = (png_byte *)CVT_PTR_NOCHECK(data);
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -050083 io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050084
Andreas Dilger47a0c421997-05-16 02:46:07 -050085 if ((png_bytep)near_data == data)
Guy Schalnate5a37791996-06-05 15:50:50 -050086 {
Andreas Dilger47a0c421997-05-16 02:46:07 -050087 check = fwrite(near_data, 1, length, io_ptr);
Guy Schalnate5a37791996-06-05 15:50:50 -050088 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050089
Guy Schalnate5a37791996-06-05 15:50:50 -050090 else
91 {
92 png_byte buf[NEAR_BUF_SIZE];
93 png_size_t written, remaining, err;
94 check = 0;
Andreas Dilger47a0c421997-05-16 02:46:07 -050095 remaining = length;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050096
Guy Schalnate5a37791996-06-05 15:50:50 -050097 do
98 {
99 written = MIN(NEAR_BUF_SIZE, remaining);
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500100 png_memcpy(buf, data, written); /* Copy far buffer to near buffer */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600101 err = fwrite(buf, 1, written, io_ptr);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500102
Guy Schalnate5a37791996-06-05 15:50:50 -0500103 if (err != written)
104 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500105
Guy Schalnate5a37791996-06-05 15:50:50 -0500106 else
107 check += err;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500108
Guy Schalnate5a37791996-06-05 15:50:50 -0500109 data += written;
110 remaining -= written;
111 }
112 while (remaining != 0);
113 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500114
Guy Schalnate5a37791996-06-05 15:50:50 -0500115 if (check != length)
Guy Schalnate5a37791996-06-05 15:50:50 -0500116 png_error(png_ptr, "Write Error");
Guy Schalnate5a37791996-06-05 15:50:50 -0500117}
118
119#endif
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600120#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500121
122/* This function is called to output any data pending writing (normally
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500123 * to disk). After png_flush is called, there should be no data pending
124 * writing in any buffers.
125 */
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500126#ifdef PNG_WRITE_FLUSH_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500127void /* PRIVATE */
Guy Schalnate5a37791996-06-05 15:50:50 -0500128png_flush(png_structp png_ptr)
129{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500130 if (png_ptr->output_flush_fn != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500131 (*(png_ptr->output_flush_fn))(png_ptr);
132}
133
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600134# ifdef PNG_STDIO_SUPPORTED
Glenn Randers-Pehrsoneae8e362010-03-12 17:36:53 -0600135void PNGCBAPI
Guy Schalnate5a37791996-06-05 15:50:50 -0500136png_default_flush(png_structp png_ptr)
137{
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500138 png_FILE_p io_ptr;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500139
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500140 if (png_ptr == NULL)
141 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500142
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500143 io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
Glenn Randers-Pehrson8fb550c2009-03-21 08:15:32 -0500144 fflush(io_ptr);
Guy Schalnate5a37791996-06-05 15:50:50 -0500145}
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600146# endif
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600147#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500148
149/* This function allows the application to supply new output functions for
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500150 * libpng if standard C streams aren't being used.
151 *
152 * This function takes as its arguments:
153 * png_ptr - pointer to a png output data structure
154 * io_ptr - pointer to user supplied structure containing info about
155 * the output functions. May be NULL.
156 * write_data_fn - pointer to a new output function that takes as its
157 * arguments a pointer to a png_struct, a pointer to
158 * data to be written, and a 32-bit unsigned int that is
159 * the number of bytes to be written. The new write
160 * function should call png_error(png_ptr, "Error msg")
161 * to exit and output any fatal error messages. May be
162 * NULL, in which case libpng's default function will
163 * be used.
164 * flush_data_fn - pointer to a new flush function that takes as its
165 * arguments a pointer to a png_struct. After a call to
166 * the flush function, there should be no data in any buffers
167 * or pending transmission. If the output method doesn't do
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500168 * any buffering of output, a function prototype must still be
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500169 * supplied although it doesn't have to do anything. If
170 * PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
171 * time, output_flush_fn will be ignored, although it must be
172 * supplied for compatibility. May be NULL, in which case
173 * libpng's default function will be used, if
174 * PNG_WRITE_FLUSH_SUPPORTED is defined. This is not
175 * a good idea if io_ptr does not point to a standard
176 * *FILE structure.
177 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500178void PNGAPI
Guy Schalnate5a37791996-06-05 15:50:50 -0500179png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600180 png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
Guy Schalnate5a37791996-06-05 15:50:50 -0500181{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500182 if (png_ptr == NULL)
183 return;
184
Guy Schalnate5a37791996-06-05 15:50:50 -0500185 png_ptr->io_ptr = io_ptr;
186
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500187#ifdef PNG_STDIO_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500188 if (write_data_fn != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500189 png_ptr->write_data_fn = write_data_fn;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500190
Guy Schalnate5a37791996-06-05 15:50:50 -0500191 else
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -0500192 png_ptr->write_data_fn = png_default_write_data;
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600193#else
194 png_ptr->write_data_fn = write_data_fn;
195#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500196
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500197#ifdef PNG_WRITE_FLUSH_SUPPORTED
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600198# ifdef PNG_STDIO_SUPPORTED
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500199
Andreas Dilger47a0c421997-05-16 02:46:07 -0500200 if (output_flush_fn != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500201 png_ptr->output_flush_fn = output_flush_fn;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500202
Guy Schalnate5a37791996-06-05 15:50:50 -0500203 else
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -0500204 png_ptr->output_flush_fn = png_default_flush;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500205
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600206# else
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600207 png_ptr->output_flush_fn = output_flush_fn;
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600208# endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500209#endif /* PNG_WRITE_FLUSH_SUPPORTED */
210
211 /* It is an error to read while writing a png file */
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500212 if (png_ptr->read_data_fn != NULL)
213 {
214 png_ptr->read_data_fn = NULL;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500215
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500216 png_warning(png_ptr,
Glenn Randers-Pehrson92a3ef42010-03-31 21:50:21 -0500217 "Can't set both read_data_fn and write_data_fn in the"
218 " same structure");
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500219 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500220}
221
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500222#ifdef USE_FAR_KEYWORD
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600223# ifdef _MSC_VER
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500224void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600225{
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600226 void *near_ptr;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600227 void FAR *far_ptr;
228 FP_OFF(near_ptr) = FP_OFF(ptr);
229 far_ptr = (void FAR *)near_ptr;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500230
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500231 if (check != 0)
232 if (FP_SEG(ptr) != FP_SEG(far_ptr))
233 png_error(png_ptr, "segment lost in conversion");
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500234
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600235 return(near_ptr);
236}
237# else
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500238void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600239{
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600240 void *near_ptr;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600241 void FAR *far_ptr;
242 near_ptr = (void FAR *)ptr;
243 far_ptr = (void FAR *)near_ptr;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500244
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500245 if (check != 0)
246 if (far_ptr != ptr)
247 png_error(png_ptr, "segment lost in conversion");
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500248
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600249 return(near_ptr);
250}
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600251# endif
252#endif
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500253#endif /* PNG_WRITE_SUPPORTED */