POV-Ray : Newsgroups : povray.general : ppm reading bug Server Time
5 Aug 2024 18:19:03 EDT (-0400)
  ppm reading bug (Message 1 to 1 of 1)  
From: David Necas (Yeti)
Subject: ppm reading bug
Date: 23 Aug 2002 06:37:03
Message: <slrnamc42f.9b1.yeti@monoceros.physics.muni.cz>
PoV-Ray can't read some valid PPM files containing comments,
most notable those created by The GIMP, starting with
something like

P6
# CREATOR: The GIMP's PNM Filter Version 1.0
320 240
255

Here I include PPM spec for reference (well, the part about
nonlinear sampling is quite controversal, since nowadays
most tools use what is called ``common variation'' there,
i.e. linear sampling)

  A  PPM  file  consists  of  a  sequence of one or more PPM
  images. There are no data, delimiters, or padding  before,
  after, or between images.

  Each PPM image consists of the following:

  - A  "magic  number" for identifying the file type.  A ppm
    image's magic number is the two characters "P6".

  - Whitespace (blanks, TABs, CRs, LFs).

  - A width, formatted as ASCII characters in decimal.

  - Whitespace.

  - A height, again in ASCII decimal.

  - Whitespace.

  - The maximum color value (Maxval), again in  ASCII  deci-
    mal.  Must be less than 65536.

  - Newline or other single whitespace character.

  - A  raster  of  Width * Height pixels, proceeding through
    the image in normal English reading order.   Each  pixel
    is  a  triplet  of red, green, and blue samples, in that
    order.  Each sample is represented  in  pure  binary  by
    either 1 or 2 bytes.  If the Maxval is less than 256, it
    is 1 byte.  Otherwise, it is 2 bytes.  The most signifi-
    cant byte is first.

  - In  the raster, the sample values are "nonlinear."  They
    are proportional to the intensity of the  CIE  Rec.  709
    red,  green,  and blue in the pixel, adjusted by the CIE
    Rec. 709 gamma transfer function.  (That transfer  func-
    tion  specifies  a  gamma number of 2.2 and has a linear
    section for small intensities).  A value of  Maxval  for
    all  three samples represents CIE D65 white and the most
    intense color in the color universe of which  the  image
    is  part  (the  color  universe is all the colors in all
    images to which this image might be compared).

  - Note that a common variation on the  PPM  format  is  to
    have  the  sample  values be "linear," i.e. as specified
    above except without  the  gamma  adjustment.   pnmgamma
    takes  such  a  PPM variant as input and produces a true
    PPM as output.

  - Characters from a "#" to the  next  end-of-line,  before
    the maxval line, are comments and are ignored.

A patch is also included (I don't send it here, not to
unofficial-patches, because it's a bugfix, not a new
feature)

Yeti


--- povray-3.50a.orig/src/ppm.cpp	Wed Aug 21 18:53:45 2002
+++ povray-3.50a/src/ppm.cpp	Wed Aug 21 20:01:12 2002
@@ -56,6 +56,8 @@
 #include "ppm.h"
 #include "file_pov.h"
 
+#include <cctype>
+
 /*****************************************************************************
 * Local preprocessor defines
 ******************************************************************************/
@@ -434,21 +436,58 @@
   if((type != '3') && (type != '6'))
     Error ("File is not in PPM format.");
 
+  /* Eat up all whitespace */
+  do {
+    data = infile->Read_Byte ();
+  } while (std::isspace (data));
+  infile->UnRead_Byte (data) ;
+
   /* Ignore any comments */
   while ((data = infile->Read_Byte ()) == '#')
     infile->getline(junk,512);
   infile->UnRead_Byte (data) ;
 
-  if ((data = infile->Read_Byte ()) != ' ')
-    infile->UnRead_Byte (data) ;
-  for (i = 0, s = junk ; (i < 8) && ((data = infile->Read_Byte ()) != ' ') ; i++,
s++)
+  /* Eat up all whitespace */
+  do {
+    data = infile->Read_Byte ();
+  } while (std::isspace (data));
+  infile->UnRead_Byte (data) ;
+
+  /* Read width */
+  for (i = 0, s = junk ; i < 8 ; i++, s++) {
+    data = infile->Read_Byte ();
+    if (std::isspace (data))
+      break ;
     *s = (char) data ;
+  }
   *s = '\0' ;
   if (*infile)
     width = atoi (junk) ;
 
-  for (i = 0, s = junk ; (i < 8) && ((data = infile->Read_Byte ()) != ' ') ; i++,
s++)
+  /* Eat up all whitespace */
+  do {
+    data = infile->Read_Byte ();
+  } while (std::isspace (data));
+  infile->UnRead_Byte (data) ;
+
+  /* Ignore any comments */
+  while ((data = infile->Read_Byte ()) == '#')
+    infile->getline(junk,512);
+  infile->UnRead_Byte (data) ;
+
+  /* Eat up all whitespace */
+  do {
+    data = infile->Read_Byte ();
+  } while (std::isspace (data));
+  infile->UnRead_Byte (data) ;
+
+  /* Read height */
+  for (i = 0, s = junk ; i < 8 ; i++, s++) {
+    data = infile->Read_Byte ();
+    if (std::isspace (data))
+      break ;
     *s = (char) data ;
+  }
   *s = '\0' ;
   if (*infile)
     height = atoi (junk) ;
@@ -456,14 +495,35 @@
   if (width == 0 || height == 0)
     Error ("Invalid width or height read from PPM image.");
 
+  /* Eat up all whitespace */
+  do {
+    data = infile->Read_Byte ();
+  } while (std::isspace (data));
+  infile->UnRead_Byte (data) ;
+
   /* Ignore any comments */
   while ((data = infile->Read_Byte ()) == '#')
     infile->getline(junk,512);
   infile->UnRead_Byte (data) ;
 
-  infile->getline(junk,512);
-  depth = atoi(junk);
-  if((depth > 255) || (depth < 1))
+  /* Eat up all whitespace */
+  do {
+    data = infile->Read_Byte ();
+  } while (std::isspace (data));
+  infile->UnRead_Byte (data) ;
+
+  /* Read depth, must end with _exactly_ one whitespace */
+  for (i = 0, s = junk ; i < 5 ; i++, s++) {
+    data = infile->Read_Byte ();
+    if (std::isspace (data))
+      break ;
+    *s = (char) data ;
+  }
+  *s = '\0' ;
+  if (*infile)
+    depth = atoi (junk) ;
+
+  if ((depth > 255) || (depth < 1))
     Error ("Unsupported number of colors (%d) in PPM image.", depth);
 
   Image->width  = (DBL)(Image->iwidth = width);


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.