Reputation: 13
I have a litte problem with the following, simple read function:
printf("File to be opened: ");
scanf("%s", input);
if ((fp = fopen(input, "r")) == NULL) {
printf("ERROR: can't open %s!", input);
}
else {
if (read_pgm_hdr(fp, &w, &h) != -1) {
printf("*** SUCCESS --%s-- opened ***\n", input);
printf("*** PGM file recognized, reading data into image struct ***\n");
for (i = 0; i < w * h; i++) {
img_data[i] = getc(fp);
}
}
In the loop, the img_data array is filled with 8bit-grayscale values of an image in .pgm. With w = 300 and h = 300, the array has the right size. In most cases, it works fine. But sometimes in the middle of an image, getc() starts filling my array with 255.
I found out that this happens, when the grayscale value is 19. It doesn't matter, where this value occurs. If the 3rd pixel is 19, the 3rd value and every following are 255. If the 127th pixel is 19, the 127th value and every following are 255.
I really have no idea, why this is happening. I hope anyone can help.
UPDATE: Ok, thank you. The combination of opening in binary mode and using fread instead of getc solved the Problem :)
Saku
Upvotes: 1
Views: 425
Reputation: 149115
I could not reproduce under Unix, but could easily reproduce under Windows. The problem is the character Ctrl-Z (code 0x1A) which under windows represents an End Of File for text files.
The problem is that getc is normally used for text files and as some old editors used to explicitely write a Ctrl-Z to delimit the end of a text file, getc still consideres it as a true EOF - BTW this is coherent with Klas Lindbäck's answer. More as you open the file in "r"
mode, it is implicetly opened as a text file.
The fix is trivial : open the file as a binary file.
if ((fp = fopen(input, "rb")) == NULL) ...
(note the b) should be enough.
For the character 19 cited in question, I did the test with the table of ASCII characters and the last correct was ... Ctrl-Y = 0x19 ... but the culprit is indeed Ctrl-Z = 0x1A.
Anyway, you should replace the loop reading one character at a time :
for (i = 0; i < w * h; i++) {
img_data[i] = getc(fp);
}
with a simple fread :
n = fread(img_data, w, h, fp); // or fread(img_data, 1, w * h, fp);
and control that n is h in first way or n * h in second.
Upvotes: 3
Reputation: 33273
255 would be the result of getc
returning EOF
.
To test for EOF
you need to store the value in an int
:
for (i = 0; i < w * h; i++) {
int tmp = getc(fp);
if (tmp == EOF) {
/* Handle EOF */
printf("EOF after readin %d bytes out of %d!!!\n", i, w*h);
break;
}
img_data[i] = tmp;
}
Upvotes: 0