]> git.imager.perl.org - imager.git/blobdiff - pnm.c
more test entries
[imager.git] / pnm.c
diff --git a/pnm.c b/pnm.c
index aadf3b323df364178fbb924971dfbf91b1d2b5af..9f62522e9c8c15c83c5188c5e0250a474b53618d 100644 (file)
--- a/pnm.c
+++ b/pnm.c
@@ -1,5 +1,4 @@
 #include "image.h"
-#include "io.h"
 #include "log.h"
 #include "iolayer.h"
 
@@ -30,7 +29,7 @@ or an entire memory mapped buffer.
 
 Some of these functions are internal.
 
-=over 4
+=over
 
 =cut
 */
@@ -229,11 +228,11 @@ i_readpnm_wiol(io_glue *ig, int length) {
   int type;
   int x, y, ch;
   int width, height, maxval, channels, pcount;
+  int rounder;
   char *cp;
   unsigned char *uc;
   mbuf buf;
   i_color val;
-  int mult;
 
   i_clear_error();
 
@@ -331,7 +330,25 @@ i_readpnm_wiol(io_glue *ig, int length) {
       mm_log((1, "i_readpnm: error reading maxval\n"));
       return NULL;
     }
+
+    if (maxval == 0) {
+      i_push_error(0, "maxval is zero - invalid pnm file");
+      mm_log((1, "i_readpnm: maxval is zero, invalid pnm file\n"));
+      return NULL;
+    }
+    else if (maxval > 65535) {
+      i_push_errorf(0, "maxval of %d is over 65535 - invalid pnm file", 
+                   maxval);
+      mm_log((1, "i_readpnm: maxval of %d is over 65535 - invalid pnm file\n"));
+      return NULL;
+    }
+    else if (type >= 4 && maxval > 255) {
+      i_push_errorf(0, "maxval of %d is over 255 - not currently supported by Imager for binary pnm", maxval);
+      mm_log((1, "i_readpnm: maxval of %d is over 255 - not currently supported by Imager for binary pnm\n", maxval));
+      return NULL;
+    }
   } else maxval=1;
+  rounder = maxval / 2;
 
   if (!(cp = gnext(&buf)) || !misspace(*cp)) {
     i_push_error(0, "garbage in header, invalid PNM file");
@@ -350,11 +367,10 @@ i_readpnm_wiol(io_glue *ig, int length) {
   case 1: /* Ascii types */
   case 2:
   case 3:
-    mult = type == 1 ? 255 : 1;
     for(y=0;y<height;y++) for(x=0; x<width; x++) {
       for(ch=0; ch<channels; ch++) {
        int t;
-       if (gnum(&buf, &t)) val.channel[ch] = t;
+       if (gnum(&buf, &t)) val.channel[ch] = (t * 255 + rounder) / maxval;
        else {
          mm_log((1,"i_readpnm: gnum() returned false in data\n"));
          return im;
@@ -366,7 +382,7 @@ i_readpnm_wiol(io_glue *ig, int length) {
     
   case 4: /* binary pbm */
     for(y=0;y<height;y++) for(x=0; x<width; x+=8) {
-      if ( (uc = gnext(&buf)) ) {
+      if ( (uc = (unsigned char*)gnext(&buf)) ) {
        int xt;
        int pc = width-x < 8 ? width-x : 8;
        /*      mm_log((1,"i_readpnm: y=%d x=%d pc=%d\n", y, x, pc)); */
@@ -385,7 +401,8 @@ i_readpnm_wiol(io_glue *ig, int length) {
   case 6: /* binary ppm */
     for(y=0;y<height;y++) for(x=0; x<width; x++) {
       for(ch=0; ch<channels; ch++) {
-       if ( (uc = gnext(&buf)) ) val.channel[ch] = *uc;
+       if ( (uc = (unsigned char*)gnext(&buf)) ) 
+         val.channel[ch] = (*uc * 255 + rounder) / maxval;
        else {
          mm_log((1,"i_readpnm: gnext() returned false in data\n"));
          return im;
@@ -439,6 +456,7 @@ i_writeppm_wiol(i_img *im, io_glue *ig) {
         while (y < im->ysize && rc >= 0) {
           i_gsamp(im, 0, im->xsize, y, data, rgb_chan, 3);
           rc = ig->writecb(ig, data, im->xsize * 3);
+          ++y;
         }
         myfree(data);
       }
@@ -477,6 +495,7 @@ i_writeppm_wiol(i_img *im, io_glue *ig) {
         while (y < im->ysize && rc >= 0) {
           i_gsamp(im, 0, im->xsize, y, data, &chan, 1);
           rc = ig->writecb(ig, data, im->xsize);
+          ++y;
         }
         myfree(data);
       }
@@ -496,6 +515,21 @@ i_writeppm_wiol(i_img *im, io_glue *ig) {
     mm_log((1,"i_writeppm: ppm/pgm is 1 or 3 channel only (current image is %d)\n",im->channels));
     return(0);
   }
+  ig->closecb(ig);
 
   return(1);
 }
+
+/*
+=back
+
+=head1 AUTHOR
+
+Arnar M. Hrafnkelsson <addi@umich.edu>
+
+=head1 SEE ALSO
+
+Imager(3)
+
+=cut
+*/