Blame converter/other/gemtopnm.c

Packit 78deda
/*
Packit 78deda
 * Convert a GEM .img file to PBM
Packit 78deda
 *
Packit 78deda
 * Author: Diomidis D. Spinellis
Packit 78deda
 * (C) Copyright 1988 Diomidis D. Spinellis.
Packit 78deda
 *
Packit 78deda
 * Permission to use, copy, modify, and distribute this software and its
Packit 78deda
 * documentation for any purpose and without fee is hereby granted,
Packit 78deda
 * provided that the above copyright notice appear in all copies and that
Packit 78deda
 * both that copyright notice and this permission notice appear in
Packit 78deda
 * supporting documentation.
Packit 78deda
 *
Packit 78deda
 * This file is provided AS IS with no warranties of any kind.  The author
Packit 78deda
 * shall have no liability with respect to the infringement of copyrights,
Packit 78deda
 * trade secrets or any patents by this file or any part thereof.  In no
Packit 78deda
 * event will the author be liable for any lost revenue or profits or
Packit 78deda
 * other special, indirect and consequential damages.
Packit 78deda
 *
Packit 78deda
 * Comments and additions should be sent to the author:
Packit 78deda
 *
Packit 78deda
 *                     Diomidis D. Spinellis
Packit 78deda
 *                     1 Myrsinis Str.
Packit 78deda
 *                     GR-145 62 Kifissia
Packit 78deda
 *                     GREECE
Packit 78deda
 *
Packit 78deda
 * 92/07/11 Johann Haider
Packit 78deda
 * Changed to read from stdin if file is omitted
Packit 78deda
 * Changed to handle line length not a multipe of 8
Packit 78deda
 *
Packit 78deda
 * 94/01/31 Andreas Schwab (schwab@ls5.informatik.uni-dortmund.de)
Packit 78deda
 * Changed to remove architecture dependency and conform to
Packit 78deda
 * PBM coding standard.
Packit 78deda
 * Added more tests for garbage.
Packit 78deda
 *
Packit 78deda
 * 2000/04/30 John Elliott <jce@seasip.demon.co.uk> Added ability to
Packit 78deda
 * read 4-plane color IMG files.  Therefore changed from PBM to PPM.
Packit 78deda
 * Bryan changed it further to use the PNM facilities so it outputs
Packit 78deda
 * both PBM and PPM in the Netpbm tradition.  Name changed from
Packit 78deda
 * gemtopbm to gemtopnm.  
Packit 78deda
 */
Packit 78deda
Packit 78deda
#include <assert.h>
Packit 78deda
#include "pnm.h"
Packit 78deda
Packit 78deda
#define MAXVAL 3
Packit 78deda
#define LIGHT  2
Packit 78deda
#define DARK   1
Packit 78deda
#define BLACK  0
Packit 78deda
Packit 78deda
char pattern[8];
Packit 78deda
Packit 78deda
static void getinit ARGS ((FILE *file, int *colsP, int *rowsP, int *padrightP,
Packit 78deda
			   int *patlenP, int *planesP));
Packit 78deda
Packit 78deda
int
Packit 78deda
main(argc, argv)
Packit 78deda
	int             argc;
Packit 78deda
	char           *argv[];
Packit 78deda
{
Packit 78deda
	int     debug = 0;
Packit 78deda
	FILE    *f;
Packit 78deda
    int     row;
Packit 78deda
	int     rows, cols, padright, patlen, planes;
Packit 78deda
      /* attributes of input image */
Packit 78deda
    int type;  /* The format type (PBM/PPM) of the output image */
Packit 78deda
	bit	*bitrow[4];
Packit 78deda
      /* One row of input, one or four planes.  (If one, only [0] is defined)*/
Packit 78deda
    xel * xelrow;  /* One row of output */
Packit 78deda
	const char * const usage = "[-debug] [gem IMG file]";
Packit 78deda
	int argn;
Packit 78deda
Packit 78deda
/* Process multiple planes by maintaining a separate row of bits for each
Packit 78deda
 * plane. In a single-plane image, all we have to do is write out the 
Packit 78deda
 * first plane; in a multiple-plane image, we combine them just before writing
Packit 78deda
 * out the row.
Packit 78deda
 */
Packit 78deda
	pnm_init( &argc, argv );
Packit 78deda
    
Packit 78deda
    argn = 1;
Packit 78deda
Packit 78deda
	while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0')
Packit 78deda
	  {
Packit 78deda
	    if (pm_keymatch(argv[1], "-debug", 2))
Packit 78deda
	      debug = 1;
Packit 78deda
	    else
Packit 78deda
	      pm_usage (usage);
Packit 78deda
	    ++argn;
Packit 78deda
	  }
Packit 78deda
Packit 78deda
	if (argc == argn)
Packit 78deda
		f = stdin;
Packit 78deda
	else {
Packit 78deda
		f = pm_openr (argv[argn]);
Packit 78deda
		++argn;
Packit 78deda
	}
Packit 78deda
Packit 78deda
	if (argn != argc)
Packit 78deda
	  pm_usage (usage);
Packit 78deda
Packit 78deda
	getinit (f, &cols, &rows, &padright, &patlen, &planes);
Packit 78deda
Packit 78deda
    if (planes == 1) 
Packit 78deda
        type = PBM_TYPE;
Packit 78deda
    else 
Packit 78deda
        type = PPM_TYPE;
Packit 78deda
Packit 78deda
	pnm_writepnminit( stdout, cols, rows, MAXVAL, type, 0 );
Packit 78deda
Packit 38c941
    overflow_add(cols, padright);
Packit 78deda
    { 
Packit 78deda
        /* allocate input row data structure */
Packit 78deda
        int plane;
Packit 78deda
        for (plane = 0; plane < planes; plane++) 
Packit 78deda
            bitrow[plane] = malloc (cols + padright);
Packit 78deda
    }
Packit 78deda
    xelrow = pnm_allocrow(cols+padright);   /* Output row */
Packit 78deda
Packit 78deda
	for (row = 0; row < rows; ) {
Packit 78deda
      int linerep;
Packit 78deda
      int plane;
Packit 78deda
Packit 78deda
	  linerep = 1;
Packit 78deda
	  for (plane = 0; plane < planes; plane++) {
Packit 78deda
        int col;
Packit 78deda
		col = 0;
Packit 78deda
		while (col < cols) {
Packit 78deda
            int c;
Packit 78deda
			switch (c = getc(f)) {
Packit 78deda
			case 0x80:	/* Bit String */
Packit 78deda
            {
Packit 78deda
                int j;
Packit 78deda
				c = getc(f);	/* Byte count */
Packit 78deda
				if (debug)
Packit 78deda
                  pm_message("bit string of %d bytes", c);
Packit 78deda
				
Packit 78deda
				if (col + c * 8 > cols + padright)
Packit 78deda
				  pm_error ("bad byte count");
Packit 78deda
				for (j = 0; j < c; ++j) {
Packit 78deda
                    int cc, k;
Packit 78deda
					cc = getc(f);
Packit 78deda
					for (k = 0x80; k; k >>= 1) {
Packit 78deda
						bitrow[plane][col] = (k & cc) ? 0 : 1;
Packit 78deda
						++col;
Packit 78deda
					}
Packit 78deda
				}
Packit 78deda
            }
Packit 78deda
            break;
Packit 78deda
			case 0:		/* Pattern run */
Packit 78deda
            {
Packit 78deda
                int j, l;
Packit 78deda
				c = getc(f);	/* Repeat count */
Packit 78deda
				if (debug)
Packit 78deda
					pm_message("pattern run of %d repetitions",	c);
Packit 78deda
                /* line repeat */
Packit 78deda
                if (c == 0) {
Packit 78deda
                    c = getc(f);
Packit 78deda
                    if (c != 0x00ff)
Packit 78deda
                        pm_error( "badly formed line repeat" );
Packit 78deda
                    linerep = getc(f);
Packit 78deda
                    break;
Packit 78deda
                }
Packit 78deda
				fread (pattern, 1, patlen, f);
Packit 78deda
				if (col + c * patlen * 8 > cols + padright)
Packit 78deda
				  pm_error ("bad pattern repeat count");
Packit 78deda
				for (j = 0; j < c; ++j)
Packit 78deda
					for (l = 0; l < patlen; ++l) {
Packit 78deda
                        int k;
Packit 78deda
						for (k = 0x80; k; k >>= 1) {
Packit 78deda
							bitrow[plane][col] = (k & pattern[l]) ? 0 : 1;
Packit 78deda
							++col;
Packit 78deda
						}
Packit 78deda
                    }
Packit 78deda
            }
Packit 78deda
            break;
Packit 78deda
Packit 78deda
			default:	/* Solid run */
Packit 78deda
            {
Packit 78deda
                int l, j;
Packit 78deda
				if (debug)
Packit 78deda
					pm_message("solid run of %d bytes %s", c & 0x7f,
Packit 78deda
                               c & 0x80 ? "on" : "off" );
Packit 78deda
                /* each byte had eight bits DSB */
Packit 78deda
                l = (c & 0x80) ? 0: 1;
Packit 78deda
                c = (c & 0x7f) * 8;
Packit 78deda
                if (col + c > cols + padright)
Packit 78deda
                    pm_error ("bad solid run repeat count");
Packit 78deda
                for (j = 0; j < c; ++j) {
Packit 78deda
                    bitrow[plane][col] = l;
Packit 78deda
					++col;
Packit 78deda
                }
Packit 78deda
            }
Packit 78deda
				break;
Packit 78deda
Packit 78deda
			case EOF:	/* End of file */
Packit 78deda
				pm_error( "end of file reached" );
Packit 78deda
Packit 78deda
			}
Packit 78deda
		}
Packit 78deda
                if ( debug )
Packit 78deda
                        pm_message( "EOL plane %d row %d", plane, row );
Packit 78deda
                if (col != cols + padright)
Packit 78deda
                        pm_error( "EOL beyond edge" );
Packit 78deda
	  }
Packit 78deda
Packit 78deda
	  if (planes == 4) {
Packit 78deda
          /* Construct a pixel from the 4 planes of bits for this row */
Packit 78deda
          int col;
Packit 78deda
          for (col = 0; col < cols; col++) {
Packit 78deda
            int r, g, b, i;
Packit 78deda
Packit 78deda
            const int r_bit = !bitrow[0][col];
Packit 78deda
            const int g_bit = !bitrow[1][col];
Packit 78deda
            const int b_bit = !bitrow[2][col];
Packit 78deda
            i = bitrow[3][col];
Packit 78deda
Packit 78deda
			/* Deal with weird GEM palette - white/black/gray are
Packit 78deda
               encoded oddly 
Packit 78deda
            */
Packit 78deda
			if (r_bit == g_bit && g_bit == b_bit) {
Packit 78deda
                /* It's black, white, or gray */
Packit 78deda
				if (r_bit && i) r = LIGHT;
Packit 78deda
				else if (r_bit) r = BLACK;
Packit 78deda
				else if (i) r = MAXVAL;
Packit 78deda
				else r = DARK;
Packit 78deda
				g = b = r;	
Packit 78deda
			} else {
Packit 78deda
                /* It's one of the twelve colored colors */
Packit 78deda
                if (!i) {
Packit 78deda
                    /* Low intensity */
Packit 78deda
                    r = r_bit * LIGHT; 
Packit 78deda
                    g = g_bit * LIGHT;
Packit 78deda
                    b = b_bit * LIGHT;
Packit 78deda
                } else {
Packit 78deda
                    /* Normal intensity */
Packit 78deda
                    r = r_bit * MAXVAL;
Packit 78deda
                    g = g_bit * MAXVAL;
Packit 78deda
                    b = b_bit * MAXVAL;
Packit 78deda
                }
Packit 78deda
            }
Packit 78deda
            PPM_ASSIGN(xelrow[col], r, g, b);
Packit 78deda
		}
Packit 78deda
	  } else {
Packit 78deda
          int col;
Packit 78deda
          for (col = 0; col < cols; col++) 
Packit 78deda
              PNM_ASSIGN1(xelrow[col], bitrow[0][col]);
Packit 78deda
      }
Packit 78deda
	  while (linerep--) {
Packit 78deda
		pnm_writepnmrow( stdout, xelrow, cols, MAXVAL, type, 0 );
Packit 78deda
		++row;
Packit 78deda
	  }
Packit 78deda
	}
Packit 78deda
    pnm_freerow(xelrow);
Packit 78deda
	pm_close( f );
Packit 78deda
	pm_close( stdout );
Packit 78deda
	exit(0);
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
static void
Packit 78deda
getinit (file, colsP, rowsP, padrightP, patlenP, planesP)
Packit 78deda
     FILE *file;
Packit 78deda
     int *colsP;
Packit 78deda
     int *rowsP;
Packit 78deda
     int *padrightP;
Packit 78deda
     int *patlenP;
Packit 78deda
     int *planesP;
Packit 78deda
{
Packit 78deda
  short s;
Packit 78deda
  short headlen;
Packit 78deda
Packit 78deda
  if (pm_readbigshort (file, &s) == -1) /* Image file version */
Packit 78deda
    pm_error ("EOF / read error");
Packit 78deda
  if (s != 1)
Packit 78deda
    pm_error ("unknown version number (%d)", (int) s);
Packit 78deda
  if (pm_readbigshort (file, &headlen) == -1) /* Header length in words */
Packit 78deda
    pm_error ("EOF / read error");
Packit 78deda
  if (headlen < 8)
Packit 78deda
    pm_error ("short header (%d)", (int) headlen);
Packit 78deda
  if (pm_readbigshort (file, &s) == -1) /* Number of planes */
Packit 78deda
    pm_error ("EOF / read error");
Packit 78deda
  if (s != 4 && s != 1)
Packit 78deda
    pm_error ("This program can interpret IMGs with only 1 or 4 planes");
Packit 78deda
  *planesP = s;
Packit 78deda
  if (pm_readbigshort (file, &s) == -1) /* Pattern definition length (bytes) */
Packit 78deda
    pm_error ("EOF / read error");
Packit 78deda
  if (s < 1 || s > 8)
Packit 78deda
    pm_error ("illegal pattern length (%d)", (int) s);
Packit 78deda
  *patlenP = (int) s;
Packit 78deda
  if (pm_readbigshort (file, &s) == -1 /* Pixel height (microns) */
Packit 78deda
      || pm_readbigshort (file, &s) == -1 /* Pixel height (microns) */
Packit 78deda
      || pm_readbigshort (file, &s) == -1) /* Scan line width */
Packit 78deda
    pm_error ("EOF / read error");
Packit 78deda
  *colsP = (int) s;
Packit 78deda
  if (pm_readbigshort (file, &s) == -1) /* Number of scan line items */
Packit 78deda
    pm_error ("EOF / read error");
Packit 78deda
  *rowsP = (int) s;
Packit 78deda
  *padrightP = 7 - ((*colsP + 7) & 7);
Packit 78deda
Packit 78deda
  headlen -= 8;
Packit 78deda
  while (headlen-- > 0)
Packit 78deda
    {
Packit 78deda
      (void) getc (file);
Packit 78deda
      (void) getc (file);
Packit 78deda
    }
Packit 78deda
}
Packit 78deda