我有一个关于zybook的项目。而且我的代码似乎可以正常工作,因为它可以正确突出显示不同图像的边缘。但是,zybooks是自动的,并且使我的edgedetect功能失效。这是我的两个功能的代码:
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<string.h>
#include<limits.h>
typedef struct _image {
int** pixels;
int width;
int height;
} Image;
Image* readImage(char* filename) {
Image *pic= malloc(sizeof(Image));
char type[3];
int maxvalue;
FILE *f1=NULL;
f1= fopen(filename,"r");
if(f1==NULL){
printf("Unable to read image: %s\n",filename);
return NULL;
}
fscanf(f1,"%s",type);
fscanf(f1,"%d",&pic->width);
fscanf(f1,"%d",&pic->height);
fscanf(f1,"%d",&maxvalue);
pic->pixels = (int **)malloc(sizeof(int *) * pic->height);
for (int i = 0; i < pic->height; i++) {
pic->pixels[i] = (int *)malloc(sizeof(int) * pic->width);
}
for (int i = 0; i < pic->height; i++) {
for (int j = 0; j < pic->width; j++) {
fscanf(f1,"%d",&pic->pixels[i][j]);
}
}
fclose(f1);
return pic;
}
Image* edgeDetect(Image* img, int threshold) {
Image *edges;
edges=malloc(sizeof(Image));
edges->pixels = (int **)malloc(sizeof(int *) * img->height);
for (int i = 0; i < img->height; i++) {
edges->pixels[i] = (int *)malloc(sizeof(int) * img->width);
}
edges->height = img->height;
edges->width = img->width;
for (int i = 0; i < img->height; i++) {
for (int j = 0; j < img->width; j++) {
edges->pixels[i][j]=0;
}
}
for(int i=0; i< edges->height;i++){
for(int j=0; j<edges->width; j++){
if( i > 0 && i< (edges->height-1) && j>0 && j<(edges->width-1) ){
if(abs(img->pixels[i][j] - img->pixels[i][j+1]) > threshold || abs(img->pixels[i][j] - img->pixels[i-1][j]) > threshold)
edges->pixels[i][j]=255;
}
}
}
return edges;
}
int saveImage(char* filename, Image* img) {
FILE* f1= NULL;
f1= fopen(filename,"w");
if(f1==NULL){
printf("Unable to write image: %s\n",filename);
return 1;
}
fprintf(f1,"P2\n");
fprintf(f1,"%d %d\n",img->width,img->height);
fprintf(f1,"255\n");
for (int i = 0; i < img->height; i++) {
for (int j = 0; j < img->width; j++) {
fprintf(f1,"%d ",img->pixels[i][j]);
}
fprintf(f1,"\n");
}
fclose(f1);
return 0;
}
void freeImage(Image* img) {
for (int i = 0; i < img->height; i++) {
free(img->pixels[i]);
}
free(img->pixels);
free(img);
}
int main(int argc, char** argv) {
if( argc !=4){
printf("Usage: ./a.out input.pgm output.pgm threshold\n");
return 1;
}
int threshold= atoi(argv[3]);
Image *data;
data=readImage(argv[1]);
if (data==NULL)
return 1;
Image *edge;
edge= edgeDetect(data,threshold);
freeImage(data);
int result= saveImage(argv[2],edge);
if (result==1)
return 1;
freeImage(edge);
return 0;
}
任何技巧都会有所帮助。我知道代码可能会令人困惑,因为它可能不遵循标准格式,但这实际上是我的第一个编码类。
关于:
Image *pic= malloc(sizeof(Image));
始终检查(!= NULL)返回值以确保操作成功。如果不成功,请致电
perror( "your error message" );
将错误消息和系统认为发生错误的文本原因输出到stderr
。
关于:
printf("Unable to read image: %s\n",filename);
错误消息应输出到stderr
,而不是stdout
。建议使用:
fprintf( stderr, "Unable to read image: %s\n %s\n", filename, strerror( errno ) );
[当调用scanf()
系列的任何功能时,例如fscanf()
,请始终检查返回的值(而不是参数值)以确保操作成功。注意:该函数系列返回成功的“输入格式转换”说明符的数量。
关于:
fscanf(f1,"%s",type);
%s
和/或%[...]
时,始终包含MAX CHARACTERS小于输入缓冲区长度的修饰符避免任何缓冲区溢出和未定义的行为,因为那些“输入格式转换”说明符总是将NUL字节附加到输入。关于:
pic->pixels = (int **)malloc(sizeof(int *) * pic->height);
在C中,返回的类型为void*
,可以将其分配给任何指针。强制转换只会使代码混乱。建议删除演员表。
为了便于阅读和理解:
for
if
else
while
do...while
switch
case
default
应该通过单个空白行分隔。 始终缩进代码。在每个大括号“ {”之后缩进。在每个右大括号'}'之前不要缩进。建议每个缩进级别是4个空格
插入适当的水平空间:括号内,在括号内,在括号内,在逗号后,在分号之后,围绕C运算符
函数:malloc()
期望参数的类型为size_t
。像这样的语句:
edges->pixels = (int **)malloc(sizeof(int *) * img->height);
作为参数的一部分传递了
int
。 (即img->height
)会导致int
和size_t
之间的隐式转换,“通常”无害,但仍然是危险的转换。