Getting the 0-255 values from a pixel in a ppm file C

2.6k views Asked by At

Ok, so I have code that will read in the header from a ppm image, allocate memory for the size of the image, and will successfully print the blank spots (a random number repeated in terminal) for each pixel. All I need to know is how I am supposed to read in the red green and blue values (the 3 separate values ranging from 0-255) for each pixel. I don't know how to access this data within each pixel. Here is my code so far:

#include <stdio.h>
#include <stdlib.h>

int subscript(int row,int column,int numberColumns);
int sub(int rd, int gr, int bl);
//table of contents for the subscript
int main(void){
        char header[5];
        scanf("%s",header);
        printf("%s",header);
        printf("\n");
        int width, height, depth;
        scanf("%d %d %d\n", &width, &height, &depth);
        printf("%d %d %d\n", width, height, depth);
        int red = 0;
        int green = 0;
        int blue = 0;
        int sm;
        int r = 0;
        int c = 0;
        //allocate memory for bit to be used throughout main
        unsigned char *bit = malloc(width*height);
        int *rgb = malloc(3*depth);
        //loops to read in table and print it
        while(r < height){
                while(c < width)
                        {
                        int col;
                        scanf("%d",&col);
                        //brings in allocated memory and values
                        bit[subscript(r,c,width)] = col;
                        int clr;
                        rgb[sub(red,green,blue)] = clr; 
                        int color = clr + col;
                        printf(" %d",clr);
                        c=c+1;
                        }
                printf("\n");
                r = r + 1;
                c = 0;
                }


        free(bit);

}
int subscript(int row,int column, int numberColumns)
        {
        return row * numberColumns + column;
        //retuns items for subscript
}

int sub(int rd, int gr, int bl)
        {
        return rd+gr+bl;
}
1

There are 1 answers

6
Iskar Jarak On

PPM files store colours as triples of bytes (one byte each for r, g, and b in that order) if the maximum colour value field in the header is less than 256 and triples of two bytes if it is 256 or greater (so two bytes for each of r, g, and b, again in that order).

In the two bytes per channel case, the bytes are MSB first (big-endian).


scanf("%c", &byte_var); will read you a single character (byte) into byte_var, which should be an appropriate type. You can then process it accordingly. scanf("%hhu", &byte_var); will read an unsigned character if you are using C99 - if you are using C89 you should look up getchar.

Now, scanf returns the number of successfully converted arguments or EOF, so you should be checking the result for both incorrect input and the end of input. For example:

int n;
char c;

while ((n = scanf("%c", &c)) != EOF && 1 == n) {
    // do something
}

An example use of this would be:

// Read width, height, work out how many bytes you need per pixel.
...

// Now read some pixels
// Here I assume one byte per pixel; this would be a good situation
// to use a function for reading different channel widths

w = 0, h = 0;
while ((n = scanf("%hhu%hhu%hhu", &r, &g, &b)) != EOF && 3 == n
        && w < width && h < height) {
  // now do something with r, g, b
  // e.g. store them in an appropriate pixels array at pixels[w][h] 
  ...

  ++w;
  if (w == width) {
    w = 0, ++h;
  }
}

I also see you are reading from stdin, which I find a bit unusual since the title indicates you are working with a file. You can open a file with fopen (don't forget to check the result), use fscanf to read from it, and use fclose to close it afterwards.

However, I suggest reading the whole file into memory and processing it there, because reading a file a few bytes at a time is slow.


Last, I note that you are only allocating width * height bytes for bit when you need bytes_per_channel * num_channels * width * height, not checking whether your malloc failed, not freeing rgb. You should fix these things.