- renaming to lowercase OBS-URL: https://build.opensuse.org/package/show/home:jsmeix/rasterview?expand=0&rev=1
371 lines
8.8 KiB
C
371 lines
8.8 KiB
C
/*
|
|
* 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
|