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