[英]Trying to manually decode PGM image file. Where does my code fail?
我在编写将 RGB 图像(在本例中为 .ppm 文件)转换为灰度图像(.pgm 输出文件)的代码时遇到问题。 代码:
int i;
typedef struct {
unsigned char r, g, b;
} rgb;
FILE *fd;
FILE *gr;
rgb *img;
unsigned width, height;
fd = fopen("rocks.ppm", "r");
fscanf(fd, "%d %d\n", &width, &height);
img = calloc(3, width * height);
fread(img, 3, width * height, fd);
unsigned char *gray;
double len = width * height;
gray = calloc(1, len);
for (i = 0; i < len; i++) {
gray[i] = img[i].r * 0.2126 + img[i].g * 0.7152 + img[i].b * 0.0722;
}
fclose(fd);
gr = fopen("rocks_gray.pgm", "w");
fprintf(gr, "P5\n%d %d\n255\n", width, height);
fwrite(gray, 1, len, gr);
fclose(gr);
当我编译并运行代码时,创建的图像文件完全变黑了,我无法指出问题所在。 任何帮助将不胜感激。
问题出在这里: fscanf(fd, "%d %d\n", &width, &height);
ppm文件以P6
开头,因此fscanf()
无法转换任何内容并返回0
, width
和height
保持不变,因此未初始化,导致程序的其余部分具有未定义的行为。
您应该更改fscanf()
并检查返回值。
更一般地说,您应该始终检查可能导致未定义行为的错误并使用有意义的错误消息报告问题。
这是修改后的版本:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
unsigned char r, g, b;
} rgb;
int main() {
const char *input_file = "rocks.ppm";
FILE *fd = fopen(input_file, "rb");
if (fd == NULL) {
perror(input_file);
return 1;
}
unsigned width, height;
char newline[2];
// Accept binary pixmaps:
// P6 <whitespace> width <whitespace> height <whitespace> 255 <single space> <raster>
if (fscanf(fd, "P6 %u %u 255%1[ \t\r\n\v\f]", &width, &height, newline) != 3) {
fprintf(stderr, "%s: invalid source format\n", input_file);
fclose(fd);
return 1;
}
unsigned len = width * height;
rgb *img = calloc(len, 3);
if (img == NULL) {
fprintf(stderr, "cannot allocate memory for %u pixels\n", len);
fclose(fd);
return 1;
}
if (fread(img, 3, len, fd) != len) {
fprintf(stderr, "%s: cannot read %u pixels\n", input_file, len);
fclose(fd);
return 1;
}
fclose(fd);
unsigned char *gray = calloc(len, 1);
if (gray == NULL) {
fprintf(stderr, "cannot allocate memory for %u gray scales\n", len);
return 1;
}
for (unsigned i = 0; i < len; i++) {
// using non standard gray scale conversion
gray[i] = img[i].r * 0.2126 + img[i].g * 0.7152 + img[i].b * 0.0722;
}
const char *output_file = "rocks_gray.pgm";
FILE *gr = fopen(output_file, "wb");
if (gr == NULL) {
perror(output_file);
return 1;
}
fprintf(gr, "P5\n%u %u\n255\n", width, height);
fwrite(gray, 1, len, gr);
fclose(gr);
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.