blob: 67e2bd8149a3c074d61990978f051d5cb7d930ca [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-Pehrson25d82242002-05-01 11:51:26 -05004 * libpng 1.2.3rc2 - May 1, 2002
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06005 * For conditions of distribution and use, see copyright notice in png.h
Glenn Randers-Pehrsonc6de22d2002-02-23 18:55:25 -06006 * Copyright (c) 1998-2002 Glenn Randers-Pehrson
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05007 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06009 *
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050010 * This file provides a location for all output. Users who need
11 * special handling are expected to write functions that have the same
12 * arguments as these and perform similar functions, but that possibly
13 * use different output methods. Note that you shouldn't change these
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060014 * functions, but rather write replacement functions and then change
15 * them at run time with png_set_write_fn(...).
16 */
Guy Schalnate5a37791996-06-05 15:50:50 -050017
18#define PNG_INTERNAL
19#include "png.h"
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -050020#ifdef PNG_WRITE_SUPPORTED
Guy Schalnate5a37791996-06-05 15:50:50 -050021
22/* Write the data to whatever output you are using. The default routine
23 writes to a file pointer. Note that this routine sometimes gets called
24 with very small lengths, so you should implement some kind of simple
25 buffering if you are using unbuffered writes. This should never be asked
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -050026 to write more than 64K on a 16 bit machine. */
Guy Schalnate5a37791996-06-05 15:50:50 -050027
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050028void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -050029png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
Guy Schalnate5a37791996-06-05 15:50:50 -050030{
Andreas Dilger47a0c421997-05-16 02:46:07 -050031 if (png_ptr->write_data_fn != NULL )
Guy Schalnate5a37791996-06-05 15:50:50 -050032 (*(png_ptr->write_data_fn))(png_ptr, data, length);
33 else
34 png_error(png_ptr, "Call to NULL write function");
35}
36
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -060037#if !defined(PNG_NO_STDIO)
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050038/* This is the function that does the actual writing of data. If you are
Guy Schalnate5a37791996-06-05 15:50:50 -050039 not writing to a standard C stream, you should create a replacement
40 write_data function and use it at run time with png_set_write_fn(), rather
41 than changing the library. */
42#ifndef USE_FAR_KEYWORD
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -050043void PNGAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -050044png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
Guy Schalnate5a37791996-06-05 15:50:50 -050045{
46 png_uint_32 check;
47
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -050048#if defined(_WIN32_WCE)
49 if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
Glenn Randers-Pehrson15dac0b2000-07-10 07:48:54 -050050 check = 0;
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -050051#else
52 check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
53#endif
Guy Schalnate5a37791996-06-05 15:50:50 -050054 if (check != length)
Guy Schalnate5a37791996-06-05 15:50:50 -050055 png_error(png_ptr, "Write Error");
Guy Schalnate5a37791996-06-05 15:50:50 -050056}
57#else
58/* this is the model-independent version. Since the standard I/O library
59 can't handle far buffers in the medium and small models, we have to copy
60 the data.
61*/
62
63#define NEAR_BUF_SIZE 1024
64#define MIN(a,b) (a <= b ? a : b)
65
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -050066void PNGAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -050067png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
Guy Schalnate5a37791996-06-05 15:50:50 -050068{
69 png_uint_32 check;
Andreas Dilger47a0c421997-05-16 02:46:07 -050070 png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -050071 png_FILE_p io_ptr;
Guy Schalnate5a37791996-06-05 15:50:50 -050072
73 /* Check if data really is near. If so, use usual code. */
Andreas Dilger47a0c421997-05-16 02:46:07 -050074 near_data = (png_byte *)CVT_PTR_NOCHECK(data);
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -050075 io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
Andreas Dilger47a0c421997-05-16 02:46:07 -050076 if ((png_bytep)near_data == data)
Guy Schalnate5a37791996-06-05 15:50:50 -050077 {
Glenn Randers-Pehrson15dac0b2000-07-10 07:48:54 -050078#if defined(_WIN32_WCE)
79 if ( !WriteFile(io_ptr, near_data, length, &check, NULL) )
80 check = 0;
81#else
Andreas Dilger47a0c421997-05-16 02:46:07 -050082 check = fwrite(near_data, 1, length, io_ptr);
Glenn Randers-Pehrson15dac0b2000-07-10 07:48:54 -050083#endif
Guy Schalnate5a37791996-06-05 15:50:50 -050084 }
85 else
86 {
87 png_byte buf[NEAR_BUF_SIZE];
88 png_size_t written, remaining, err;
89 check = 0;
Andreas Dilger47a0c421997-05-16 02:46:07 -050090 remaining = length;
Guy Schalnate5a37791996-06-05 15:50:50 -050091 do
92 {
93 written = MIN(NEAR_BUF_SIZE, remaining);
94 png_memcpy(buf, data, written); /* copy far buffer to near buffer */
Glenn Randers-Pehrson15dac0b2000-07-10 07:48:54 -050095#if defined(_WIN32_WCE)
96 if ( !WriteFile(io_ptr, buf, written, &err, NULL) )
97 err = 0;
98#else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060099 err = fwrite(buf, 1, written, io_ptr);
Glenn Randers-Pehrson15dac0b2000-07-10 07:48:54 -0500100#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500101 if (err != written)
102 break;
103 else
104 check += err;
105 data += written;
106 remaining -= written;
107 }
108 while (remaining != 0);
109 }
110 if (check != length)
Guy Schalnate5a37791996-06-05 15:50:50 -0500111 png_error(png_ptr, "Write Error");
Guy Schalnate5a37791996-06-05 15:50:50 -0500112}
113
114#endif
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600115#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500116
117/* This function is called to output any data pending writing (normally
118 to disk). After png_flush is called, there should be no data pending
119 writing in any buffers. */
120#if defined(PNG_WRITE_FLUSH_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500121void /* PRIVATE */
Guy Schalnate5a37791996-06-05 15:50:50 -0500122png_flush(png_structp png_ptr)
123{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500124 if (png_ptr->output_flush_fn != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500125 (*(png_ptr->output_flush_fn))(png_ptr);
126}
127
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600128#if !defined(PNG_NO_STDIO)
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -0500129void PNGAPI
Guy Schalnate5a37791996-06-05 15:50:50 -0500130png_default_flush(png_structp png_ptr)
131{
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500132#if !defined(_WIN32_WCE)
133 png_FILE_p io_ptr;
134 io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500135 if (io_ptr != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600136 fflush(io_ptr);
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500137#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500138}
139#endif
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600140#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500141
142/* This function allows the application to supply new output functions for
143 libpng if standard C streams aren't being used.
144
145 This function takes as its arguments:
146 png_ptr - pointer to a png output data structure
147 io_ptr - pointer to user supplied structure containing info about
148 the output functions. May be NULL.
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500149 write_data_fn - pointer to a new output function that takes as its
Guy Schalnate5a37791996-06-05 15:50:50 -0500150 arguments a pointer to a png_struct, a pointer to
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500151 data to be written, and a 32-bit unsigned int that is
Guy Schalnate5a37791996-06-05 15:50:50 -0500152 the number of bytes to be written. The new write
153 function should call png_error(png_ptr, "Error msg")
154 to exit and output any fatal error messages.
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500155 flush_data_fn - pointer to a new flush function that takes as its
Guy Schalnate5a37791996-06-05 15:50:50 -0500156 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. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500164void PNGAPI
Guy Schalnate5a37791996-06-05 15:50:50 -0500165png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
166 png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
167{
168 png_ptr->io_ptr = io_ptr;
169
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600170#if !defined(PNG_NO_STDIO)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500171 if (write_data_fn != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500172 png_ptr->write_data_fn = write_data_fn;
173 else
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -0500174 png_ptr->write_data_fn = png_default_write_data;
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600175#else
176 png_ptr->write_data_fn = write_data_fn;
177#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500178
179#if defined(PNG_WRITE_FLUSH_SUPPORTED)
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600180#if !defined(PNG_NO_STDIO)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500181 if (output_flush_fn != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500182 png_ptr->output_flush_fn = output_flush_fn;
183 else
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -0500184 png_ptr->output_flush_fn = png_default_flush;
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600185#else
186 png_ptr->output_flush_fn = output_flush_fn;
187#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500188#endif /* PNG_WRITE_FLUSH_SUPPORTED */
189
190 /* It is an error to read while writing a png file */
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500191 if (png_ptr->read_data_fn != NULL)
192 {
193 png_ptr->read_data_fn = NULL;
194 png_warning(png_ptr,
195 "Attempted to set both read_data_fn and write_data_fn in");
196 png_warning(png_ptr,
197 "the same structure. Resetting read_data_fn to NULL.");
198 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500199}
200
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600201#if defined(USE_FAR_KEYWORD)
202#if defined(_MSC_VER)
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600203void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600204{
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600205 void *near_ptr;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600206 void FAR *far_ptr;
207 FP_OFF(near_ptr) = FP_OFF(ptr);
208 far_ptr = (void FAR *)near_ptr;
209 if(check != 0)
210 if(FP_SEG(ptr) != FP_SEG(far_ptr))
211 png_error(png_ptr,"segment lost in conversion");
212 return(near_ptr);
213}
214# else
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600215void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600216{
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600217 void *near_ptr;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600218 void FAR *far_ptr;
219 near_ptr = (void FAR *)ptr;
220 far_ptr = (void FAR *)near_ptr;
221 if(check != 0)
222 if(far_ptr != ptr)
223 png_error(png_ptr,"segment lost in conversion");
224 return(near_ptr);
225}
226# endif
227# endif
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500228#endif /* PNG_WRITE_SUPPORTED */