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:
"w"
o "wb"
tronca a 0 byte; fopen
successo; fscanf
, dati binari con fread
. Allo stesso modo, scrivere ASCII dovrebbe essere fatto con fprintf
e solo i dati binari di nuovo con fwrite
. 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:
Image *
se si stanno comunque modificando i dati in loco