2014-05-12 1 views
0

J'écris un programme qui prend en charge deux fichiers PNM P6 en double, place la mémoire du premier fichier dans un tampon, crée une ligne diagonale jaune et écrit le résultat dans le second fichier. Lorsque je l'exécute, le fichier de sortie est corrompu et ne peut pas être affiché. J'ai remarqué en regardant la sortie qui il manque les trois lignes qui devraient être en haut:Problèmes d'écriture PNM P6

P6 
1786 1344 
255 

Je ne sais pas comment faire en sorte que ces lignes programme restent dans le code - je ne peux pas pourquoi ils sont même écrasés en premier lieu.

Lorsque j'ajoute manuellement ces lignes à la sortie, le fichier n'est plus corrompu. Cependant, aucune ligne diagonale jaune n'apparaît. Est-ce que cela fait partie du même problème, ou y a-t-il autre chose que je devrais envisager de corriger?

Mon code:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

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 < input->x; i++) 
    { 
     for (j=0; j < input->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 <input image file> <output image file>\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"); 
} 
+1

ouverture d'un fichier nouveau pour la sortie efface son co actuelle ntents. Donc, avant d'écrire vos données, assurez-vous d'écrire ces lignes aussi bien.(Préféré sur l'alternative, qui est ouvert pour * mise à jour *, 'fseek' à la position correcte, et en écrivant vos nouvelles données là.) – usr2564301

+1

Donc quelque chose comme ça? ' vide WriteImage (Image * img, char * nom_fichier) { \t FICHIER * f = fopen (nomfichier," wb "); Fwrite (img-> magicNum, 1, sizeof (char), f); Fwrite (img-> x, 1, sizeof (int), f); Fwrite (img-> y, 1, sizeof (int), f) \t; Fwrite (img-> maxval, 1, sizeof (int), f) \t fwrite (img-> données, taille de (iPixel), img-> x * img-> y, f); \t fclose (f); } ' – user3626715

+0

Absolument pas. Essayez-le et inspectez le fichier! Vous écrivez * binary * où vous devez utiliser ASCII, selon les spécifications (et le fichier d'entrée). – usr2564301

Répondre

1

Prenez soin de écrire exactement le même format que vous êtes lecture. Le format PNM est well defined et vous le lisez correctement. Cependant, dans la routine d'écriture, il y avait quelques erreurs:

  1. ouverture d'un fichier avec "w" ou "wb" tronque à 0 octets;
  2. La meilleure pratique est toujours de vérifier si fopen réussit;
  3. La lecture de données ASCII réelles peut être effectuée avec fscanf, les données binaires avec fread. De même, l'écriture ASCII doit être faite avec fprintf et seulement les données binaires avec fwrite.
  4. Si vous voulez vous assurer d'écrire les mêmes données que celles que vous avez déjà lues, vous devez les enregistrer quelque part. La variable maxval est lue, mais pas enregistrée, et je ne peux donc pas l'écrire. Cependant, ce n'est pas un problème énorme parce que le reste de votre code suppose que l'image est R8G8B8 de toute façon, et donc maxval devrait toujours être 255.

Voici un WriteImage ajusté qui fonctionne.

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); 
} 

Avec ce qui précède sur le chemin, vous pouvez voir votre « diagonale » est pas correct! Je ne vais pas corriger cela (je suppose ne pas être en mesure de voir ce qui est arrivé vous arrêté dans vos pistes), mais voici quelques conseils juste pour vous guider:

  • pas besoin de retourner un Image * si vous sont la modification des données in situ de toute façon
  • pas besoin de vérifier chaque chèque pixel
  • les coordonnées de ce que les pixels sont changés ...