c - 使用 C 读取图像 (PPM)
问题描述
所以我必须以 PPM 格式读取此图像,然后将其写入另一个文件。它可以工作,但是如果图像有评论,它就会停止工作。如果图像是这样的:
P3
3 2
255
255 0 0
0 255 0
0 0 255
255 255 0
255 255 255
0 0 0
它有效,但如果图像是这样的:
P3
3 2
255
# "3 2" is the width and height of the image in pixels
# "255" is the maximum value for each color
# The part below is image data: RGB triplets
255 0 0 # red
0 255 0 # green
0 0 255 # blue
255 255 0 # yellow
255 255 255 # white
0 0 0 # black
它停止工作。我真的不知道为什么,因为我已经编程忽略评论。我将在下面留下代码,也许有人可以提供帮助。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef struct pixel {
unsigned int r,g,b;
} pixel;
typedef struct imagem{
int cols,rows;
char mnumber[2];
int maxcolor;
pixel *matrix;
}imagem;
static imagem read(const char *filename)
{
imagem img;
FILE *f;
f = fopen(filename,"rb");
if(f == NULL) {
scanf("%c %c",&img.mnumber[0],&img.mnumber[1]);
scanf("%d %d",&img.cols,&img.rows);
scanf("%d",&img.maxcolor);
img.matrix = (pixel*) malloc(img.cols*img.rows*sizeof(pixel));
for(int i = 0; i < img.cols*img.rows;i++)
{
scanf("%u %u %u",&img.matrix[i].r,&img.matrix[i].g,&img.matrix[i].b);
}
} else {
int i = 0;
while(i != 2)
{
img.mnumber[i] = getc(f);
//printf("%c\n",(char) img.mnumber[i]);
i++;
}
int c = getc(f);
while (c == '#') {
while (getc(f) != '\n') {
getc(f);
}
c = getc(f);
}
ungetc(c, f);
fscanf(f,"%d %d",&img.cols,&img.rows);
fscanf(f,"%d",&img.maxcolor);
img.matrix = (pixel*)malloc(img.cols * img.rows* sizeof(pixel));
for(int i = 0; i < img.cols*img.rows;i++)
{
fscanf(f,"%u %u %u",&img.matrix[i].r,&img.matrix[i].g,&img.matrix[i].b);
}
fclose(f);
return img;
}
return img;
}
解决方案
我会把它写成这样的:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef struct pixel {
unsigned int r,g,b;
} pixel;
typedef struct imagem{
int cols, rows;
char mnumber[2];
int maxcolor;
pixel *matrix;
} imagem;
static imagem read(const char *filename)
{
imagem img;
FILE *f;
int i;
char buf[BUFSIZ];
if (filename == NULL) {
f = stdin;
} else {
f = fopen(filename, "r");
if (f == NULL) {
fprintf(stderr, "Can't open %s\n", filename);
exit(1);
}
}
if (fgets(buf, sizeof buf, f) == NULL) {
fprintf(stderr, "Can't read data\n");
exit(1);
}
for (i = 0; i < 2; i++) {
img.mnumber[i] = buf[i];
}
if (fgets(buf, sizeof buf, f) == NULL) {
fprintf(stderr, "Can't read data\n");
exit(1);
}
sscanf(buf, "%d %d", &img.cols, &img.rows);
if (fgets(buf, sizeof buf, f) == NULL) {
fprintf(stderr, "Can't read data\n");
exit(1);
}
sscanf(buf, "%d", &img.maxcolor);
img.matrix = malloc(img.cols * img.rows * sizeof(pixel));
if (img.matrix == NULL) {
fprintf(stderr, "malloc failed\n");
exit(1);
}
i = 0;
while (fgets(buf, sizeof buf, f) != NULL) {
if (buf[0] == '#') continue;
else {
sscanf(buf, "%u %u %u", &img.matrix[i].r, &img.matrix[i].g, &img.matrix[i].b);
i++;
}
} fclose(f);
return img;
}
- 正如建议的那样,最好使用 and 的组合,
fgets()
而sscanf()
不是fscanf()
特别是当我们需要处理不规则线条时。 stdin
当文件名被省略时,您不必编写特定的代码来读取。只需将文件指针分配f
给stdin
.- 建议将函数名称更改为
read()
其他名称,因为它与现有的系统调用函数冲突read(2)
。
推荐阅读
- c++ - 没有 const_cast<> 的 const 更改 为什么没有编译器警告/错误?
- node.js - 我应该在哪里存储 npm 包的个人数据?
- android - Maximo Anywhere 开发环境:预览版仅显示空白屏幕
- c++ - 将引用变量分配给引用变量
- python - 如何继续检查项目列表
- c# - AbpUserRequestCultureProvider 返回了以下不受支持的文化
- reactjs - 获取复选框中所有勾选项目的值
- node.js - 如何使用节点和 postgresql 数据库管理授权(不是身份验证)?
- c# - 自动映射器映射属性保持为空
- android - 无法解决:Lcom/google/android/gms/location/LocationRequest