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