about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2010-04-08 02:47:49 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2010-04-08 02:47:49 +0000
commit7bee81b77d9d3aa55382e652dbe3502f2fd0d9f6 (patch)
tree56e10636d439c6d5afb04ff11ca300e688c4cb80
parent8cfba0404e06f030c4f0ef45f5702f4442769d02 (diff)
downloadnetpbm-mirror-7bee81b77d9d3aa55382e652dbe3502f2fd0d9f6.tar.gz
netpbm-mirror-7bee81b77d9d3aa55382e652dbe3502f2fd0d9f6.tar.xz
netpbm-mirror-7bee81b77d9d3aa55382e652dbe3502f2fd0d9f6.zip
cleanup
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1180 9d0c8265-081b-0410-96cb-a4ca84ce46f8
-rw-r--r--converter/pbm/pbmtoascii.c208
1 files changed, 150 insertions, 58 deletions
diff --git a/converter/pbm/pbmtoascii.c b/converter/pbm/pbmtoascii.c
index 3f060a7b..fd590aa6 100644
--- a/converter/pbm/pbmtoascii.c
+++ b/converter/pbm/pbmtoascii.c
@@ -10,9 +10,33 @@
 ** implied warranty.
 */
 
+#include <assert.h>
 #include "mallocvar.h"
 #include "pbm.h"
 
+/*
+  The algorithm is based on describing the 2 or 8 pixels in a cell with a
+  single integer called a signature, which we use as an index into an array to
+  get the character whose glyph best matches those pixels.  The encoding is as
+  follows.  Make a string of bits, with each bit being one pixel of the cell,
+  1 = black, 0 = white.  The order of the string is left to right across the
+  top row, then the next row down, etc.  Considering that string to be a
+  binary cipher, the integer it represents is the signature.
+
+  Example: the 2x4 cell consists of these pixels: (* = black)
+
+      * *
+      *
+
+        *
+  The bit string to represent this is 11100001.  So the signature for this
+  cell is the integer 0xE1 (225).
+
+  You index the array carr2x4 with 0xE1, and get '?' as the character to
+  represent that cell.  (We don't really try very hard to match the shape;
+  it's mostly important to match the density).
+*/
+
 #define SQQ '\''
 #define BSQ '\\'
 
@@ -38,44 +62,141 @@ static char const carr1x2[4] = {
 #define D04 '?'
 static char const carr2x4[256] = {
 /*0  1    2   3    4   5    6   7    8   9    A   B    C   D    E   F  */
-' ',SQQ, '`','"', '-',SQQ, SQQ,SQQ, '-','`', '`','`', '-','^', '^','"',/*00-0F*/
-'.',':', ':',':', '|','|', '/',D04, '/','>', '/','>', '~','+', '/','*',/*10-1F*/
-'.',':', ':',':', BSQ,BSQ, '<','<', '|',BSQ, '|',D04, '~',BSQ, '+','*',/*20-2F*/
-'-',':', ':',':', '~',D04, '<','<', '~','>', D04,'>', '=','b', 'd','#',/*30-3F*/
-'.',':', ':',':', ':','!', '/',D04, ':',':', '/',D04, ':',D04, D04,'P',/*40-4F*/
-',','i', '/',D04, '|','|', '|','T', '/',D04, '/','7', 'r','}', '/','P',/*50-5F*/
-',',':', ';',D04, '>',D04, 'S','S', '/',')', '|','7', '>',D05, D05,D06,/*60-6F*/
-'v',D04, D04,D05, '+','}', D05,'F', '/',D05, '/',D06, 'p','D', D06,D07,/*70-7F*/
-'.',':', ':',':', ':',BSQ, ':',D04, ':',BSQ, '!',D04, ':',D04, D04,D05,/*80-8F*/
-BSQ,BSQ, ':',D04, BSQ,'|', '(',D05, '<','%', D04,'Z', '<',D05, D05,D06,/*90-9F*/
-',',BSQ, 'i',D04, BSQ,BSQ, D04,BSQ, '|','|', '|','T', D04,BSQ, '4','9',/*A0-AF*/
-'v',D04, D04,D05, BSQ,BSQ, D05,D06, '+',D05, '{',D06, 'q',D06, D06,D07,/*B0-BF*/
-'_',':', ':',D04, ':',D04, D04,D05, ':',D04, D04,D05, ':',D05, D05,D06,/*C0-CF*/
-BSQ,D04, D04,D05, D04,'L', D05,'[', '<','Z', '/','Z', 'c','k', D06,'R',/*D0-DF*/
-',',D04, D04,D05, '>',BSQ, 'S','S', D04,D05, 'J',']', '>',D06, '1','9',/*E0-EF*/
-'o','b', 'd',D06, 'b','b', D06,'6', 'd',D06, 'd',D07, '#',D07, D07,D08 /*F0-FF*/
+' ',SQQ, '`','"', '-',SQQ, SQQ,SQQ, '-','`', '`','`', '-','^','^','"',/*00-0F*/
+'.',':', ':',':', '|','|', '/',D04, '/','>', '/','>', '~','+','/','*',/*10-1F*/
+'.',':', ':',':', BSQ,BSQ, '<','<', '|',BSQ, '|',D04, '~',BSQ,'+','*',/*20-2F*/
+'-',':', ':',':', '~',D04, '<','<', '~','>', D04,'>', '=','b','d','#',/*30-3F*/
+'.',':', ':',':', ':','!', '/',D04, ':',':', '/',D04, ':',D04,D04,'P',/*40-4F*/
+',','i', '/',D04, '|','|', '|','T', '/',D04, '/','7', 'r','}','/','P',/*50-5F*/
+',',':', ';',D04, '>',D04, 'S','S', '/',')', '|','7', '>',D05,D05,D06,/*60-6F*/
+'v',D04, D04,D05, '+','}', D05,'F', '/',D05, '/',D06, 'p','D',D06,D07,/*70-7F*/
+'.',':', ':',':', ':',BSQ, ':',D04, ':',BSQ, '!',D04, ':',D04,D04,D05,/*80-8F*/
+BSQ,BSQ, ':',D04, BSQ,'|', '(',D05, '<','%', D04,'Z', '<',D05,D05,D06,/*90-9F*/
+',',BSQ, 'i',D04, BSQ,BSQ, D04,BSQ, '|','|', '|','T', D04,BSQ,'4','9',/*A0-AF*/
+'v',D04, D04,D05, BSQ,BSQ, D05,D06, '+',D05, '{',D06, 'q',D06,D06,D07,/*B0-BF*/
+'_',':', ':',D04, ':',D04, D04,D05, ':',D04, D04,D05, ':',D05,D05,D06,/*C0-CF*/
+BSQ,D04, D04,D05, D04,'L', D05,'[', '<','Z', '/','Z', 'c','k',D06,'R',/*D0-DF*/
+',',D04, D04,D05, '>',BSQ, 'S','S', D04,D05, 'J',']', '>',D06,'1','9',/*E0-EF*/
+'o','b', 'd',D06, 'b','b', D06,'6', 'd',D06, 'd',D07, '#',D07,D07,D08 /*F0-FF*/
 };
 
 
 
 static void
+makeRowOfSigs(FILE *         const ifP,
+              unsigned int   const cols,
+              unsigned int   const rows,
+              int            const format,
+              unsigned int   const cellWidth,
+              unsigned int   const cellHeight,
+              unsigned int   const row,
+              unsigned int * const sig,
+              unsigned int   const ccols) {
+/*----------------------------------------------------------------------------
+   Compute the signatures for every cell in a row.
+
+   Read the pixels from *ifP, which is positioned to the first pixel row
+   of the cell row, which is row number 'row'.  The image dimensions are
+   'cols' x 'rows' pixels.
+
+   Each cell is 'cellWidth' x 'cellHeight'.
+
+   Return the signatures as sig[], which is 'ccols' wide because that's how
+   many cells you get from 'cols' pixels divided into cells 'cellWidth' pixels
+   wide.
+-----------------------------------------------------------------------------*/
+    unsigned int b;
+    unsigned int subrow;  /* row within cell */
+    bit * bitrow;        /* malloc'ed array */
+
+    bitrow = pbm_allocrow(cols);
+    {
+        unsigned int col;
+        for (col = 0; col < ccols; ++col)
+            sig[col] = 0;
+    }
+
+    b = 0x1;  /* initial value */
+    for (subrow = 0; subrow < cellHeight; ++subrow) {
+        if (row + subrow < rows) {
+            unsigned int subcol;  /* col within cell */
+            pbm_readpbmrow(ifP, bitrow, cols, format);
+            for (subcol = 0; subcol < cellWidth; ++subcol) {
+                unsigned int col, ccol;
+                for (col = subcol, ccol = 0;
+                     col < cols;
+                     col += cellWidth, ++ccol) {
+                    if (bitrow[col] == PBM_BLACK)
+                        sig[ccol] |= b;
+                }
+                b <<= 1;
+            }
+        }
+    }
+    pbm_freerow(bitrow);
+}
+
+
+
+static void
+findRightMargin(const unsigned int * const sig,
+                unsigned int         const ccols,
+                const char *         const carr,
+                unsigned int *       const endColP) {
+/*----------------------------------------------------------------------------
+   Find the first cell of the right margin, i.e. a contiguous set of
+   all-white cells at the right end of the row.
+-----------------------------------------------------------------------------*/
+    unsigned int endcol;
+
+    for (endcol = ccols; endcol > 0; --endcol) {
+        if (carr[sig[endcol-1]] != ' ')
+            break;
+    }
+    *endColP = endcol;
+}
+
+
+
+static void
+assembleCellRow(const unsigned int * const sig,
+                unsigned int         const ccols,
+                const char *         const carr,
+                char *               const line) {
+/*----------------------------------------------------------------------------
+   Return as line[] the line of ASCII codes for the characters of one
+   row of cells, ready for printing.
+-----------------------------------------------------------------------------*/
+    unsigned int col;
+
+    for (col = 0; col < ccols; ++col)
+        line[col] = carr[sig[col]];
+
+    line[ccols] = '\0';
+}
+
+
+
+static void
 pbmtoascii(FILE *       const ifP,
-           unsigned int const gridx,
-           unsigned int const gridy,
+           unsigned int const cellWidth,
+           unsigned int const cellHeight,
            const char * const carr) {
 
     int cols, rows, format;
     unsigned int ccols;
-    bit * bitrow;        /* malloc'ed array */
     char * line;         /* malloc'ed array */
     unsigned int row;
     unsigned int * sig;  /* malloc'ed array */
+        /* This describes in a single integer the pixels of a cell,
+           as described above.
+        */
+    assert(cellWidth * cellHeight <= sizeof(sig[0]*8));
 
     pbm_readpbminit(ifP, &cols, &rows, &format);
 
-    ccols = (cols + gridx - 1) / gridx;
+    ccols = (cols + cellWidth - 1) / cellWidth;
 
-    bitrow = pbm_allocrow(cols);
     MALLOCARRAY(sig, ccols);
     if (sig == NULL)
         pm_error("No memory for %u columns", ccols);
@@ -83,47 +204,18 @@ pbmtoascii(FILE *       const ifP,
     if (line == NULL)
         pm_error("No memory for %u columns", ccols);
 
-    for (row = 0; row < rows; row += gridy) {
-        /* Get a character-row's worth of sigs. */
-        unsigned int b;
-        unsigned int subrow;
+    for (row = 0; row < rows; row += cellHeight) {
+        unsigned int endCol;
 
-        {
-            unsigned int col;
-            for (col = 0; col < ccols; ++col)
-                sig[col] = 0;
-        }
+        makeRowOfSigs(ifP, cols, rows, format, cellWidth, cellHeight,
+                      row, sig, ccols);
+
+        findRightMargin(sig, ccols, carr, &endCol);
+
+        assembleCellRow(sig, endCol, carr, line);
 
-        b = 1;
-        for (subrow = 0; subrow < gridy; ++subrow) {
-            if (row + subrow < rows) {
-                unsigned int subcol;
-                pbm_readpbmrow(ifP, bitrow, cols, format);
-                for (subcol = 0; subcol < gridx; ++subcol) {
-                    unsigned int col, s;
-                    for (col = subcol, s = 0; col < cols; col += gridx, ++s) {
-                        if (bitrow[col] == PBM_BLACK)
-                            sig[s] |= b;
-                    }
-                    b <<= 1;
-                }
-            }
-        }
-        {
-            /* Ok, now remove trailing blanks.  */
-            unsigned int col;
-            unsigned int endcol;
-            for (endcol = ccols; endcol > 0; --endcol)
-                if (carr[sig[endcol-1]] != ' ')
-                    break;
-            /* Copy chars to an array and print. */
-            for (col = 0; col < endcol; ++col)
-                line[col] = carr[sig[col]];
-            line[endcol] = '\0';
-        }
         puts(line);
     }
-    pbm_freerow(bitrow);
     free(sig);
     free(line);
 }