From 7bee81b77d9d3aa55382e652dbe3502f2fd0d9f6 Mon Sep 17 00:00:00 2001 From: giraffedata Date: Thu, 8 Apr 2010 02:47:49 +0000 Subject: cleanup git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1180 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- converter/pbm/pbmtoascii.c | 208 ++++++++++++++++++++++++++++++++------------- 1 file 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 #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); } -- cgit 1.4.1