pngwio.c 7.4 KB
Newer Older
G
Guy Schalnat 已提交
1 2

/* pngwio.c - functions for data output
3
 *
4
 * Last changed in libpng 1.5.0 [April 1, 2010]
5
 * Copyright (c) 1998-2010 Glenn Randers-Pehrson
6 7
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (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 14 15 16
 * This file provides a location for all output.  Users who need
 * special handling are expected to write functions that have the same
 * arguments as these and perform similar functions, but that possibly
 * use different output methods.  Note that you shouldn't change these
17 18 19
 * functions, but rather write replacement functions and then change
 * them at run time with png_set_write_fn(...).
 */
G
Guy Schalnat 已提交
20

21
#include "pngpriv.h"
G
Guy Schalnat 已提交
22

23 24
#ifdef PNG_WRITE_SUPPORTED

G
Guy Schalnat 已提交
25
/* Write the data to whatever output you are using.  The default routine
26 27 28 29 30
 * writes to a file pointer.  Note that this routine sometimes gets called
 * with very small lengths, so you should implement some kind of simple
 * buffering if you are using unbuffered writes.  This should never be asked
 * to write more than 64K on a 16 bit machine.
 */
G
Guy Schalnat 已提交
31

32
void /* PRIVATE */
A
Andreas Dilger 已提交
33
png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
G
Guy Schalnat 已提交
34
{
A
Andreas Dilger 已提交
35
   if (png_ptr->write_data_fn != NULL )
G
Guy Schalnat 已提交
36 37 38 39 40
      (*(png_ptr->write_data_fn))(png_ptr, data, length);
   else
      png_error(png_ptr, "Call to NULL write function");
}

41
#ifdef PNG_STDIO_SUPPORTED
42
/* This is the function that does the actual writing of data.  If you are
43 44 45 46
 * not writing to a standard C stream, you should create a replacement
 * write_data function and use it at run time with png_set_write_fn(), rather
 * than changing the library.
 */
G
Guy Schalnat 已提交
47
#ifndef USE_FAR_KEYWORD
48
void PNGCBAPI
A
Andreas Dilger 已提交
49
png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
G
Guy Schalnat 已提交
50 51 52
{
   png_uint_32 check;

53 54
   if (png_ptr == NULL)
      return;
55
   check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
G
Guy Schalnat 已提交
56 57 58 59
   if (check != length)
      png_error(png_ptr, "Write Error");
}
#else
60 61 62 63
/* This is the model-independent version. Since the standard I/O library
 * can't handle far buffers in the medium and small models, we have to copy
 * the data.
 */
G
Guy Schalnat 已提交
64 65 66 67

#define NEAR_BUF_SIZE 1024
#define MIN(a,b) (a <= b ? a : b)

68
void PNGCBAPI
A
Andreas Dilger 已提交
69
png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
G
Guy Schalnat 已提交
70 71
{
   png_uint_32 check;
A
Andreas Dilger 已提交
72
   png_byte *near_data;  /* Needs to be "png_byte *" instead of "png_bytep" */
73
   png_FILE_p io_ptr;
G
Guy Schalnat 已提交
74

75 76
   if (png_ptr == NULL)
      return;
G
Guy Schalnat 已提交
77
   /* Check if data really is near. If so, use usual code. */
A
Andreas Dilger 已提交
78
   near_data = (png_byte *)CVT_PTR_NOCHECK(data);
79
   io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
A
Andreas Dilger 已提交
80
   if ((png_bytep)near_data == data)
G
Guy Schalnat 已提交
81
   {
A
Andreas Dilger 已提交
82
      check = fwrite(near_data, 1, length, io_ptr);
G
Guy Schalnat 已提交
83 84 85 86 87 88
   }
   else
   {
      png_byte buf[NEAR_BUF_SIZE];
      png_size_t written, remaining, err;
      check = 0;
A
Andreas Dilger 已提交
89
      remaining = length;
G
Guy Schalnat 已提交
90 91 92
      do
      {
         written = MIN(NEAR_BUF_SIZE, remaining);
93
         png_memcpy(buf, data, written); /* Copy far buffer to near buffer */
A
Andreas Dilger 已提交
94
         err = fwrite(buf, 1, written, io_ptr);
G
Guy Schalnat 已提交
95 96
         if (err != written)
            break;
97

G
Guy Schalnat 已提交
98 99
         else
            check += err;
100

G
Guy Schalnat 已提交
101 102 103 104 105 106 107 108 109
         data += written;
         remaining -= written;
      }
      while (remaining != 0);
   }
   if (check != length)
      png_error(png_ptr, "Write Error");
}

110
#endif
G
Guy Schalnat 已提交
111 112 113
#endif

/* This function is called to output any data pending writing (normally
114 115 116
 * to disk).  After png_flush is called, there should be no data pending
 * writing in any buffers.
 */
117
#ifdef PNG_WRITE_FLUSH_SUPPORTED
118
void /* PRIVATE */
G
Guy Schalnat 已提交
119 120
png_flush(png_structp png_ptr)
{
A
Andreas Dilger 已提交
121
   if (png_ptr->output_flush_fn != NULL)
G
Guy Schalnat 已提交
122 123 124
      (*(png_ptr->output_flush_fn))(png_ptr);
}

125
#  ifdef PNG_STDIO_SUPPORTED
126
void PNGCBAPI
G
Guy Schalnat 已提交
127 128
png_default_flush(png_structp png_ptr)
{
129
   png_FILE_p io_ptr;
130 131
   if (png_ptr == NULL)
      return;
132
   io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
133
   fflush(io_ptr);
G
Guy Schalnat 已提交
134
}
135
#  endif
136
#endif
G
Guy Schalnat 已提交
137 138

/* This function allows the application to supply new output functions for
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
 * libpng if standard C streams aren't being used.
 *
 * This function takes as its arguments:
 * png_ptr       - pointer to a png output data structure
 * io_ptr        - pointer to user supplied structure containing info about
 *                 the output functions.  May be NULL.
 * write_data_fn - pointer to a new output function that takes as its
 *                 arguments a pointer to a png_struct, a pointer to
 *                 data to be written, and a 32-bit unsigned int that is
 *                 the number of bytes to be written.  The new write
 *                 function should call png_error(png_ptr, "Error msg")
 *                 to exit and output any fatal error messages.  May be
 *                 NULL, in which case libpng's default function will
 *                 be used.
 * flush_data_fn - pointer to a new flush function that takes as its
 *                 arguments a pointer to a png_struct.  After a call to
 *                 the flush function, there should be no data in any buffers
 *                 or pending transmission.  If the output method doesn't do
 *                 any buffering of ouput, a function prototype must still be
 *                 supplied although it doesn't have to do anything.  If
 *                 PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
 *                 time, output_flush_fn will be ignored, although it must be
 *                 supplied for compatibility.  May be NULL, in which case
 *                 libpng's default function will be used, if
 *                 PNG_WRITE_FLUSH_SUPPORTED is defined.  This is not
 *                 a good idea if io_ptr does not point to a standard
 *                 *FILE structure.
 */
167
void PNGAPI
G
Guy Schalnat 已提交
168
png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
169
    png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
G
Guy Schalnat 已提交
170
{
171 172 173
   if (png_ptr == NULL)
      return;

G
Guy Schalnat 已提交
174 175
   png_ptr->io_ptr = io_ptr;

176
#ifdef PNG_STDIO_SUPPORTED
A
Andreas Dilger 已提交
177
   if (write_data_fn != NULL)
G
Guy Schalnat 已提交
178
      png_ptr->write_data_fn = write_data_fn;
179

G
Guy Schalnat 已提交
180
   else
181
      png_ptr->write_data_fn = png_default_write_data;
182 183 184
#else
   png_ptr->write_data_fn = write_data_fn;
#endif
G
Guy Schalnat 已提交
185

186
#ifdef PNG_WRITE_FLUSH_SUPPORTED
187
#  ifdef PNG_STDIO_SUPPORTED
A
Andreas Dilger 已提交
188
   if (output_flush_fn != NULL)
G
Guy Schalnat 已提交
189
      png_ptr->output_flush_fn = output_flush_fn;
190

G
Guy Schalnat 已提交
191
   else
192
      png_ptr->output_flush_fn = png_default_flush;
193
#  else
194
   png_ptr->output_flush_fn = output_flush_fn;
195
#  endif
G
Guy Schalnat 已提交
196 197 198
#endif /* PNG_WRITE_FLUSH_SUPPORTED */

   /* It is an error to read while writing a png file */
199 200 201 202
   if (png_ptr->read_data_fn != NULL)
   {
      png_ptr->read_data_fn = NULL;
      png_warning(png_ptr,
203 204
          "Can't set both read_data_fn and write_data_fn in the"
          " same structure");
205
   }
G
Guy Schalnat 已提交
206 207
}

208
#ifdef USE_FAR_KEYWORD
209
#  ifdef _MSC_VER
210
void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
A
Andreas Dilger 已提交
211
{
212
   void *near_ptr;
A
Andreas Dilger 已提交
213 214 215
   void FAR *far_ptr;
   FP_OFF(near_ptr) = FP_OFF(ptr);
   far_ptr = (void FAR *)near_ptr;
216

217 218 219
   if (check != 0)
      if (FP_SEG(ptr) != FP_SEG(far_ptr))
         png_error(png_ptr, "segment lost in conversion");
220

A
Andreas Dilger 已提交
221 222 223
   return(near_ptr);
}
#  else
224
void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
A
Andreas Dilger 已提交
225
{
226
   void *near_ptr;
A
Andreas Dilger 已提交
227 228 229
   void FAR *far_ptr;
   near_ptr = (void FAR *)ptr;
   far_ptr = (void FAR *)near_ptr;
230

231 232 233
   if (check != 0)
      if (far_ptr != ptr)
         png_error(png_ptr, "segment lost in conversion");
234

A
Andreas Dilger 已提交
235 236
   return(near_ptr);
}
237 238
#  endif
#endif
239
#endif /* PNG_WRITE_SUPPORTED */