PVN File format specifications (PVN/PVB/PVG/PVP)

Text Revision: 20120514
Specification Revision: 20060106
* note: minor restriction in header as of 20040720
- header must conclude with a single CR/LF delimiter
* note: can now accept doubles for framerate 20040722
* Addition of PV?b signed integer format, 20040723
* Addition of [0,maxval], [-maxval,0] support (signedMaxVal) 20060106
   * the PVN file format described here (also known as PVB/PVG/PVP)
     is (c) 2003-2006 Jacob (Jack) Gryn

   * the author grants full rights to all who wish to use
     and distribute this information/code and the corresponding file
     formats on the assumption that credit is given to the author if asked

   * Note: As of July 2012, the author, Jacob (Jack) Gryn will no longer be at York University. There is not content change except for contact information since the Text revision 20061016

   * new e-mail: jgryn ( at ) co4 (dot) com, web: http://www.co4.com/jgryn

   * The official version of these specifications are available at 
     http://www.cse.yorku.ca/~jgryn/research/pvnspecs.html

   * download sample PVN code here

   * Thanks to Richard Wildes for his help and consultation towards the creation
     of these specifications

Preface:

Researchers often use the PNM (PBM/PGM/PPM) file format initially developed
by Jef Poskanzer in 1989 as an easy way to access pixel data in images.

Recently, research involving video and other data making use of a series
of images have left users with the burden of dealing with large numbers
of PNM format images.

Additionally, the lack of a standard format to store signed and floating point
data has created another burden forcing many labs and organizations to write
their own proprietary file formats.

The PVN: Portable Video aNymap - referring to any of the file formats below
   (PVB - Portable Video Bitmap, 
    PVG - Portable Video Greymap,
    PVP - Portable Video Pixmap)
file format has been created in order to ease these burdens with as many
similarities to the PNM file format as possible (to allow easy conversion).

New features include:

The specifications:

The Header:

The header is in plain text format for similarity to PNM; header fields can
be annotated with comments by the use of the the '#' comment character.  All
characters in any line (in the header) after the '#' character 
are ignored!

Comments can be entered on any line in the header BEFORE (but not 
including) the line containing the FRAMERATE field.

 MAGIC: (string)
 - A  "magic number" to identify the format of the file.
   This is 4 character string beginning with "PV". 
   For example "PV6a" is the integer format of a colour image.

   The third character is one of: [4, 5, or 6] corresponding to P4/P5/P6 images
   in the PNM specification.  (i.e. PV4, PV5, PV6)
   NOTE: ASCII based images (1,2,3) are NOT supported in this file format

   The forth character in the MAGIC is either 'a', 'b', 'f', or 'd'
   (note the lower case!).  'a' refers to an UNSIGNED INTEGER-based file
   'b' refers to a SIGNED INTEGER-based file, 'f' refers to a single precision 
   (32bit) IEEE floating point file and 'd' refers to a double precision (64bit) 
   IEEE floating point file.

 - One or more space characters (SPACE, TAB, CR/LF).

 WIDTH: (unsigned integer)
 - The width (in pixels) of the images (as an ASCII/decimal integer)

 - One or more space characters (SPACE, TAB, CR/LF).

 HEIGHT: (unsigned integer)
 - The height (in pixels) of the images (as an ASCII/decimal integer)

 - One or more space characters (SPACE, TAB, CR/LF).

 DEPTH: (unsigned integer)
 - The depth (or number of images) stored in the file (as an ASCII/decimal 
   integer)

 - Set this to 0 for 'streaming PVN'

 - One or more space characters (SPACE, TAB, CR/LF).

 MAXCOLOUR/MAXVAL (double)
 - For integer based files, the number of bits each pixel-channel
   requires (as ASCII/floating point number).  (i.e. a value of 8 signifies 8bpp 
   Greyscale, or 24bpp RGB/colour data).

   This value MUST always be a multiple of 8 and less than or equal to 32! 
   (except in the case of bitmap files which should always be 1;
    floating-point formats are also exempt from the above rule).

   NOTE: This is different than PNM, as this stores the number of bits
         while PNM stores the maximum possible value.
         (for example, if this value is 255 in a PNM file its PVN equivalent 
          would be 8.          MAXVAL=log(PNM_MAXVAL+1)/log(2) ).

 - For floating-point based files, this specifies the range that the values
   are to be stretched out across.  

   FOR SYMMETRIC RANGES, this should be stored as a POSITIVE ASCII REAL NUMBER!
   The range would be [-maxval,+maxval]. This can be any POSITIVE REAL NUMBER
   (0 is invalid!!)

   For example, maval=10.0 would give a range of [-10,10], and converting
   an 8-bit integer into a float with maxval=10 would be as follows:
     8bit UINT     FLOAT(maxval=10.0)
      0              -10.0
      127            -0.08 [approx]
      128            +0.08 [approx]
      255            +10.0

   FOR 0..+max or -min..0 RANGES, this should be stored as an ASCII REAL NUMBER
   CONTAINING THE SIGN CHARACHTER.  (0 is invalid!!)
   The range would be [0,+maxval], or [-maxval,0].

   For example, maxval=+10.0 would give a range of [0,+10.0], while 
   maxval=-10.0 would give a range of [-10.0,0].
   (NOTE: the explicit inclusion of the sign in maxval=+10.0 is important for
          this case as maxval=+10.0 differs from maxval=10.0.  The explicit 
          sign is what differentiates this from a symmetric range.)

 - One or more space characters (SPACE, TAB, CR/LF).

 FRAMERATE (double)
 - the frame rate (in Hz or frames per second) (as an ASCII/floating point number)
 - note: negative numbers are reserved for future use, to allow videos to play
         backwards

 - A SINGLE CR/LF delimiter; 
   NOTE: ending with just LF only is ok, but NOT with just a single CR, as 
   problems may occur in the unlikely event that the first byte of data is 
   an LF character,
        
 

The Data:

The data section of PVN files begin immediately after the header ends.  
A single CR/LF is the only delimiter between the header and the
data.

The method of storing data corresponds to the storage of data in PNM files
(see man page on ppm/pgm/pbm (c) 1989, 1992 Jef Poskanzer for more detailed 
specifications).

In all formats, pixels in each image are stored corresponding to left-to-right 
(in the image) then top-down.  Images are stored chronologically, from the
oldest to the most recent.  There are no special delimiters between each image.

BITMAP FILES:

The MAGIC must be "PV4a" For PV4a files (PVN/PVB bitmap) each pixel is represented by a single bit with 0 = white, 1 = black. Eight pixels are represented in a single byte of data with the leftmost pixel corresponding to the most significant bit. Images with a width that is not a multiple of eight contain 'pad-bits' at the end of each row, so that each row uses a multiple of 8 bits of data storage. PV4 Images can ONLY be stored as bitmaps; MAXCOLOUR/MAXVAL should always be 1. Floating point versions of PV4 are not supported as it would be redundant to store binary data in this fashion.

INTEGER-BASED FILES:

For UNSIGNED Integer files, the MAGIC must be prefixed with "PV?a", where ? can be 5, or 6 for Greymap or (colour) Pixmap respectively. For SIGNED Integer files, the MAGIC must be prefixed with "PV?b", where ? can be 5, or 6 for Greymap or (colour) Pixmap respectively. The MAXCOLOUR/MAXVAL must be a multiple of 8 and less than or equal to 32. This specifies the precision in bits per pixel for each channel (i.e. a value of 8 signifies 8bpp Greyscale, or 24bpp RGB/colour data). Data is stored in BIG ENDIAN style (most significant byte first) as integers. (No byte re-ordering is needed when MAXCOLOUR/MAXVAL = 8; however if MAXCOLOR >= 16, little endian machines, such as x86 based PCs will need to rearrange the data before displaying, or writing to disk). For the purposes of displaying and converting PV?b files, data should be converted to unsigned integers by adding 2^(MAXCOLOUR-1) to each pixel. For example, when displaying 8-bit (MAXCOLOUR=8) PV5b data, a value of 128 (2^7 = 2^MAXCOLOUR-1) is added to each pixel, so the signed value 0 gets mapped to greylevel 128, a signed value of -128 will get mapped to greylevel 0, and a signed value of +127 will get mapped to greylevel 255. With PV6a/b files, the first word (with the word-length, in bits, defined by MAXCOLOUR/MAXVAL) represents RED of the first pixel, the second represents GREEN, the third represents BLUE. Each pixel contains 3 words (R, G, B), and each is stored sequentially.

FLOATING-POINT-BASED FILES:

The MAGIC must be prefixed with "PV?f" or "PV?d" where ? can be 5, or 6 for Greymap or (colour) Pixmap (respectively); 'f' represents single-precision IEEE floating point, and 'd' represents double-precision IEEE numbers. The MAXCOLOUR/MAXVAL should follow specifications listed for the 'floating-point-based files' and are DIFFERENT to the specs of that variable for integer files. Data is stored in BIG-ENDIAN style (most significant byte first). This entails that little endian machines, such as the x86/PC will need to do byte reordering before displaying or writing to disl. A suggestion to convert to big-endian style on a little-endian machine would be to cast a pointer to a floating point number into a (char *), then read each of the 4 or 8 characters (depending on the precision, 'f' = 4 byte, 'd' = 8 byte) and then reverse the order for storage. Specifications for storage of PV6f/PV6d files are the same for PV6a files (R,G,B stored sequentially), except that the data is stored as IEEE floating point numbers between -MAXVAL and +MAXVAL. Any data outside this range shall cause the file to be considered 'corrupt'.