Version 1: Generate histogram from a single PGM file
The C program below loads a grey scale image from a plain text PGM file and generates a histogram of pixel values between 0 and 255. The histogram data are saved to a file “histogram.csv”. To plot the histogram in MATLAB / Octave, use the following commands:
h = csvread('histogram.csv');
plot (h)
This is the C code for the single file version:
//
// histogram.c - Written by Ted Burke on 21-Nov-2022
// Counts the number of pixels with each colour
// value (0-255) in a PGM image.
//
// The filename of the input PGM should be specified
// as a command line argument.
//
// histogram.exe image001.pgm
//
#include <stdio.h>
// 2D pixel array, like a spreadsheet with 1000 rows & 1000 columns
int p[1000][1000];
// Other image properties - width, height, white value
int w, h, maxval;
int main(int argc, char *argv[])
{
FILE *f;
char line[200];
int x, y;
// Check whether an input filename was provided
// as a command line argument
if (argc < 2)
{
printf("Error: No input file specified\n");
return 1;
}
// Open input image file
if ((f = fopen(argv[1], "r")) == NULL)
{
printf("Error: Invalid input file specified\n");
return 2;
}
// Read 4 header lines.
// The first two lines are simply ignored.
// The next two lines contain the width,
// height and maximum pixel value (white).
fscanf(f, "%[^\n]\n", line);
fscanf(f, "%[^\n]\n", line);
fscanf(f, "%d %d\n", &w, &h);
fscanf(f, "%d\n", &maxval);
// Read pixel data into 2-D array, p[][]
for (y=0 ; y<h ; ++y) for (x=0 ; x<w ; ++x) fscanf(f, "%d", &p[y][x]);
fclose(f); // Close input file
// Count number of pixels for each colour value
int hist[256] = {0};
for (y=0 ; y<h ; ++y) for (x=0 ; x<w ; ++x) hist[p[y][x]]++;
// Open output file
if ((f = fopen("histogram.csv", "w")) == NULL)
{
printf("Error: Failed to open output file\n");
return 3;
}
// Print pixel data into file
for (int c=0 ; c<256 ; ++c) fprintf(f, "%d\n", hist[c]);
fclose(f); // Close output file
return 0; // Exit normally
}
Version 2: Generate histogram from multiple PGM files
This version generates a single pixel value histogram from multiple PGM files. The input files are specified as command line arguments. The histogram data can be plotted in MATLAB/Octave the same way as for the previous version (see above).
//
// histogram2.c - Written by Ted Burke on 21-Nov-2022
// Counts the number of pixels with each colour
// value (0-255) in multiple PGM images.
//
// The filenames of the input PGM images should be
// specified as command line arguments.
//
// histogram2.exe image001.pgm
//
#include <stdio.h>
// 2D pixel array, like a spreadsheet with 1000 rows & 1000 columns
int p[1000][1000];
// Other image properties - width, height, white value
int w, h, maxval;
int main(int argc, char *argv[])
{
FILE *f;
char line[200];
int hist[256] = {0};
int i, x, y;
for (i=1 ; i<argc ; ++i)
{
// Open next input image file
if ((f = fopen(argv[i], "r")) == NULL)
{
printf("Error: Invalid input file specified\n");
return 2;
}
// Read 4 header lines.
// The first two lines are simply ignored.
// The next two lines contain the width,
// height and maximum pixel value (white).
fscanf(f, "%[^\n]\n", line);
fscanf(f, "%[^\n]\n", line);
fscanf(f, "%d %d\n", &w, &h);
fscanf(f, "%d\n", &maxval);
// Read pixel data into 2-D array, p[][]
for (y=0 ; y<h ; ++y) for (x=0 ; x<w ; ++x) fscanf(f, "%d", &p[y][x]);
fclose(f); // Close input file
// Count number of pixels for each colour value
for (y=0 ; y<h ; ++y) for (x=0 ; x<w ; ++x) hist[p[y][x]]++;
}
// Open output file
if ((f = fopen("histogram.csv", "w")) == NULL)
{
printf("Error: Failed to open output file\n");
return 3;
}
// Print pixel data into file
for (int c=0 ; c<256 ; ++c) fprintf(f, "%d\n", hist[c]);
fclose(f); // Close output file
return 0; // Exit normally
}