about summary refs log tree commit diff
path: root/converter/pbm/mdatopbm.c
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-08-19 03:12:28 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-08-19 03:12:28 +0000
commit1fd361a1ea06e44286c213ca1f814f49306fdc43 (patch)
tree64c8c96cf54d8718847339a403e5e67b922e8c3f /converter/pbm/mdatopbm.c
downloadnetpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.gz
netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.xz
netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.zip
Create Subversion repository
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter/pbm/mdatopbm.c')
-rw-r--r--converter/pbm/mdatopbm.c271
1 files changed, 271 insertions, 0 deletions
diff --git a/converter/pbm/mdatopbm.c b/converter/pbm/mdatopbm.c
new file mode 100644
index 00000000..d8e06572
--- /dev/null
+++ b/converter/pbm/mdatopbm.c
@@ -0,0 +1,271 @@
+
+/***************************************************************************
+
+    MDATOPBM: Convert Microdesign area to portable bitmap
+    Copyright (C) 1999 John Elliott <jce@seasip.demon.co.uk>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    See the file mdaspec.txt for a specification of the MDA format.
+******************************************************************************/
+
+#include <string.h>
+#include <stdio.h>
+#include "pbm.h"
+#include "mallocvar.h"
+
+/* Simple MDA -> portable bitmap converter */
+
+typedef unsigned char mdbyte;   /* Must be exactly one byte */
+
+static FILE *infile;            /* Input file */
+static mdbyte header[128];      /* MDA file header */
+static bit **data;          /* PBM image */
+static mdbyte *mdrow;           /* MDA row after decompression (MD3 only) */
+static int bInvert = 0;     /* Invert image? */
+static int bScale  = 0;     /* Scale image? */
+static int bAscii  = 0;     /* Ouput ASCII PBM? */
+static int nInRows, nInCols;        /* Height, width of input (rows x bytes) */
+static int nOutCols, nOutRows;      /* Height, width of output (rows x bytes) */
+
+static mdbyte 
+getbyte(void) {
+    /* Read a byte from the input stream, with error trapping */
+    int b;
+
+    b = fgetc(infile);
+
+    if (b == EOF) pm_error("Unexpected end of MDA file\n");
+    
+    return (mdbyte)b;
+}
+
+
+
+static void 
+render_byte(int *col, int *xp, int *yp, int b) {
+
+/* Convert a byte to 8 cells in the destination bitmap 
+ *
+ * *col = source column
+ * *xp  = destination column
+ * *yp  = destination row
+ *  b   = byte to draw
+ *
+ * Will update *col, *xp and *yp to point to the next bit of the row.
+ */
+
+    int mask = 0x80;
+    int n;
+    int y3 = *yp;
+
+    if (bScale) y3 *= 2;
+
+    if (y3 >= nOutRows) return;
+
+    for (n = 0; n < 8; ++n) {
+        if (bInvert) data[y3][*xp] = (b & mask) ? PBM_BLACK : PBM_WHITE;
+        else         data[y3][*xp] = (b & mask) ? PBM_WHITE : PBM_BLACK;
+        mask = mask >> 1;
+        if (bScale) data[y3+1][*xp] = data[y3][*xp];
+        ++(*xp);
+    }
+    ++(*col);       /* Next byte */
+    if ((*col) >= nInCols) {
+        /* Onto next line? */
+        *col = 0;
+        *xp = 0;
+        ++(*yp);
+    }
+}
+
+
+static void 
+md2_trans(void) {
+    /* Convert a MicroDesign 2 area to PBM */
+    /* MD2 has RLE encoding that may go over */
+
+    int x1, y1, col;    /* multiple lines. */
+    mdbyte b;
+    int c;
+
+    x1 = y1 = col = 0;
+
+    while (y1 < nInRows) {
+        b = getbyte();
+    
+        if (b == 0 || b == 0xFF) {
+            /* RLE sequence */
+            c = getbyte();
+            if (c == 0) c = 256;
+            while (c > 0) { 
+                render_byte(&col, &x1, &y1, b); 
+                --c; 
+            }
+        }
+        else 
+            render_byte(&col, &x1, &y1, b);    /* Not RLE */
+    }
+}
+
+
+
+static void 
+md3_trans(void) {
+    /* Convert MD3 file. MD3 are encoded as rows, and 
+       there are three types. 
+    */
+    int x1, y1, col;
+    mdbyte b;
+    int c, d, n;
+
+    for (y1 = 0; y1 < nInRows; ++y1) {
+        b = getbyte();   /* Row type */
+        switch(b)  {
+        case 0: /* All the same byte */
+            c = getbyte();
+            for (n = 0; n < nInCols; n++) 
+                mdrow[n] = c;
+            break;
+            
+        case 1:      /* Encoded data */
+        case 2: col = 0; /* Encoded as XOR with previous row */
+            while (col < nInCols) {
+                c = getbyte();
+                if (c >= 129) {
+                    /* RLE sequence */
+                    c = 257 - c;
+                    d = getbyte();
+                    for (n = 0; n < c; ++n) {
+                        if (b == 1) 
+                            mdrow[col++] = d;
+                        else 
+                            mdrow[col++] ^= d;
+                    }   
+                } else {
+                    /* not RLE sequence */
+                        ++c;
+                        for (n = 0; n < c; ++n) {
+                            d = getbyte();
+                            if (b == 1) 
+                                mdrow[col++] = d;
+                            else
+                                mdrow[col++] ^= d;
+                        }
+                } 
+            }
+        }
+        /* Row loaded. Convert it. */
+        x1 = 0; col = 0; 
+        for (n = 0; n < nInCols; ++n) {
+            d  = y1;
+            render_byte(&col, &x1, &d, mdrow[n]);
+        }
+    }
+}
+
+
+
+static void 
+usage(char *s) {        
+    printf("mdatopbm v1.00, Copyright (C) 1999 "
+           "John Elliott <jce@seasip.demon.co.uk>\n"
+           "This program is redistributable under the terms of "
+           "the GNU General Public\n"
+           "License, version 2 or later.\n\n"
+           "Usage: %s [ -a ] [ -d ] [ -i ] [ -- ] [ infile ]\n\n"
+           "-a: Output an ASCII pbm file\n"
+           "-d: Double height (to compensate for the PCW aspect ratio)\n"
+           "-i: Invert colors\n"
+           "--: No more options (use if filename begins with a dash)\n",
+           s);
+
+    exit(0);
+}
+
+
+
+int 
+main(int argc, char **argv) {
+    int n, optstop = 0;
+    char *fname = NULL;
+
+    pbm_init(&argc, argv);
+
+    /* Parse options */
+
+    for (n = 1; n < argc; ++n) {
+        if (argv[n][0] == '-' && !optstop) {   
+            if (argv[n][1] == 'a' || argv[n][1] == 'A') bAscii = 1;
+            if (argv[n][1] == 'd' || argv[n][1] == 'D') bScale = 1;
+            if (argv[n][1] == 'i' || argv[n][1] == 'I') bInvert = 1;
+            if (argv[n][1] == 'h' || argv[n][1] == 'H') usage(argv[0]);
+            if (argv[n][1] == '-' && argv[n][2] == 0 && !fname) {
+                /* "--" */
+                optstop = 1;
+            }
+            if (argv[n][1] == '-' && (argv[n][2] == 'h' || argv[n][2] == 'H'))
+                usage(argv[0]);
+        }
+        else if (argv[n][0] && !fname) {
+            /* Filename */
+            fname = argv[n];
+        }
+    }
+
+    if (fname) 
+        infile = pm_openr(fname);
+    else
+        infile = stdin;
+
+    /* Read MDA file header */
+
+    if (fread(header, 1, 128, infile) < 128)
+        pm_error("Not a .MDA file\n");
+
+    if (strncmp((char*) header, ".MDA", 4) && 
+        strncmp((char*) header, ".MDP", 4))
+        pm_error("Not a .MDA file\n");
+
+    {
+        short yy;
+        pm_readlittleshort(infile, &yy); nInRows = yy;
+        pm_readlittleshort(infile, &yy); nInCols = yy;
+    }
+    
+    nOutCols = 8 * nInCols;
+    nOutRows = nInRows;
+    if (bScale) 
+        nOutRows *= 2;
+
+    data = pbm_allocarray(nOutCols, nOutRows);
+    
+    MALLOCARRAY_NOFAIL(mdrow, nInCols);
+
+    if (header[21] == '0') 
+        md2_trans();
+    else
+        md3_trans();
+
+    pbm_writepbm(stdout, data, nInCols*8, nOutRows, bAscii);
+
+    if (infile != stdin) 
+        pm_close(infile);
+    fflush(stdout);
+    pbm_freearray(data, nOutRows);
+    free(mdrow);
+
+    return 0;
+}