PGM image processing example

This C program is an example of simple image processing using PGM files. PGM files can be viewed using programs such as ImageMagick, GIMP, and IrfanView.

//
// process_pgm.c - Loads, modifies and saves a PGM image file
//
// Written by Ted Burke - last modified 18-11-2011
//
// Included image processing operations:
//
//  1. invert colours
//  2. threshold
//  3. Count white pixels
//  4. horizontal edge detect
//  5. vertical edge detect
//
// To compile:
//
//      gcc process_pgm.c -o process_pgm.exe
//

#include <stdio.h>

// 2-D pixel array, like a spreadsheet with 1000 rows & 1000 columns
int p[1000][1000];
int w, h;

// Image file functions
void load_image_from_file(char[]);
void save_image_to_file(char[]);

// Image processing functions
void invert_colours();
void apply_threshold(int);
int count_white_pixels();
void horizontal_edge_detect(int);
void vertical_edge_detect(int);

int main()
{
    // Try out the invert colours function
    load_image_from_file("input.pgm");
    invert_colours();
    save_image_to_file("inverted_image.pgm");

    // Try out the image threshold function
    load_image_from_file("input.pgm");
    apply_threshold(127);
    save_image_to_file("thresholded_image.pgm");

    int edge_threshold = 30;

    // Horizontal edge detect
    load_image_from_file("input.pgm");
    horizontal_edge_detect(edge_threshold);
    save_image_to_file("horizontal_edges.pgm");

    // Vertical edge detect
    load_image_from_file("input.pgm");
    vertical_edge_detect(edge_threshold);
    save_image_to_file("vertical_edges.pgm");

    // exit normally
    return 0;
}

void load_image_from_file(char filename[])
{
   // Variables
    FILE *f;
    char line[200];
    int x, y;

    // Open input image file
    printf("Opening input file %s\n", filename);
    f = fopen(filename, "r");

    // Read 4 header lines.
    // These will just be ignored, but we need to read
    // them to get down to the table of numbers further
    // down in the file.
    printf("Reading file header info\n");
    fscanf(f, "%[^\n]\n", line);
    fscanf(f, "%[^\n]\n", line);
    fscanf(f, "%d %d\n", &w, &h);
    fscanf(f, "%[^\n]\n", line);

    // Read pixel data into 2-D array
    printf("Reading pixel data from file %s\n", filename);
    y = 0;
    while(y < h)
    {
        x = 0;
        while(x < w)
        {
            fscanf(f, "%d", &p[y][x]);
            x = x + 1;
        }
        y = y + 1;
    }

    // Close input file
    printf("Closing input file %s\n", filename);
    fclose(f);
}

void save_image_to_file(char filename[])
{
    // variables
    FILE *f;
    int x, y;

    // open output file
    printf("Opening output file %s\n", filename);
    f = fopen(filename, "w");

    // Print header info into file
    printf("Printing file header to file %s\n", filename);
    fprintf(f, "P2\n");
    fprintf(f, "# My PGM file\n");
    fprintf(f, "%d %d\n", w, h);
    fprintf(f, "255\n");

    // Print pixel data into file
    printf("Printing pixel data to file %s\n", filename);
    y = 0;
    while(y < h)
    {
        x = 0;
        while(x < w)
        {
            fprintf(f, "%d ", p[y][x]);
            x = x + 1;
        }
        fprintf(f, "\n");
        y = y + 1;
    }

    // Close file
    printf("Closing output file %s\n", filename);
    fclose(f);
}

void invert_colours(int threshold)
{
    // variables
    int x, y;

    // Modify all pixel values one at a time
    printf("Inverting colours...");
    y = 0;
    while(y < h)
    {
        x = 1;
        while(x < w)
        {
            p[y][x] = 255 - p[y][x];
            x = x + 1;
        }
        y = y + 1;
    }
    printf("OK\n");
}

void apply_threshold(int threshold)
{
    // variables
    int x, y;

    // Modify all pixel values one at a time
    printf("Applying threshold...");
    y = 0;
    while(y < h)
    {
        x = 0;
        while(x < w)
        {
            if (p[y][x] > threshold)
            {
                p[y][x] = 255;
            }
            else
            {
                p[y][x] = 0;
            }
            x = x + 1;
        }
        y = y + 1;
    }
    printf("OK\n");
}

int count_white_pixels()
{
    // variables
    int x, y;
    int counter = 0;

    printf("Counting white pixels...");
    y = 0;
    while(y < h)
    {
        x = 1;
        while(x < w)
        {
            if (p[y][x] == 255)
            {
                counter = counter + 1;
            }
            x = x + 1;
        }
        y = y + 1;
    }
    printf("OK\n");

    return counter;
}

void horizontal_edge_detect(int min_diff)
{
    // variables
    int x, y;
    int diff;

    // Any pixel that differs from its right-hand neighbour
    // by more than min_diff will become white. Other pixels
    // become black.
    printf("Detecting horizontal edges...");

    y = 0;
    while(y < h)
    {
        x = 0;
        while(x < w-1)
        {
            // Find the difference in colour between
            // this pixel and the one to the right of it
            diff = p[y][x+1] - p[y][x];

            // Make sure difference is positive
            if (diff < 0) diff = -diff;

            // If the difference exceeds the threshold
            // make the pixel white
            if (diff > min_diff) p[y][x] = 255;
            else p[y][x] = 0;

            x = x + 1;
        }
        y = y + 1;
    }
    printf("OK\n");
}

void vertical_edge_detect(int min_diff)
{
    // variables
    int x, y;
    int diff;

    // Any pixel that differs from the one immediately below
    // it by more than min_diff will become white. All other
    // pixels become black.
    printf("Detecting vertical edges...");

    y = 0;
    while(y < h-1)
    {
        x = 0;
        while(x < w)
        {
            // Find the difference in colour between
            // this pixel and the one below it
            diff = p[y+1][x] - p[y][x];

            // Make sure difference is positive
            if (diff < 0) diff = -diff;

            // If the difference exceeds the threshold
            // make the pixel white
            if (diff > min_diff) p[y][x] = 255;
            else p[y][x] = 0;

            x = x + 1;
        }
        y = y + 1;
    }
    printf("OK\n");
}
Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s