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;
    }
  }
}


openSUSE Build Service is sponsored by