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