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); }
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); }
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); } } }
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); }
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); }