C未进入合并2 PPM图像的循环
我已经完全麻木了试图合并两个相同类型和大小的PPM图像在一起。我的代码可以读取、显示和保存PPM图像,但不会进入组合两个图像的for循环。下面是组合函数:C未进入合并2 PPM图像的循环,c,for-loop,struct,malloc,ppm,C,For Loop,Struct,Malloc,Ppm,我已经完全麻木了试图合并两个相同类型和大小的PPM图像在一起。我的代码可以读取、显示和保存PPM图像,但不会进入组合两个图像的for循环。下面是组合函数: struct MFI AddImages (struct MFI AddImgOne, struct MFI AddImgTwo) { struct MFI AddImgThree = {'P6', AddImgOne.ImgHeight, AddImgOne.ImgWidth, AddImgOne.
struct MFI AddImages (struct MFI AddImgOne, struct MFI AddImgTwo)
{
struct MFI AddImgThree = {'P6', AddImgOne.ImgHeight, AddImgOne.ImgWidth, AddImgOne.MaxInfo, AddImgOne.ImageSize};
int CombineCounter;
if(AddImgOne.ImgWidth != AddImgTwo.ImgWidth || AddImgOne.ImgHeight != AddImgTwo.ImgHeight)
{
printf("They're not the same size you dummy!");
exit(0);
}
AddImgThree.ImageSize = AddImgOne.ImgHeight * AddImgTwo.ImgWidth;
AddImgThree.ImageMemory = malloc(AddImgThree.ImageSize * sizeof(unsigned long long));
if (!AddImgThree.ImageMemory)
{printf("theres no space!\n");
exit(0);}
if (AddImgThree.ImageMemory)
{
for (CombineCounter = 1; CombineCounter < AddImgOne.ImageSize; CombineCounter++)
{
AddImgThree.RGB[CombineCounter].red = AddImgOne.RGB[CombineCounter].red + AddImgTwo.RGB[CombineCounter].red;
AddImgThree.RGB[CombineCounter].blue = AddImgOne.RGB[CombineCounter].blue + AddImgTwo.RGB[CombineCounter].blue;
AddImgThree.RGB[CombineCounter].green = AddImgOne.RGB[CombineCounter].green + AddImgTwo.RGB[CombineCounter].green;
if (AddImgThree.RGB[CombineCounter].red > 255)
{AddImgThree.RGB[CombineCounter].red = 255;}
if (AddImgThree.RGB[CombineCounter].blue > 255)
{AddImgThree.RGB[CombineCounter].blue = 255;}
if (AddImgThree.RGB[CombineCounter].green > 255)
{AddImgThree.RGB[CombineCounter].green = 255;}
}
}
else
printf ("it's not right\n");
free(AddImgThree.ImageMemory);
return AddImgThree;
}
struct MFI Reading (char filename[128])
{
struct MFI R;
FILE *ImageRead; // file pointer or handle
int p;
if(strstr(filename, ".ppm") == NULL)
{strcat(filename, ".ppm");}
ImageRead = fopen(filename, "rb");
//check if it exists
if (ImageRead == NULL) {
printf("Nope doesn't exist\n");
exit(0);}
//get all the image information
fscanf(ImageRead, "%s %d %d %d", R.Format, &R.ImgWidth, &R.ImgHeight, &R.MaxInfo);
//allocate memory for image//
R.ImageMemory = malloc(R.ImgHeight * R.ImgWidth * sizeof(int*));
if (!R.ImageMemory)
{printf("theres no space!\n");
exit(0);}
//check if its a PPM
if (!strcmp(R.Format, "P3"))
printf("This is a ppm\n");
else
{
if (!strcmp (R.Format, "P2"))
printf("This is a pgm\n");
else
{
if (!strcmp (R.Format, "P5"))
printf("This is a pgm\n");
else
{printf("this isn't a ppm file");}
}
}
p = getc(ImageRead);
while (p == '#')
{
while (getc(ImageRead) != '\n')
{
p = getc(ImageRead);
}
}
ungetc(p, ImageRead);
//check image size
if(R.ImgHeight > 1080 || R.ImgWidth > 1920)
{printf ("This is too big!!");}
R.ImageSize = R.ImgWidth*R.ImgHeight;
while (fgetc(ImageRead) != '\n');
R.RGB = malloc(3*R.ImageSize * sizeof(R.RGB));
if (fread(R.RGB, 3*R.ImgHeight, 4*R.ImgWidth-3, ImageRead) != EOF)
printf("error with loading image");
//reading image width and height
printf("The height of the image is %d and the width is %d\n", R.ImgWidth, R.ImgHeight);
printf("The maximum value of each pixel is %d\n", R.MaxInfo);
return R;
}
void Save(struct MFI S)
{ FILE *SavePointer;
char InputFileName[128];
printf("\nPlease Enter the Name of the file you want to Store this Array In: \n");
scanf("%s", InputFileName);
SavePointer = fopen(InputFileName, "r");
if(SavePointer != NULL)
{
printf("File exits, try another name");
fclose(SavePointer);
exit(0);
}
else
{
fclose(SavePointer);
printf("File is good to go!");
}
if(strstr(InputFileName, ".ppm") == NULL)
{strcat(InputFileName, ".ppm");}
SavePointer = fopen(InputFileName, "wb");
if (!SavePointer)
{
printf ("Lost your File pointer!");
exit (0);
}
fprintf(SavePointer, "%s\n%d %d\n%d\n", S.Format, S.ImgWidth, S.ImgHeight, S.MaxInfo);
fwrite(S.RGB, 3*S.ImgHeight, 4*S.ImgWidth-3, SavePointer);
fclose(SavePointer);
return;
}
和我的保存功能:
struct MFI AddImages (struct MFI AddImgOne, struct MFI AddImgTwo)
{
struct MFI AddImgThree = {'P6', AddImgOne.ImgHeight, AddImgOne.ImgWidth, AddImgOne.MaxInfo, AddImgOne.ImageSize};
int CombineCounter;
if(AddImgOne.ImgWidth != AddImgTwo.ImgWidth || AddImgOne.ImgHeight != AddImgTwo.ImgHeight)
{
printf("They're not the same size you dummy!");
exit(0);
}
AddImgThree.ImageSize = AddImgOne.ImgHeight * AddImgTwo.ImgWidth;
AddImgThree.ImageMemory = malloc(AddImgThree.ImageSize * sizeof(unsigned long long));
if (!AddImgThree.ImageMemory)
{printf("theres no space!\n");
exit(0);}
if (AddImgThree.ImageMemory)
{
for (CombineCounter = 1; CombineCounter < AddImgOne.ImageSize; CombineCounter++)
{
AddImgThree.RGB[CombineCounter].red = AddImgOne.RGB[CombineCounter].red + AddImgTwo.RGB[CombineCounter].red;
AddImgThree.RGB[CombineCounter].blue = AddImgOne.RGB[CombineCounter].blue + AddImgTwo.RGB[CombineCounter].blue;
AddImgThree.RGB[CombineCounter].green = AddImgOne.RGB[CombineCounter].green + AddImgTwo.RGB[CombineCounter].green;
if (AddImgThree.RGB[CombineCounter].red > 255)
{AddImgThree.RGB[CombineCounter].red = 255;}
if (AddImgThree.RGB[CombineCounter].blue > 255)
{AddImgThree.RGB[CombineCounter].blue = 255;}
if (AddImgThree.RGB[CombineCounter].green > 255)
{AddImgThree.RGB[CombineCounter].green = 255;}
}
}
else
printf ("it's not right\n");
free(AddImgThree.ImageMemory);
return AddImgThree;
}
struct MFI Reading (char filename[128])
{
struct MFI R;
FILE *ImageRead; // file pointer or handle
int p;
if(strstr(filename, ".ppm") == NULL)
{strcat(filename, ".ppm");}
ImageRead = fopen(filename, "rb");
//check if it exists
if (ImageRead == NULL) {
printf("Nope doesn't exist\n");
exit(0);}
//get all the image information
fscanf(ImageRead, "%s %d %d %d", R.Format, &R.ImgWidth, &R.ImgHeight, &R.MaxInfo);
//allocate memory for image//
R.ImageMemory = malloc(R.ImgHeight * R.ImgWidth * sizeof(int*));
if (!R.ImageMemory)
{printf("theres no space!\n");
exit(0);}
//check if its a PPM
if (!strcmp(R.Format, "P3"))
printf("This is a ppm\n");
else
{
if (!strcmp (R.Format, "P2"))
printf("This is a pgm\n");
else
{
if (!strcmp (R.Format, "P5"))
printf("This is a pgm\n");
else
{printf("this isn't a ppm file");}
}
}
p = getc(ImageRead);
while (p == '#')
{
while (getc(ImageRead) != '\n')
{
p = getc(ImageRead);
}
}
ungetc(p, ImageRead);
//check image size
if(R.ImgHeight > 1080 || R.ImgWidth > 1920)
{printf ("This is too big!!");}
R.ImageSize = R.ImgWidth*R.ImgHeight;
while (fgetc(ImageRead) != '\n');
R.RGB = malloc(3*R.ImageSize * sizeof(R.RGB));
if (fread(R.RGB, 3*R.ImgHeight, 4*R.ImgWidth-3, ImageRead) != EOF)
printf("error with loading image");
//reading image width and height
printf("The height of the image is %d and the width is %d\n", R.ImgWidth, R.ImgHeight);
printf("The maximum value of each pixel is %d\n", R.MaxInfo);
return R;
}
void Save(struct MFI S)
{ FILE *SavePointer;
char InputFileName[128];
printf("\nPlease Enter the Name of the file you want to Store this Array In: \n");
scanf("%s", InputFileName);
SavePointer = fopen(InputFileName, "r");
if(SavePointer != NULL)
{
printf("File exits, try another name");
fclose(SavePointer);
exit(0);
}
else
{
fclose(SavePointer);
printf("File is good to go!");
}
if(strstr(InputFileName, ".ppm") == NULL)
{strcat(InputFileName, ".ppm");}
SavePointer = fopen(InputFileName, "wb");
if (!SavePointer)
{
printf ("Lost your File pointer!");
exit (0);
}
fprintf(SavePointer, "%s\n%d %d\n%d\n", S.Format, S.ImgWidth, S.ImgHeight, S.MaxInfo);
fwrite(S.RGB, 3*S.ImgHeight, 4*S.ImgWidth-3, SavePointer);
fclose(SavePointer);
return;
}
编辑
我已经重写了函数的最后一部分,所以现在程序将进入for循环,但在分配数组元素值时将停止
for (CombineCounter = 0; CombineCounter < AddImgOne.ImageSize; CombineCounter++)
{
unsigned int red = AddImgOne.RGB[CombineCounter].red + AddImgTwo.RGB[CombineCounter].red;
if (red > 255)
{red = 255;}
AddImgThree.RGB[CombineCounter].red = red; //exits entire code when here
unsigned int blue = AddImgOne.RGB[CombineCounter].blue + AddImgTwo.RGB[CombineCounter].blue;
if (blue > 255)
{blue = 255;}
AddImgThree.RGB[CombineCounter].blue = blue;
unsigned int green = AddImgOne.RGB[CombineCounter].green + AddImgTwo.RGB[CombineCounter].green;
if (green > 255)
{green = 255;}
AddImgThree.RGB[CombineCounter].green = green;
}
(CombineCounter=0;CombineCounter通过调整剪辑,
添加的图像非常接近
但是,代码中的其他地方存在一些问题
在读取中
,我们需要分配RGB
(而不是ImageMemory
)。正如我在顶部评论中提到的,ImageMemory
是多余的
我们想要的是fgetc
,而不是getc
读取
检查有效格式,但它只处理P6
[binary]格式
P6
格式的像素可以大于一个字节[如果MaxInfo
是65535而不是255]。但是,Reading
尝试对像素数据执行单个fread
,因此我们只能处理255种情况
但是,[再次]正如我在顶部评论中提到的,这些是字节(即无符号字符
)值。因此,RGBPixel
的每个元素都需要是unsigned char
而不是int
正如您所看到的(例如),文件中像素0的RGB值和像素1的R值存储在第一个RGB数组元素的[4字节]red
元素中
fread
返回计数,而不是EOF
fread
调用[和Save
]中的fwrite
未传输正确的字节数
并非所有调用都会检查错误返回。而且,如果他们确实出错,它可以帮助打印原因(例如,strerror(errno)
)
不要在stdin
上执行fseek
虽然“按值”将struct
传递给函数是有效的,但更常见的是“按指针”传递struct
。按值传递时,struct
的全部内容必须推送到堆栈上。而且,如果按值返回结构
,调用方必须在堆栈帧中为返回值保留空间
在目前的情况下,这并不太糟糕。但是,它的伸缩性不太好。如果(例如)有一个包含大量数据的struct
,它可能非常慢,并可能导致堆栈溢出:
struct bigstruct {
int x;
int y;
int array[10000000];
};
从风格上讲,保持参数名和堆栈变量名简短是一种很好的做法
下面是重构后的代码。我添加了一些注释。在可能的情况下,我用cpp
条件将旧代码和新代码括起来:
#if 0
// old code
#else
// new code
#endif
我还为struct
s添加了typedef
语句。我将函数转换为使用指向结构的指针
虽然我试图尽可能多地保留您的代码,但我不得不对其进行一些重构
正如我提到的,AddImages
状态良好,但我对其进行了重构,使其更简单,并演示了指向像素的指针的使用
我用一些P6
文件图像对它进行了测试,它似乎可以工作
下面是代码:
#include <stdio.h> /* printf, scanf, seekf */
#include <string.h> /* strstr, strcmp, strcat */
#include <stdlib.h> /* malloc free command */
#include <errno.h>
#include <sys/stat.h>
#define fault(_fmt...) \
do { \
printf(_fmt); \
exit(1); \
} while (0)
typedef struct RGBPixel {
#if 0
int red;
int green;
int blue;
#else
unsigned char red;
unsigned char green;
unsigned char blue;
#endif
} RGBPixel;
typedef struct MFI {
char Format[3];
int ImgHeight;
int ImgWidth;
int MaxInfo;
int ImgSize;
RGBPixel *RGB;
} MFI;
void
Display(MFI *D)
{
}
static inline unsigned char
AddPixel(unsigned int p1,unsigned int p2)
{
unsigned int p3;
// NOTE: to prevent truncation on the right side of the assignment, we're
// using "unsigned int" [instead of "unsigned char"] for the arguments.
//
// as part of the C calling conventions, passing "unsigned char" values are
// "zero extended" to "unsigned int" _even_ if the arg is "unsigned char"
// because [most] stack pushes have to be word aligned
//
// we take advantage of that to eliminate the explicit casting below
#if 0
p3 = (unsigned int) p1 + (unsigned int) p2;
#else
p3 = p1 + p2;
#endif
if (p3 > 255)
p3 = 255;
return p3;
}
void
AddImages(MFI *img3,const MFI *img1,const MFI *img2)
{
int CombineCounter;
const RGBPixel *pix1;
const RGBPixel *pix2;
RGBPixel *pix3;
if (img1->ImgWidth != img2->ImgWidth || img1->ImgHeight != img2->ImgHeight)
fault("They're not the same size you dummy!");
*img3 = *img1;
img3->RGB = malloc(sizeof(*img3->RGB) * img3->ImgSize);
if (img3 == NULL)
fault("no memory for img3 -- %s\n",strerror(errno));
pix1 = img1->RGB;
pix2 = img2->RGB;
pix3 = img3->RGB;
for (CombineCounter = 0; CombineCounter < img1->ImgSize;
++CombineCounter, ++pix3, ++pix1, ++pix2) {
pix3->red = AddPixel(pix1->red,pix2->red);
pix3->green = AddPixel(pix1->green,pix2->green);
pix3->blue = AddPixel(pix1->blue,pix2->blue);
}
}
void
P6read(MFI *img,FILE *ImageRead)
{
size_t count;
count = fread(img->RGB,sizeof(*img->RGB),img->ImgSize,ImageRead);
if (count != img->ImgSize)
fault("error with loading image -- %s\n",strerror(errno));
}
void
Reading(MFI *img,char *filename)
{
FILE *ImageRead; // file pointer or handle
int p;
if (strstr(filename, ".ppm") == NULL) {
strcat(filename, ".ppm");
}
printf("Reading: %s ...\n",filename);
ImageRead = fopen(filename, "rb");
// check if it exists
if (ImageRead == NULL)
fault("Nope doesn't exist\n");
// get all the image information
fscanf(ImageRead, "%s %d %d %d",
img->Format, &img->ImgWidth, &img->ImgHeight, &img->MaxInfo);
img->ImgSize = img->ImgWidth * img->ImgHeight;
// allocate memory for image
img->RGB = malloc(sizeof(*img->RGB) * img->ImgSize);
if (img->RGB == NULL)
fault("theres no space!\n");
// skip over comment
#if 0
p = fgetc(ImageRead);
while (p == '#') {
while (fgetc(ImageRead) != '\n') {
p = fgetc(ImageRead);
}
}
ungetc(p, ImageRead);
#else
while (1) {
p = fgetc(ImageRead);
if (p != '#')
break;
while (1) {
if (p == '\n')
break;
if (p == EOF)
break;
p = fgetc(ImageRead);
}
}
if (p != '\n')
fault("image file too short\n");
#endif
// check image size
if (img->ImgHeight > 1080 || img->ImgWidth > 1920)
fault("This is too big -- ImgHeight=%d ImgWidth=%d\n",
img->ImgHeight,img->ImgWidth);
// reading image width and height
printf("The height of the image is %d and the width is %d\n",
img->ImgWidth, img->ImgHeight);
printf("The maximum value of each pixel is %d\n", img->MaxInfo);
switch (img->Format[0]) {
case 'P':
switch (img->Format[1]) {
case '1':
fault("This is a P1\n");
break;
case '2':
fault("This is a pgm\n");
break;
case '3':
fault("This is a ppm P3\n");
break;
case '5':
printf("This is a pgm\n");
break;
case '6':
printf("This is a ppm P6\n");
if (img->MaxInfo == 255)
P6read(img,ImageRead);
else
fault("Unsupported pixel size -- MaxInfo=%d\n",img->MaxInfo);
break;
default:
fault("this isn't a ppm file");
break;
}
break;
default:
fault("this isn't a ppm file");
break;
}
}
void
Save(const MFI *img,char *InputFileName)
{
FILE *SavePointer;
// NOTE/FIX: this must be done _before_ the existence check
#if 1
if (strstr(InputFileName, ".ppm") == NULL)
strcat(InputFileName, ".ppm");
#endif
#if 0
SavePointer = fopen(InputFileName, "r");
if (SavePointer != NULL) {
fclose(SavePointer);
exit(0);
}
else {
fclose(SavePointer);
printf("File is good to go!");
}
#else
struct stat st;
if (stat(InputFileName,&st) >= 0)
fault("File exists, try another name");
printf("File is good to go!");
#endif
// NOTE/BUG: this must be done _before_ the existence check
#if 0
if (strstr(InputFileName, ".ppm") == NULL)
strcat(InputFileName, ".ppm");
#endif
SavePointer = fopen(InputFileName, "wb");
if (!SavePointer)
fault("unable to open output file -- %s\n",strerror(errno));
fprintf(SavePointer, "%s\n%d %d\n%d\n",
img->Format, img->ImgWidth, img->ImgHeight, img->MaxInfo);
#if 0
fwrite(S.RGB, 3 * S.ImgHeight, 4 * S.ImgWidth - 3, SavePointer);
#else
size_t count = fwrite(img->RGB,sizeof(*img->RGB),img->ImgSize,SavePointer);
if (count != img->ImgSize)
fault("fault during fwrite -- %s\n",strerror(errno));
#endif
fclose(SavePointer);
}
void
getfile(char ***argp,char *file,const char *prompt)
{
char **argv = *argp;
char *cp;
do {
cp = *argv;
if (cp != NULL) {
++argv;
strcpy(file,cp);
printf("%s is %s\n",prompt,file);
break;
}
printf("please enter the name of %s:",prompt);
scanf(" %s",file);
} while (0);
*argp = argv;
}
int
main(int argc,char **argv)
{
struct MFI ImgOne;
struct MFI ImgTwo;
struct MFI ImgThree;
char Image1[128];
char Image2[128];
char Image3[128];
--argc;
++argv;
getfile(&argv,Image1,"image 1");
getfile(&argv,Image2,"image 2");
getfile(&argv,Image3,"output");
#if 0
ImgOne = Reading(Image1);
ImgTwo = Reading(Image2);
#else
Reading(&ImgOne,Image1);
Reading(&ImgTwo,Image2);
#endif
#if 0
Display(ImgOne);
Display(ImgTwo);
#endif
#if 0
ImgThree = AddImages(ImgOne, ImgTwo);
#else
AddImages(&ImgThree, &ImgOne, &ImgTwo);
#endif
Save(&ImgThree,Image3);
printf("\nfile is closed\n");
#if 0
free(ImgOne.ImageMemory);
free(ImgTwo.ImageMemory);
free(ImgThree.ImageMemory);
#else
free(ImgOne.RGB);
free(ImgTwo.RGB);
free(ImgThree.RGB);
#endif
printf("\nimage freed\n");
return 0;
}
#包括/*printf、scanf、seekf*/
#包括/*strstr、strcmp、strcat*/
#include/*malloc free命令*/
#包括
#包括
#定义故障(_fmt…)\
做{\
printf(_fmt)\
出口(1)\
}而(0)
typedef结构RGBPixel{
#如果0
红色;
绿色;
蓝色;
#否则
无符号字符红色;
无符号字符绿色;
无符号字符蓝色;
#恩迪夫
}RGB像素;
类型定义结构MFI{
字符格式[3];
国际照明;
int ImgWidth;
int MaxInfo;
int ImgSize;
RGB像素*RGB;
}货币金融机构;
无效的
显示器(MFI*D)
{
}
静态内联无符号字符
AddPixel(无符号整数p1、无符号整数p2)
{
无符号整数p3;
//注意:为了防止在赋值的右侧截断,我们
//使用“unsigned int”[而不是“unsigned char”]作为参数。
//
//作为C调用约定的一部分,传递“unsigned char”值是
//如果arg为“unsigned char”,则“零扩展”为“unsigned int”
//因为[大多数]堆栈推送必须是字对齐的
//
//我们利用这一点来消除下面的显式转换
#如果0
p3=(无符号整数)p1+(无符号整数)p2;
#否则
p3=p1+p2;
#恩迪夫
如果(p3>255)
p3=255;
返回p3;
}
无效的
附加映像(MFI*img3、常量MFI*img1、常量MFI*img2)
{
int组合计数器;
常数RGBPixel*pix1;
常数RGBPixel*pix2;
RGB像素*pix3;
如果(img1->ImgWidth!=img2->ImgWidth | | img1->ImgHeight!=img2->ImgHeight)
错误(“它们和你这个笨蛋的尺寸不一样!”);
*img3=*img1;
img3->RGB=malloc(sizeof(*img3->RGB)*img3->ImgSize);
如果(img3==NULL)
故障(“img3没有内存--%s\n”,strerror(errno));
pix1=img1->RGB;
pix2=img2->RGB;
pix3=img3->RGB;
法罗群岛