| /* |
| * "$Id: image-sun.c 7223 2008-01-16 23:41:19Z mike $" |
| * |
| * Sun Raster image file routines for CUPS. |
| * |
| * Copyright 2007-2011 by Apple Inc. |
| * Copyright 1993-2007 by Easy Software Products. |
| * |
| * These coded instructions, statements, and computer programs are the |
| * property of Apple Inc. 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 |
| * file is missing or damaged, see the license at "http://www.cups.org/". |
| * |
| * This file is subject to the Apple OS-Developed Software exception. |
| * |
| * Contents: |
| * |
| * _cupsImageReadSunRaster() - Read a SunRaster image file. |
| * read_unsigned() - Read a 32-bit unsigned integer. |
| */ |
| |
| /* |
| * Include necessary headers... |
| */ |
| |
| #include "image-private.h" |
| |
| |
| #define RAS_MAGIC 0x59a66a95 |
| |
| /* Sun supported ras_type's */ |
| #define RT_OLD 0 /* Raw pixrect image in 68000 byte order */ |
| #define RT_STANDARD 1 /* Raw pixrect image in 68000 byte order */ |
| #define RT_BYTE_ENCODED 2 /* Run-length compression of bytes */ |
| #define RT_FORMAT_RGB 3 /* XRGB or RGB instead of XBGR or BGR */ |
| #define RT_EXPERIMENTAL 0xffff /* Reserved for testing */ |
| |
| /* Sun registered ras_maptype's */ |
| #define RMT_RAW 2 |
| /* Sun supported ras_maptype's */ |
| #define RMT_NONE 0 /* ras_maplength is expected to be 0 */ |
| #define RMT_EQUAL_RGB 1 /* red[ras_maplength/3],green[],blue[] */ |
| |
| #define RAS_RLE 0x80 |
| |
| /* |
| * NOTES: |
| * Each line of the image is rounded out to a multiple of 16 bits. |
| * This corresponds to the rounding convention used by the memory pixrect |
| * package (/usr/include/pixrect/memvar.h) of the SunWindows system. |
| * The ras_encoding field (always set to 0 by Sun's supported software) |
| * was renamed to ras_length in release 2.0. As a result, rasterfiles |
| * of type 0 generated by the old software claim to have 0 length; for |
| * compatibility, code reading rasterfiles must be prepared to compute the |
| * true length from the width, height, and depth fields. |
| */ |
| |
| /* |
| * Local functions... |
| */ |
| |
| static unsigned read_unsigned(FILE *fp); |
| |
| |
| /* |
| * '_cupsImageReadSunRaster()' - Read a SunRaster image file. |
| */ |
| |
| int /* O - Read status */ |
| _cupsImageReadSunRaster( |
| 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, x, y, |
| bpp, /* Bytes per pixel */ |
| scanwidth, |
| run_count, |
| run_value; |
| cups_ib_t *in, |
| *out, |
| *scanline, |
| *scanptr, |
| *p, |
| bit; |
| unsigned ras_depth, /* depth (1, 8, or 24 bits) of pixel */ |
| ras_type, /* type of file; see RT_* below */ |
| ras_maplength; /* length (bytes) of following map */ |
| unsigned char cmap[3][256]; /* colormap */ |
| |
| |
| /* |
| * Read the header; we already know that this is a raster file (cupsImageOpen |
| * checks this) so we don't need to check the magic number again. |
| */ |
| |
| fputs("DEBUG: Reading Sun Raster image...\n", stderr); |
| |
| read_unsigned(fp); /* Skip magic */ |
| img->xsize = read_unsigned(fp); |
| img->ysize = read_unsigned(fp); |
| ras_depth = read_unsigned(fp); |
| /* ras_length */read_unsigned(fp); |
| ras_type = read_unsigned(fp); |
| /* ras_maptype*/read_unsigned(fp); |
| ras_maplength = read_unsigned(fp); |
| |
| fprintf(stderr, "DEBUG: ras_width=%d, ras_height=%d, ras_depth=%d, ras_type=%d, ras_maplength=%d\n", |
| img->xsize, img->ysize, ras_depth, ras_type, ras_maplength); |
| |
| if (ras_maplength > 768 || |
| img->xsize == 0 || img->xsize > CUPS_IMAGE_MAX_WIDTH || |
| img->ysize == 0 || img->ysize > CUPS_IMAGE_MAX_HEIGHT || |
| ras_depth == 0 || ras_depth > 32) |
| { |
| fputs("DEBUG: Raster image cannot be loaded!\n", stderr); |
| return (1); |
| } |
| |
| if (ras_maplength > 0) |
| { |
| memset(cmap[0], 255, sizeof(cmap[0])); |
| memset(cmap[1], 0, sizeof(cmap[1])); |
| memset(cmap[2], 0, sizeof(cmap[2])); |
| |
| fread(cmap[0], 1, ras_maplength / 3, fp); |
| fread(cmap[1], 1, ras_maplength / 3, fp); |
| fread(cmap[2], 1, ras_maplength / 3, fp); |
| } |
| |
| /* |
| * Compute the width of each line and allocate memory as needed... |
| */ |
| |
| scanwidth = (img->xsize * ras_depth + 7) / 8; |
| if (scanwidth & 1) |
| scanwidth ++; |
| |
| if (ras_depth < 24 && ras_maplength == 0) |
| { |
| img->colorspace = secondary; |
| in = malloc(img->xsize + 1); |
| } |
| else |
| { |
| img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB : primary; |
| in = malloc(img->xsize * 3 + 1); |
| } |
| |
| if (!in) |
| { |
| fputs("DEBUG: Unable to allocate memory!\n", stderr); |
| fclose(fp); |
| return (1); |
| } |
| |
| bpp = cupsImageGetDepth(img); |
| |
| if ((out = malloc(img->xsize * bpp)) == NULL) |
| { |
| fputs("DEBUG: Unable to allocate memory!\n", stderr); |
| fclose(fp); |
| free(in); |
| return (1); |
| } |
| |
| if ((scanline = malloc(scanwidth)) == NULL) |
| { |
| fputs("DEBUG: Unable to allocate memory!\n", stderr); |
| fclose(fp); |
| free(in); |
| free(out); |
| return (1); |
| } |
| |
| run_count = 0; |
| run_value = 0; |
| |
| fprintf(stderr, "DEBUG: bpp=%d, scanwidth=%d\n", bpp, scanwidth); |
| |
| for (y = 0; y < img->ysize; y ++) |
| { |
| if ((ras_depth != 8 && ras_depth != 24) || ras_maplength > 0) |
| p = scanline; |
| else |
| p = in; |
| |
| if (ras_type != RT_BYTE_ENCODED) |
| fread(p, scanwidth, 1, fp); |
| else |
| { |
| for (i = scanwidth; i > 0; i --, p ++) |
| { |
| if (run_count > 0) |
| { |
| *p = run_value; |
| run_count --; |
| } |
| else |
| { |
| run_value = getc(fp); |
| |
| if (run_value == RAS_RLE) |
| { |
| run_count = getc(fp); |
| if (run_count == 0) |
| *p = RAS_RLE; |
| else |
| run_value = *p = getc(fp); |
| } |
| else |
| *p = run_value; |
| } |
| } |
| } |
| |
| if (ras_depth == 1 && ras_maplength == 0) |
| { |
| /* |
| * 1-bit B&W image... |
| */ |
| |
| for (x = img->xsize, bit = 128, scanptr = scanline, p = in; |
| x > 0; |
| x --, p ++) |
| { |
| if (*scanptr & bit) |
| *p = 255; |
| else |
| *p = 0; |
| |
| if (bit > 1) |
| bit >>= 1; |
| else |
| { |
| bit = 128; |
| scanptr ++; |
| } |
| } |
| } |
| else if (ras_depth == 1) |
| { |
| /* |
| * 1-bit colormapped image... |
| */ |
| |
| for (x = img->xsize, bit = 128, scanptr = scanline, p = in; |
| x > 0; |
| x --) |
| { |
| if (*scanptr & bit) |
| { |
| *p++ = cmap[0][1]; |
| *p++ = cmap[1][1]; |
| *p++ = cmap[2][1]; |
| } |
| else |
| { |
| *p++ = cmap[0][0]; |
| *p++ = cmap[1][0]; |
| *p++ = cmap[2][0]; |
| } |
| |
| if (bit > 1) |
| bit >>= 1; |
| else |
| { |
| bit = 128; |
| scanptr ++; |
| } |
| } |
| } |
| else if (ras_depth == 8 && ras_maplength > 0) |
| { |
| /* |
| * 8-bit colormapped image. |
| */ |
| |
| for (x = img->xsize, scanptr = scanline, p = in; |
| x > 0; |
| x --) |
| { |
| *p++ = cmap[0][*scanptr]; |
| *p++ = cmap[1][*scanptr]; |
| *p++ = cmap[2][*scanptr++]; |
| } |
| } |
| else if (ras_depth == 24 && ras_type != RT_FORMAT_RGB) |
| { |
| /* |
| * Convert BGR to RGB... |
| */ |
| |
| for (x = img->xsize, scanptr = scanline, p = in; |
| x > 0; |
| x --, scanptr += 3) |
| { |
| *p++ = scanptr[2]; |
| *p++ = scanptr[1]; |
| *p++ = scanptr[0]; |
| } |
| } |
| |
| if (ras_depth <= 8 && ras_maplength == 0) |
| { |
| 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 : |
| 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_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(scanline); |
| free(in); |
| free(out); |
| |
| fclose(fp); |
| |
| return (0); |
| } |
| |
| |
| /* |
| * 'read_unsigned()' - Read a 32-bit unsigned integer. |
| */ |
| |
| static unsigned /* O - Integer from file */ |
| read_unsigned(FILE *fp) /* I - File to read from */ |
| { |
| unsigned v; /* Integer from file */ |
| |
| |
| v = getc(fp); |
| v = (v << 8) | getc(fp); |
| v = (v << 8) | getc(fp); |
| v = (v << 8) | getc(fp); |
| |
| return (v); |
| } |
| |
| |
| /* |
| * End of "$Id: image-sun.c 7223 2008-01-16 23:41:19Z mike $". |
| */ |