Problemi con la scrittura di PNM P6

Sto scrivendo un programma che contiene due file PNM P6 duplicati, inserisce la memoria del primo file in un buffer, crea una linea diagonale gialla e scrive il risultato nel secondo file. Quando lo eseguo, il file di output è danneggiato e non può essere visualizzato. Ho notato guardando all’output che mancano le tre linee che dovrebbero essere in cima:

P6 1786 1344 255 

Non so come garantire a livello di codice che quelle righe rimangano nel codice – non riesco a capire perché vengono addirittura sovrascritte in primo luogo.

Quando aggiungo manualmente queste righe all’output, il file non è più danneggiato. Tuttavia, non appare alcuna linea diagonale gialla. Fa parte dello stesso problema o c’è qualcos’altro che dovrei cercare di risolvere?

Il mio codice:

 #include  #include  #include  typedef struct { unsigned char red, green, blue; } iPixel; typedef struct { int x, y; iPixel *data; } Image; Image * ReadImage(char *filename) { FILE *f = fopen(filename, "rb"); Image *img = NULL; char magicNum[128]; int width, height, maxval; if (f == NULL) { fprintf(stderr, "Unable to open file %s\n", filename); return NULL; } fscanf(f, "%s\n%d %d\n%d\n", magicNum, &width, &height, &maxval); /* printf("Magic num = %s width = %d, height = %d, maxval = %d\n", magicNum, width, height, maxval) ; */ if (strcmp(magicNum, "P6") != 0) { fprintf(stderr, "Unable to read from file %s, because it is not a PNM file of type P6\n", filename); return NULL; } img = (Image *) malloc(sizeof(Image)); img -> x = width; img -> y = height; img -> data = (iPixel*) malloc(img -> x * img -> y * sizeof(iPixel)); fread(img -> data, sizeof(iPixel), width*height, f); fclose(f); return img; } void WriteImage(Image *img, char *filename) { FILE *f = fopen(filename, "wb"); fwrite(img->data, sizeof(iPixel), img-> x * img-> y, f); fclose(f); } Image * YellowDiagonal(Image *input) { int i, j; for (i = 0; i x; i++) { for (j=0; j y; j++) { if (i==j) { input->data[i].red=255; input->data[i].green=255; input->data[i].blue=0; } } } return input; } int main(int argc, char *argv[]) { if (argc != 3) { fprintf(stderr, "Usage: ./3A_c.c  \n"); exit(EXIT_FAILURE); } Image *img; img = ReadImage(argv[1]); fprintf(stderr, "Read.\n"); YellowDiagonal(img); fprintf(stderr, "Diagonal line.\n"); WriteImage(img, argv[2]); fprintf(stderr, "Write.\n"); } 

    Fai attenzione a scrivere esattamente lo stesso formato che stai leggendo . Il formato PNM è ben definito e lo stai leggendo correttamente. Tuttavia, nella routine di scrittura ci sono stati un paio di errori:

    1. aprire un file con "w" o "wb" tronca a 0 byte;
    2. la migliore pratica è sempre quella di verificare se la fopen successo;
    3. la lettura dei dati ASCII effettivi può essere eseguita con fscanf , dati binari con fread . Allo stesso modo, scrivere ASCII dovrebbe essere fatto con fprintf e solo i dati binari di nuovo con fwrite .
    4. Se vuoi assicurarti di scrivere gli stessi dati che hai letto prima, devi salvarlo da qualche parte. La variabile maxval viene letta, ma non salvata, quindi non posso scriverla di nuovo. Tuttavia, non è un problema enorme perché il resto del codice presuppone comunque che l’immagine sia R8G8B8 e quindi maxval deve essere sempre 255 .

    Ecco una WriteImage corretta che funziona.

     void WriteImage(Image *img, char *filename) { FILE *f = fopen(filename, "wb"); if (f == NULL) { printf ("Unable to open '%s' for writing!\n", filename); /* better would be: "return -1" to indicate an error, 0 otherwise */ return; } fprintf (f, "P6\n"); fprintf (f, "%d %d\n", img->x, img->y); /* actually you need to write 'maxval' here */ fprintf (f, "%d\n", 255); fwrite(img->data, sizeof(iPixel), img->x * img->y, f); fclose(f); } 

    Con quanto sopra, ora puoi vedere che la tua “linea diagonale” non è corretta! Non ho intenzione di aggiustarlo (suppongo di non essere in grado di vedere cosa è successo ti ha fermato nei tuoi brani), ma qui ci sono alcune indicazioni solo per guidarti:

    • non è necessario restituire Image * se si stanno comunque modificando i dati in loco
    • non è necessario controllare ogni singolo pixel
    • controlla le coordinate di quali pixel sono cambiati …