因此,我的代码包括读取PPM图像,然后将其存储在数组中,以便将其保存在新的PPM文件中。尽管我认为我的指针有问题,这意味着它实际上并没有读取文件。此外,我的代码在为数组分配内存后结束。非常感谢您的帮助。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define maxheight 1080
#define maxwidth 1920
#define RGB_COMPONENT_COLOUR 255
#define pgmtype "P2"
#define ppmtype "P3"
typedef struct
{
int red, green, blue;
} PPMPixel;
typedef struct
{
int x, y;
} PPMImage;
typedef struct
{
int rgb_comp_colour;
char filetype[3];
int height;
int width;
} PPMHead;
/*PPMHead head[3];
{
head[3].filetype;
head[3].height;
head[3].width;
}*/
PPMHead head;
PPMHead* head_ptr = &head;
PPMPixel p;
PPMPixel* p_ptr = &p;
PPMPixel *data; //Defines pointer to PPMPixel
int **Array; //Double pointer defines as a pointer pointing to a pointer that is pointing to an integer
PPMPixel **RGBArray; //Double pointer defines as a pointer pointing to a pointer that is pointing to the PPMPixel structure
FILE *fp;
int r, g, b;
void headercheck ()
{
fscanf(fp, "%s %d %d %d", head.filetype, &head.width, &head.height, &head.rgb_comp_colour);
printf("%s %d %d %d", head.filetype, head.width, head.height, head.rgb_comp_colour);
if (head.width > maxwidth || head.height > maxheight)
{
printf("tInvalid image size. The maximum value of image is 1920x1080.n");
printf("tImage size is %d x %dn", head.width, head.height);
}
else
{
printf("tImage size is validn");
printf("tImage size is %d x %dn", head.width, head.height);
}
if ((strcmp (head.filetype, pgmtype)!=0) && (strcmp (head.filetype, ppmtype)!=0))
{
printf("tInvalid filetypen");
}
else
{
if(strcmp (head.filetype, pgmtype)==0)
{
printf("t File is PGM type imagen");
}
else
{
if(strcmp (head.filetype, ppmtype)==0)
{
printf("t File is PPM type imagen");
}
}
}
if ((head.rgb_comp_colour == RGB_COMPONENT_COLOUR))
{
printf("t Image is 8 bitn");
}
else
{
if (head.rgb_comp_colour > RGB_COMPONENT_COLOUR)
{
printf("Maximum bit-depth is 8 bitsn");
}
else
{
printf("tImage is not 8 bitn");
}
}
}
int main(void)
{
char fname[100];
printf("Enter file name: ");
scanf("%s", fname);
fseek(stdin,0,SEEK_END);
fp = fopen(fname, "r");
if (fp == NULL)
{
printf("tError while opening the filen");
}
else
{
printf("tReading in %sn", fname);
}
headercheck();
if (strcmp (head.filetype, ppmtype)==0)
{
RGBArray = (PPMPixel **)malloc(head.height*sizeof(PPMPixel*)); //Points to malloc
if((RGBArray == NULL))
{
printf("Error allocating memory to the array");
}
else
{
printf("Memory allocated to the PPM array sucessfully");
}
for (int i=0;i<head.width;i++)
{
RGBArray[i] = (PPMPixel *)malloc(head.width*sizeof(PPMPixel));
}
printf("Error 2");
//Initialising each element
for (int j=0;j<head.height;j++)
{
for (int i=0;i<head.width;i++)
{
fscanf(fp, "%3d %3d %3d ", &p.red, &p.green, &p.blue); //Scans in integers of the address pointer to PPMPixel
data = &RGBArray[i][j]; //Defines data pointer pointing to address of RGBArray[i][j]
data->red = p.red; //Access member of PPMPixel structure to equal one of the three RGB channels
data->green = p.green;
data->blue = p.blue;
}
}
}
fclose(fp);
//Save PPM Array Into New PPM File
FILE *pf;
int i, j;
char fname2[100];
printf("Enter file name: ");
scanf("%s", fname2);
fseek(stdin,0,SEEK_END);
pf = fopen(fname2, "w");
if (pf == NULL)
{
printf("tError while opening the filen");
}
else
{
printf("tWriting in %sn", fname2);
}
for(j=0;j<head.height;j++)
{
fprintf(pf, "n");
for(i=0;i<head.width;i++)
{
fprintf(pf, "%3d ", RGBArray[i][j].red);
fprintf(pf, "%3d ", RGBArray[i][j].green);
fprintf(pf, "%3d ", RGBArray[i][j].blue);
//fprintf(pf, "%3d ", (RGBArray+j*head.width + i)*r);
//fprintf(pf, "%3d ", (RGBArray+j*head.width + i)*g);
//fprintf(pf, "%3d ", (RGBArray+j*head.width + i)*b);
}
}
fclose(pf);
free(RGBArray);
RGBArray = NULL;
for(int i=0;i<head.width;i++)
{
free(RGBArray[i]);
RGBArray[i] = NULL;
}
return 0;
}
您主要混合了width
和height
,但还有其他问题。
width
是列数height
是行数
内存顺序中的C二维数组为Row Major
用于在存储器中存储图像的约定是";按行">
索引为RGBArray[col][row]
(在您的代码中应该为RGBArray[j][i]
(。
插图:
RGBArray[0][0] RGBArray[0][14]
| |
V V
<--- width --->
RGBArray[0] -> ############### ^
RGBArray[1] -> ############### |
RGBArray[2] -> ############### height
RGBArray[3] -> ############### |
RGBArray[4] -> ############### V
我使用以下PPM文本文件进行测试(in.ppm
(:
P3
# ppm comment
4 3
255
1 2 3 11 12 13 21 22 23 31 32 33
101 102 103 111 112 113 121 122 123 131 132 133
201 202 203 211 212 213 221 222 223 231 232 233
更正代码(请阅读注释(:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define maxheight 1080
#define maxwidth 1920
#define RGB_COMPONENT_COLOUR 255
#define pgmtype "P2"
#define ppmtype "P3"
typedef struct
{
int red, green, blue;
} PPMPixel;
typedef struct
{
int x, y;
} PPMImage;
typedef struct
{
int rgb_comp_colour;
char filetype[3];
int height;
int width;
} PPMHead;
PPMHead head;
PPMHead* head_ptr = &head;
PPMPixel p;
PPMPixel* p_ptr = &p;
PPMPixel *data; //Defines pointer to PPMPixel
int **Array; //Double pointer defines as a pointer pointing to a pointer that is pointing to an integer
PPMPixel **RGBArray; //Double pointer defines as a pointer pointing to a pointer that is pointing to the PPMPixel structure
FILE *fp;
int r, g, b;
void headercheck()
{
char tmp[201]; //Temporary string.
fscanf(fp, "%2s", head.filetype); //%2s ensures that no more than two characters are read.
fscanf(fp, "%200s", tmp);
if (tmp[0] == '#')
{
//The second line may be a comment starting with '#'
fgets(tmp, 200, fp); //Skip the comment.
fscanf(fp, "%d", &head.width);
}
else
{
//If not a comment, read width from tmp.
sscanf(tmp, "%d", &head.width);
}
//fscanf(fp, "%s %d %d %d", head.filetype, &head.width, &head.height, &head.rgb_comp_colour);
fscanf(fp, "%d %d", &head.height, &head.rgb_comp_colour);
printf("%s %d %d %d", head.filetype, head.width, head.height, head.rgb_comp_colour);
if (head.width > maxwidth || head.height > maxheight)
{
printf("tInvalid image size. The maximum value of image is 1920x1080.n");
printf("tImage size is %d x %dn", head.width, head.height);
}
else
{
printf("tImage size is validn");
printf("tImage size is %d x %dn", head.width, head.height);
}
if ((strcmp(head.filetype, pgmtype) != 0) && (strcmp(head.filetype, ppmtype) != 0))
{
printf("tInvalid filetypen");
}
else
{
if (strcmp(head.filetype, pgmtype) == 0)
{
printf("t File is PGM type imagen");
}
else
{
if (strcmp(head.filetype, ppmtype) == 0)
{
printf("t File is PPM type imagen");
}
}
}
if ((head.rgb_comp_colour == RGB_COMPONENT_COLOUR))
{
printf("t Image is 8 bitn");
}
else
{
if (head.rgb_comp_colour > RGB_COMPONENT_COLOUR)
{
printf("Maximum bit-depth is 8 bitsn");
}
else
{
printf("tImage is not 8 bitn");
}
}
}
int main(void)
{
const char *fname = "in.ppm";
//char fname[100];
//printf("Enter file name: ");
//scanf("%s", fname);
//fseek(stdin, 0, SEEK_END);
fp = fopen(fname, "r");
if (fp == NULL)
{
printf("tError while opening the filen");
}
else
{
printf("tReading in %sn", fname);
}
headercheck();
if (strcmp(head.filetype, ppmtype) == 0)
{
RGBArray = (PPMPixel **)malloc(head.height * sizeof(PPMPixel*)); //Points to malloc
if ((RGBArray == NULL))
{
printf("Error allocating memory to the arrayn");
}
else
{
printf("Memory allocated to the PPM array successfullyn");
}
//for (int i = 0; i < head.width; i++)
for (int i = 0; i < head.height; i++) //Iterate height rows
{
RGBArray[i] = (PPMPixel *)malloc(head.width * sizeof(PPMPixel));
if ((RGBArray[i] == NULL))
{
printf("Error allocating memory to the arrayn");
}
}
//printf("Error 2");
//Initializing each element
for (int j = 0; j < head.height; j++)
{
for (int i = 0; i < head.width; i++)
{
fscanf(fp, "%3d %3d %3d ", &p.red, &p.green, &p.blue); //Scans in integers of the address pointer to PPMPixel
//data = &RGBArray[i][j]; //Defines data pointer pointing to address of RGBArray[i][j]
data = &RGBArray[j][i]; //The row index comes first - (use [j][i] instead of [i][j])
data->red = p.red; //Access member of PPMPixel structure to equal one of the three RGB channels
data->green = p.green;
data->blue = p.blue;
}
}
}
fclose(fp);
//Save PPM Array Into New PPM File
FILE *pf;
int i, j;
//char fname2[100];
//printf("Enter file name: ");
//scanf("%s", fname2);
//fseek(stdin, 0, SEEK_END);
const char *fname2 = "out.ppm";
pf = fopen(fname2, "w");
if (pf == NULL)
{
printf("tError while opening the filen");
}
else
{
printf("tWriting in %sn", fname2);
}
//Write the PPM header
////////////////////////////////////////////////////////////////////////////
fprintf(fp, "%sn", head.filetype);
fprintf(fp, "%d %dn", head.width, head.height);
fprintf(fp, "%dn", head.rgb_comp_colour);
////////////////////////////////////////////////////////////////////////////
for (j = 0; j < head.height; j++)
{
//fprintf(pf, "n");
for (i = 0; i < head.width; i++)
{
//fprintf(pf, "%3d ", RGBArray[i][j].red);
//fprintf(pf, "%3d ", RGBArray[i][j].green);
//fprintf(pf, "%3d ", RGBArray[i][j].blue);
fprintf(pf, "%3d ", RGBArray[j][i].red); //row index comes first - use [j][i] instead of [i][j]
fprintf(pf, "%3d ", RGBArray[j][i].green);
fprintf(pf, "%3d ", RGBArray[j][i].blue);
}
fprintf(pf, "n");
}
fclose(pf);
//free(RGBArray);
//RGBArray = NULL;
for (int i = 0; i < head.height; i++)
{
free(RGBArray[i]);
RGBArray[i] = NULL;
}
free(RGBArray); //Free RGBArray after free RGBArray[i]
RGBArray = NULL;
return 0;
}
输出文件(out.ppm
(:
P3
4 3
255
1 2 3 11 12 13 21 22 23 31 32 33
101 102 103 111 112 113 121 122 123 131 132 133
201 202 203 211 212 213 221 222 223 231 232 233