blob: f8dda215a46875a38308979a8b9f5ec306bbd0fa [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-Pehrson65a22372010-03-03 05:38:29 -06004 * Last changed in libpng 1.5.0 [March 3, 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-Pehrsonf9795312010-02-09 01:16:48 -060021#define PNG_EXPOSE_INTERNAL_STRUCTURES
Glenn Randers-Pehrson03f9b022009-12-04 08:40:41 -060022#define PNG_NO_PEDANTIC_WARNINGS
Guy Schalnate5a37791996-06-05 15:50:50 -050023#include "png.h"
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -050024#ifdef PNG_WRITE_SUPPORTED
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -050025#include "pngpriv.h"
Guy Schalnate5a37791996-06-05 15:50:50 -050026
27/* Write the data to whatever output you are using. The default routine
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050028 * writes to a file pointer. Note that this routine sometimes gets called
29 * with very small lengths, so you should implement some kind of simple
30 * buffering if you are using unbuffered writes. This should never be asked
31 * to write more than 64K on a 16 bit machine.
32 */
Guy Schalnate5a37791996-06-05 15:50:50 -050033
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050034void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -050035png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
Guy Schalnate5a37791996-06-05 15:50:50 -050036{
Andreas Dilger47a0c421997-05-16 02:46:07 -050037 if (png_ptr->write_data_fn != NULL )
Guy Schalnate5a37791996-06-05 15:50:50 -050038 (*(png_ptr->write_data_fn))(png_ptr, data, length);
39 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-Pehrson25d82242002-05-01 11:51:26 -050050void PNGAPI
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-Pehrson316f97a2000-07-08 13:19:41 -050057 check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
Guy Schalnate5a37791996-06-05 15:50:50 -050058 if (check != length)
Guy Schalnate5a37791996-06-05 15:50:50 -050059 png_error(png_ptr, "Write Error");
Guy Schalnate5a37791996-06-05 15:50:50 -050060}
61#else
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050062/* This is the model-independent version. Since the standard I/O library
63 * can't handle far buffers in the medium and small models, we have to copy
64 * the data.
65 */
Guy Schalnate5a37791996-06-05 15:50:50 -050066
67#define NEAR_BUF_SIZE 1024
68#define MIN(a,b) (a <= b ? a : b)
69
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -050070void PNGAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -050071png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
Guy Schalnate5a37791996-06-05 15:50:50 -050072{
73 png_uint_32 check;
Andreas Dilger47a0c421997-05-16 02:46:07 -050074 png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -050075 png_FILE_p io_ptr;
Guy Schalnate5a37791996-06-05 15:50:50 -050076
Glenn Randers-Pehrsond8eb62f2009-05-30 20:19:20 -050077 if (png_ptr == NULL)
78 return;
Guy Schalnate5a37791996-06-05 15:50:50 -050079 /* Check if data really is near. If so, use usual code. */
Andreas Dilger47a0c421997-05-16 02:46:07 -050080 near_data = (png_byte *)CVT_PTR_NOCHECK(data);
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -050081 io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
Andreas Dilger47a0c421997-05-16 02:46:07 -050082 if ((png_bytep)near_data == data)
Guy Schalnate5a37791996-06-05 15:50:50 -050083 {
Andreas Dilger47a0c421997-05-16 02:46:07 -050084 check = fwrite(near_data, 1, length, io_ptr);
Guy Schalnate5a37791996-06-05 15:50:50 -050085 }
86 else
87 {
88 png_byte buf[NEAR_BUF_SIZE];
89 png_size_t written, remaining, err;
90 check = 0;
Andreas Dilger47a0c421997-05-16 02:46:07 -050091 remaining = length;
Guy Schalnate5a37791996-06-05 15:50:50 -050092 do
93 {
94 written = MIN(NEAR_BUF_SIZE, remaining);
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -050095 png_memcpy(buf, data, written); /* Copy far buffer to near buffer */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060096 err = fwrite(buf, 1, written, io_ptr);
Guy Schalnate5a37791996-06-05 15:50:50 -050097 if (err != written)
98 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050099
Guy Schalnate5a37791996-06-05 15:50:50 -0500100 else
101 check += err;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500102
Guy Schalnate5a37791996-06-05 15:50:50 -0500103 data += written;
104 remaining -= written;
105 }
106 while (remaining != 0);
107 }
108 if (check != length)
Guy Schalnate5a37791996-06-05 15:50:50 -0500109 png_error(png_ptr, "Write Error");
Guy Schalnate5a37791996-06-05 15:50:50 -0500110}
111
112#endif
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600113#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500114
115/* This function is called to output any data pending writing (normally
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500116 * to disk). After png_flush is called, there should be no data pending
117 * writing in any buffers.
118 */
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500119#ifdef PNG_WRITE_FLUSH_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500120void /* PRIVATE */
Guy Schalnate5a37791996-06-05 15:50:50 -0500121png_flush(png_structp png_ptr)
122{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500123 if (png_ptr->output_flush_fn != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500124 (*(png_ptr->output_flush_fn))(png_ptr);
125}
126
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600127# ifdef PNG_STDIO_SUPPORTED
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -0500128void PNGAPI
Guy Schalnate5a37791996-06-05 15:50:50 -0500129png_default_flush(png_structp png_ptr)
130{
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500131 png_FILE_p io_ptr;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500132 if (png_ptr == NULL)
133 return;
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500134 io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
Glenn Randers-Pehrson8fb550c2009-03-21 08:15:32 -0500135 fflush(io_ptr);
Guy Schalnate5a37791996-06-05 15:50:50 -0500136}
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600137# endif
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600138#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500139
140/* This function allows the application to supply new output functions for
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500141 * libpng if standard C streams aren't being used.
142 *
143 * This function takes as its arguments:
144 * png_ptr - pointer to a png output data structure
145 * io_ptr - pointer to user supplied structure containing info about
146 * the output functions. May be NULL.
147 * write_data_fn - pointer to a new output function that takes as its
148 * arguments a pointer to a png_struct, a pointer to
149 * data to be written, and a 32-bit unsigned int that is
150 * the number of bytes to be written. The new write
151 * function should call png_error(png_ptr, "Error msg")
152 * to exit and output any fatal error messages. May be
153 * NULL, in which case libpng's default function will
154 * be used.
155 * flush_data_fn - pointer to a new flush function that takes as its
156 * arguments a pointer to a png_struct. After a call to
157 * the flush function, there should be no data in any buffers
158 * or pending transmission. If the output method doesn't do
159 * any buffering of ouput, a function prototype must still be
160 * supplied although it doesn't have to do anything. If
161 * PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
162 * time, output_flush_fn will be ignored, although it must be
163 * supplied for compatibility. May be NULL, in which case
164 * libpng's default function will be used, if
165 * PNG_WRITE_FLUSH_SUPPORTED is defined. This is not
166 * a good idea if io_ptr does not point to a standard
167 * *FILE structure.
168 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500169void PNGAPI
Guy Schalnate5a37791996-06-05 15:50:50 -0500170png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600171 png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
Guy Schalnate5a37791996-06-05 15:50:50 -0500172{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500173 if (png_ptr == NULL)
174 return;
175
Guy Schalnate5a37791996-06-05 15:50:50 -0500176 png_ptr->io_ptr = io_ptr;
177
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500178#ifdef PNG_STDIO_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500179 if (write_data_fn != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500180 png_ptr->write_data_fn = write_data_fn;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500181
Guy Schalnate5a37791996-06-05 15:50:50 -0500182 else
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -0500183 png_ptr->write_data_fn = png_default_write_data;
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600184#else
185 png_ptr->write_data_fn = write_data_fn;
186#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500187
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500188#ifdef PNG_WRITE_FLUSH_SUPPORTED
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600189# ifdef PNG_STDIO_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500190 if (output_flush_fn != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500191 png_ptr->output_flush_fn = output_flush_fn;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500192
Guy Schalnate5a37791996-06-05 15:50:50 -0500193 else
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -0500194 png_ptr->output_flush_fn = png_default_flush;
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600195# else
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600196 png_ptr->output_flush_fn = output_flush_fn;
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600197# endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500198#endif /* PNG_WRITE_FLUSH_SUPPORTED */
199
200 /* It is an error to read while writing a png file */
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500201 if (png_ptr->read_data_fn != NULL)
202 {
203 png_ptr->read_data_fn = NULL;
204 png_warning(png_ptr,
205 "Attempted to set both read_data_fn and write_data_fn in");
206 png_warning(png_ptr,
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500207 "the same structure. Resetting read_data_fn to NULL");
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500208 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500209}
210
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500211#ifdef USE_FAR_KEYWORD
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600212# ifdef _MSC_VER
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500213void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600214{
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600215 void *near_ptr;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600216 void FAR *far_ptr;
217 FP_OFF(near_ptr) = FP_OFF(ptr);
218 far_ptr = (void FAR *)near_ptr;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500219
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500220 if (check != 0)
221 if (FP_SEG(ptr) != FP_SEG(far_ptr))
222 png_error(png_ptr, "segment lost in conversion");
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500223
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600224 return(near_ptr);
225}
226# else
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500227void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600228{
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600229 void *near_ptr;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600230 void FAR *far_ptr;
231 near_ptr = (void FAR *)ptr;
232 far_ptr = (void FAR *)near_ptr;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500233
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500234 if (check != 0)
235 if (far_ptr != ptr)
236 png_error(png_ptr, "segment lost in conversion");
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500237
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600238 return(near_ptr);
239}
Glenn Randers-Pehrson6f6a91a2010-03-06 13:54:59 -0600240# endif
241#endif
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500242#endif /* PNG_WRITE_SUPPORTED */