]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - filter/image-png.c
Load cups into easysw/current.
[thirdparty/cups.git] / filter / image-png.c
diff --git a/filter/image-png.c b/filter/image-png.c
new file mode 100644 (file)
index 0000000..d240fac
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * "$Id: image-png.c 4741 2005-10-02 04:25:52Z mike $"
+ *
+ *   PNG image routines for the Common UNIX Printing System (CUPS).
+ *
+ *   Copyright 1993-2005 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 USA
+ *
+ *       Voice: (301) 373-9600
+ *       EMail: cups-info@cups.org
+ *         WWW: http://www.cups.org
+ *
+ *   This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ *   _cupsImageReadPNG() - Read a PNG image file.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "image-private.h"
+
+#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
+#  include <png.h>     /* Portable Network Graphics (PNG) definitions */
+
+
+/*
+ * '_cupsImageReadPNG()' - Read a PNG image file.
+ */
+
+int                                    /* O - Read status */
+_cupsImageReadPNG(
+    cups_image_t    *img,              /* IO - cupsImage */
+    FILE            *fp,               /* I - cupsImage file */
+    cups_icspace_t  primary,           /* I - Primary choice for colorspace */
+    cups_icspace_t  secondary,         /* I - Secondary choice for colorspace */
+    int             saturation,                /* I - Color saturation (%) */
+    int             hue,               /* I - Color hue (degrees) */
+    const cups_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 */
+  cups_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",
+          (int)info->width, (int)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 == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB : primary;
+  else
+    img->colorspace = secondary;
+
+  if (info->width == 0 || info->width > CUPS_IMAGE_MAX_WIDTH ||
+      info->height == 0 || info->height > CUPS_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;
+    }
+  }
+
+  cupsImageSetMaxTiles(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 = cupsImageGetDepth(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)
+           cupsImageRGBAdjust(inptr, img->xsize, saturation, hue);
+
+         switch (img->colorspace)
+         {
+           case CUPS_IMAGE_WHITE :
+               cupsImageRGBToWhite(inptr, out, img->xsize);
+               break;
+           case CUPS_IMAGE_RGB :
+           case CUPS_IMAGE_RGB_CMYK :
+               memcpy(out, inptr, img->xsize * 3);
+               break;
+           case CUPS_IMAGE_BLACK :
+               cupsImageRGBToBlack(inptr, out, img->xsize);
+               break;
+           case CUPS_IMAGE_CMY :
+               cupsImageRGBToCMY(inptr, out, img->xsize);
+               break;
+           case CUPS_IMAGE_CMYK :
+               cupsImageRGBToCMYK(inptr, out, img->xsize);
+               break;
+         }
+       }
+       else
+       {
+         switch (img->colorspace)
+         {
+           case CUPS_IMAGE_WHITE :
+               memcpy(out, inptr, img->xsize);
+               break;
+           case CUPS_IMAGE_RGB :
+           case CUPS_IMAGE_RGB_CMYK :
+               cupsImageWhiteToRGB(inptr, out, img->xsize);
+               break;
+           case CUPS_IMAGE_BLACK :
+               cupsImageWhiteToBlack(inptr, out, img->xsize);
+               break;
+           case CUPS_IMAGE_CMY :
+               cupsImageWhiteToCMY(inptr, out, img->xsize);
+               break;
+           case CUPS_IMAGE_CMYK :
+               cupsImageWhiteToCMYK(inptr, out, img->xsize);
+               break;
+         }
+       }
+
+       if (lut)
+         cupsImageLut(out, img->xsize * bpp, lut);
+
+       _cupsImagePutRow(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 4741 2005-10-02 04:25:52Z mike $".
+ */