2010-04-22 13 views

Antwort

3

Hier ist die PPM specification.

Die PPM-Datei besteht aus 9 Abschnitten, die durch Leerzeichen voneinander getrennt sind.

  • Öffnen Sie die Datei
  • Lese bis zum ersten Leerzeichen und überprüfen Sie P6 bekam. Dann überspringen Sie andere Leerzeichen.
  • Lesen Sie bis zum nächsten Leerraum, konvertieren Sie Ihren Puffer in eine ganze Breite. Dann überspringen Sie andere Leerstellen
  • lesen Sie bis zum nächsten Leerraum, konvertieren Sie Ihren Puffer in eine ganze Zahl Höhe. Dann überspringen andere weißen Räume
  • Vergeben Sie einen 2D-Array von ganzen Zahlen in der Größe der Höhe * Breite
  • die max-val
  • Lese Zeile für Zeile lesen und füllt das Array
+2

Ich denke, Sie müssen klären, was in dieser Antwort los ist, es ist nicht sehr klar. –

+1

Dies schlägt bei vielen PNM-Dateien fehl, da Kommentarzeilen nicht berücksichtigt werden. – deegee

18

Den folgenden Code zeigt, wie zu lesen, ändern Sie die Pixelfarbe und schreiben Sie ein Bild in PPM-Format. Ich hoffe, es hilft.

#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

Dieser Code wird bei vielen PNM-Dateien fehlschlagen, da PNM Leerzeichen zwischen den Header-Einträgen verwendet und nicht nur die Verwendung von LF festlegt. Eine Kommentarzeile kann sich auch fast überall im Header befinden und ist technisch die einzige Zeile, die mit einem CR oder LF terminiert werden muss. Das Design des PNM-Binärdateiformats ist ein zerbrochenes Durcheinander. Die Sourceforge netpbm gibt sogar an, dass die Aufnahme eines Kommentars, obwohl es ein gültiges Header-Objekt ist, im Wesentlichen das Dateiformat durchbricht. – deegee

+1

Sie haben Mallocs, warum gibt es keine Frees? – imre