J'essaye d'écrire le dossier de PPM sur le disque. PPM est un simple format d'image qui se compose d'en-tête d'image ASCII et tableau d'octets de pixels:std :: ofstream ajoute le retour de chariot (CR; r) après n automatiquement
P6\n
width height\n
255\n
[width*height*3 bytes total]
C'est ma classe de PPM (simplifié):
class PPMImage
{
protected:
friend std::istream& operator >>(std::istream &inputStream, PPMImage &other);
friend std::ostream& operator <<(std::ostream&, const PPMImage&);
size_t width;
size_t height;
// eg. "P6"
std::string magicNumber;
// Normally 255
uint16_t maxBrightness;
std::vector<std::vector<ImagePixel>> pixels;
};
Voilà comment j'écrire l'image std::ofstream
:
std::ostream& operator <<(std::ostream &output, const PPMImage &other) {
// Writing header - THIS IS WHERE THE PROBLEM IS!
output<<"P6\n"<<other.width<<'\n'<<other.height<<'\n'<<other.maxBrightness<<'\n';
// The rest is pretty much irrelevant
size_t position = output.tellp();
output.seekp(position+other.width*other.height*3);
// Force the stream to be specific size
const char zero = 200;
output.write(&zero, 1);
// Write the image
output.seekp(position);
for(size_t y=0, yl=other.height; y<yl; ++y) {
for(size_t x=0, xl=other.width; x<xl; ++x) {
output.write((char*)&(other.pixels[y][x].r), 1);
output.write((char*)&(other.pixels[y][x].g), 1);
output.write((char*)&(other.pixels[y][x].b), 1);
}
}
return output;
}
Voilà comment j'utilise cette API:
std::ofstream out;
out.open("copy.ppm");
if(!out.is_open()) {
// error and exit here
}
out<<image;
out.close();
L'image semble ok, à l'exception du fait que ofstream ajoute \r
avant chaque \n
dans l'en-tête:
P6\r\n
width height\r\n
255\r\n
[width*height*3 bytes total]
Cela est inacceptable. J'ai essayé de changer le code d'initialisation comme ceci:
std::ofstream out("copy.ppm", std::ios::binary);
// I wonder why I have to mention "copy.ppm" twice...
out.open("copy.ppm");
Mais cela crée juste le fichier vide. Quelqu'un peut-il expliquer comment écrire correctement PPM wile sans retour chariot?
En d'autres termes: Comment correctement initialiser le ofstream afin qu'il écrit sans \r
?
Le binaire ios :: est correct, mais il est déjà ouvert. Vous l'ouvrez à nouveau sans le mode binaire? Cela fonctionne bien pour moi si je dis juste si (out.is_open()) out << "bonjour \ n"; À la réflexion, non, je ne peux pas reproduire votre problème.Il continue même \ n même si j'appelle une seconde fois sans spécifier le mode, ce qui me surprend. –
J'ai un fichier vide et je peux le reproduire. Peut-être que ce sont les fenêtres spécifiques? –
Je ne suis pas allé à l'extrême d'appeler un opérateur ostream. Je vais essayer de reproduire le tout. –