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

Text Revision: 20040722
Specification Revision: 20040723
* 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

       * the PVN (PVB/PVG/PVP) file format described here
         is (c) 2003,2004 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

       * e-mail: jgryn(at)cs.yorku.ca, web: http://www.cs.yorku.ca/~jgryn/research

       * 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.

    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:

- Ability to include multiple images in a single PVN file, and specify the number of images in the header
- Ability to specify a frame rate in the header for video/animation playback use
- Multiple precision levels, including:
  - INT (8, 16, 24, 32 bits per channel; unsigned or signed)
  - FLOAT (single and double precision 32/64 bit signed)
- Ability to specify range boundary for floating point files
- Easy to convert to/from PNM files
- Capable of streaming video

## 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.  (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 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              -10
          127            0
          255            +10

     - 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 occor 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'.