2015-11-06 1 views
-1

J'essaie de lire un fichier ppm et j'en crée un nouveau identique. Mais quand je les ouvre avec GIMP2 les images ne sont pas les mêmes.Comment lire et écrire un fichier ppm?

Où est le problème avec mon code?

int main() 
{ 
    FILE *in, *out; 
    in = fopen("parrots.ppm","r"); 
    if(in == NULL) 
    { 
     std::cout<<"Error.\n"; 
     return 0; 
    } 

    unsigned char *buffer = NULL; 

    long size = 0; 
    fseek(in, 0, 2); 
    size = ftell(in); 
    fseek(in, 0, 0); 

    buffer = new unsigned char[size]; 
    if(buffer == NULL) 
    { 
     std::cout<<"Error\n"; 
     return 0; 
    } 

    if(fread(buffer, size, 1, in) < 0) 
    { 
      std::cout<<"Error.\n"; 
      return 0 ; 
    } 

    out = fopen("out.ppm","w"); 
    if(in == NULL) 
    { 
     std::cout<<"Error.\n"; 
     return 0; 
    } 

    if(fwrite(buffer, size, 1, out) < 0) 
    { 
     std::cout<<"Error.\n"; 
     return 0; 
    } 

    delete[] buffer; 

    fcloseall(); 

    return 0; 
} 

Avant que je lire le fichier ppm dans une structure et quand je l'ai écrit je reçois la même image, mais le vert est plus intense que dans l'image originale. Puis j'ai essayé cette simple lecture et écriture mais j'ai obtenu le même résultat.

+0

Avez-vous essayé d'utiliser la bibliothèque officielle à cet effet? - http://netpbm.sourceforge.net/. FYI. – Dummy00001

Répondre

1
int main() 

Les éléments manquants incluent.

FILE *in, *out; 

E/S de style C dans un programme C++, pourquoi? En outre, déclarez au point d'initialisation, proche de la première utilisation.

in = fopen("parrots.ppm","r"); 

C'est l'ouverture du fichier en mode texte, ce qui est certainement pas ce que vous voulez. Utilisez "rb" pour le mode.

unsigned char *buffer = NULL; 

déclarer, au moment de l'initialisation, à proximité de la première utilisation.

fseek(in, 0, 2); 

Vous êtes censé utiliser SEEK_END, qui n'est pas garantie à définir comme 2.

fseek(in, 0, 0); 

Voir ci-dessus, pour SEEK_SET pas garantie à définir comme 0.

buffer = new unsigned char[size]; 
if(buffer == NULL) 

Par défaut, new ne reviendra pas un pointeur NULL, mais lancer une exception std::bad_alloc. (La superposition étant la norme sur la plupart des systèmes d'exploitation actuels, la recherche de NULL ne vous protégerait pas de la mémoire insuffisante même avec malloc(), mais bon à voir, vous avez pris l'habitude de vérifier quand même.)

C++ 11 nous a apporté smart pointers. Utilise les. Ils sont un excellent outil pour éviter les fuites de mémoire (l'une des rares faiblesses de C++).

if(fread(buffer, size, 1, in) < 0) 

L'utilisation réussie de fread doit retourner le nombre d'objets écrits, qui doit être vérifié pour être égal au troisième paramètre (!= 1), non < 0.

out = fopen("out.ppm","w"); 

mode texte nouveau, vous voulez "wb" ici.

if(fwrite(buffer, size, 1, out) < 0) 

Voir la note sur la valeur fread de retour ci-dessus. La même chose s'applique ici.

fcloseall(); 

Non une fonction standard. Utilisez fclose(in); et fclose(out);.


Une solution C de 11 ified (en omettant l'erreur de vérification par souci de concision) ressemblerait un peu comme ceci:

#include <iostream> 
#include <fstream> 
#include <memory> 

int main() 
{ 
    std::ifstream in("parrots.ppm", std::ios::binary); 
    std::ofstream out("out.ppm", std::ios::binary); 

    in.seekg(0, std::ios::end); 
    auto size = in.tellg(); 
    in.seekg(0); 

    std::unique_ptr<char[]> buffer(new char[ size ]); 

    in.read(buffer.get(), size); 
    out.write(buffer.get(), size); 

    in.close(); 
    out.close(); 

    return 0; 
} 

Bien sûr, une solution intelligente ferait une copie du système de fichiers réel , soit par Boost.Filesystem ou standard functionality (expérimental au point de cet écrit).