Search code examples
cimageppm

How to do a black-and-white picture of a ppm file in C?


hey I need a little help with my code, I read a ppm file, change the colors to black and white and want to save it to a new file. I could read the header of my file and write it to the new file but I've struggles with changing the colors. I know that I can get the grey value with the formula: 0.299 * red component + 0.587 * green component + 0.114 * blue component. Does anyone know how I can write this as a code?

int main(int argc, char **argv)
{   

    FILE *oldFile, *newFile;
    int width, height, max_colour;
    oldFile = fopen("oldpic.ppm","rb"); 
    newFile = fopen("newpic.ppm","wb");

    fscanf (oldFile, "P6\n %d %d %d", &width, &height, &max_colour);

    unsigned char *data = malloc(width*height);
    fread(data,1,width*height,oldFile);


   fprintf(newFile, "P6\n%d %d\n%d\n", width, height, max_colour);

  for (int j = 0; j < width; ++j)
  {
    for (int i = 0; i < height; ++i)
    {

       unsigned char color[3];
      color[0] = 0.299 * ? + 0.587 * ? + 0.114 * ?; /* red */
      color[1] = 0.299 * ? + 0.587 * ? + 0.114 * ?;  /* green */
      color[2] = 0.299 * ? + 0.587 * ? + 0.114 * ?;  /* blue */
      (void) fwrite(color, 1, 3, newFile);
    }
  }
  (void) fclose(newFile);
   return 0;
} 

Solution

  • You probably want scaled binary arithmetic.

    Also, even though you can read the input data into a large array, it may be easier to read it and process it a pixel at a time.

    Here's your code reworked to do just that:

    int
    main(int argc, char **argv)
    {
    
        FILE *oldFile;
        FILE *newFile;
        int width;
        int height;
        int max_colour;
    
        oldFile = fopen("oldpic.ppm", "rb");
        newFile = fopen("newpic.ppm", "wb");
    
        fscanf(oldFile, "P6\n %d %d %d", &width, &height, &max_colour);
    
    #if 0
        unsigned char *data = malloc(width * height);
        fread(data, 1, width * height, oldFile);
    #endif
    
        fprintf(newFile, "P6\n%d %d\n%d\n", width, height, max_colour);
    
        for (int j = 0; j < width; ++j) {
            for (int i = 0; i < height; ++i) {
                unsigned char color[3];
                unsigned int grey;
    
                fread(color, 1, 3, oldFile);
    
                grey = 0;
                grey += 299u * color[0];  // red
                grey += 586u * color[1];  // green
                grey += 114u * color[2];  // blue
                grey /= 1000;
    
                color[0] = grey;
                color[1] = grey;
                color[2] = grey;
    
                fwrite(color, 1, 3, newFile);
            }
        }
    
        fclose(oldFile);
        fclose(newFile);
    
        return 0;
    }