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