#include "image.h"
#define RAS_MAGIC 0x59a66a95
#define RT_OLD 0
#define RT_STANDARD 1
#define RT_BYTE_ENCODED 2
#define RT_FORMAT_RGB 3
#define RT_EXPERIMENTAL 0xffff
#define RMT_RAW 2
#define RMT_NONE 0
#define RMT_EQUAL_RGB 1
#define RAS_RLE 0x80
static unsigned read_unsigned(FILE *fp);
int
ImageReadSunRaster(image_t *img,
FILE *fp,
int primary,
int secondary,
int saturation,
int hue,
const ib_t *lut)
{
int i, x, y,
bpp,
scanwidth,
run_count,
run_value;
ib_t *in,
*out,
*scanline,
*scanptr,
*p,
bit;
unsigned ras_depth,
ras_type,
ras_maplength;
unsigned char cmap[3][256];
read_unsigned(fp);
img->xsize = read_unsigned(fp);
img->ysize = read_unsigned(fp);
ras_depth = read_unsigned(fp);
read_unsigned(fp);
ras_type = read_unsigned(fp);
read_unsigned(fp);
ras_maplength = read_unsigned(fp);
if (ras_maplength > 0)
{
fread(cmap[0], 1, ras_maplength / 3, fp);
fread(cmap[1], 1, ras_maplength / 3, fp);
fread(cmap[2], 1, ras_maplength / 3, fp);
}
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 == IMAGE_RGB_CMYK) ? IMAGE_RGB : primary;
in = malloc(img->xsize * 3 + 1);
}
bpp = ImageGetDepth(img);
out = malloc(img->xsize * bpp);
scanline = malloc(scanwidth);
run_count = 0;
run_value = 0;
for (y = 0; y < img->ysize; y ++)
{
if (ras_depth != 8 || 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)
{
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 = 128;
scanptr ++;
}
else
bit >>= 1;
}
}
else if (ras_depth == 1)
{
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 = 128;
scanptr ++;
}
else
bit >>= 1;
}
}
else if (ras_depth == 8 && ras_maplength > 0)
{
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)
{
for (x = img->xsize, scanptr = scanline, p = in;
x > 0;
x --, scanptr += 3)
{
*p++ = scanptr[2];
*p++ = scanptr[1];
*p++ = scanptr[0];
}
}
if (bpp == 1)
{
if (img->colorspace == IMAGE_WHITE)
{
if (lut)
ImageLut(in, img->xsize, lut);
ImagePutRow(img, 0, y, img->xsize, in);
}
else
{
switch (img->colorspace)
{
case IMAGE_RGB :
ImageWhiteToRGB(in, out, img->xsize);
break;
case IMAGE_BLACK :
ImageWhiteToBlack(in, out, img->xsize);
break;
case IMAGE_CMY :
ImageWhiteToCMY(in, out, img->xsize);
break;
case IMAGE_CMYK :
ImageWhiteToCMYK(in, out, img->xsize);
break;
}
if (lut)
ImageLut(out, img->xsize * bpp, lut);
ImagePutRow(img, 0, y, img->xsize, out);
}
}
else
{
if (img->colorspace == IMAGE_RGB)
{
if (saturation != 100 || hue != 0)
ImageRGBAdjust(in, img->xsize, saturation, hue);
if (lut)
ImageLut(in, img->xsize * 3, lut);
ImagePutRow(img, 0, y, img->xsize, in);
}
else
{
if ((saturation != 100 || hue != 0) && bpp > 1)
ImageRGBAdjust(in, img->xsize, saturation, hue);
switch (img->colorspace)
{
case IMAGE_WHITE :
ImageRGBToWhite(in, out, img->xsize);
break;
case IMAGE_BLACK :
ImageRGBToBlack(in, out, img->xsize);
break;
case IMAGE_CMY :
ImageRGBToCMY(in, out, img->xsize);
break;
case IMAGE_CMYK :
ImageRGBToCMYK(in, out, img->xsize);
break;
}
if (lut)
ImageLut(out, img->xsize * bpp, lut);
ImagePutRow(img, 0, y, img->xsize, out);
}
}
}
free(scanline);
free(in);
free(out);
fclose(fp);
return (0);
}
static unsigned
read_unsigned(FILE *fp)
{
unsigned v;
v = getc(fp);
v = (v << 8) | getc(fp);
v = (v << 8) | getc(fp);
v = (v << 8) | getc(fp);
return (v);
}