cppm

Writing a 1D binary array of size N to a (N/2, N/2) size PPM image


I have the following code '''

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

void main()
{
    int n = 32;
    int* img = malloc(sizeof(int)*n*n);
    for(int i = 0; i < n*n; i++) { 
        if(i%n < n/2) { 
            img[i] =   0;
        }
        else { 
            img[i] = 255;
        }
    }
    FILE *fp = fopen("img.ppm", "wb"); /* b - binary mode */
    fprintf(fp, "P6\n%d %d\n255\n", n, n);
    fwrite(img, sizeof(img), 1, fp);
    fclose(fp);
    free(img);
}

But this is simply generating a blank image. I am not sure where the issue is.


Solution

  • There are several issues with your code. A type P6 NetPBM uses 3 bytes for each pixel (one byte for each of red, green, blue). You are presumably writing a 32×32 image, so you would need 3 times more values than what you have (well, unless the use of ints was intentional, in which case you have too many values – we'll get back to that). I'll assume you actually want a grayscale image, so we'll switch to a type P5 image. Furthermore, you are writing ints, and they are presumably 4 or 8 bytes long. Was this intentional? Lastly, sizeof(img) gives you the size of the type of img, which is pointer-to-int, i.e. 4 or 8 bytes depending on your system. It is not the size of your array.

    Here's a suggestion:

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h> // I'll use uint8_t for the pixel bytes. That's personal preference, you can also stick with chars if you want.
    
    int main() // Not relevant, but main should return int
    {
        int n = 32;
        uint8_t * img = malloc(n*n); // Each pixel is a byte, an 8-bit unsigned integer.
        for(int i = 0; i < n*n; i++) { 
            if(i%n < n/2) { 
                img[i] =   0;
            }
            else { 
                img[i] = 255;
            }
        }
        FILE *fp = fopen("img.ppm", "wb");
        fprintf(fp, "P5\n%d %d\n255\n", n, n); // P5 mode for grayscale, since you don't specify in your question what you want to do with colors.
        fwrite(img, 1, n*n, fp); // n*n pixel values, each 1 byte long.
        fclose(fp);
        free(img);
        return 0;
    }