17dd7cddfSDavid du Colombier
27dd7cddfSDavid du Colombier /* pngrio.c - functions for data input
37dd7cddfSDavid du Colombier *
4*593dc095SDavid du Colombier * libpng 1.2.8 - December 3, 2004
57dd7cddfSDavid du Colombier * For conditions of distribution and use, see copyright notice in png.h
6*593dc095SDavid du Colombier * Copyright (c) 1998-2004 Glenn Randers-Pehrson
7*593dc095SDavid du Colombier * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8*593dc095SDavid du Colombier * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
97dd7cddfSDavid du Colombier *
10*593dc095SDavid du Colombier * This file provides a location for all input. Users who need
11*593dc095SDavid du Colombier * special handling are expected to write a function that has the same
12*593dc095SDavid du Colombier * arguments as this and performs a similar function, but that possibly
13*593dc095SDavid du Colombier * has a different input method. Note that you shouldn't change this
147dd7cddfSDavid du Colombier * function, but rather write a replacement function and then make
157dd7cddfSDavid du Colombier * libpng use it at run time with png_set_read_fn(...).
167dd7cddfSDavid du Colombier */
177dd7cddfSDavid du Colombier
187dd7cddfSDavid du Colombier #define PNG_INTERNAL
197dd7cddfSDavid du Colombier #include "png.h"
207dd7cddfSDavid du Colombier
217dd7cddfSDavid du Colombier /* Read the data from whatever input you are using. The default routine
227dd7cddfSDavid du Colombier reads from a file pointer. Note that this routine sometimes gets called
237dd7cddfSDavid du Colombier with very small lengths, so you should implement some kind of simple
247dd7cddfSDavid du Colombier buffering if you are using unbuffered reads. This should never be asked
257dd7cddfSDavid du Colombier to read more then 64K on a 16 bit machine. */
26*593dc095SDavid du Colombier void /* PRIVATE */
png_read_data(png_structp png_ptr,png_bytep data,png_size_t length)277dd7cddfSDavid du Colombier png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
287dd7cddfSDavid du Colombier {
29*593dc095SDavid du Colombier png_debug1(4,"reading %d bytes\n", (int)length);
307dd7cddfSDavid du Colombier if (png_ptr->read_data_fn != NULL)
317dd7cddfSDavid du Colombier (*(png_ptr->read_data_fn))(png_ptr, data, length);
327dd7cddfSDavid du Colombier else
337dd7cddfSDavid du Colombier png_error(png_ptr, "Call to NULL read function");
347dd7cddfSDavid du Colombier }
357dd7cddfSDavid du Colombier
367dd7cddfSDavid du Colombier #if !defined(PNG_NO_STDIO)
37*593dc095SDavid du Colombier /* This is the function that does the actual reading of data. If you are
387dd7cddfSDavid du Colombier not reading from a standard C stream, you should create a replacement
397dd7cddfSDavid du Colombier read_data function and use it at run time with png_set_read_fn(), rather
407dd7cddfSDavid du Colombier than changing the library. */
417dd7cddfSDavid du Colombier #ifndef USE_FAR_KEYWORD
42*593dc095SDavid du Colombier void PNGAPI
png_default_read_data(png_structp png_ptr,png_bytep data,png_size_t length)437dd7cddfSDavid du Colombier png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
447dd7cddfSDavid du Colombier {
457dd7cddfSDavid du Colombier png_size_t check;
467dd7cddfSDavid du Colombier
477dd7cddfSDavid du Colombier /* fread() returns 0 on error, so it is OK to store this in a png_size_t
487dd7cddfSDavid du Colombier * instead of an int, which is what fread() actually returns.
497dd7cddfSDavid du Colombier */
50*593dc095SDavid du Colombier #if defined(_WIN32_WCE)
51*593dc095SDavid du Colombier if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
52*593dc095SDavid du Colombier check = 0;
53*593dc095SDavid du Colombier #else
547dd7cddfSDavid du Colombier check = (png_size_t)fread(data, (png_size_t)1, length,
55*593dc095SDavid du Colombier (png_FILE_p)png_ptr->io_ptr);
56*593dc095SDavid du Colombier #endif
577dd7cddfSDavid du Colombier
587dd7cddfSDavid du Colombier if (check != length)
597dd7cddfSDavid du Colombier png_error(png_ptr, "Read Error");
607dd7cddfSDavid du Colombier }
617dd7cddfSDavid du Colombier #else
627dd7cddfSDavid du Colombier /* this is the model-independent version. Since the standard I/O library
637dd7cddfSDavid du Colombier can't handle far buffers in the medium and small models, we have to copy
647dd7cddfSDavid du Colombier the data.
657dd7cddfSDavid du Colombier */
667dd7cddfSDavid du Colombier
677dd7cddfSDavid du Colombier #define NEAR_BUF_SIZE 1024
687dd7cddfSDavid du Colombier #define MIN(a,b) (a <= b ? a : b)
697dd7cddfSDavid du Colombier
70*593dc095SDavid du Colombier static void /* PRIVATE */
png_default_read_data(png_structp png_ptr,png_bytep data,png_size_t length)717dd7cddfSDavid du Colombier png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
727dd7cddfSDavid du Colombier {
737dd7cddfSDavid du Colombier int check;
747dd7cddfSDavid du Colombier png_byte *n_data;
75*593dc095SDavid du Colombier png_FILE_p io_ptr;
767dd7cddfSDavid du Colombier
777dd7cddfSDavid du Colombier /* Check if data really is near. If so, use usual code. */
787dd7cddfSDavid du Colombier n_data = (png_byte *)CVT_PTR_NOCHECK(data);
79*593dc095SDavid du Colombier io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
807dd7cddfSDavid du Colombier if ((png_bytep)n_data == data)
817dd7cddfSDavid du Colombier {
82*593dc095SDavid du Colombier #if defined(_WIN32_WCE)
83*593dc095SDavid du Colombier if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
84*593dc095SDavid du Colombier check = 0;
85*593dc095SDavid du Colombier #else
867dd7cddfSDavid du Colombier check = fread(n_data, 1, length, io_ptr);
87*593dc095SDavid du Colombier #endif
887dd7cddfSDavid du Colombier }
897dd7cddfSDavid du Colombier else
907dd7cddfSDavid du Colombier {
917dd7cddfSDavid du Colombier png_byte buf[NEAR_BUF_SIZE];
927dd7cddfSDavid du Colombier png_size_t read, remaining, err;
937dd7cddfSDavid du Colombier check = 0;
947dd7cddfSDavid du Colombier remaining = length;
957dd7cddfSDavid du Colombier do
967dd7cddfSDavid du Colombier {
977dd7cddfSDavid du Colombier read = MIN(NEAR_BUF_SIZE, remaining);
98*593dc095SDavid du Colombier #if defined(_WIN32_WCE)
99*593dc095SDavid du Colombier if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) )
100*593dc095SDavid du Colombier err = 0;
101*593dc095SDavid du Colombier #else
1027dd7cddfSDavid du Colombier err = fread(buf, (png_size_t)1, read, io_ptr);
103*593dc095SDavid du Colombier #endif
1047dd7cddfSDavid du Colombier png_memcpy(data, buf, read); /* copy far buffer to near buffer */
1057dd7cddfSDavid du Colombier if(err != read)
1067dd7cddfSDavid du Colombier break;
1077dd7cddfSDavid du Colombier else
1087dd7cddfSDavid du Colombier check += err;
1097dd7cddfSDavid du Colombier data += read;
1107dd7cddfSDavid du Colombier remaining -= read;
1117dd7cddfSDavid du Colombier }
1127dd7cddfSDavid du Colombier while (remaining != 0);
1137dd7cddfSDavid du Colombier }
1147dd7cddfSDavid du Colombier if ((png_uint_32)check != (png_uint_32)length)
1157dd7cddfSDavid du Colombier png_error(png_ptr, "read Error");
1167dd7cddfSDavid du Colombier }
1177dd7cddfSDavid du Colombier #endif
1187dd7cddfSDavid du Colombier #endif
1197dd7cddfSDavid du Colombier
1207dd7cddfSDavid du Colombier /* This function allows the application to supply a new input function
1217dd7cddfSDavid du Colombier for libpng if standard C streams aren't being used.
1227dd7cddfSDavid du Colombier
1237dd7cddfSDavid du Colombier This function takes as its arguments:
1247dd7cddfSDavid du Colombier png_ptr - pointer to a png input data structure
1257dd7cddfSDavid du Colombier io_ptr - pointer to user supplied structure containing info about
1267dd7cddfSDavid du Colombier the input functions. May be NULL.
127*593dc095SDavid du Colombier read_data_fn - pointer to a new input function that takes as its
1287dd7cddfSDavid du Colombier arguments a pointer to a png_struct, a pointer to
1297dd7cddfSDavid du Colombier a location where input data can be stored, and a 32-bit
130*593dc095SDavid du Colombier unsigned int that is the number of bytes to be read.
1317dd7cddfSDavid du Colombier To exit and output any fatal error messages the new write
1327dd7cddfSDavid du Colombier function should call png_error(png_ptr, "Error msg"). */
133*593dc095SDavid du Colombier void PNGAPI
png_set_read_fn(png_structp png_ptr,png_voidp io_ptr,png_rw_ptr read_data_fn)1347dd7cddfSDavid du Colombier png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
1357dd7cddfSDavid du Colombier png_rw_ptr read_data_fn)
1367dd7cddfSDavid du Colombier {
1377dd7cddfSDavid du Colombier png_ptr->io_ptr = io_ptr;
1387dd7cddfSDavid du Colombier
1397dd7cddfSDavid du Colombier #if !defined(PNG_NO_STDIO)
1407dd7cddfSDavid du Colombier if (read_data_fn != NULL)
1417dd7cddfSDavid du Colombier png_ptr->read_data_fn = read_data_fn;
1427dd7cddfSDavid du Colombier else
1437dd7cddfSDavid du Colombier png_ptr->read_data_fn = png_default_read_data;
1447dd7cddfSDavid du Colombier #else
1457dd7cddfSDavid du Colombier png_ptr->read_data_fn = read_data_fn;
1467dd7cddfSDavid du Colombier #endif
1477dd7cddfSDavid du Colombier
1487dd7cddfSDavid du Colombier /* It is an error to write to a read device */
149*593dc095SDavid du Colombier if (png_ptr->write_data_fn != NULL)
150*593dc095SDavid du Colombier {
1517dd7cddfSDavid du Colombier png_ptr->write_data_fn = NULL;
152*593dc095SDavid du Colombier png_warning(png_ptr,
153*593dc095SDavid du Colombier "It's an error to set both read_data_fn and write_data_fn in the ");
154*593dc095SDavid du Colombier png_warning(png_ptr,
155*593dc095SDavid du Colombier "same structure. Resetting write_data_fn to NULL.");
156*593dc095SDavid du Colombier }
1577dd7cddfSDavid du Colombier
1587dd7cddfSDavid du Colombier #if defined(PNG_WRITE_FLUSH_SUPPORTED)
1597dd7cddfSDavid du Colombier png_ptr->output_flush_fn = NULL;
160*593dc095SDavid du Colombier #endif
1617dd7cddfSDavid du Colombier }
162