2010-04-22 147 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

相關問題