about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2010-10-23 18:56:40 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2010-10-23 18:56:40 +0000
commit3b85c09e19ebdd0f54e49d1626f0bef0edd8ec5d (patch)
tree1620cd09b59a06890552f21ea851fac5c5932025
parentb58715c62b6e24e61fdee85417fbf5528af46605 (diff)
downloadnetpbm-mirror-3b85c09e19ebdd0f54e49d1626f0bef0edd8ec5d.tar.gz
netpbm-mirror-3b85c09e19ebdd0f54e49d1626f0bef0edd8ec5d.tar.xz
netpbm-mirror-3b85c09e19ebdd0f54e49d1626f0bef0edd8ec5d.zip
Use packed bits, work with 32 bit items, work with Depth=8
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1341 9d0c8265-081b-0410-96cb-a4ca84ce46f8
-rw-r--r--converter/pbm/icontopbm.c228
1 files changed, 120 insertions, 108 deletions
diff --git a/converter/pbm/icontopbm.c b/converter/pbm/icontopbm.c
index a0d1bd2b..bad47c24 100644
--- a/converter/pbm/icontopbm.c
+++ b/converter/pbm/icontopbm.c
@@ -10,150 +10,162 @@
 ** implied warranty.
 */
 
+/*
+  Most icon images are monochrome: Depth=1
+  Depth=8 images are extremely rare.  At least some of these are color
+  images but we can't tell the pallete color order.
+  Output will be in pgm.  Convert to ppm with pgmtoppm or pamlookup
+  if necessary.
+*/
+
+#include <assert.h>
 #include <string.h>
 
 #include "nstring.h"
 #include "pbm.h"
+#include "pgm.h"
+
 
-/* size in bytes of a bitmap */
-#define BitmapSize(width, height) (((((width) + 15) >> 3) &~ 1) * (height))
 
 static void
-ReadIconFile(FILE *                const file, 
-             int *                 const widthP, 
-             int *                 const heightP, 
-             short unsigned int ** const dataP) {
+ReadIconFileHeader(FILE * const file, 
+                   int *  const widthP, 
+                   int *  const heightP, 
+                   int *  const depthP,
+                   int *  const bitsPerItemP) {
 
-    char variable[80+1];
-    int ch;
-    int status, value, i, data_length, gotsome;
+    unsigned int fieldCt;
 
-    gotsome = 0;
+    fieldCt = 0;
     *widthP = *heightP = -1;
-    for ( ; ; )
-    {
-        while ( ( ch = getc( file ) ) == ',' || ch == '\n' || ch == '\t' ||
-                ch == ' ' )
+
+    for ( ; ; ) {
+        char variable[80+1];
+        int ch;
+        unsigned int i;
+        int value;
+
+        while ((ch = getc(file)) == ',' || ch == '\n' || ch == '\t' ||
+                ch == ' ')
             ;
-        for ( i = 0;
-              ch != '=' && ch != ',' && ch != '\n' && ch != '\t' && 
-                  ch != ' ' && (i < (sizeof(variable) - 1));
-              i++ )
-        {
+        for (i = 0;
+             ch != '=' && ch != ',' && ch != '\n' && ch != '\t' && 
+                 ch != ' ' && (i < (sizeof(variable) - 1));
+             ++i) {
             variable[i] = ch;
             if ((ch = getc( file )) == EOF)
                 pm_error( "invalid input file -- premature EOF" );
         }
         variable[i] = '\0';
 
-        if ( streq( variable, "*/" )&& gotsome )
+        if (streq(variable, "*/") && fieldCt > 0)
             break;
 
-        if ( fscanf( file, "%d", &value ) != 1 )
+        if (fscanf( file, "%d", &value ) != 1)
             continue;
 
-        if ( streq( variable, "Width" ) )
-        {
+        if (streq( variable, "Width")) {
             *widthP = value;
-            gotsome = 1;
-        }
-        else if ( streq( variable, "Height" ) )
-        {
+            ++fieldCt;
+        } else if (streq( variable, "Height")) {
             *heightP = value;
-            gotsome = 1;
-        }
-        else if ( streq( variable, "Depth" )  )
-        {
-            if ( value != 1 )
-                pm_error( "invalid depth" );
-            gotsome = 1;
-        }
-        else if ( streq( variable, "Format_version" ) )
-        {
-            if ( value != 1 )
-                pm_error( "invalid Format_version" );
-            gotsome = 1;
-        }
-        else if ( streq( variable, "Valid_bits_per_item" ) )
-        {
-            if ( value != 16 )
-                pm_error( "invalid Valid_bits_per_item" );
-            gotsome = 1;
+            ++fieldCt;
+        } else if (streq( variable, "Depth")) {
+            if (value != 1 && value != 8)
+                pm_error("invalid depth");
+            *depthP = value;
+            ++fieldCt;
+        } else if (streq(variable, "Format_version")) {
+            if (value != 1)
+                pm_error("invalid Format_version");
+            ++fieldCt;
+        } else if (streq(variable, "Valid_bits_per_item")) {
+            if (value != 16 && value !=32)
+                pm_error("invalid Valid_bits_per_item");
+            *bitsPerItemP = value; 
+            ++fieldCt;
         }
     }
 
-    if ( *widthP <= 0 )
-        pm_error( "invalid width (must be positive): %d", *widthP );
-    if ( *heightP <= 0 )
-        pm_error( "invalid height (must be positive): %d", *heightP );
-
-    data_length = BitmapSize( *widthP, *heightP );
-    *dataP = (short unsigned int *) malloc( data_length );
-    if ( *dataP == NULL )
-        pm_error( "out of memory" );
-    data_length /= sizeof( short );
-    
-    for ( i = 0 ; i < data_length; i++ )
-    {
-        if ( i == 0 )
-            status = fscanf( file, " 0x%4hx", *dataP );
-        else
-            status = fscanf( file, ", 0x%4hx", *dataP + i );
-        if ( status != 1 )
-            pm_error( "error 4 scanning bits item" );
-    }
-}
+    if (fieldCt < 5)
+        pm_error("invalid sun icon file header: "
+                 "only %u out of required 5 fields present", fieldCt);
 
+    if (*widthP <= 0)
+        pm_error("invalid width (must be positive): %d", *widthP);
+    if (*heightP <= 0)
+        pm_error("invalid height (must be positive): %d", *heightP);
 
+}
 
-int
-main(int  argc, char ** argv) {
 
-    FILE* ifp;
-    bit* bitrow;
-    register bit* bP;
-    int rows, cols, row, col, shortcount, mask;
-    short unsigned int * data;
+int
+main(int argc, const char ** argv) {
 
+    FILE * ifP;
+    bit * bitrow;
+    gray * grayrow;
+    int rows, cols, depth, row, format, maxval, colChars, bitsPerItem;
 
-    pbm_init( &argc, argv );
+    pm_proginit(&argc, argv);
 
-    if ( argc > 2 )
-        pm_usage( "[iconfile]" );
+    if (argc-1 > 1)
+        pm_error("Too many arguments (%u).  Program takes at most one: "
+                 "name of input file", argc-1);
 
-    if ( argc == 2 )
-        ifp = pm_openr( argv[1] );
+    if (argc-1 == 1)
+        ifP = pm_openr(argv[1]);
     else
-        ifp = stdin;
-
-    ReadIconFile( ifp, &cols, &rows, &data );
-
-    pm_close( ifp );
-
-    pbm_writepbminit( stdout, cols, rows, 0 );
-    bitrow = pbm_allocrow( cols );
-
-    for ( row = 0; row < rows; row++ )
-    {
-        shortcount = 0;
-        mask = 0x8000;
-        for ( col = 0, bP = bitrow; col < cols; col++, bP++ )
-        {
-            if ( shortcount >= 16 )
-            {
-                data++;
-                shortcount = 0;
-                mask = 0x8000;
-            }
-            *bP = ( *data & mask ) ? PBM_BLACK : PBM_WHITE;
-            shortcount++;
-            mask = mask >> 1;
+        ifP = stdin;
+
+    ReadIconFileHeader(ifP, &cols, &rows, &depth, &bitsPerItem);
+
+    if (depth == 1) {
+        format = PBM_TYPE;
+        maxval = 1;
+        pbm_writepbminit(stdout, cols, rows, 0);
+        bitrow = pbm_allocrow_packed(cols);
+        colChars = cols / 8;
+    } else {
+        assert(depth == 8);
+        format = PGM_TYPE;
+        maxval = 255;
+        grayrow = pgm_allocrow(cols);
+        colChars = cols / depth;
+    }
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int colChar;
+        for (colChar = 0; colChar < colChars; ++colChar) {
+            unsigned int data;
+            int status;
+
+            /* read 8 bits */
+            if (row==0 && colChar == 0)
+                status = fscanf(ifP, " 0x%2x", &data);
+            else if (colChar % (bitsPerItem/8) == 0)
+                status = fscanf(ifP, ", 0x%2x", &data);
+            else
+                status = fscanf(ifP, "%2x", &data);
+
+            /* write 8 bits */
+            if (status == 1) {
+                if (format == PBM_TYPE)
+                    bitrow[colChar]  = data;
+                else
+                    grayrow[colChar] = data;
+            } else
+                pm_error("error scanning bits item %u" , colChar);
         }
-        data++;
-        pbm_writepbmrow( stdout, bitrow, cols, 0 );
+
+        /* output row */
+        if (format == PBM_TYPE)
+            pbm_writepbmrow_packed(stdout, bitrow, cols, 0);
+        else
+            pgm_writepgmrow(stdout, grayrow, cols, maxval, 0);
     }
 
-    pm_close( stdout );
-    exit( 0 );
+    pm_close(ifP);
+    pm_close(stdout);
+    return 0;
 }
-