1
2/* pngwio.c - functions for data output
3 *
4 * Last changed in libpng 1.4.0 [January 3, 2010]
5 * Copyright (c) 1998-2010 Glenn Randers-Pehrson
6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8 *
9 * This code is released under the libpng license.
10 * For conditions of distribution and use, see the disclaimer
11 * and license in png.h
12 *
13 * 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
17 * functions, but rather write replacement functions and then change
18 * them at run time with png_set_write_fn(...).
19 */
20
21#define PNG_NO_PEDANTIC_WARNINGS
22#include "png.h"
23#ifdef PNG_WRITE_SUPPORTED
24#include "pngpriv.h"
25
26/* Write the data to whatever output you are using.  The default routine
27 * writes to a file pointer.  Note that this routine sometimes gets called
28 * with very small lengths, so you should implement some kind of simple
29 * buffering if you are using unbuffered writes.  This should never be asked
30 * to write more than 64K on a 16 bit machine.
31 */
32
33void /* PRIVATE */
34png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
35{
36   if (png_ptr->write_data_fn != NULL )
37      (*(png_ptr->write_data_fn))(png_ptr, data, length);
38   else
39      png_error(png_ptr, "Call to NULL write function");
40}
41
42#ifdef PNG_STDIO_SUPPORTED
43/* This is the function that does the actual writing of data.  If you are
44 * 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 */
48#ifndef USE_FAR_KEYWORD
49void PNGAPI
50png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
51{
52   png_uint_32 check;
53
54   if (png_ptr == NULL)
55      return;
56   check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
57   if (check != length)
58      png_error(png_ptr, "Write Error");
59}
60#else
61/* This is the model-independent version. Since the standard I/O library
62 * can't handle far buffers in the medium and small models, we have to copy
63 * the data.
64 */
65
66#define NEAR_BUF_SIZE 1024
67#define MIN(a,b) (a <= b ? a : b)
68
69void PNGAPI
70png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
71{
72   png_uint_32 check;
73   png_byte *near_data;  /* Needs to be "png_byte *" instead of "png_bytep" */
74   png_FILE_p io_ptr;
75
76   if (png_ptr == NULL)
77      return;
78   /* Check if data really is near. If so, use usual code. */
79   near_data = (png_byte *)CVT_PTR_NOCHECK(data);
80   io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
81   if ((png_bytep)near_data == data)
82   {
83      check = fwrite(near_data, 1, length, io_ptr);
84   }
85   else
86   {
87      png_byte buf[NEAR_BUF_SIZE];
88      png_size_t written, remaining, err;
89      check = 0;
90      remaining = length;
91      do
92      {
93         written = MIN(NEAR_BUF_SIZE, remaining);
94         png_memcpy(buf, data, written); /* Copy far buffer to near buffer */
95         err = fwrite(buf, 1, written, io_ptr);
96         if (err != written)
97            break;
98
99         else
100            check += err;
101
102         data += written;
103         remaining -= written;
104      }
105      while (remaining != 0);
106   }
107   if (check != length)
108      png_error(png_ptr, "Write Error");
109}
110
111#endif
112#endif
113
114/* This function is called to output any data pending writing (normally
115 * to disk).  After png_flush is called, there should be no data pending
116 * writing in any buffers.
117 */
118#ifdef PNG_WRITE_FLUSH_SUPPORTED
119void /* PRIVATE */
120png_flush(png_structp png_ptr)
121{
122   if (png_ptr->output_flush_fn != NULL)
123      (*(png_ptr->output_flush_fn))(png_ptr);
124}
125
126#ifdef PNG_STDIO_SUPPORTED
127void PNGAPI
128png_default_flush(png_structp png_ptr)
129{
130   png_FILE_p io_ptr;
131   if (png_ptr == NULL)
132      return;
133   io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
134   fflush(io_ptr);
135}
136#endif
137#endif
138
139/* This function allows the application to supply new output functions for
140 * libpng if standard C streams aren't being used.
141 *
142 * This function takes as its arguments:
143 * png_ptr       - pointer to a png output data structure
144 * io_ptr        - pointer to user supplied structure containing info about
145 *                 the output functions.  May be NULL.
146 * write_data_fn - pointer to a new output function that takes as its
147 *                 arguments a pointer to a png_struct, a pointer to
148 *                 data to be written, and a 32-bit unsigned int that is
149 *                 the number of bytes to be written.  The new write
150 *                 function should call png_error(png_ptr, "Error msg")
151 *                 to exit and output any fatal error messages.  May be
152 *                 NULL, in which case libpng's default function will
153 *                 be used.
154 * flush_data_fn - pointer to a new flush function that takes as its
155 *                 arguments a pointer to a png_struct.  After a call to
156 *                 the flush function, there should be no data in any buffers
157 *                 or pending transmission.  If the output method doesn't do
158 *                 any buffering of output, a function prototype must still be
159 *                 supplied although it doesn't have to do anything.  If
160 *                 PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
161 *                 time, output_flush_fn will be ignored, although it must be
162 *                 supplied for compatibility.  May be NULL, in which case
163 *                 libpng's default function will be used, if
164 *                 PNG_WRITE_FLUSH_SUPPORTED is defined.  This is not
165 *                 a good idea if io_ptr does not point to a standard
166 *                 *FILE structure.
167 */
168void PNGAPI
169png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
170   png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
171{
172   if (png_ptr == NULL)
173      return;
174
175   png_ptr->io_ptr = io_ptr;
176
177#ifdef PNG_STDIO_SUPPORTED
178   if (write_data_fn != NULL)
179      png_ptr->write_data_fn = write_data_fn;
180
181   else
182      png_ptr->write_data_fn = png_default_write_data;
183#else
184   png_ptr->write_data_fn = write_data_fn;
185#endif
186
187#ifdef PNG_WRITE_FLUSH_SUPPORTED
188#ifdef PNG_STDIO_SUPPORTED
189   if (output_flush_fn != NULL)
190      png_ptr->output_flush_fn = output_flush_fn;
191
192   else
193      png_ptr->output_flush_fn = png_default_flush;
194#else
195   png_ptr->output_flush_fn = output_flush_fn;
196#endif
197#endif /* PNG_WRITE_FLUSH_SUPPORTED */
198
199   /* It is an error to read while writing a png file */
200   if (png_ptr->read_data_fn != NULL)
201   {
202      png_ptr->read_data_fn = NULL;
203      png_warning(png_ptr,
204         "Attempted to set both read_data_fn and write_data_fn in");
205      png_warning(png_ptr,
206         "the same structure.  Resetting read_data_fn to NULL");
207   }
208}
209
210#ifdef USE_FAR_KEYWORD
211#ifdef _MSC_VER
212void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
213{
214   void *near_ptr;
215   void FAR *far_ptr;
216   FP_OFF(near_ptr) = FP_OFF(ptr);
217   far_ptr = (void FAR *)near_ptr;
218
219   if (check != 0)
220      if (FP_SEG(ptr) != FP_SEG(far_ptr))
221         png_error(png_ptr, "segment lost in conversion");
222
223   return(near_ptr);
224}
225#  else
226void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
227{
228   void *near_ptr;
229   void FAR *far_ptr;
230   near_ptr = (void FAR *)ptr;
231   far_ptr = (void FAR *)near_ptr;
232
233   if (check != 0)
234      if (far_ptr != ptr)
235         png_error(png_ptr, "segment lost in conversion");
236
237   return(near_ptr);
238}
239#   endif
240#   endif
241#endif /* PNG_WRITE_SUPPORTED */
242