Blame converter/pgm/pgmtolispm.c

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
}