blob: 8e6c1d3d90835524e4257631c32974d572e41987 [file] [log] [blame]
/*
* "$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 $".
*/