/* * "$Id: image-png.c,v 1.1.1.10 2004/06/05 02:42:32 jlovell Exp $" * * PNG image routines for the Common UNIX Printing System (CUPS). * * Copyright 1993-2004 by Easy Software Products. * * These coded instructions, statements, and computer programs are the * property of Easy Software Products and are protected by Federal * copyright law. Distribution and use rights are outlined in the file * "LICENSE.txt" which should have been included with this file. If this * file is missing or damaged please contact Easy Software Products * at: * * Attn: CUPS Licensing Information * Easy Software Products * 44141 Airport View Drive, Suite 204 * Hollywood, Maryland 20636-3111 USA * * Voice: (301) 373-9603 * EMail: cups-info@cups.org * WWW: http://www.cups.org * * This file is subject to the Apple OS-Developed Software exception. * * Contents: * * ImageReadPNG() - Read a PNG image file. */ /* * Include necessary headers... */ #include "image.h" #if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) #include /* Portable Network Graphics (PNG) definitions */ /* * 'ImageReadPNG()' - Read a PNG image file. */ int /* O - Read status */ ImageReadPNG(image_t *img, /* IO - Image */ FILE *fp, /* I - Image file */ int primary, /* I - Primary choice for colorspace */ int secondary, /* I - Secondary choice for colorspace */ int saturation, /* I - Color saturation (%) */ int hue, /* I - Color hue (degrees) */ const ib_t *lut) /* I - Lookup table for gamma/brightness */ { int y; /* Looping var */ png_structp pp; /* PNG read pointer */ png_infop info; /* PNG info pointers */ int bpp; /* Bytes per pixel */ int pass, /* Current pass */ passes; /* Number of passes required */ ib_t *in, /* Input pixels */ *inptr, /* Pointer into pixels */ *out; /* Output pixels */ png_color_16 bg; /* Background color */ /* * Setup the PNG data structures... */ pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info = png_create_info_struct(pp); /* * Initialize the PNG read "engine"... */ png_init_io(pp, fp); /* * Get the image dimensions and load the output image... */ png_read_info(pp, info); fprintf(stderr, "DEBUG: PNG image: %dx%dx%d, color_type=%x (%s%s%s)\n", info->width, info->height, info->bit_depth, info->color_type, (info->color_type & PNG_COLOR_MASK_COLOR) ? "RGB" : "GRAYSCALE", (info->color_type & PNG_COLOR_MASK_ALPHA) ? "+ALPHA" : "", (info->color_type & PNG_COLOR_MASK_PALETTE) ? "+PALETTE" : ""); if (info->color_type & PNG_COLOR_MASK_PALETTE) png_set_expand(pp); else if (info->bit_depth < 8) { png_set_packing(pp); png_set_expand(pp); } else if (info->bit_depth == 16) png_set_strip_16(pp); if (info->color_type & PNG_COLOR_MASK_COLOR) img->colorspace = (primary == IMAGE_RGB_CMYK) ? IMAGE_RGB : primary; else img->colorspace = secondary; if (info->width == 0 || info->width > IMAGE_MAX_WIDTH || info->height == 0 || info->height > IMAGE_MAX_HEIGHT) { fprintf(stderr, "ERROR: PNG image has invalid dimensions %ux%u!\n", (unsigned)info->width, (unsigned)info->height); fclose(fp); return (1); } img->xsize = info->width; img->ysize = info->height; if (info->valid & PNG_INFO_pHYs && info->phys_unit_type == PNG_RESOLUTION_METER) { img->xppi = (int)((float)info->x_pixels_per_unit * 0.0254); img->yppi = (int)((float)info->y_pixels_per_unit * 0.0254); if (img->xppi == 0 || img->yppi == 0) { fprintf(stderr, "ERROR: PNG image has invalid resolution %dx%d PPI\n", img->xppi, img->yppi); img->xppi = img->yppi = 128; } } ImageSetMaxTiles(img, 0); passes = png_set_interlace_handling(pp); /* * Handle transparency... */ if (png_get_valid(pp, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(pp); bg.red = 65535; bg.green = 65535; bg.blue = 65535; png_set_background(pp, &bg, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); if (passes == 1) { /* * Load one row at a time... */ if (info->color_type == PNG_COLOR_TYPE_GRAY || info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) in = malloc(img->xsize); else in = malloc(img->xsize * 3); } else { /* * Interlaced images must be loaded all at once... */ if (info->color_type == PNG_COLOR_TYPE_GRAY || info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) in = malloc(img->xsize * img->ysize); else in = malloc(img->xsize * img->ysize * 3); } bpp = ImageGetDepth(img); out = malloc(img->xsize * bpp); /* * Read the image, interlacing as needed... */ for (pass = 1; pass <= passes; pass ++) for (inptr = in, y = 0; y < img->ysize; y ++) { png_read_row(pp, (png_bytep)inptr, NULL); if (pass == passes) { /* * Output this row... */ if (info->color_type & PNG_COLOR_MASK_COLOR) { if ((saturation != 100 || hue != 0) && bpp > 1) ImageRGBAdjust(inptr, img->xsize, saturation, hue); switch (img->colorspace) { case IMAGE_WHITE : ImageRGBToWhite(inptr, out, img->xsize); break; case IMAGE_RGB : memcpy(out, inptr, img->xsize * 3); break; case IMAGE_BLACK : ImageRGBToBlack(inptr, out, img->xsize); break; case IMAGE_CMY : ImageRGBToCMY(inptr, out, img->xsize); break; case IMAGE_CMYK : ImageRGBToCMYK(inptr, out, img->xsize); break; } } else { switch (img->colorspace) { case IMAGE_WHITE : memcpy(out, inptr, img->xsize); break; case IMAGE_RGB : ImageWhiteToRGB(inptr, out, img->xsize); break; case IMAGE_BLACK : ImageWhiteToBlack(inptr, out, img->xsize); break; case IMAGE_CMY : ImageWhiteToCMY(inptr, out, img->xsize); break; case IMAGE_CMYK : ImageWhiteToCMYK(inptr, out, img->xsize); break; } } if (lut) ImageLut(out, img->xsize * bpp, lut); ImagePutRow(img, 0, y, img->xsize, out); } if (passes > 1) { if (info->color_type & PNG_COLOR_MASK_COLOR) inptr += img->xsize * 3; else inptr += img->xsize; } } png_read_end(pp, info); png_read_destroy(pp, info, NULL); fclose(fp); free(in); free(out); return (0); } #endif /* HAVE_LIBPNG && HAVE_LIBZ */ /* * End of "$Id: image-png.c,v 1.1.1.10 2004/06/05 02:42:32 jlovell Exp $". */