]> git.imager.perl.org - imager.git/blobdiff - png.c
fix broken link from the animated GIF entry in the concept index.
[imager.git] / png.c
diff --git a/png.c b/png.c
index 65c3c181c850fce104c998c17e806f2814f575ce..af9033e886c068b4de56c43953f711f1ccf2d4e4 100644 (file)
--- a/png.c
+++ b/png.c
@@ -1,5 +1,5 @@
 #include "iolayer.h"
-#include "image.h"
+#include "imageri.h"
 #include "png.h"
 
 /* Check to see if a file is a PNG file using png_sig_cmp().  png_sig_cmp()
@@ -26,7 +26,7 @@
 /* this is a way to get number of channels from color space 
  * Color code to channel number */
 
-int CC2C[PNG_COLOR_MASK_PALETTE|PNG_COLOR_MASK_COLOR|PNG_COLOR_MASK_ALPHA];
+static int CC2C[PNG_COLOR_MASK_PALETTE|PNG_COLOR_MASK_COLOR|PNG_COLOR_MASK_ALPHA];
 
 #define PNG_BYTES_TO_CHECK 4
  
@@ -67,13 +67,11 @@ check_if_png(char *file_name, FILE **fp) {
 undef_int
 i_writepng_wiol(i_img *im, io_glue *ig) {
   png_structp png_ptr;
-  png_infop info_ptr;
+  png_infop info_ptr = NULL;
   int width,height,y;
   volatile int cspace,channels;
   double xres, yres;
   int aspect_only, have_res;
-  double offx, offy;
-  char offunit[20] = "pixel";
 
   io_glue_commit_types(ig);
   mm_log((1,"i_writepng(im %p ,ig %p)\n", im, ig));
@@ -107,7 +105,7 @@ i_writepng_wiol(i_img *im, io_glue *ig) {
   info_ptr = png_create_info_struct(png_ptr);
 
   if (info_ptr == NULL) {
-    png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
+    png_destroy_write_struct(&png_ptr, &info_ptr);
     return 0;
   }
   
@@ -115,7 +113,7 @@ i_writepng_wiol(i_img *im, io_glue *ig) {
    * error hadnling functions in the png_create_write_struct() call.
    */
   if (setjmp(png_ptr->jmpbuf)) {
-    png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
+    png_destroy_write_struct(&png_ptr, &info_ptr);
     return(0);
   }
   
@@ -164,22 +162,16 @@ i_writepng_wiol(i_img *im, io_glue *ig) {
   }
   else {
     unsigned char *data = mymalloc(im->xsize * im->channels);
-    if (data) {
-      for (y = 0; y < height; y++) {
-        i_gsamp(im, 0, im->xsize, y, data, NULL, im->channels);
-        png_write_row(png_ptr, (png_bytep)data);
-      }
-      myfree(data);
-    }
-    else {
-      png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
-      return 0;
+    for (y = 0; y < height; y++) {
+      i_gsamp(im, 0, im->xsize, y, data, NULL, im->channels);
+      png_write_row(png_ptr, (png_bytep)data);
     }
+    myfree(data);
   }
 
   png_write_end(png_ptr, info_ptr);
 
-  png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
+  png_destroy_write_struct(&png_ptr, &info_ptr);
 
   ig->closecb(ig);
 
@@ -192,7 +184,7 @@ static void get_png_tags(i_img *im, png_structp png_ptr, png_infop info_ptr);
 
 i_img*
 i_readpng_wiol(io_glue *ig, int length) {
-  i_img *im;
+  i_img *im = NULL;
   png_structp png_ptr;
   png_infop info_ptr;
   png_uint_32 width, height;
@@ -216,6 +208,7 @@ i_readpng_wiol(io_glue *ig, int length) {
   }
   
   if (setjmp(png_ptr->jmpbuf)) {
+    if (im) i_img_destroy(im);
     mm_log((1,"i_readpng_wiol: error.\n"));
     png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
     return NULL;
@@ -239,6 +232,12 @@ i_readpng_wiol(io_glue *ig, int length) {
 
   mm_log((1,"i_readpng_wiol: channels %d\n",channels));
 
+  if (!i_int_check_image_file_limits(width, height, channels, sizeof(i_sample_t))) {
+    mm_log((1, "i_readpnm: image size exceeds limits\n"));
+    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+    return NULL;
+  }
+
   png_set_strip_16(png_ptr);
   png_set_packing(png_ptr);
   if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr);
@@ -255,6 +254,10 @@ i_readpng_wiol(io_glue *ig, int length) {
   png_read_update_info(png_ptr, info_ptr);
   
   im = i_img_empty_ch(NULL,width,height,channels);
+  if (!im) {
+    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+    return NULL;
+  }
 
   for (pass = 0; pass < number_passes; pass++)
     for (y = 0; y < height; y++) { png_read_row(png_ptr,(png_bytep) &(im->idata[channels*width*y]), NULL); }
@@ -273,11 +276,13 @@ i_readpng_wiol(io_glue *ig, int length) {
 static void get_png_tags(i_img *im, png_structp png_ptr, png_infop info_ptr) {
   png_uint_32 xres, yres;
   int unit_type;
+
+  i_tags_add(&im->tags, "i_format", 0, "png", -1, 0);
   if (png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type)) {
     mm_log((1,"pHYs (%d, %d) %d\n", xres, yres, unit_type));
     if (unit_type == PNG_RESOLUTION_METER) {
-      i_tags_set_float(&im->tags, "i_xres", 0, xres * 0.0254);
-      i_tags_set_float(&im->tags, "i_yres", 0, xres * 0.0254);
+      i_tags_set_float2(&im->tags, "i_xres", 0, xres * 0.0254, 5);
+      i_tags_set_float2(&im->tags, "i_yres", 0, yres * 0.0254, 5);
     }
     else {
       i_tags_addn(&im->tags, "i_xres", 0, xres);