Example #1
0
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 */
  png_uint_32	width,			/* Width of image */
		height;			/* Height of image */
  int		bit_depth,		/* Bit depth */
		color_type,		/* Color type */
		interlace_type,		/* Interlace type */
		compression_type,	/* Compression type */
		filter_type;		/* Filter type */
  png_uint_32	xppm,			/* X pixels per meter */
		yppm;			/* Y pixels per meter */
  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);

  png_get_IHDR(pp, info, &width, &height, &bit_depth, &color_type,
               &interlace_type, &compression_type, &filter_type);

  fprintf(stderr, "DEBUG: PNG image: %dx%dx%d, color_type=%x (%s%s%s)\n",
          (int)width, (int)height, bit_depth, color_type,
	  (color_type & PNG_COLOR_MASK_COLOR) ? "RGB" : "GRAYSCALE",
	  (color_type & PNG_COLOR_MASK_ALPHA) ? "+ALPHA" : "",
	  (color_type & PNG_COLOR_MASK_PALETTE) ? "+PALETTE" : "");

  if (color_type & PNG_COLOR_MASK_PALETTE)
    png_set_expand(pp);
  else if (bit_depth < 8)
  {
    png_set_packing(pp);
    png_set_expand(pp);
  }
  else if (bit_depth == 16)
    png_set_strip_16(pp);

  if (color_type & PNG_COLOR_MASK_COLOR)
    img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB :
                                                         primary;
  else
    img->colorspace = secondary;

  if (width == 0 || width > CUPS_IMAGE_MAX_WIDTH ||
      height == 0 || height > CUPS_IMAGE_MAX_HEIGHT)
  {
    fprintf(stderr, "DEBUG: PNG image has invalid dimensions %ux%u!\n",
            (unsigned)width, (unsigned)height);
    fclose(fp);
    return (1);
  }

  img->xsize = width;
  img->ysize = height;

  if ((xppm = png_get_x_pixels_per_meter(pp, info)) != 0 &&
      (yppm = png_get_y_pixels_per_meter(pp, info)) != 0)
  {
    img->xppi = (int)((float)xppm * 0.0254);
    img->yppi = (int)((float)yppm * 0.0254);

    if (img->xppi == 0 || img->yppi == 0)
    {
      fprintf(stderr, "DEBUG: 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 (color_type == PNG_COLOR_TYPE_GRAY ||
	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...
    */

    size_t bufsize;			/* Size of buffer */


    if (color_type == PNG_COLOR_TYPE_GRAY ||
	color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    {
      bufsize = img->xsize * img->ysize;

      if ((bufsize / img->ysize) != img->xsize)
      {
	fprintf(stderr, "DEBUG: PNG image dimensions (%ux%u) too large!\n",
		(unsigned)width, (unsigned)height);
	fclose(fp);
	return (1);
      }
    }
    else
    {
      bufsize = img->xsize * img->ysize * 3;

      if ((bufsize / (img->ysize * 3)) != img->xsize)
      {
	fprintf(stderr, "DEBUG: PNG image dimensions (%ux%u) too large!\n",
		(unsigned)width, (unsigned)height);
	fclose(fp);
	return (1);
      }
    }

    in = malloc(bufsize);
  }

  bpp = cupsImageGetDepth(img);
  out = malloc(img->xsize * bpp);

  if (!in || !out)
  {
    fputs("DEBUG: Unable to allocate memory for PNG image!\n", stderr);

    if (in)
      free(in);

    if (out)
      free(out);

    fclose(fp);

    return (1);
  }

 /*
  * 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 (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 :
		cupsImageRGBToRGB(inptr, out, img->xsize);
		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 (color_type & PNG_COLOR_MASK_COLOR)
          inptr += img->xsize * 3;
	else
          inptr += img->xsize;
      }
    }

  png_read_end(pp, info);
  png_destroy_read_struct(&pp, &info, NULL);

  fclose(fp);
  free(in);
  free(out);

  return (0);
}
Example #2
0
int					/* O - Read status */
_cupsImageReadSGI(
    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		i, y;			/* Looping vars */
  int		bpp;			/* Bytes per pixel */
  sgi_t		*sgip;			/* SGI image file */
  cups_ib_t	*in,			/* Input pixels */
		*inptr,			/* Current input pixel */
		*out;			/* Output pixels */
  unsigned short *rows[4],		/* Row pointers for image data */
		*red,
		*green,
		*blue,
		*gray,
		*alpha;


 /*
  * Setup the SGI file...
  */

  sgip = sgiOpenFile(fp, SGI_READ, 0, 0, 0, 0, 0);

 /*
  * Get the image dimensions and load the output image...
  */

 /*
  * Check the image dimensions; since xsize and ysize are unsigned shorts,
  * just check if they are 0 since they can't exceed CUPS_IMAGE_MAX_WIDTH or
  * CUPS_IMAGE_MAX_HEIGHT...
  */

  if (sgip->xsize == 0 || sgip->ysize == 0 ||
      sgip->zsize == 0 || sgip->zsize > 4)
  {
    fprintf(stderr, "DEBUG: Bad SGI image dimensions %ux%ux%u!\n",
            sgip->xsize, sgip->ysize, sgip->zsize);
    sgiClose(sgip);
    return (1);
  }

  if (sgip->zsize < 3)
    img->colorspace = secondary;
  else
    img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB : primary;

  img->xsize = sgip->xsize;
  img->ysize = sgip->ysize;

  cupsImageSetMaxTiles(img, 0);

  bpp = cupsImageGetDepth(img);

  if ((in = malloc(img->xsize * sgip->zsize)) == NULL)
  {
    fputs("DEBUG: Unable to allocate memory!\n", stderr);
    sgiClose(sgip);
    return (1);
  }

  if ((out = malloc(img->xsize * bpp)) == NULL)
  {
    fputs("DEBUG: Unable to allocate memory!\n", stderr);
    sgiClose(sgip);
    free(in);
    return (1);
  }

  if ((rows[0] = calloc(img->xsize * sgip->zsize,
                        sizeof(unsigned short))) == NULL)
  {
    fputs("DEBUG: Unable to allocate memory!\n", stderr);
    sgiClose(sgip);
    free(in);
    free(out);
    return (1);
  }

  for (i = 1; i < sgip->zsize; i ++)
    rows[i] = rows[0] + i * img->xsize;

 /*
  * Read the SGI image file...
  */

  for (y = 0; y < img->ysize; y ++)
  {
    for (i = 0; i < sgip->zsize; i ++)
      sgiGetRow(sgip, rows[i], img->ysize - 1 - y, i);

    switch (sgip->zsize)
    {
      case 1 :
          if (sgip->bpp == 1)
	    for (i = img->xsize - 1, gray = rows[0], inptr = in;
		 i >= 0;
		 i --)
            {
              *inptr++ = *gray++;
            }
          else
	    for (i = img->xsize - 1, gray = rows[0], inptr = in;
		 i >= 0;
		 i --)
            {
              *inptr++ = (*gray++) / 256 + 128;
            }
          break;
      case 2 :
          if (sgip->bpp == 1)
	    for (i = img->xsize - 1, gray = rows[0], alpha = rows[1], inptr = in;
		 i >= 0;
		 i --)
            {
              *inptr++ = (*gray++) * (*alpha++) / 255;
            }
          else
	    for (i = img->xsize - 1, gray = rows[0], alpha = rows[1], inptr = in;
		 i >= 0;
		 i --)
            {
              *inptr++ = ((*gray++) / 256 + 128) * (*alpha++) / 32767;
            }
          break;
      case 3 :
          if (sgip->bpp == 1)
	    for (i = img->xsize - 1, red = rows[0], green = rows[1],
	             blue = rows[2], inptr = in;
		 i >= 0;
		 i --)
            {
              *inptr++ = *red++;
              *inptr++ = *green++;
              *inptr++ = *blue++;
            }
          else
	    for (i = img->xsize - 1, red = rows[0], green = rows[1],
	             blue = rows[2], inptr = in;
		 i >= 0;
		 i --)
            {
              *inptr++ = (*red++) / 256 + 128;
              *inptr++ = (*green++) / 256 + 128;
              *inptr++ = (*blue++) / 256 + 128;
            }
          break;
      case 4 :
          if (sgip->bpp == 1)
	    for (i = img->xsize - 1, red = rows[0], green = rows[1],
	             blue = rows[2], alpha = rows[3], inptr = in;
		 i >= 0;
		 i --)
            {
              *inptr++ = (*red++) * (*alpha) / 255;
              *inptr++ = (*green++) * (*alpha) / 255;
              *inptr++ = (*blue++) * (*alpha++) / 255;
            }
          else
	    for (i = img->xsize - 1, red = rows[0], green = rows[1],
	             blue = rows[2], alpha = rows[3], inptr = in;
		 i >= 0;
		 i --)
            {
              *inptr++ = ((*red++) / 256 + 128) * (*alpha) / 32767;
              *inptr++ = ((*green++) / 256 + 128) * (*alpha) / 32767;
              *inptr++ = ((*blue++) / 256 + 128) * (*alpha++) / 32767;
            }
          break;
    }

    if (sgip->zsize < 3)
    {
      if (img->colorspace == CUPS_IMAGE_WHITE)
      {
        if (lut)
	  cupsImageLut(in, img->xsize, lut);

        _cupsImagePutRow(img, 0, y, img->xsize, in);
      }
      else
      {
	switch (img->colorspace)
	{
	  default :
	      break;

	  case CUPS_IMAGE_RGB :
	  case CUPS_IMAGE_RGB_CMYK :
	      cupsImageWhiteToRGB(in, out, img->xsize);
	      break;
	  case CUPS_IMAGE_BLACK :
	      cupsImageWhiteToBlack(in, out, img->xsize);
	      break;
	  case CUPS_IMAGE_CMY :
	      cupsImageWhiteToCMY(in, out, img->xsize);
	      break;
	  case CUPS_IMAGE_CMYK :
	      cupsImageWhiteToCMYK(in, out, img->xsize);
	      break;
	}

        if (lut)
	  cupsImageLut(out, img->xsize * bpp, lut);

        _cupsImagePutRow(img, 0, y, img->xsize, out);
      }
    }
    else
    {
      if ((saturation != 100 || hue != 0) && bpp > 1)
	cupsImageRGBAdjust(in, img->xsize, saturation, hue);

      switch (img->colorspace)
      {
	default :
	    break;

	case CUPS_IMAGE_WHITE :
	    cupsImageRGBToWhite(in, out, img->xsize);
	    break;
	case CUPS_IMAGE_RGB :
	    cupsImageRGBToRGB(in, out, img->xsize);
	    break;
	case CUPS_IMAGE_BLACK :
	    cupsImageRGBToBlack(in, out, img->xsize);
	    break;
	case CUPS_IMAGE_CMY :
	    cupsImageRGBToCMY(in, out, img->xsize);
	    break;
	case CUPS_IMAGE_CMYK :
	    cupsImageRGBToCMYK(in, out, img->xsize);
	    break;
      }

      if (lut)
	cupsImageLut(out, img->xsize * bpp, lut);

      _cupsImagePutRow(img, 0, y, img->xsize, out);
    }
  }

  free(in);
  free(out);
  free(rows[0]);

  sgiClose(sgip);

  return (0);
}
Example #3
0
int					/* O - Read status */
_cupsImageReadGIF(
    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 */
{
  unsigned char	buf[1024];		/* Input buffer */
  gif_cmap_t	cmap;			/* Colormap */
  int		i,			/* Looping var */
		bpp,			/* Bytes per pixel */
		gray,			/* Grayscale image? */
		ncolors,		/* Bits per pixel */
		transparent;		/* Transparent color index */


 /*
  * GIF files are either grayscale or RGB - no CMYK...
  */

  if (primary == CUPS_IMAGE_RGB_CMYK)
    primary = CUPS_IMAGE_RGB;

 /*
  * Read the header; we already know it is a GIF file...
  */

  fread(buf, 13, 1, fp);

  img->xsize = (buf[7] << 8) | buf[6];
  img->ysize = (buf[9] << 8) | buf[8];
  ncolors    = 2 << (buf[10] & 0x07);
  gray       = primary == CUPS_IMAGE_BLACK || primary == CUPS_IMAGE_WHITE;

  if (buf[10] & GIF_COLORMAP)
    if (gif_read_cmap(fp, ncolors, cmap, &gray))
    {
      fclose(fp);
      return (-1);
    }

  transparent = -1;

  for (;;)
  {
    switch (getc(fp))
    {
      case ';' :	/* End of image */
          fclose(fp);
          return (-1);		/* Early end of file */

      case '!' :	/* Extension record */
          buf[0] = getc(fp);
          if (buf[0] == 0xf9)	/* Graphic Control Extension */
          {
            gif_get_block(fp, buf);
            if (buf[0] & 1)	/* Get transparent color index */
              transparent = buf[3];
          }

          while (gif_get_block(fp, buf) != 0);
          break;

      case ',' :	/* cupsImage data */
          fread(buf, 9, 1, fp);

          if (buf[8] & GIF_COLORMAP)
          {
            ncolors = 2 << (buf[8] & 0x07);
            gray = primary == CUPS_IMAGE_BLACK || primary == CUPS_IMAGE_WHITE;

	    if (gif_read_cmap(fp, ncolors, cmap, &gray))
	    {
              fclose(fp);
	      return (-1);
	    }
	  }

          if (transparent >= 0)
          {
           /*
            * Make transparent color white...
            */

            cmap[transparent][0] = 255;
            cmap[transparent][1] = 255;
            cmap[transparent][2] = 255;
          }

	  if (gray)
	  {
	    switch (secondary)
	    {
              case CUPS_IMAGE_CMYK :
        	  for (i = ncolors - 1; i >= 0; i --)
        	    cupsImageWhiteToCMYK(cmap[i], cmap[i], 1);
        	  break;
              case CUPS_IMAGE_CMY :
        	  for (i = ncolors - 1; i >= 0; i --)
        	    cupsImageWhiteToCMY(cmap[i], cmap[i], 1);
        	  break;
              case CUPS_IMAGE_BLACK :
        	  for (i = ncolors - 1; i >= 0; i --)
        	    cupsImageWhiteToBlack(cmap[i], cmap[i], 1);
        	  break;
              case CUPS_IMAGE_WHITE :
        	  break;
              case CUPS_IMAGE_RGB :
              case CUPS_IMAGE_RGB_CMYK :
        	  for (i = ncolors - 1; i >= 0; i --)
        	    cupsImageWhiteToRGB(cmap[i], cmap[i], 1);
        	  break;
	    }

            img->colorspace = secondary;
	  }
	  else
	  {
	    if (hue != 0 || saturation != 100)
              for (i = ncolors - 1; i >= 0; i --)
        	cupsImageRGBAdjust(cmap[i], 1, saturation, hue);

	    switch (primary)
	    {
              case CUPS_IMAGE_CMYK :
        	  for (i = ncolors - 1; i >= 0; i --)
        	    cupsImageRGBToCMYK(cmap[i], cmap[i], 1);
        	  break;
              case CUPS_IMAGE_CMY :
        	  for (i = ncolors - 1; i >= 0; i --)
        	    cupsImageRGBToCMY(cmap[i], cmap[i], 1);
        	  break;
              case CUPS_IMAGE_BLACK :
        	  for (i = ncolors - 1; i >= 0; i --)
        	    cupsImageRGBToBlack(cmap[i], cmap[i], 1);
        	  break;
              case CUPS_IMAGE_WHITE :
        	  for (i = ncolors - 1; i >= 0; i --)
        	    cupsImageRGBToWhite(cmap[i], cmap[i], 1);
        	  break;
              case CUPS_IMAGE_RGB :
              case CUPS_IMAGE_RGB_CMYK :
        	  for (i = ncolors - 1; i >= 0; i --)
        	    cupsImageRGBToRGB(cmap[i], cmap[i], 1);
        	  break;
	    }

            img->colorspace = primary;
	  }

          if (lut)
	  {
	    bpp = cupsImageGetDepth(img);

            for (i = ncolors - 1; i >= 0; i --)
              cupsImageLut(cmap[i], bpp, lut);
	  }

          img->xsize = (buf[5] << 8) | buf[4];
          img->ysize = (buf[7] << 8) | buf[6];

         /*
	  * Check the dimensions of the image; since the dimensions are
	  * a 16-bit integer we just need to check for 0...
	  */

          if (img->xsize == 0 || img->ysize == 0)
	  {
	    fprintf(stderr, "DEBUG: Bad GIF image dimensions: %dx%d\n",
	            img->xsize, img->ysize);
	    fclose(fp);
	    return (1);
	  }

	  i = gif_read_image(fp, img, cmap, buf[8] & GIF_INTERLACE);
          fclose(fp);
          return (i);
    }
  }
}
Example #4
0
int					/* O - Read status */
_cupsImageReadPIX(
    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 */
{
  short		width,			/* Width of image */
		height,			/* Height of image */
		depth;			/* Depth of image (bits) */
  int		count,			/* Repetition count */
		bpp,			/* Bytes per pixel */
		x, y;			/* Looping vars */
  cups_ib_t	r, g, b;		/* Red, green/gray, blue values */
  cups_ib_t	*in,			/* Input pixels */
		*out,			/* Output pixels */
		*ptr;			/* Pointer into pixels */


 /*
  * Get the image dimensions and setup the image...
  */

  width  = read_short(fp);
  height = read_short(fp);
  read_short(fp);
  read_short(fp);
  depth  = read_short(fp);

 /*
  * Check the dimensions of the image.  Since the short values used for the
  * width and height cannot exceed CUPS_IMAGE_MAX_WIDTH or
  * CUPS_IMAGE_MAX_HEIGHT, we just need to verify they are positive integers.
  */

  if (width <= 0 || height <= 0 ||
      (depth != 8 && depth != 24))
  {
    fprintf(stderr, "DEBUG: Bad PIX image dimensions %dx%dx%d\n",
            width, height, depth);
    fclose(fp);
    return (1);
  }

  if (depth == 8)
    img->colorspace = secondary;
  else
    img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB : primary;

  img->xsize = width;
  img->ysize = height;

  cupsImageSetMaxTiles(img, 0);

  bpp = cupsImageGetDepth(img);

  if ((in = malloc(img->xsize * (depth / 8))) == NULL)
  {
    fputs("DEBUG: Unable to allocate memory!\n", stderr);
    fclose(fp);
    return (1);
  }

  if ((out = malloc(img->xsize * bpp)) == NULL)
  {
    fputs("DEBUG: Unable to allocate memory!\n", stderr);
    fclose(fp);
    free(in);
    return (1);
  }

 /*
  * Read the image data...
  */

  if (depth == 8)
  {
    for (count = 0, y = 0, g = 0; y < img->ysize; y ++)
    {
      if (img->colorspace == CUPS_IMAGE_WHITE)
        ptr = out;
      else
        ptr = in;

      for (x = img->xsize; x > 0; x --, count --)
      {
        if (count == 0)
	{
          count = getc(fp);
	  g     = getc(fp);
	}

        *ptr++ = g;
      }

      if (img->colorspace != CUPS_IMAGE_WHITE)
	switch (img->colorspace)
	{
	  default :
	      cupsImageWhiteToRGB(in, out, img->xsize);
	      break;
	  case CUPS_IMAGE_BLACK :
	      cupsImageWhiteToBlack(in, out, img->xsize);
	      break;
	  case CUPS_IMAGE_CMY :
	      cupsImageWhiteToCMY(in, out, img->xsize);
	      break;
	  case CUPS_IMAGE_CMYK :
	      cupsImageWhiteToCMYK(in, out, img->xsize);
	      break;
	}

      if (lut)
	cupsImageLut(out, img->xsize * bpp, lut);

      _cupsImagePutRow(img, 0, y, img->xsize, out);
    }
  }
  else
  {
    for (count = 0, y = 0, r = 0, g = 0, b = 0; y < img->ysize; y ++)
    {
      ptr = in;

      for (x = img->xsize; x > 0; x --, count --)
      {
        if (count == 0)
	{
          count = getc(fp);
	  b     = getc(fp);
	  g     = getc(fp);
	  r     = getc(fp);
	}

        *ptr++ = r;
        *ptr++ = g;
        *ptr++ = b;
      }

      if (saturation != 100 || hue != 0)
	cupsImageRGBAdjust(in, img->xsize, saturation, hue);

      switch (img->colorspace)
      {
	default :
	    break;

	case CUPS_IMAGE_WHITE :
	    cupsImageRGBToWhite(in, out, img->xsize);
	    break;
	case CUPS_IMAGE_RGB :
	    cupsImageRGBToWhite(in, out, img->xsize);
	    break;
	case CUPS_IMAGE_BLACK :
	    cupsImageRGBToBlack(in, out, img->xsize);
	    break;
	case CUPS_IMAGE_CMY :
	    cupsImageRGBToCMY(in, out, img->xsize);
	    break;
	case CUPS_IMAGE_CMYK :
	    cupsImageRGBToCMYK(in, out, img->xsize);
	    break;
      }

      if (lut)
	cupsImageLut(out, img->xsize * bpp, lut);

      _cupsImagePutRow(img, 0, y, img->xsize, out);
    }
  }

  fclose(fp);
  free(in);
  free(out);

  return (0);
}
Example #5
0
int					/* O  - Read status */
_cupsImageReadJPEG(
    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 */
{
  struct jpeg_decompress_struct	cinfo;	/* Decompressor info */
  struct jpeg_error_mgr	jerr;		/* Error handler info */
  cups_ib_t		*in,		/* Input pixels */
			*out;		/* Output pixels */
  jpeg_saved_marker_ptr	marker;		/* Pointer to marker data */
  int			psjpeg = 0;	/* Non-zero if Photoshop CMYK JPEG */
  static const char	*cspaces[] =
			{		/* JPEG colorspaces... */
			  "JCS_UNKNOWN",
			  "JCS_GRAYSCALE",
			  "JCS_RGB",
			  "JCS_YCbCr",
			  "JCS_CMYK",
			  "JCS_YCCK"
			};


 /*
  * Read the JPEG header...
  */

  cinfo.err = jpeg_std_error(&jerr);
  jpeg_create_decompress(&cinfo);
  jpeg_save_markers(&cinfo, JPEG_APP0 + 14, 0xffff); /* Adobe JPEG */
  jpeg_stdio_src(&cinfo, fp);
  jpeg_read_header(&cinfo, 1);

 /*
  * Parse any Adobe APPE data embedded in the JPEG file.  Since Adobe doesn't
  * bother following standards, we have to invert the CMYK JPEG data written by
  * Adobe apps...
  */

  for (marker = cinfo.marker_list; marker; marker = marker->next)
    if (marker->marker == (JPEG_APP0 + 14) && marker->data_length >= 12 &&
        !memcmp(marker->data, "Adobe", 5))
    {
      fputs("DEBUG: Adobe CMYK JPEG detected (inverting color values)\n",
	    stderr);
      psjpeg = 1;
    }

  cinfo.quantize_colors = 0;

  fprintf(stderr, "DEBUG: num_components = %d\n", cinfo.num_components);
  fprintf(stderr, "DEBUG: jpeg_color_space = %s\n",
          cspaces[cinfo.jpeg_color_space]);

  if (cinfo.num_components == 1)
  {
    fputs("DEBUG: Converting image to grayscale...\n", stderr);

    cinfo.out_color_space      = JCS_GRAYSCALE;
    cinfo.out_color_components = 1;
    cinfo.output_components    = 1;

    img->colorspace = secondary;
  }
  else if (cinfo.num_components == 4)
  {
    fputs("DEBUG: Converting image to CMYK...\n", stderr);

    cinfo.out_color_space      = JCS_CMYK;
    cinfo.out_color_components = 4;
    cinfo.output_components    = 4;

    img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_CMYK : primary;
  }
  else
  {
    fputs("DEBUG: Converting image to RGB...\n", stderr);

    cinfo.out_color_space      = JCS_RGB;
    cinfo.out_color_components = 3;
    cinfo.output_components    = 3;

    img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB : primary;
  }

  jpeg_calc_output_dimensions(&cinfo);

  if (cinfo.output_width <= 0 || cinfo.output_width > CUPS_IMAGE_MAX_WIDTH ||
      cinfo.output_height <= 0 || cinfo.output_height > CUPS_IMAGE_MAX_HEIGHT)
  {
    fprintf(stderr, "DEBUG: Bad JPEG dimensions %dx%d!\n",
            cinfo.output_width, cinfo.output_height);

    jpeg_destroy_decompress(&cinfo);

    fclose(fp);
    return (1);
  }

  img->xsize      = cinfo.output_width;
  img->ysize      = cinfo.output_height;

  if (cinfo.X_density > 0 && cinfo.Y_density > 0 && cinfo.density_unit > 0)
  {
    if (cinfo.density_unit == 1)
    {
      img->xppi = cinfo.X_density;
      img->yppi = cinfo.Y_density;
    }
    else
    {
      img->xppi = (int)((float)cinfo.X_density * 2.54);
      img->yppi = (int)((float)cinfo.Y_density * 2.54);
    }

    if (img->xppi == 0 || img->yppi == 0)
    {
      fprintf(stderr, "DEBUG: Bad JPEG image resolution %dx%d PPI.\n",
              img->xppi, img->yppi);
      img->xppi = img->yppi = 128;
    }
  }

  fprintf(stderr, "DEBUG: JPEG image %dx%dx%d, %dx%d PPI\n",
          img->xsize, img->ysize, cinfo.output_components,
	  img->xppi, img->yppi);

  cupsImageSetMaxTiles(img, 0);

  in  = malloc(img->xsize * cinfo.output_components);
  out = malloc(img->xsize * cupsImageGetDepth(img));

  jpeg_start_decompress(&cinfo);

  while (cinfo.output_scanline < cinfo.output_height)
  {
    jpeg_read_scanlines(&cinfo, (JSAMPROW *)&in, (JDIMENSION)1);

    if (psjpeg && cinfo.output_components == 4)
    {
     /*
      * Invert CMYK data from Photoshop...
      */

      cups_ib_t	*ptr;	/* Pointer into buffer */
      int	i;	/* Looping var */


      for (ptr = in, i = img->xsize * 4; i > 0; i --, ptr ++)
        *ptr = 255 - *ptr;
    }

    if ((saturation != 100 || hue != 0) && cinfo.output_components == 3)
      cupsImageRGBAdjust(in, img->xsize, saturation, hue);

    if ((img->colorspace == CUPS_IMAGE_WHITE && cinfo.out_color_space == JCS_GRAYSCALE) ||
	(img->colorspace == CUPS_IMAGE_CMYK && cinfo.out_color_space == JCS_CMYK))
    {
#ifdef DEBUG
      int	i, j;
      cups_ib_t	*ptr;


      fputs("DEBUG: Direct Data...\n", stderr);

      fputs("DEBUG:", stderr);

      for (i = 0, ptr = in; i < img->xsize; i ++)
      {
        putc(' ', stderr);
	for (j = 0; j < cinfo.output_components; j ++, ptr ++)
	  fprintf(stderr, "%02X", *ptr & 255);
      }

      putc('\n', stderr);
#endif /* DEBUG */

      if (lut)
        cupsImageLut(in, img->xsize * cupsImageGetDepth(img), lut);

      _cupsImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, in);
    }
    else if (cinfo.out_color_space == JCS_GRAYSCALE)
    {
      switch (img->colorspace)
      {
        default :
	    break;

        case CUPS_IMAGE_BLACK :
            cupsImageWhiteToBlack(in, out, img->xsize);
            break;
        case CUPS_IMAGE_RGB :
            cupsImageWhiteToRGB(in, out, img->xsize);
            break;
        case CUPS_IMAGE_CMY :
            cupsImageWhiteToCMY(in, out, img->xsize);
            break;
        case CUPS_IMAGE_CMYK :
            cupsImageWhiteToCMYK(in, out, img->xsize);
            break;
      }

      if (lut)
        cupsImageLut(out, img->xsize * cupsImageGetDepth(img), lut);

      _cupsImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, out);
    }
    else if (cinfo.out_color_space == JCS_RGB)
    {
      switch (img->colorspace)
      {
        default :
	    break;

        case CUPS_IMAGE_RGB :
            cupsImageRGBToRGB(in, out, img->xsize);
	    break;
        case CUPS_IMAGE_WHITE :
            cupsImageRGBToWhite(in, out, img->xsize);
            break;
        case CUPS_IMAGE_BLACK :
            cupsImageRGBToBlack(in, out, img->xsize);
            break;
        case CUPS_IMAGE_CMY :
            cupsImageRGBToCMY(in, out, img->xsize);
            break;
        case CUPS_IMAGE_CMYK :
            cupsImageRGBToCMYK(in, out, img->xsize);
            break;
      }

      if (lut)
        cupsImageLut(out, img->xsize * cupsImageGetDepth(img), lut);

      _cupsImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, out);
    }
    else /* JCS_CMYK */
    {
      fputs("DEBUG: JCS_CMYK\n", stderr);

      switch (img->colorspace)
      {
        default :
	    break;

        case CUPS_IMAGE_WHITE :
            cupsImageCMYKToWhite(in, out, img->xsize);
            break;
        case CUPS_IMAGE_BLACK :
            cupsImageCMYKToBlack(in, out, img->xsize);
            break;
        case CUPS_IMAGE_CMY :
            cupsImageCMYKToCMY(in, out, img->xsize);
            break;
        case CUPS_IMAGE_RGB :
            cupsImageCMYKToRGB(in, out, img->xsize);
            break;
      }

      if (lut)
        cupsImageLut(out, img->xsize * cupsImageGetDepth(img), lut);

      _cupsImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, out);
    }
  }

  free(in);
  free(out);

  jpeg_finish_decompress(&cinfo);
  jpeg_destroy_decompress(&cinfo);

  fclose(fp);

  return (0);
}