Imported Upstream version 1.6.13
[platform/upstream/libpng.git] / contrib / pngminus / pnm2png.c
index 4cdfad8..b073414 100644 (file)
@@ -18,6 +18,7 @@
 #include <mem.h>
 #include <fcntl.h>
 #endif
+#include <zlib.h>
 
 #ifndef BOOL
 #define BOOL unsigned char
@@ -49,7 +50,8 @@
 
 int  main (int argc, char *argv[]);
 void usage ();
-BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, BOOL alpha);
+BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace,
+    BOOL alpha);
 void get_token(FILE *pnm_file, char *token);
 png_uint_32 get_data (FILE *pnm_file, int depth);
 png_uint_32 get_value (FILE *pnm_file, int depth);
@@ -175,7 +177,8 @@ void usage()
   fprintf (stderr, "   or:  ... | pnm2png [options]\n");
   fprintf (stderr, "Options:\n");
   fprintf (stderr, "   -i[nterlace]   write png-file with interlacing on\n");
-  fprintf (stderr, "   -a[lpha] <file>.pgm read PNG alpha channel as pgm-file\n");
+  fprintf (stderr,
+      "   -a[lpha] <file>.pgm read PNG alpha channel as pgm-file\n");
   fprintf (stderr, "   -h | -?  print this help-information\n");
 }
 
@@ -183,29 +186,36 @@ void usage()
  *  pnm2png
  */
 
-BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, BOOL alpha)
+BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace,
+     BOOL alpha)
 {
   png_struct    *png_ptr = NULL;
   png_info      *info_ptr = NULL;
   png_byte      *png_pixels = NULL;
   png_byte      **row_pointers = NULL;
   png_byte      *pix_ptr = NULL;
-  png_uint_32   row_bytes;
+  volatile png_uint_32   row_bytes;
 
   char          type_token[16];
   char          width_token[16];
   char          height_token[16];
   char          maxval_token[16];
-  int           color_type;
-  png_uint_32   width, alpha_width;
-  png_uint_32   height, alpha_height;
+  volatile int           color_type;
+  unsigned long   ul_width=0, ul_alpha_width=0;
+  unsigned long   ul_height=0, ul_alpha_height=0;
+  unsigned long   ul_maxval=0;
+  volatile png_uint_32   width, height;
+  volatile png_uint_32   alpha_width, alpha_height;
   png_uint_32   maxval;
-  int           bit_depth = 0;
+  volatile int           bit_depth = 0;
   int           channels;
   int           alpha_depth = 0;
   int           alpha_present;
   int           row, col;
   BOOL          raw, alpha_raw = FALSE;
+#if defined(PNG_WRITE_INVERT_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
+  BOOL          packed_bitmap = FALSE;
+#endif
   png_uint_32   tmp16;
   int           i;
 
@@ -218,20 +228,36 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace,
   }
   else if ((type_token[1] == '1') || (type_token[1] == '4'))
   {
+#if defined(PNG_WRITE_INVERT_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
     raw = (type_token[1] == '4');
     color_type = PNG_COLOR_TYPE_GRAY;
+    get_token(pnm_file, width_token);
+    sscanf (width_token, "%lu", &ul_width);
+    width = (png_uint_32) ul_width;
+    get_token(pnm_file, height_token);
+    sscanf (height_token, "%lu", &ul_height);
+    height = (png_uint_32) ul_height;
     bit_depth = 1;
+    packed_bitmap = TRUE;
+#else
+    fprintf (stderr, "PNM2PNG built without PNG_WRITE_INVERT_SUPPORTED and \n");
+    fprintf (stderr, "PNG_WRITE_PACK_SUPPORTED can't read PBM (P1,P4) files\n");
+#endif
   }
   else if ((type_token[1] == '2') || (type_token[1] == '5'))
   {
     raw = (type_token[1] == '5');
     color_type = PNG_COLOR_TYPE_GRAY;
     get_token(pnm_file, width_token);
-    sscanf (width_token, "%lu", &width);
+    sscanf (width_token, "%lu", &ul_width);
+    width = (png_uint_32) ul_width;
     get_token(pnm_file, height_token);
-    sscanf (height_token, "%lu", &height);
+    sscanf (height_token, "%lu", &ul_height);
+    height = (png_uint_32) ul_height;
     get_token(pnm_file, maxval_token);
-    sscanf (maxval_token, "%lu", &maxval);
+    sscanf (maxval_token, "%lu", &ul_maxval);
+    maxval = (png_uint_32) ul_maxval;
+
     if (maxval <= 1)
       bit_depth = 1;
     else if (maxval <= 3)
@@ -248,11 +274,14 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace,
     raw = (type_token[1] == '6');
     color_type = PNG_COLOR_TYPE_RGB;
     get_token(pnm_file, width_token);
-    sscanf (width_token, "%lu", &width);
+    sscanf (width_token, "%lu", &ul_width);
+    width = (png_uint_32) ul_width;
     get_token(pnm_file, height_token);
-    sscanf (height_token, "%lu", &height);
+    sscanf (height_token, "%lu", &ul_height);
+    height = (png_uint_32) ul_height;
     get_token(pnm_file, maxval_token);
-    sscanf (maxval_token, "%lu", &maxval);
+    sscanf (maxval_token, "%lu", &ul_maxval);
+    maxval = (png_uint_32) ul_maxval;
     if (maxval <= 1)
       bit_depth = 1;
     else if (maxval <= 3)
@@ -287,15 +316,18 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace,
     {
       alpha_raw = (type_token[1] == '5');
       get_token(alpha_file, width_token);
-      sscanf (width_token, "%lu", &alpha_width);
+      sscanf (width_token, "%lu", &ul_alpha_width);
+      alpha_width=(png_uint_32) ul_alpha_width;
       if (alpha_width != width)
         return FALSE;
       get_token(alpha_file, height_token);
-      sscanf (height_token, "%lu", &alpha_height);
+      sscanf (height_token, "%lu", &ul_alpha_height);
+      alpha_height = (png_uint_32) ul_alpha_height;
       if (alpha_height != height)
         return FALSE;
       get_token(alpha_file, maxval_token);
-      sscanf (maxval_token, "%lu", &maxval);
+      sscanf (maxval_token, "%lu", &ul_maxval);
+      maxval = (png_uint_32) ul_maxval;
       if (maxval <= 1)
         alpha_depth = 1;
       else if (maxval <= 3)
@@ -329,51 +361,66 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace,
 
   alpha_present = (channels - 1) % 2;
 
-  /* row_bytes is the width x number of channels x (bit-depth / 8) */
-  row_bytes = width * channels * ((bit_depth <= 8) ? 1 : 2);
+#if defined(PNG_WRITE_INVERT_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
+  if (packed_bitmap)
+    /* row data is as many bytes as can fit width x channels x bit_depth */
+    row_bytes = (width * channels * bit_depth + 7) / 8;
+  else
+#endif
+    /* row_bytes is the width x number of channels x (bit-depth / 8) */
+    row_bytes = width * channels * ((bit_depth <= 8) ? 1 : 2);
 
-  if ((png_pixels = (png_byte *) malloc (row_bytes * height * sizeof (png_byte))) == NULL)
+  if ((png_pixels = (png_byte *)
+     malloc (row_bytes * height * sizeof (png_byte))) == NULL)
     return FALSE;
 
   /* read data from PNM file */
   pix_ptr = png_pixels;
 
-  for (row = 0; row < height; row++)
+  for (row = 0; row < (int) height; row++)
   {
-    for (col = 0; col < width; col++)
+#if defined(PNG_WRITE_INVERT_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
+    if (packed_bitmap) {
+      for (i = 0; i < (int) row_bytes; i++)
+        /* png supports this format natively so no conversion is needed */
+        *pix_ptr++ = get_data (pnm_file, 8);
+    } else
+#endif
     {
-      for (i = 0; i < (channels - alpha_present); i++)
+      for (col = 0; col < (int) width; col++)
       {
-        if (raw)
-          *pix_ptr++ = get_data (pnm_file, bit_depth);
-        else
-          if (bit_depth <= 8)
-            *pix_ptr++ = get_value (pnm_file, bit_depth);
+        for (i = 0; i < (channels - alpha_present); i++)
+        {
+          if (raw)
+            *pix_ptr++ = get_data (pnm_file, bit_depth);
           else
-          {
-            tmp16 = get_value (pnm_file, bit_depth);
-            *pix_ptr = (png_byte) ((tmp16 >> 8) & 0xFF);
-            pix_ptr++;
-            *pix_ptr = (png_byte) (tmp16 & 0xFF);
-            pix_ptr++;
-          }
-      }
-
-      if (alpha) /* read alpha-channel from pgm file */
-      {
-        if (alpha_raw)
-          *pix_ptr++ = get_data (alpha_file, alpha_depth);
-        else
-          if (alpha_depth <= 8)
-            *pix_ptr++ = get_value (alpha_file, bit_depth);
+            if (bit_depth <= 8)
+              *pix_ptr++ = get_value (pnm_file, bit_depth);
+            else
+            {
+              tmp16 = get_value (pnm_file, bit_depth);
+              *pix_ptr = (png_byte) ((tmp16 >> 8) & 0xFF);
+              pix_ptr++;
+              *pix_ptr = (png_byte) (tmp16 & 0xFF);
+              pix_ptr++;
+            }
+        }
+
+        if (alpha) /* read alpha-channel from pgm file */
+        {
+          if (alpha_raw)
+            *pix_ptr++ = get_data (alpha_file, alpha_depth);
           else
-          {
-            tmp16 = get_value (alpha_file, bit_depth);
-            *pix_ptr++ = (png_byte) ((tmp16 >> 8) & 0xFF);
-            *pix_ptr++ = (png_byte) (tmp16 & 0xFF);
-          }
-      } /* if alpha */
-
+            if (alpha_depth <= 8)
+              *pix_ptr++ = get_value (alpha_file, bit_depth);
+            else
+            {
+              tmp16 = get_value (alpha_file, bit_depth);
+              *pix_ptr++ = (png_byte) ((tmp16 >> 8) & 0xFF);
+              *pix_ptr++ = (png_byte) (tmp16 & 0xFF);
+            }
+        } /* if alpha */
+      } /* if packed_bitmap */
     } /* end for col */
   } /* end for row */
 
@@ -390,6 +437,14 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace,
     return FALSE;
   }
 
+#if defined(PNG_WRITE_INVERT_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
+  if (packed_bitmap == TRUE)
+  {
+    png_set_packing (png_ptr);
+    png_set_invert_mono (png_ptr);
+  }
+#endif
+
   /* setjmp() must be called in every function that calls a PNG-reading libpng function */
   if (setjmp (png_jmpbuf(png_ptr)))
   {
@@ -411,7 +466,8 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace,
   /* if needed we will allocate memory for an new array of row-pointers */
   if (row_pointers == (unsigned char**) NULL)
   {
-    if ((row_pointers = (png_byte **) malloc (height * sizeof (png_bytep))) == NULL)
+    if ((row_pointers = (png_byte **)
+        malloc (height * sizeof (png_bytep))) == NULL)
     {
       png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
       return FALSE;
@@ -419,13 +475,13 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace,
   }
 
   /* set the individual row_pointers to point at the correct offsets */
-  for (i = 0; i < (height); i++)
+  for (i = 0; i < (int) height; i++)
     row_pointers[i] = png_pixels + i * row_bytes;
 
   /* write out the entire image data in one call */
   png_write_image (png_ptr, row_pointers);
 
-  /* write the additional chuncks to the PNG file (not really needed) */
+  /* write the additional chunks to the PNG file (not really needed) */
   png_write_end (png_ptr, info_ptr);
 
   /* clean up after the write, and free any memory allocated */
@@ -446,19 +502,32 @@ BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace,
 void get_token(FILE *pnm_file, char *token)
 {
   int i = 0;
+  int ret;
 
-  /* remove white-space */
+  /* remove white-space and comment lines */
   do
   {
-    token[i] = (unsigned char) fgetc (pnm_file);
+    ret = fgetc(pnm_file);
+    if (ret == '#') {
+      /* the rest of this line is a comment */
+      do
+      {
+        ret = fgetc(pnm_file);
+      }
+      while ((ret != '\n') && (ret != '\r') && (ret != EOF));
+    }
+    if (ret == EOF) break;
+    token[i] = (unsigned char) ret;
   }
   while ((token[i] == '\n') || (token[i] == '\r') || (token[i] == ' '));
 
   /* read string */
   do
   {
+    ret = fgetc(pnm_file);
+    if (ret == EOF) break;
     i++;
-    token[i] = (unsigned char) fgetc (pnm_file);
+    token[i] = (unsigned char) ret;
   }
   while ((token[i] != '\n') && (token[i] != '\r') && (token[i] != ' '));
 
@@ -510,6 +579,7 @@ png_uint_32 get_value (FILE *pnm_file, int depth)
 {
   static png_uint_32 mask = 0;
   png_byte token[16];
+  unsigned long ul_ret_value;
   png_uint_32 ret_value;
   int i = 0;
 
@@ -518,7 +588,8 @@ png_uint_32 get_value (FILE *pnm_file, int depth)
       mask = (mask << 1) | 0x01;
 
   get_token (pnm_file, (char *) token);
-  sscanf ((const char *) token, "%lu", &ret_value);
+  sscanf ((const char *) token, "%lu", &ul_ret_value);
+  ret_value = (png_uint_32) ul_ret_value;
 
   ret_value &= mask;