|
Packit |
78deda |
/* pgmtolispm.c - read a pgm and write a file acceptable to the
|
|
Packit |
78deda |
** tv:read-bit-array-file function of TI Explorer and Symbolics Lisp Machines.
|
|
Packit |
78deda |
**
|
|
Packit |
78deda |
** Written by Jamie Zawinski based on code (C) 1988 by Jef Poskanzer.
|
|
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, provided
|
|
Packit |
78deda |
** that the above copyright notice appear in all copies and that both that
|
|
Packit |
78deda |
** copyright notice and this permission notice appear in supporting
|
|
Packit |
78deda |
** documentation. This software is provided "as is" without express or
|
|
Packit |
78deda |
** implied warranty.
|
|
Packit |
78deda |
**
|
|
Packit |
78deda |
** When one writes a multi-plane bitmap with tv:write-bit-array-file, it is
|
|
Packit |
78deda |
** usually a color image; but a color map is not written in the file, so we
|
|
Packit |
78deda |
** treat this as a graymap instead. To convert a color image to Lispm
|
|
Packit |
78deda |
** format, you must convert it to a pgm, and hand-edit a color map... Ick.
|
|
Packit |
78deda |
**
|
|
Packit |
78deda |
** Feb 2010 afu
|
|
Packit |
78deda |
** Added dimension check to prevent short int from overflowing
|
|
Packit |
78deda |
** Changed code style (ANSI-style function definitions, etc.)
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include "pm.h"
|
|
Packit |
78deda |
#include "pgm.h"
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#define LISPM_MAGIC "This is a BitMap file"
|
|
Packit |
78deda |
#define INT16MAX 32767
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static unsigned int item;
|
|
Packit |
78deda |
static unsigned int bitsperitem, maxbitsperitem, bitshift;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static unsigned int
|
|
Packit |
78deda |
depth_to_word_size(unsigned int const depth) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* Lispm architecture specific - if a bitmap is written */
|
|
Packit |
78deda |
/* out with a depth of 5, it really has a depth of 8, and */
|
|
Packit |
78deda |
/* is stored that way in the file. */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int const wordSize =
|
|
Packit |
78deda |
depth == 1 ? 1 :
|
|
Packit |
78deda |
depth == 2 ? 2 :
|
|
Packit |
78deda |
depth <= 4 ? 4 :
|
|
Packit |
78deda |
depth <= 8 ? 8 :
|
|
Packit |
78deda |
depth <= 16 ? 16 :
|
|
Packit |
78deda |
depth <= 32 ? 32 :
|
|
Packit |
78deda |
0;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (wordSize == 0)
|
|
Packit |
78deda |
pm_error("depth was %u, which is not in the range 1-32", depth);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return wordSize;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
putinit(unsigned int const cols,
|
|
Packit |
78deda |
unsigned int const rows,
|
|
Packit |
78deda |
unsigned int const depth) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int const cols32 = ((cols + 31 ) / 32) * 32;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int i;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* Lispms are able to write bit files that are not mod32 wide, but we */
|
|
Packit |
78deda |
/* don't. This should be ok, since bit arrays which are not mod32 wide */
|
|
Packit |
78deda |
/* are pretty useless on a lispm (can't hand them to bitblt). */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (rows > INT16MAX || cols > INT16MAX || cols32 > INT16MAX)
|
|
Packit |
78deda |
pm_error("Input image is too large.");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
printf(LISPM_MAGIC);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_writelittleshort(stdout, cols);
|
|
Packit |
78deda |
pm_writelittleshort(stdout, rows);
|
|
Packit |
78deda |
pm_writelittleshort(stdout, cols32);
|
|
Packit |
78deda |
putchar(depth & 0xFF);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (i = 0; i < 9; ++i)
|
|
Packit |
78deda |
putchar(0); /* pad bytes */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
item = 0;
|
|
Packit |
78deda |
bitsperitem = 0;
|
|
Packit |
78deda |
maxbitsperitem = depth_to_word_size(depth);
|
|
Packit |
78deda |
bitshift = 0;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
putitem(void) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_writelittlelong(stdout, ~item);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
item = 0;
|
|
Packit |
78deda |
bitsperitem = 0;
|
|
Packit |
78deda |
bitshift = 0;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
putval(gray const b) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (bitsperitem == 32)
|
|
Packit |
78deda |
putitem();
|
|
Packit |
78deda |
|
|
Packit |
78deda |
item = item | (b << bitshift);
|
|
Packit |
78deda |
bitsperitem = bitsperitem + maxbitsperitem;
|
|
Packit |
78deda |
bitshift = bitshift + maxbitsperitem;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
putrest(void) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (bitsperitem > 0)
|
|
Packit |
78deda |
putitem();
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int
|
|
Packit |
78deda |
main(int argc, const char * argv[]) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
FILE * ifP;
|
|
Packit |
78deda |
gray * grayrow;
|
|
Packit |
78deda |
int rows;
|
|
Packit |
78deda |
int cols;
|
|
Packit |
78deda |
unsigned int depth;
|
|
Packit |
78deda |
int format;
|
|
Packit |
78deda |
unsigned int padright;
|
|
Packit |
78deda |
unsigned int row;
|
|
Packit |
78deda |
gray maxval;
|
|
Packit |
78deda |
const char * inputFile;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_proginit(&argc, argv);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (argc-1 < 1)
|
|
Packit |
78deda |
inputFile = "-";
|
|
Packit |
78deda |
else {
|
|
Packit |
78deda |
inputFile = argv[1];
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (argc-1 > 2)
|
|
Packit |
78deda |
pm_error("Too many arguments. The only argument is the optional "
|
|
Packit |
78deda |
"input file name");
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ifP = pm_openr(inputFile);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pgm_readpgminit(ifP, &cols, &rows, &maxval, &format);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
grayrow = pgm_allocrow(cols);
|
|
Packit |
78deda |
depth = pm_maxvaltobits(maxval);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* Compute padding to round cols up to the nearest multiple of 32. */
|
|
Packit |
78deda |
padright = ((cols + 31) / 32) * 32 - cols;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
putinit(cols, rows, depth);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = 0; row < rows; ++row) {
|
|
Packit |
78deda |
unsigned int col;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pgm_readpgmrow(ifP, grayrow, cols, maxval, format);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (col = 0; col < cols; ++col)
|
|
Packit |
78deda |
putval(grayrow[col]);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (col = 0; col < padright; ++col)
|
|
Packit |
78deda |
putval(0);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_close(ifP);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
putrest();
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return 0;
|
|
Packit |
78deda |
}
|