Blame converter/pbm/pbmtomda.c

Packit 78deda
Packit 78deda
/***************************************************************************
Packit 78deda
Packit 78deda
    PBMTOMDA: Convert portable bitmap to Microdesign area
Packit 78deda
    Copyright (C) 1999,2004 John Elliott <jce@seasip.demon.co.uk>
Packit 78deda
Packit 78deda
    This program is free software; you can redistribute it and/or modify
Packit 78deda
    it under the terms of the GNU General Public License as published by
Packit 78deda
    the Free Software Foundation; either version 2 of the License, or
Packit 78deda
    (at your option) any later version.
Packit 78deda
Packit 78deda
    This program is distributed in the hope that it will be useful,
Packit 78deda
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 78deda
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 78deda
    GNU General Public License for more details.
Packit 78deda
Packit 78deda
    You should have received a copy of the GNU General Public License
Packit 78deda
    along with this program; if not, write to the Free Software
Packit 78deda
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Packit 78deda
Packit 78deda
******************************************************************************/
Packit 78deda
Packit 78deda
#include <stdio.h>
Packit 78deda
#include <string.h>
Packit 78deda
Packit 78deda
#include "pbm.h"
Packit 78deda
#include "mallocvar.h"
Packit 78deda
Packit 78deda
/* I'm being somewhat conservative in the PBM -> MDA translation. I output 
Packit 78deda
 * only the MD2 format and don't allow RLE over the ends of lines.
Packit 78deda
 */
Packit 78deda
Packit 78deda
typedef unsigned char mdbyte;
Packit 78deda
Packit 78deda
static FILE *infile;
Packit 78deda
static mdbyte header[128];
Packit 78deda
static int bInvert = 0;
Packit 78deda
static int bScale  = 0;
Packit 78deda
Packit 78deda
/* Encode 8 pixels as a byte */
Packit 78deda
Packit 78deda
static mdbyte 
Packit 78deda
encode(bit ** const bits, int const row, int const col)
Packit 78deda
{
Packit 78deda
    int n;
Packit 78deda
    int mask;
Packit 78deda
    mdbyte b;
Packit 78deda
Packit 78deda
    mask = 0x80;   /* initial value */
Packit 78deda
    b = 0;  /* initial value */
Packit 78deda
Packit 78deda
    for (n = 0; n < 8; n++) {
Packit 78deda
        if (bits[row][col+n] == PBM_BLACK) b |= mask;
Packit 78deda
        mask = mask >> 1;
Packit 78deda
    }
Packit 78deda
    return b;
Packit 78deda
}
Packit 78deda
Packit 78deda
/* Translate a pbm to MD2 format, one row at a time */
Packit 78deda
Packit 78deda
static void 
Packit 78deda
do_translation(bit ** const bits, 
Packit 78deda
               int    const nOutCols, 
Packit 78deda
               int    const nOutRows,
Packit 78deda
               int    const nInRows)
Packit 78deda
{
Packit 78deda
    int row;
Packit 78deda
    mdbyte *mdrow;  /* malloc'ed */
Packit 78deda
Packit 78deda
    int const step = bScale ? 2 : 1;
Packit 78deda
Packit 78deda
    MALLOCARRAY(mdrow, nOutCols);
Packit 78deda
Packit 78deda
    if (mdrow == NULL)
Packit 78deda
        pm_error("Not enough memory for conversion.");
Packit 78deda
Packit 78deda
    for (row = 0; row < nOutRows; row+=step)
Packit 78deda
    {
Packit 78deda
        int col;
Packit 78deda
        int x1;
Packit 78deda
Packit 78deda
        /* Encode image into non-compressed bitmap */
Packit 78deda
        for (col = 0; col < nOutCols; ++col) {
Packit 78deda
            mdbyte b;
Packit 78deda
Packit 78deda
            if (row < nInRows)
Packit 78deda
                b = encode(bits, row, col*8);
Packit 78deda
            else
Packit 78deda
                b = 0xff;  /* All black */
Packit 78deda
Packit 78deda
            mdrow[col] = bInvert ? b : ~b;
Packit 78deda
        }
Packit 78deda
Packit 78deda
        /* Encoded. Now RLE it */
Packit 78deda
        for (col = 0; col < nOutCols; )
Packit 78deda
        {
Packit 78deda
            mdbyte const b = mdrow[col];
Packit 78deda
Packit 78deda
            if (b != 0xFF && b != 0) /* Normal byte */
Packit 78deda
            {
Packit 78deda
                putchar(b);
Packit 78deda
                ++col;
Packit 78deda
            }
Packit 78deda
            else    /* RLE a run of 0s or 0xFFs */
Packit 78deda
            {
Packit 78deda
                for (x1 = col; x1 < nOutCols; x1++)
Packit 78deda
                {
Packit 78deda
                    if (mdrow[x1] != b) break;
Packit 78deda
                    if (x1 - col > 256) break;
Packit 78deda
                }
Packit 78deda
                x1 -= col;    /* x1 = no. of repeats */
Packit 78deda
                if (x1 == 256) x1 = 0;
Packit 78deda
                putchar(b);
Packit 78deda
                putchar(x1);
Packit 78deda
                col += x1;        
Packit 78deda
            }   
Packit 78deda
        }
Packit 78deda
    }
Packit 78deda
    free(mdrow);
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
static void usage(char *s)
Packit 78deda
{        
Packit 78deda
    printf("pbmtomda v1.01, Copyright (C) 1999,2004 John Elliott <jce@seasip.demon.co.uk>\n"
Packit 78deda
         "This program is redistributable under the terms of the GNU General Public\n"
Packit 78deda
                 "License, version 2 or later.\n\n"
Packit 78deda
                 "Usage: %s [ -d ] [ -i ] [ -- ] [ infile ]\n\n"
Packit 78deda
                 "-d: Halve height (to compensate for the PCW aspect ratio)\n"
Packit 78deda
                 "-i: Invert colors\n"
Packit 78deda
                 "--: No more options (use if filename begins with a dash)\n",
Packit 78deda
        s);
Packit 78deda
Packit 78deda
    exit(0);
Packit 78deda
}
Packit 78deda
Packit 78deda
int main(int argc, char **argv)
Packit 78deda
{
Packit 78deda
    int nOutRowsUnrounded;  /* Before rounding up to multiple of 4 */
Packit 78deda
    int nOutCols, nOutRows;
Packit 78deda
    int nInCols, nInRows;
Packit 78deda
    bit **bits;
Packit 78deda
    int rc;
Packit 78deda
Packit 78deda
    int n, optstop = 0;
Packit 78deda
    char *fname = NULL;
Packit 78deda
Packit 78deda
    pbm_init(&argc, argv);
Packit 78deda
Packit 78deda
    /* Output v2-format MDA images. Simulate MDA header...
Packit 78deda
     * 2004-01-11: Hmm. Apparently some (but not all) MDA-reading 
Packit 78deda
     * programs insist on the program identifier being exactly 
Packit 78deda
     * 'MicroDesignPCW'. The spec does not make this clear. */
Packit 78deda
    strcpy((char*) header, ".MDAMicroDesignPCWv1.00\r\npbm2mda\r\n");
Packit 78deda
Packit 78deda
    for (n = 1; n < argc; n++)
Packit 78deda
    {
Packit 78deda
        if (argv[n][0] == '-' && !optstop)
Packit 78deda
        {   
Packit 78deda
            if (argv[n][1] == 'd' || argv[n][1] == 'D') bScale = 1;
Packit 78deda
            if (argv[n][1] == 'i' || argv[n][1] == 'I') bInvert = 1;
Packit 78deda
            if (argv[n][1] == 'h' || argv[n][1] == 'H') usage(argv[0]);
Packit 78deda
            if (argv[n][1] == '-' && argv[n][2] == 0 && !fname)     /* "--" */
Packit 78deda
            {
Packit 78deda
                optstop = 1;
Packit 78deda
            }
Packit 78deda
            if (argv[n][1] == '-' && (argv[n][2] == 'h' || argv[n][2] == 'H')) usage(argv[0]);
Packit 78deda
        }
Packit 78deda
        else if (argv[n][0] && !fname)  /* Filename */
Packit 78deda
        {
Packit 78deda
            fname = argv[n];
Packit 78deda
        }
Packit 78deda
    }
Packit 78deda
Packit 78deda
    if (fname) infile = pm_openr(fname);
Packit 78deda
    else       infile = stdin;
Packit 78deda
Packit 78deda
    bits = pbm_readpbm(infile, &nInCols, &nInRows);
Packit 78deda
    
Packit 78deda
    nOutRowsUnrounded = bScale ? nInRows/2 : nInRows;
Packit 78deda
Packit 38c941
    overflow_add(nOutRowsUnrounded, 3);
Packit 78deda
    nOutRows = ((nOutRowsUnrounded + 3) / 4) * 4;
Packit 78deda
        /* MDA wants rows a multiple of 4 */   
Packit 78deda
    nOutCols = nInCols / 8;
Packit 78deda
Packit 78deda
    rc = fwrite(header, 1, 128, stdout);
Packit 78deda
    if (rc < 128)
Packit 78deda
        pm_error("Unable to write header to output file.  errno=%d (%s)",
Packit 78deda
                 errno, strerror(errno));
Packit 78deda
Packit 78deda
    pm_writelittleshort(stdout, nOutRows);
Packit 78deda
    pm_writelittleshort(stdout, nOutCols);
Packit 78deda
Packit 78deda
    do_translation(bits, nOutCols, nOutRows, nInRows);
Packit 78deda
Packit 78deda
    pm_close(infile);
Packit 78deda
    fflush(stdout);
Packit 78deda
    pbm_freearray(bits, nInRows);
Packit 78deda
    
Packit 78deda
    return 0;
Packit 78deda
}