Thread: Reading a PPM image into an array so it can be stored, accessed and manipulated

  1. #1
    Registered User
    Join Date
    Dec 2021
    Posts
    34

    Reading a PPM image into an array so it can be stored, accessed and manipulated

    I'm trying to use malloc so that a PPM can be read into an array and then for that array to be saved into a file using a switch case statement. So far nothing really seems to happen. Any help is much appreciated. Thanks.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    #define height 1080
    #define width 1920
    #define RGB_COMPONENT_COLOUR 255
    
    
    typedef struct
    {
        unsigned char red, green, blue;
    } PPMPixel;
    
    
    typedef struct
    {
        int x, y;
        PPMPixel *data;
    } PPMImage;
    
    
    void clear_to_end(FILE *fp)
    {
        int c;
        while ((c = fgetc(fp)) != EOF && c != '\n');
    }
    
    
    PPMImage* load_file()
    {
        FILE *fp;
        PPMImage *img = malloc(sizeof(*img));
        int d, rgb_comp_colour;
        char buff[80];
        char fname[100];
        printf("Enter file name: ");
        scanf("%s", fname);
        fseek(stdin,0,SEEK_END);
        fp = fopen(fname, "r");
        if (fp == NULL)
        {   
            printf("\tError while opening the file\n");
            return NULL;
        }                        
        else    
        {
            printf("\tReading in %s\n", fname);
        }
    
    
        //Checking for comments
        //Skip whitespace and comments
        d = getc(fp);
        while (d=='#')
        {
            while(getc(fp)!='\n')
            d=getc(fp);
        }
        ungetc(d,fp);
    
    
        //Checking header
        if (!fgets(buff,sizeof(buff),fp))
        {
            perror(fname);
            exit(1);
        }
    
    
        if (buff[0] =='P' && (buff[1] == '2' || buff[1] == '3'))
        {
            printf("\tReading PGM/PPM image in...\n");
        }
        else
        {
            printf("\tIncorrect image format\n");
            return NULL;
        }
    
    
        //Read image size information
        if (fscanf(fp, "%u %u", &img->y, &img->x) !=2)
        {
            printf("\tInvalid image size\n");
            printf("\tImage size is: %u x %u\n", img->y, img->x);
        }
        else
        {
            printf("\tImage size is valid\n");
            printf("\tImage size is: %u x %u\n", img->y, img->x);
        }
    
    
        if (fscanf(fp, "%d", &rgb_comp_colour) !=1)
        {
            printf("Invalid RGB component for %s\n", fname);
        }
        else
        {
            printf("\tRGB component is valid\n");
            printf("%d", rgb_comp_colour);
        }
        fscanf(fp, "%c ", &d);
    
    
        //Check RGB component depth
        if (rgb_comp_colour!=RGB_COMPONENT_COLOUR)
        {
            printf("\t'%s' is not 8 bit\n", fname);
        }
        else
        {
        printf("\t'%s' is 8 bit\n", fname);
        }
        int i, j;
        int array[i][j];
        **array = malloc (width*height*sizeof(array[i][j]));
        for (i=0; i<width; i++)
        {
            *array[i] = malloc(width * sizeof(int));
            for(j=0; j<height; j++)
            {
                fseek(fp, 0, SEEK_SET);
                fscanf(fp, "%d ", &array[i][j]);
            }  
        }
    
    
        for (i=0; i<width; i++)
        {
            for(j=0; j<height; j++)
            {
                printf("%d ", array[i][j]);
            }
            printf("\n");
        }
        fclose(fp);
        return img;
    }
    
    
    
    
    void save_file(PPMImage *img)
    {
        //Save PPM Array Into New PPM File
    }
    
    
    
    
    int main()
    {
        char key = 0;
        PPMImage* img = NULL;
        do {
            puts("\tPress r to read in an image in ppm format");
            puts("\tPress s to save image in ppm format");
            puts("\tPress q to quit");
            
            scanf(" %c", &key);
            clear_to_end(stdin);
            switch (key) {
                case 'r':
                {
                    PPMImage *img = load_file("fname");
                    free(img);
                }
                    break;
                case 's':
                {
                    save_file(img);
                }
                    break;
                case 'q':
                {
                    puts("\tTerminating program...");
                }
                    break;
                default:
                {
                    puts("\tInvalid Input");
                }
                    break;
            }
        } while (key != 'q');
        return 0;
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Code:
        int i, j;
        int array[i][j];
        **array = malloc (width*height*sizeof(array[i][j]));
    This makes no sense.
    i and j are uninitialised values, then you go and make an array out of them.

    What you should be allocating is
    img->data = malloc(width*height*sizeof(*img->data));


    But as your pixel array is a 1D thing, not a 2D thing, you need to manually flatten the image.
    Code:
    int p = 0;
        for (i=0; i<width; i++)
        {
            for(j=0; j<height; j++)
            {
                int r,g,b;
                fscanf(fp, "%d %d %d", &r, &g, &b);
                img->data[p].red = r;
                img->data[p].green = g;
                img->data[p].blue = b;
                p++;
            }  
        }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Dec 2021
    Posts
    34
    Quote Originally Posted by Salem View Post
    Code:
        int i, j;
        int array[i][j];
        **array = malloc (width*height*sizeof(array[i][j]));
    This makes no sense.
    i and j are uninitialised values, then you go and make an array out of them.

    What you should be allocating is
    img->data = malloc(width*height*sizeof(*img->data));


    But as your pixel array is a 1D thing, not a 2D thing, you need to manually flatten the image.
    Code:
    int p = 0;
        for (i=0; i<width; i++)
        {
            for(j=0; j<height; j++)
            {
                int r,g,b;
                fscanf(fp, "%d %d %d", &r, &g, &b);
                img->data[p].red = r;
                img->data[p].green = g;
                img->data[p].blue = b;
                p++;
            }  
        }
    Thanks again for the tips! The only issue is none of the array code can be seen in the terminal when I run the code, even my error checking (though this may be a problem with my software rather than the code itself). I am also wondering why omit array[i] malloc, what is p used for, and can this be made to work for greyscale (PGMs) as well?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Reading a PPM image into a 1d or 2d array
    By Robert Harp in forum C Programming
    Replies: 1
    Last Post: 04-04-2013, 10:18 AM
  2. Accessing an image stored in an array.
    By Mr.Sellars in forum C++ Programming
    Replies: 1
    Last Post: 07-11-2008, 11:46 AM
  3. Reading data from a randomly accessed file
    By DLR in forum C Programming
    Replies: 2
    Last Post: 04-19-2006, 09:25 PM
  4. storing a manipulated array in a new array
    By axon in forum C++ Programming
    Replies: 7
    Last Post: 03-04-2003, 01:27 PM
  5. creating image from pixels stored in file
    By Kristian25 in forum Windows Programming
    Replies: 3
    Last Post: 01-21-2003, 02:08 PM

Tags for this Thread