Home arrow Studies arrow Coding arrow PGM Image Format
PGM Image Format PDF Print


PGM (Portable GrayMap) is a grayscale image. It has two versions. First one is ASCII PGM which is just a text file as shown in Figure 1. Second one is binary PGM. Binary format is easier to implement than ASCII format and runs faster. Figure 2. shows the structure of the binary PGM format.

Click here to get some binary PGM files.



Figure 1. ASCII PGM Format.

 


Figure 2. Binary PGM format. 


Example for PGM ASCII Format (P2)

Sample C Source Code for Binary PGM Format

PGM read/write functions use dynamically allocated matrices section.

/*

 *   Give a reference to this site if you like to use this code.

 *
 *                               Written by Chasan Chouse, 2004

 */

 

/******************************/
/*  ERROR MESSAGES            */
/******************************/
void DispError(char Err[])
{
    MessageBox(hDlg, Err, "Error", MB_OK | MB_ICONERROR);
//  fprintf(stderr,Err);

}

int PGM_Read_Header(char FileName[],
                    
long *width,
                    
long *height,
                    
long *max_color,
                    
long *f_start)
{
    FILE *fl;
    char ch_width[6], ch_height[6], ch_max_color[6];
    unsigned char ch;
    long i;

    if ( (fl = fopen(FileName,"rb")) == NULL )
    {
        DispError("\nERROR! Couldn't open image file\n");
        return 1;
    }
//  only BINARY PGM is supported
    if (fgetc(fl) == 'P' )
    {
        if (fgetc(fl) == '5')
        {
            fgetc(fl); // skips white space
            ch = fgetc(fl);
            if (ch == '#')
            {
                // skips the comment space
                while( (fgetc(fl) != 10) && (ftell(fl) < filesize(fl)));
                ch = fgetc(fl);
            }
            // get with
            i=0;
            while32 != ch) // between width and height there is a space character
            {
                ch_width[i] = ch;
                ch = fgetc(fl);
                i++;
            }
            ch_width[i] = 0;
            *width = atol(ch_width);
            // get height
            i=0;
            ch = fgetc(fl);
            while10 != ch)
            {
                ch_height[i] = ch;
                ch = fgetc(fl);
                i++;
            }
            ch_height[i] = 0;
            *height = atol(ch_height);
            // get max_color
            i=0;
            ch = fgetc(fl);
            while10 != ch)
            {
                ch_max_color[i] = ch;
                ch = fgetc(fl);
                i++;
            }
            ch_max_color[i] = 0;
            *max_color = (short)atol(ch_max_color);
            *f_start = ftell(fl);
        }
        else
        {
            DispError("\nERROR! File is not PGM binary format\n");
            return 1;
        }
    }
    else
    {
        DispError("\nERROR! File is not a PGM image\n");
        return 1;
    }

    fclose(fl);
    return true;
}


/************************************/
/*  READS IMAGE DATA, INFORMATION   */
/************************************/
int PGM_Get_Data(char FileName[],
                 long width,
                 long height,
                 long f_start,
                 UCHAR **img_data)
{
    FILE *fl;
    UCHAR ch;
    long i, j;

    if ( (fl = fopen(FileName,"rb")) == NULL )
    {
        DispError("\nERROR! Couldn't open image file\n");
        return 1;
    }
    fseek(fl, f_start, SEEK_SET);
    //  READ DATA INTO MATRIX
    for(i=0;i<height;i++)
    {
        for(j=0;j<width;j++)
        {
            ch = fgetc(fl);
            img_data[i][j] = (UCHAR)ch;
            //img_data[i*width + j] = ch;
        }
    }

    fclose(fl);
    return true;
}

/********************************************************/
/*  WRITES IMAGE DATA and INFORMATION TO a GIVEN FILE   */
/********************************************************/
int PGM_Put_Data(char FileName[],
                 long width,
                 long height,
                 long max_color,
                 UCHAR **img_data)
{
    FILE *fl;
    char str[128];
    long i, j, pls;

    if ( (fl = fopen(FileName,"wb")) == NULL )
    {
        DispError("\nERROR! Couldn't open image file\n");
        return 1;
    }
    //  Header
    fputc('P', fl);
    fputc('5', fl);
    fputc( 10, fl); // white space

    // comment will be written to file
    strcpy(str, "# Created by Chasan Chouse");
    pls = (long)strlen(str);
    fwrite(str, pls, 1, fl);
    fputc( 10, fl); // white space

    // width will be written to file
    ltoa(width, str, 10);
    pls = (long)strlen(str);
    fwrite(str, pls, 1, fl);
    fputc( 32, fl); //  space

    // HEIGHT will be written to file
    ltoa(height, str, 10);
    pls = (long)strlen(str);
    fwrite(str, pls, 1, fl);
    fputc( 10, fl); // white space

    // MAX_COLOR will be written to file
    ltoa(max_color, str, 10);
    pls = (long)strlen(str);
    fwrite(str, pls, 1, fl);
    fputc( 10, fl); // white space

    // put with
    for(i=0;i<height;i++)
    {
        for(j=0;j<width;j++)
        {
            fputc( img_data[i][j], fl);
        }
    }
    fclose(fl);
    return true;
}

P2
24 7
15
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
0  3  3  3  3  0  0  7  7  7  7  0  0 11 11 11 11  0  0 15 15 15 15  0
0  3  0  0  0  0  0  7  0  0  0  0  0 11  0  0  0  0  0 15  0  0 15  0
0  3  3  3  0  0  0  7  7  7  0  0  0 11 11 11  0  0  0 15 15 15 15  0
0  3  0  0  0  0  0  7  0  0  0  0  0 11  0  0  0  0  0 15  0  0  0  0
0  3  0  0  0  0  0  7  7  7  7  0  0 11 11 11 11  0  0 15  0  0  0  0
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0

 

Copyright 2003-2007 by Chasan Chouse.

Locations of visitors to this page