Blame converter/pbm/mdatopbm.c

Packit 78deda
Packit 78deda
/***************************************************************************
Packit 78deda
Packit 78deda
    MDATOPBM: Convert Microdesign area to portable bitmap
Packit 78deda
    Copyright (C) 1999 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
    See the file mdaspec.txt for a specification of the MDA format.
Packit 78deda
******************************************************************************/
Packit 78deda
Packit 78deda
#include <string.h>
Packit 78deda
#include <stdio.h>
Packit 78deda
#include "pbm.h"
Packit 78deda
#include "mallocvar.h"
Packit 78deda
Packit 78deda
/* Simple MDA -> portable bitmap converter */
Packit 78deda
Packit 78deda
typedef unsigned char mdbyte;   /* Must be exactly one byte */
Packit 78deda
Packit 78deda
static FILE *infile;            /* Input file */
Packit 78deda
static mdbyte header[128];      /* MDA file header */
Packit 78deda
static bit **data;          /* PBM image */
Packit 78deda
static mdbyte *mdrow;           /* MDA row after decompression (MD3 only) */
Packit 78deda
static int bInvert = 0;     /* Invert image? */
Packit 78deda
static int bScale  = 0;     /* Scale image? */
Packit 78deda
static int bAscii  = 0;     /* Ouput ASCII PBM? */
Packit 78deda
static int nInRows, nInCols;        /* Height, width of input (rows x bytes) */
Packit 78deda
static int nOutCols, nOutRows;      /* Height, width of output (rows x bytes) */
Packit 78deda
Packit 78deda
static mdbyte 
Packit 78deda
getbyte(void) {
Packit 78deda
    /* Read a byte from the input stream, with error trapping */
Packit 78deda
    int b;
Packit 78deda
Packit 78deda
    b = fgetc(infile);
Packit 78deda
Packit 78deda
    if (b == EOF) pm_error("Unexpected end of MDA file\n");
Packit 78deda
    
Packit 78deda
    return (mdbyte)b;
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
static void 
Packit 78deda
render_byte(int *col, int *xp, int *yp, int b) {
Packit 78deda
Packit 78deda
/* Convert a byte to 8 cells in the destination bitmap 
Packit 78deda
 *
Packit 78deda
 * *col = source column
Packit 78deda
 * *xp  = destination column
Packit 78deda
 * *yp  = destination row
Packit 78deda
 *  b   = byte to draw
Packit 78deda
 *
Packit 78deda
 * Will update *col, *xp and *yp to point to the next bit of the row.
Packit 78deda
 */
Packit 78deda
Packit 78deda
    int mask = 0x80;
Packit 78deda
    int n;
Packit 78deda
    int y3 = *yp;
Packit 78deda
Packit 78deda
    if (bScale) y3 *= 2;
Packit 78deda
Packit 78deda
    if (y3 >= nOutRows) return;
Packit 78deda
Packit 78deda
    for (n = 0; n < 8; ++n) {
Packit 78deda
        if (bInvert) data[y3][*xp] = (b & mask) ? PBM_BLACK : PBM_WHITE;
Packit 78deda
        else         data[y3][*xp] = (b & mask) ? PBM_WHITE : PBM_BLACK;
Packit 78deda
        mask = mask >> 1;
Packit 78deda
        if (bScale) data[y3+1][*xp] = data[y3][*xp];
Packit 78deda
        ++(*xp);
Packit 78deda
    }
Packit 78deda
    ++(*col);       /* Next byte */
Packit 78deda
    if ((*col) >= nInCols) {
Packit 78deda
        /* Onto next line? */
Packit 78deda
        *col = 0;
Packit 78deda
        *xp = 0;
Packit 78deda
        ++(*yp);
Packit 78deda
    }
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
static void 
Packit 78deda
md2_trans(void) {
Packit 78deda
    /* Convert a MicroDesign 2 area to PBM */
Packit 78deda
    /* MD2 has RLE encoding that may go over */
Packit 78deda
Packit 78deda
    int x1, y1, col;    /* multiple lines. */
Packit 78deda
    mdbyte b;
Packit 78deda
    int c;
Packit 78deda
Packit 78deda
    x1 = y1 = col = 0;
Packit 78deda
Packit 78deda
    while (y1 < nInRows) {
Packit 78deda
        b = getbyte();
Packit 78deda
    
Packit 78deda
        if (b == 0 || b == 0xFF) {
Packit 78deda
            /* RLE sequence */
Packit 78deda
            c = getbyte();
Packit 78deda
            if (c == 0) c = 256;
Packit 78deda
            while (c > 0) { 
Packit 78deda
                render_byte(&col, &x1, &y1, b); 
Packit 78deda
                --c; 
Packit 78deda
            }
Packit 78deda
        }
Packit 78deda
        else 
Packit 78deda
            render_byte(&col, &x1, &y1, b);    /* Not RLE */
Packit 78deda
    }
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
static void 
Packit 78deda
md3_trans(void) {
Packit 78deda
    /* Convert MD3 file. MD3 are encoded as rows, and 
Packit 78deda
       there are three types. 
Packit 78deda
    */
Packit 78deda
    int x1, y1, col;
Packit 78deda
    mdbyte b;
Packit 78deda
    int c, d, n;
Packit 78deda
Packit 78deda
    for (y1 = 0; y1 < nInRows; ++y1) {
Packit 78deda
        b = getbyte();   /* Row type */
Packit 78deda
        switch(b)  {
Packit 78deda
        case 0: /* All the same byte */
Packit 78deda
            c = getbyte();
Packit 78deda
            for (n = 0; n < nInCols; n++) 
Packit 78deda
                mdrow[n] = c;
Packit 78deda
            break;
Packit 78deda
            
Packit 78deda
        case 1:      /* Encoded data */
Packit 78deda
        case 2: col = 0; /* Encoded as XOR with previous row */
Packit 78deda
            while (col < nInCols) {
Packit 78deda
                c = getbyte();
Packit 78deda
                if (c >= 129) {
Packit 78deda
                    /* RLE sequence */
Packit 78deda
                    c = 257 - c;
Packit 78deda
                    d = getbyte();
Packit 78deda
                    for (n = 0; n < c; ++n) {
Packit 78deda
                        if (b == 1) 
Packit 78deda
                            mdrow[col++] = d;
Packit 78deda
                        else 
Packit 78deda
                            mdrow[col++] ^= d;
Packit 78deda
                    }   
Packit 78deda
                } else {
Packit 78deda
                    /* not RLE sequence */
Packit 78deda
                        ++c;
Packit 78deda
                        for (n = 0; n < c; ++n) {
Packit 78deda
                            d = getbyte();
Packit 78deda
                            if (b == 1) 
Packit 78deda
                                mdrow[col++] = d;
Packit 78deda
                            else
Packit 78deda
                                mdrow[col++] ^= d;
Packit 78deda
                        }
Packit 78deda
                } 
Packit 78deda
            }
Packit 78deda
        }
Packit 78deda
        /* Row loaded. Convert it. */
Packit 78deda
        x1 = 0; col = 0; 
Packit 78deda
        for (n = 0; n < nInCols; ++n) {
Packit 78deda
            d  = y1;
Packit 78deda
            render_byte(&col, &x1, &d, mdrow[n]);
Packit 78deda
        }
Packit 78deda
    }
Packit 78deda
}
Packit 78deda
Packit 78deda
Packit 78deda
Packit 78deda
static void 
Packit 78deda
usage(char *s) {        
Packit 78deda
    printf("mdatopbm v1.00, Copyright (C) 1999 "
Packit 78deda
           "John Elliott <jce@seasip.demon.co.uk>\n"
Packit 78deda
           "This program is redistributable under the terms of "
Packit 78deda
           "the GNU General Public\n"
Packit 78deda
           "License, version 2 or later.\n\n"
Packit 78deda
           "Usage: %s [ -a ] [ -d ] [ -i ] [ -- ] [ infile ]\n\n"
Packit 78deda
           "-a: Output an ASCII pbm file\n"
Packit 78deda
           "-d: Double 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
Packit 78deda
Packit 78deda
int 
Packit 78deda
main(int argc, char **argv) {
Packit 78deda
    int n, optstop = 0;
Packit 78deda
    char *fname = NULL;
Packit 78deda
Packit 78deda
    pbm_init(&argc, argv);
Packit 78deda
Packit 78deda
    /* Parse options */
Packit 78deda
Packit 78deda
    for (n = 1; n < argc; ++n) {
Packit 78deda
        if (argv[n][0] == '-' && !optstop) {   
Packit 78deda
            if (argv[n][1] == 'a' || argv[n][1] == 'A') bAscii = 1;
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'))
Packit 78deda
                usage(argv[0]);
Packit 78deda
        }
Packit 78deda
        else if (argv[n][0] && !fname) {
Packit 78deda
            /* Filename */
Packit 78deda
            fname = argv[n];
Packit 78deda
        }
Packit 78deda
    }
Packit 78deda
Packit 78deda
    if (fname) 
Packit 78deda
        infile = pm_openr(fname);
Packit 78deda
    else
Packit 78deda
        infile = stdin;
Packit 78deda
Packit 78deda
    /* Read MDA file header */
Packit 78deda
Packit 78deda
    if (fread(header, 1, 128, infile) < 128)
Packit 78deda
        pm_error("Not a .MDA file\n");
Packit 78deda
Packit 78deda
    if (strncmp((char*) header, ".MDA", 4) && 
Packit 78deda
        strncmp((char*) header, ".MDP", 4))
Packit 78deda
        pm_error("Not a .MDA file\n");
Packit 78deda
Packit 78deda
    {
Packit 78deda
        short yy;
Packit 78deda
        pm_readlittleshort(infile, &yy;; nInRows = yy;
Packit 78deda
        pm_readlittleshort(infile, &yy;; nInCols = yy;
Packit 78deda
    }
Packit 78deda
    
Packit 78deda
    nOutCols = 8 * nInCols;
Packit 78deda
    nOutRows = nInRows;
Packit Service 2370ca
    if (bScale) 
Packit 78deda
        nOutRows *= 2;
Packit 78deda
Packit 78deda
    data = pbm_allocarray(nOutCols, nOutRows);
Packit 78deda
    
Packit 78deda
    MALLOCARRAY_NOFAIL(mdrow, nInCols);
Packit 78deda
Packit 78deda
    if (header[21] == '0') 
Packit 78deda
        md2_trans();
Packit 78deda
    else
Packit 78deda
        md3_trans();
Packit 78deda
Packit 78deda
    pbm_writepbm(stdout, data, nInCols*8, nOutRows, bAscii);
Packit 78deda
Packit 78deda
    if (infile != stdin) 
Packit 78deda
        pm_close(infile);
Packit 78deda
    fflush(stdout);
Packit 78deda
    pbm_freearray(data, nOutRows);
Packit 78deda
    free(mdrow);
Packit 78deda
Packit 78deda
    return 0;
Packit 78deda
}