File cupsraster2ppm.c of Package rasterview
/*
* cupsraster2ppm.c -- a converter to make rasterfiles usable to the rest of the world.
*
* cups raster files are unrelated to sun raster files.
*
* 2012-01-18, jw@suse.de
* Distribute under GPL-2.0
*/
#include <stdio.h>
#include <arpa/inet.h> // htonl
#include "error.c" // from http://www.easysw.com/~mike/rasterview/rasterview-1.3.tar.gz
#include "raster.c" // from http://www.easysw.com/~mike/rasterview/rasterview-1.3.tar.gz
#if 0
# define endian_offset 0 // Big endian
#else
# define endian_offset 1 // Little endian
#endif
static void convert_rgb();
int main()
{
cups_raster_t *in = cupsRasterOpen(0, CUPS_RASTER_READ);
if (!in) { fprintf(stderr, "cupsRasterOpen(stdin): not a cups rasterfile.\n"); exit(1); }
cups_page_header2_t header;
int ok = cupsRasterReadHeader2(in, &header);
if (!ok) { fprintf(stderr, "cupsRasterReadHeader2(stdin) failed.\n"); exit(1); }
printf((header.cupsNumColors == 1) ? "P4\n" : "P6\n");
printf("# HWResolution = {%d, %d}\n",
header.HWResolution[0],
header.HWResolution[1]);
printf("# PageSize = {%d, %d}\n",
header.PageSize[0],
header.PageSize[1]);
printf("# ImagingBoundingBox = {%d, %d, %d, %d}\n",
header.ImagingBoundingBox[0],
header.ImagingBoundingBox[1],
header.ImagingBoundingBox[2],
header.ImagingBoundingBox[3]);
printf("# LeadingEdge = %d (0=CUPS_EDGE_TOP)\n", (int)header.LeadingEdge);
printf("# cupsColorSpace = %d (1=CUPS_CSPACE_RGB)\n", (int)header.cupsColorSpace);
printf("# cupsNumColors = %d\n", header.cupsNumColors);
printf("# cupsBitsPerColor = %d\n", header.cupsBitsPerColor); // 8
printf("# cupsBitsPerPixel = %d\n", header.cupsBitsPerPixel); // 24
printf("# cupsWidth = %d\n", header.cupsWidth);
printf("# cupsHeight = %d\n", header.cupsHeight);
printf("# cupsBytesPerLine = %d\n", header.cupsBytesPerLine);
printf("%d %d\n%d\n",
header.cupsWidth, header.cupsHeight,
(1<<header.cupsBitsPerColor)-1);
if (header.cupsColorSpace != CUPS_CSPACE_RGB)
{
fprintf(stderr, "cupsColorSpace=%d not impl. only (1 = CUPS_CSPACE_RGB)\n", header.cupsColorSpace);
exit(2);
}
if (isatty(1))
{
fprintf(stderr, "\nOOPS: stdout is a tty, aborting...\n");
exit(0);
}
int bpc = (header.cupsBitsPerPixel + 7) / 8;
int bpp = header.cupsNumColors == 1 ? 1 : 3;
int py;
unsigned char *line = (unsigned char *)calloc(header.cupsBytesPerLine, 1);
unsigned char *colors = (unsigned char *)calloc(header.cupsWidth, bpc);
unsigned char *pixels = (unsigned char *)calloc(header.cupsWidth, bpp);
for (py = 0; py < header.cupsHeight; py++)
{
if (!cupsRasterReadPixels(in, line, header.cupsBytesPerLine))
{
fprintf(stderr, "cupsRasterReadPixels(stdin, y=%d) failed: %s\n", py, strerror(errno));
exit(1);
}
convert_rgb(&header, line, colors, pixels);
int x;
unsigned char *p = pixels;
for (x = header.cupsWidth; x > 0; x--)
{
if (bpp == 3)
{
putchar(*p++); // R
putchar(*p++); // G
putchar(*p++); // B
}
else
{
putchar(*p++); // V
}
}
}
return 0;
}
// taken from RasterDisplay.cxx
static void
convert_rgb(
cups_page_header2_t *header, // I - Raster header */
unsigned char *line, // I - Raster line
unsigned char *colors, // O - Original pixels
unsigned char *pixels) // O - RGB pixels
{
int x, // X position in line
w, // Width of line
val; // Pixel value
unsigned char *rptr, // Red pointer
*gptr, // Green pointer
*bptr, // Blue pointer
bit; // Current bit
w = header->cupsWidth;
if (header->cupsColorOrder == CUPS_ORDER_CHUNKED)
{
// Chunky
switch (header->cupsBitsPerColor)
{
case 1 :
memset(pixels, 0, w * 3);
for (x = w; x > 0; x -= 2, pixels += 6)
{
bit = *line++;
*colors++ = bit >> 4;
if (bit & 0x40)
pixels[0] = 255;
if (bit & 0x20)
pixels[1] = 255;
if (bit & 0x10)
pixels[2] = 255;
if (x > 1)
{
*colors++ = bit & 0x0f;
if (bit & 0x04)
pixels[3] = 255;
if (bit & 0x02)
pixels[4] = 255;
if (bit & 0x01)
pixels[5] = 255;
}
}
break;
case 2 :
for (x = w; x > 0; x --)
{
*colors++ = bit = *line++;
*pixels++ = 85 * ((bit & 0x30) >> 4);
*pixels++ = 85 * ((bit & 0x0c) >> 2);
*pixels++ = 85 * (bit & 0x03);
}
break;
case 4 :
memset(pixels, 0, w * 3);
for (x = w; x > 0; x --, pixels += 3)
{
bit = *line++;
*colors++ = bit;
if (bit & 0x0f)
pixels[0] += 17 * (bit & 0x0f);
bit = *line++;
*colors++ = bit;
if (bit & 0xf0)
pixels[1] += 17 * ((bit & 0xf0) >> 4);
if (bit & 0x0f)
pixels[2] += 17 * (bit & 0x0f);
}
break;
case 8 :
memcpy(colors, line, w * 3);
memcpy(pixels, line, w * 3);
break;
case 16 :
if (endian_offset)
*colors++ = *line++;
for (x = w; x > 0; x --)
{
*colors++ = *pixels++ = *line++;
*colors++ = *line++;
*colors++ = *pixels++ = *line++;
*colors++ = *line++;
*colors++ = *pixels++ = *line++;
if (!endian_offset || x > 1)
*colors++ = *line++;
}
break;
}
}
else
{
// Banded
int bytespercolor = (header->cupsBitsPerColor * header->cupsWidth + 7) / 8;
rptr = line;
gptr = line + bytespercolor;
bptr = line + 2 * bytespercolor;
switch (header->cupsBitsPerColor)
{
case 1 :
memset(pixels, 0, w * 3);
for (x = w, bit = 0x80; x > 0; x --, pixels += 3)
{
if (*rptr & bit)
{
*colors++ = 1;
pixels[0] = 255;
}
else
colors ++;
if (*gptr & bit)
{
*colors++ = 1;
pixels[1] = 255;
}
else
colors ++;
if (*bptr & bit)
{
*colors++ = 1;
pixels[2] = 255;
}
else
colors ++;
if (bit > 1)
bit >>= 1;
else
{
bit = 0x80;
rptr ++;
gptr ++;
bptr ++;
}
}
break;
case 2 :
for (x = 0; x < w; x ++)
{
switch (x & 3)
{
case 0 :
*colors++ = val = (*rptr & 0xc0) >> 6;
*pixels++ = 85 * val;
*colors++ = val = (*gptr & 0xc0) >> 6;
*pixels++ = 85 * val;
*colors++ = val = (*bptr & 0xc0) >> 6;
*pixels++ = 85 * val;
break;
case 1 :
*colors++ = val = (*rptr & 0x30) >> 4;
*pixels++ = 85 * val;
*colors++ = val = (*gptr & 0x30) >> 4;
*pixels++ = 85 * val;
*colors++ = val = (*bptr & 0x30) >> 4;
*pixels++ = 85 * val;
break;
case 2 :
*colors++ = val = (*rptr & 0x0c) >> 2;
*pixels++ = 85 * val;
*colors++ = val = (*gptr & 0x0c) >> 2;
*pixels++ = 85 * val;
*colors++ = val = (*bptr & 0x0c) >> 2;
*pixels++ = 85 * val;
break;
case 3 :
*colors++ = val = *rptr & 0x03;
*pixels++ = 85 * val;
*colors++ = val = *gptr & 0x03;
*pixels++ = 85 * val;
*colors++ = val = *bptr & 0x03;
*pixels++ = 85 * val;
rptr ++;
gptr ++;
bptr ++;
break;
}
}
break;
case 4 :
for (x = 0; x < w; x ++)
{
switch (x & 1)
{
case 0 :
*colors++ = val = (*rptr & 0xf0) >> 4;
*pixels++ = 17 * val;
*colors++ = val = (*gptr & 0xf0) >> 4;
*pixels++ = 17 * val;
*colors++ = val = (*bptr & 0xf0) >> 4;
*pixels++ = 17 * val;
break;
case 1 :
*colors++ = val = *rptr & 0x0f;
*pixels++ = 17 * val;
*colors++ = val = *gptr & 0x0f;
*pixels++ = 17 * val;
*colors++ = val = *bptr & 0x0f;
*pixels++ = 17 * val;
rptr ++;
gptr ++;
bptr ++;
break;
}
}
break;
case 8 :
for (x = w; x > 0; x --)
{
*colors++ = *pixels++ = *rptr++;
*colors++ = *pixels++ = *gptr++;
*colors++ = *pixels++ = *bptr++;
}
break;
case 16 :
if (endian_offset)
{
for (x = w; x > 0; x --)
{
*colors++ = *rptr++;
*colors++ = *pixels++ = *rptr++;
*colors++ = *gptr++;
*colors++ = *pixels++ = *gptr++;
*colors++ = *bptr++;
*colors++ = *pixels++ = *bptr++;
}
}
else
{
for (x = w; x > 0; x --)
{
*colors++ = *pixels++ = *rptr++;
*colors++ = *rptr++;
*colors++ = *pixels++ = *gptr++;
*colors++ = *gptr++;
*colors++ = *pixels++ = *bptr++;
*colors++ = *bptr++;
}
}
break;
}
}
}