C语言 读取 PPM 文件并将其存储在数组中;用 C 编码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2693631/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
read PPM file and store it in an array; coded with C
提问by mary
I need to read a PPM file and store it in an array written in C. Can anybody help me out doing this?
我需要读取一个 PPM 文件并将其存储在一个用 C 编写的数组中。有人可以帮助我这样做吗?
Thanks a lot.
非常感谢。
回答by rpf
The following code shows how to read, change the pixel colour and write an image in PPM format. I hope it helps.
以下代码显示了如何以 PPM 格式读取、更改像素颜色和写入图像。我希望它有帮助。
#include<stdio.h>
#include<stdlib.h>
typedef struct {
unsigned char red,green,blue;
} PPMPixel;
typedef struct {
int x, y;
PPMPixel *data;
} PPMImage;
#define CREATOR "RPFELGUEIRAS"
#define RGB_COMPONENT_COLOR 255
static PPMImage *readPPM(const char *filename)
{
char buff[16];
PPMImage *img;
FILE *fp;
int c, rgb_comp_color;
//open PPM file for reading
fp = fopen(filename, "rb");
if (!fp) {
fprintf(stderr, "Unable to open file '%s'\n", filename);
exit(1);
}
//read image format
if (!fgets(buff, sizeof(buff), fp)) {
perror(filename);
exit(1);
}
//check the image format
if (buff[0] != 'P' || buff[1] != '6') {
fprintf(stderr, "Invalid image format (must be 'P6')\n");
exit(1);
}
//alloc memory form image
img = (PPMImage *)malloc(sizeof(PPMImage));
if (!img) {
fprintf(stderr, "Unable to allocate memory\n");
exit(1);
}
//check for comments
c = getc(fp);
while (c == '#') {
while (getc(fp) != '\n') ;
c = getc(fp);
}
ungetc(c, fp);
//read image size information
if (fscanf(fp, "%d %d", &img->x, &img->y) != 2) {
fprintf(stderr, "Invalid image size (error loading '%s')\n", filename);
exit(1);
}
//read rgb component
if (fscanf(fp, "%d", &rgb_comp_color) != 1) {
fprintf(stderr, "Invalid rgb component (error loading '%s')\n", filename);
exit(1);
}
//check rgb component depth
if (rgb_comp_color!= RGB_COMPONENT_COLOR) {
fprintf(stderr, "'%s' does not have 8-bits components\n", filename);
exit(1);
}
while (fgetc(fp) != '\n') ;
//memory allocation for pixel data
img->data = (PPMPixel*)malloc(img->x * img->y * sizeof(PPMPixel));
if (!img) {
fprintf(stderr, "Unable to allocate memory\n");
exit(1);
}
//read pixel data from file
if (fread(img->data, 3 * img->x, img->y, fp) != img->y) {
fprintf(stderr, "Error loading image '%s'\n", filename);
exit(1);
}
fclose(fp);
return img;
}
void writePPM(const char *filename, PPMImage *img)
{
FILE *fp;
//open file for output
fp = fopen(filename, "wb");
if (!fp) {
fprintf(stderr, "Unable to open file '%s'\n", filename);
exit(1);
}
//write the header file
//image format
fprintf(fp, "P6\n");
//comments
fprintf(fp, "# Created by %s\n",CREATOR);
//image size
fprintf(fp, "%d %d\n",img->x,img->y);
// rgb component depth
fprintf(fp, "%d\n",RGB_COMPONENT_COLOR);
// pixel data
fwrite(img->data, 3 * img->x, img->y, fp);
fclose(fp);
}
void changeColorPPM(PPMImage *img)
{
int i;
if(img){
for(i=0;i<img->x*img->y;i++){
img->data[i].red=RGB_COMPONENT_COLOR-img->data[i].red;
img->data[i].green=RGB_COMPONENT_COLOR-img->data[i].green;
img->data[i].blue=RGB_COMPONENT_COLOR-img->data[i].blue;
}
}
}
int main(){
PPMImage *image;
image = readPPM("can_bottom.ppm");
changeColorPPM(image);
writePPM("can_bottom2.ppm",image);
printf("Press any key...");
getchar();
}
回答by eyalm
Here is the PPM specification.
这是 PPM 规范。
The PPM file is built in 9 sections separated by white-spaces.
PPM 文件由用空格分隔的 9 个部分构成。
- Open the file
- read until the first white space and check you got
P6. Then skip other white-spaces. - read until the next white space, convert your buffer to an integer width. Then skip other white-spaces
- read until the next white space, convert your buffer to an integer height. Then skip other white-spaces
- Allocate a 2D array of integers in the size of height*width
- read the max-val
- read line by line and fill the array
- 打开文件
- 读到第一个空格并检查你得到了
P6. 然后跳过其他空格。 - 读到下一个空格,将缓冲区转换为整数宽度。然后跳过其他空格
- 读到下一个空格,将缓冲区转换为整数高度。然后跳过其他空格
- 分配一个高度*宽度大小的二维整数数组
- 读取最大值
- 逐行读取并填充数组

