671242f350d172e106580348e24bab66b0d7e6a5vboxsync/*---------------------------------------------------------------------------
671242f350d172e106580348e24bab66b0d7e6a5vboxsync rpng - simple PNG display program readpng.c
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ---------------------------------------------------------------------------
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Copyright (c) 1998-2000 Greg Roelofs. All rights reserved.
671242f350d172e106580348e24bab66b0d7e6a5vboxsync This software is provided "as is," without warranty of any kind,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync express or implied. In no event shall the author or contributors
671242f350d172e106580348e24bab66b0d7e6a5vboxsync be held liable for any damages arising in any way from the use of
671242f350d172e106580348e24bab66b0d7e6a5vboxsync this software.
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Permission is granted to anyone to use this software for any purpose,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync including commercial applications, and to alter it and redistribute
671242f350d172e106580348e24bab66b0d7e6a5vboxsync it freely, subject to the following restrictions:
671242f350d172e106580348e24bab66b0d7e6a5vboxsync 1. Redistributions of source code must retain the above copyright
671242f350d172e106580348e24bab66b0d7e6a5vboxsync notice, disclaimer, and this list of conditions.
671242f350d172e106580348e24bab66b0d7e6a5vboxsync 2. Redistributions in binary form must reproduce the above copyright
671242f350d172e106580348e24bab66b0d7e6a5vboxsync notice, disclaimer, and this list of conditions in the documenta-
671242f350d172e106580348e24bab66b0d7e6a5vboxsync tion and/or other materials provided with the distribution.
671242f350d172e106580348e24bab66b0d7e6a5vboxsync 3. All advertising materials mentioning features or use of this
671242f350d172e106580348e24bab66b0d7e6a5vboxsync software must display the following acknowledgment:
671242f350d172e106580348e24bab66b0d7e6a5vboxsync This product includes software developed by Greg Roelofs
671242f350d172e106580348e24bab66b0d7e6a5vboxsync and contributors for the book, "PNG: The Definitive Guide,"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync published by O'Reilly and Associates.
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ---------------------------------------------------------------------------*/
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#include "png.h" /* libpng header; includes zlib.h */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#include "readpng.h" /* typedefs, common macros, public prototypes */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/* future versions of libpng will provide this macro: */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n",
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n",
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncint readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* first do a quick check that the file really is a PNG image; could
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * have used slightly more general png_sig_cmp() function instead */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* could pass pointers to user-defined error handlers instead of NULLs: */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* we could create a second info struct here (end_info), but it's only
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * useful if we want to keep pre- and post-IDAT chunk info separated
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * (mainly for PNG-aware image editors and converters) */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* setjmp() must be called in every function that calls a PNG-reading
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * libpng function */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* alternatively, could make separate calls to png_get_image_width(),
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * etc., but want bit_depth and color_type for later [don't care about
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * compression_type and filter_type => NULLs] */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* OK, that's all we need for now; return happy */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * scales values to 8-bit if necessary */
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncint readpng_get_bgcolor(uch *red, uch *green, uch *blue)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* setjmp() must be called in every function that calls a PNG-reading
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * libpng function */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD))
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* it is not obvious from the libpng documentation, but this function
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * takes a pointer to a pointer, and it always returns valid red, green
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * and blue values, regardless of color_type: */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* however, it always returns the raw bKGD data, regardless of any
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * bit-depth transformations, so check depth and adjust if necessary */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *red = *green = *blue = pBackground->gray? 255 : 0;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *red = *green = *blue = (255/3) * pBackground->gray;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync else /* bit_depth == 4 */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *red = *green = *blue = (255/15) * pBackground->gray;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/* display_exponent == LUT_exponent * CRT_exponent */
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncuch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* setjmp() must be called in every function that calls a PNG-reading
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * libpng function */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * transparency chunks to full alpha channel; strip 16-bit-per-sample
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * images to 8 bits per sample; and convert grayscale to RGB[A] */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* unlike the example in the libpng documentation, we have *no* idea where
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * this file may have come from--so if it doesn't have a file gamma, don't
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * do any correction ("do no harm") */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* all transformations have been registered; now update info_ptr data,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * get rowbytes and channels, and allocate image memory */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *pChannels = (int)png_get_channels(png_ptr, info_ptr);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Trace((stderr, "readpng_get_image: channels = %d, rowbytes = %ld, height = %ld\n", *pChannels, rowbytes, height));
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* set the individual row_pointers to point at the correct offsets */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync for (i = 0; i < height; ++i)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* now we can go ahead and just read the whole image */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* and we're done! (png_read_end() can be omitted if no processing of
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * post-IDAT text/time/etc. is desired) */