Reading PPM format images

I’m fairly new to C programming and I’ve been trying to figure out how to do this for 6 hours without any success.

I’m trying to read this PPM format image, which contains an ASCII header followed by binary pixel data. The header consists of something like this:

P6
650 652
255

P6 indicates that it is a PPM image. The next two fields are the width and height of the image. The last field gives the maximum pixel value. At the end of the header is a \n and then the binary pixel data. The image is in color so there are three bytes (red, green, blue). The goal of my readPPM function is to return the pixel data in a one-dimensional array of unsigned chars, plus the width and height of the image. The goal of my writePPM function (I haven't done anything for that function yet) is to write the PPM format image to an empty file from the given information returned from my readPPM function. I'm still not sure how to make this program work so I don't store the 650 in width and 652 in height. I'll worry about that once I can actually read and write the text files.

Update: I've successfully stored the header (P6, 650, 652, and 255)) in their right variables (I know because I tried printing their values and they came out right). My output is shown below. I was wondering what those nonsense characters below the maximum were. Are those the binary pixel data? If so, then I just need to write my writePPM function.

Output:
PSix: P6

Width: 650

Height: 652

maximum: 255

?ɡ?Ƞ?ɢ?ˤ?ɢ?Ş?ĝ?Ǡ?ʤ?ɣ?ɡ?ɡ?ǟ?Ĝ?ŝ?Ƞ?ȡ?ʣ?ʣ?ȡ?Ŝ?Ŝ?Ȟ?ʠ?̤?ƞ?Ơ?ʤ?ʦ?ʦ?ɧ?Ƥ?ǥ?Ȧ?ɩ?ʪ?ʫ?ʫ?ʪ?ʨ?ɤ?Ǡ?ʢ?̤?ȡ?ȡ?ʥ?ɥ?ʧ?Ģ?ǥ?Ƥ?Ģ? ????Ƥ????ǥ?ʨ?ɧ?ʨ?ɧ?ɧ?ͨ?ϧ?ʟ?ˠ?Х?Φ?ͥ?ˣ?ǟ??Ơ?ʦ?ɥ?Ġ????????????? ?????ħ?Ũ???????©?Ǯ?????????????Ǩ?˭?ū?????????????????????????鴢紣㴢ⳡ޴?ܴᷟ?⺡㻢Ḥ⹥޴?ݳ?۱?ܲ?۱?خ?׭?ٯ?֮?ѫ?Ъ?̨?մ?յ?Ǫ?̲?ٿ?һ????ư?ɳ?ɳ?ɱ?ɱ?˰?ˮ?ɪ?Ȧ?ͫ?ֵ?ұ?Ť?¡?ʩ?Ӳ?Ϯ?ͫ?ϭ?ѯ?ѯ?Ϭ?̭?˰?Ͷ?͵?˳?ʱ?Ǯ?ȯ?ε?ӷ?ϳ?̯?ɬ?̫?ͬ?ͭ?˪?ΰ?ͮ?ί?Ӵ?Ӷ?ϲ?ˮ?ɬ?ʭ?Ѵ?ҵ?г?ϲ?ˮ?ȫ?ɬ?ǩ?ϱ?в?˭?ʬ?˭?̭?ί?ͮ?ͮ?ͮ?ί?ˬ?ȩ?ʫ?ͮ?ղ?ү?Ӳ?ֵ?Ҵ?ѳ?ϲ?ˮ?ȭ?˰?ˮ?ˮ?ͯ?̮?̬?ͯ?ˮ?̱?˲?ȯ?ƭ?Ư?Ů?®?¯?????????????????????????????????????¨?é?é?ū?¨???????????????????????????????ī?ī?ī?Ŭ?Ŭ?ī?ū?ū?é???????ĭ?Ů?®???????????©??????????ȫ?ȫ?Ȫ?ɫ?̭?̭?˭?ʬ?ɫ?ʬ?ʮ?˯?˯?˯?˯?Ȭ?Ȫ?ɫ?̮?ͯ?ϱ?ѳ?ӵ?Ѵ?б?ϰ?ϭ?ά?Ѯ?Ա?Ӱ?Э?Ϭ?ү?ү?Э?ά?ѯ?ױ?ӭ?ϩ?ͧ?ϧ?ѩ?Ԭ?ذ?խ?ѩ?Ϧ?Ϧ?Ч?ҩ?ҩ?ҩ?ת?ث?׭?خ?ׯ?֮?կ?կ?Ԭ?խ?ج?ج?ܬ?߰?㳩䴨峨ݫ?٧?ެ?䲧峨䲧䲧Ⱗ䲩붮?ﺲ국굯???????걦뱥ﶥ???????????????????????????????????????±????ð?????????????????????????????????????????????????æ?ũ?ç?é?Ī?ë???????£?Ʀ?Ʀ?ƥ?Ť?Ť?ƥ?ɧ?ʨ?ͫ?ά?ʩ?Ť?â?ţ?Ǩ?ť?Ƨ?ˬ?ɭ?¦???????????????????????????????ç???????????????????????????????????????????????????????????????????????????????????????????????????????????????????ñ?°?ñ??????????î????????????????????????鲯豮汭尬䯫汭곮췱洫ᱧద嵫緭䴪᯦᯦䲩洫鴬鴬鴬국국贩춬??????뵩괪???????????겱⪭????겳???뵫贩贩趫긭긭긭跩綨깫컭궩糦뵩뷩켨컪鸧綨浧絬鷮鷰峬洫???긭跩긭캱캳깲綯㳩ᱧ㳧嵩㵨᳦᳤ⴥ乩缬轭轭缬ߴ?۰?ߴ?幬


main.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
int main() {

	//char fileName[50] = "binary_pixels.txt";
	char fileName[50] = "test.ppm";
	char pSix[10];		// indicates this is a PPM image
	int width = 0;		// width of the image
	int height = 0;		// heigt of the image
	int maximum = 0;	// maximum pixel value
	int size = 128;		// size of the array

	// read the PPM file and store its contents inside an array and return the pointer to that array to pixelArray
	unsigned char* pixelArray = readPPM(fileName, pSix, &width, &height, &maximum);
}



readWritePPM.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
unsigned char* readPPM(const char* fileName, char* pSix, int* width, int* height, int* maximum) {

	// open the file to read just the header reading
	FILE* fr = fopen(fileName, "r");

	// formatted read of header
	fscanf(fr, "%s", pSix);

	// check to see if it's a PPM image file
	if (strncmp(pSix, "P6" , 10) != 0) {
		printf("They are not the same\n");
	} else {
		printf("They are the same\n");
	}

	// read the rest of header
	fscanf(fr, "%d\n %d\n", width, height);

    fscanf(fr, "%d\n", maximum);

    // check to see if they were stored properly
    printf("PSix: %s\n", pSix);
    printf("Width: %d\n", *width);
    printf("Height: %d\n", *height);
    printf("maximum: %d\n", *maximum);

    //int size = width * height;
    int size = 423800;

    // allocate array for pixels
    unsigned char* pixels = new unsigned char[size];

	// unformatted read of binary pixel data
	while (fread(pixels, sizeof(int), 128, fr)) {
		printf("%s", pixels);
	} // end of for loop

	// close file
	fclose(fr);

	// return the array
	return pixels;
	
} // end of readPPM 
Last edited on
I'm pretty sure you need to open the file in binary mode, not ASCII mode.
 
FILE* fr = fopen(fileName, "rb");
Array dimensions must be constant expressions.
When reading binary files better use fread.
http://www.cplusplus.com/reference/cstdio/fread/

unsigned char* pixelArray[size] = readPPM(fileName, &width, &height);

Shoud be unsigned char* pixelArray = readPPM(fileName, &width, &height);

Why do you pass width and height and don't use them ?
Also you need to remember to delete pixelArray.
I've successfully stored the header (P6, 650, 652, and 255)) in their right variables (I know because I tried printing their values and they came out right). My output is shown below. I was wondering what those nonsense characters below the maximum were. Are those the binary pixel data? If so, then I just need to write my writePPM function. I also updated my codes above if you're curious.
Out of interest, some time ago I came across some code to read/write ppm images using C++.
https://github.com/sol-prog/Perlin_Noise
Here, only the files ppm.h and ppm.cpp are relevant. They might be of interest. In this case, the image pixel data is stored in three independent vectors, for the red, green and blue components.

My apologies, I haven't really studied the code posted in this thread, but it seems reasonable that the binary pixel data would appear as 'nonsense characters' if displayed as ordinary text, since it wouldn't just include the ordinary printable ASCII characters, but other either non-printable or non-standard characters as well.
^^ here's the article for that repository
https://solarianprogrammer.com/2012/07/18/perlin-noise-cpp-11/

though this one is more relevant to ppm
https://solarianprogrammer.com/2011/12/16/cpp-11-thread-tutorial/
Last edited on
Topic archived. No new replies allowed.