2010-04-22 115 views

回答

3

这是 PPM specification

PPM文件由9个部分构成,由空格分隔。

  • 打开文件
  • 读,直到第一个空格,并检查你有P6。然后跳过其他空格。
  • 直到下一个空白为止,将缓冲区转换为整数宽度。然后跳过其他空格
  • 读取直到下一个空格,将缓冲区转换为整数高度。然后跳到其它的空格
  • 分配整数的高度*宽度
  • 的尺寸的二维阵列读取由线最大-VAL
  • 读取线和填充所述阵列
+2

我认为你需要澄清这个答案是怎么回事,这不是很清楚。 – 2010-04-22 19:52:56

+1

许多PNM文件会失败,因为它没有对注释行进行说明。 – deegee 2013-09-21 23:41:30

18

下面的代码显示如何读取,更改像素颜色并以 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(); 
} 
+1

此代码在许多PNM文件上失败,因为PNM在标题条目之间使用空格,并且固定为仅使用LF。注释行也可以位于标题的几乎任何位置,并且在技术上是唯一必须以CR或LF结尾的行。 PNM二进制文件格式设计是一团糟。 sourceforge netpbm甚至规定,即使它是一个有效的头对象,包含注释本质上也会破坏文件格式。 – deegee 2013-09-21 23:49:40

+1

你有mallocs,为什么没有释放? – imre 2014-03-25 16:19:32

相关问题