Frage bezüglich des Schreibens einer BMP datei in Datei
-
Hallo, versuche gerade eine BMP datei via fstream in eine andere Datei zu schreiben. Zwar erzeugt der Code keinen Fehler und IRGENDWAS wird auch in die Datei geschrieben/kopiert, jedoch scheinbar nur Teile. Das Laden in die Bitmapklasse dürfte aufjedenfall funktionieren.
Hiermal der Code, sowie ein Auszug aus der Klasse die zum laden des Bitmaps benutzt wird(nicht von mir):
#include <fstream> #include <iostream> #include "Bitmap.h" using namespace std; int main () { Bitmap test("test.bmp"); cout << endl; fstream myfile("temp.bmp",ios::out | ios::binary); myfile.write((char*)&(test.bmfh),sizeof(BitmapFileHeader)); myfile.write((char*)&(test.bmih),sizeof(BitmapInfoHeader)); myfile.write((char*)(test.colours),sizeof(RGBQuad)*256); myfile.write(test.data,test.dataSize); /* // open it for output then write to it fstream myfile; myfile.open("test.txt",ios::out | ios::trunc); if (myfile.is_open()) { myfile << "This outputting a line.\n"; myfile.close(); } */ myfile.close(); getchar(); return 0; }//load a bitmap from a file and represent it correctly //in memory bool Bitmap::loadBMP(char* file) { FILE *in; //file stream for reading char *tempData; //temp storage for image data int numColours; //total available colours //bitmap is not loaded yet loaded=false; //make sure memory is not lost if(colours!=0) { delete[] colours; } if(data!=0) { delete[] data; } //open the file for reading in binary mode in=fopen(file,"rb"); //if the file does not exist return in error if(in==NULL) { error="File not found"; fclose(in); return false; } //read in the entire BITMAPFILEHEADER fread(&bmfh,sizeof(BitmapFileHeader),1,in); cout << "sizeof(BitmapFileHeader)=" << sizeof(BitmapFileHeader) << endl; //check for the magic number that says this is a bitmap if(bmfh.bfType!=BITMAP_MAGIC_NUMBER) { error="File is not in DIB format"; fclose(in); return false; } //read in the entire BITMAPINFOHEADER fread(&bmih,sizeof(BitmapInfoHeader),1,in); cout << "sizeof(BitmapInfoHeader)=" << sizeof(BitmapInfoHeader) << endl; //save the width, height and bits per pixel for external use width=bmih.biWidth; height=bmih.biHeight; bpp=bmih.biBitCount; cout << "biBitCount =" << bmih.biBitCount << endl; cout << "biClrImportant =" << bmih.biClrImportant << endl; cout << "biClrUsed =" << bmih.biClrUsed << endl; cout << "biCompression =" << bmih.biCompression << endl; cout << "biHeight =" << bmih.biHeight << endl; cout << "biPlanes =" << bmih.biPlanes << endl; cout << "biSize =" << bmih.biSize << endl; cout << "biSizeImage =" << bmih.biSizeImage << endl; cout << "biWidth =" << bmih.biWidth << endl; cout << "biXPelsPerMeter =" << bmih.biXPelsPerMeter << endl; cout << "biYPelsPerMeter =" << bmih.biYPelsPerMeter << endl; //calculate the size of the image data with padding dataSize=(width*height*(unsigned int)(bmih.biBitCount/8.0)); //calculate the number of available colours numColours=1<<bmih.biBitCount; cout << numColours << endl; //if the bitmap is not 8 bits per pixel or more //return in error if(bpp<8) { error="File is not 8 or 24 bits per pixel"; fclose(in); return false; } //load the palette for 8 bits per pixel if(bpp==8) { colours=new RGBQuad[numColours]; fread(colours,sizeof(RGBQuad),numColours,in); } //set up the temporary buffer for the image data tempData=new char[dataSize]; //exit if there is not enough memory if(tempData==NULL) { error="Not enough memory to allocate a temporary buffer"; fclose(in); return false; } //read in the entire image fread(tempData,sizeof(char),dataSize,in); //close the file now that we have all the info fclose(in); //calculate the witdh of the final image in bytes byteWidth=padWidth=(int)((float)width*(float)bpp/8.0); //adjust the width for padding as necessary while(padWidth%4!=0) { padWidth++; } //change format from GBR to RGB if(bpp==8) { loaded=convert8(tempData); } else if(bpp==24) { loaded=convert24(tempData); } //clean up memory delete[] tempData; //bitmap is now loaded error="Bitmap loaded"; //return success return loaded; }Das Ergebnis sieht so aus:
http://up.picr.de/4198297.jpgIm Original natürlich ohne die komische Huntergrundfarbe sowie mit weiteren schwarzen Linien.
Ich vermute, dass es an der Umwandlung von BGR zu RGB liegt, aber wenn ich die Ausschalte ist in der Ausgabedatei gar nichts mehr

Hoffe man kann den Post einigermaßen lesen, ich weiß ist sehr viel

Vielen Dank für eure Hilfe
Ps: Wenn das hier in n anderes Forum muss, dann bitte verschieben, Danke.
-
(char*)&(test.bmfh)BitmapFileHeader ist doch ein struct/class, oder? Wie kommst du darauf, dass Der Adressoperator da das richtige macht?
Kannst du denn die Schreib/Leseoperationen nicht in vernünftige Methoden auslagern? Dass man ein Bitmap öffnen und speichern kann?class Bitmap { public: void open( const char* file ); bool write( const char* file ); };Dein BitmapFileHeader kann dann z.B. ein writeTo(ostream& stream); bekommen, womit du den Header in einen Stream schreiben kannst. Dann ist nömlich die jeweilige Klasse für ihre eigenen Infos verantwortlich, und nicht am Ende der User selber!
-
Na klar könnte ich das, aber darum gehts mir ja (zunächst) gar nicht. Ich will erstmal nur den Bitmap in eine anderee Datei schreiben. Wenn das funktioniert, gehts weiter.
Ich hab das so in einer Anleitung gesehen, in der komplexe Datenstrukturen(im Beispiel eine struktur) in eine binarydatei geschrieben wurden und zwar mit dem adressoperator. Ohne gibt es einen Compilerfehler
Ist auch sinniger als ohne?! Die Struktur kann ich ja schlecht zu nem Zeiger auf char umwandeln.
-
Du könntest jetzt bitte die Klassendefinition von (z.B.) BitmapFileHeader posten.
Und nur weil du es so gesehen hast, heißt das nicht dass es bei deiner BitmapFileHeader-Klasse klappt. Es ist eher unwahrscheinlich, dass die Klasse so im Speicher liegt, dass dein Objekt korrekt in einen char* umgewandelt wird, nur durch den cast, so dass der korrekte Bitmap-Header rauskommt!
-
#ifndef _BITMAP_H #define _BITMAP_H //File: Bitmap.h //Written by: Mark Bernard //on GameDev.net: Captain Jester //e-mail: mark.bernard@rogers.com //Please feel free to use and abuse this code as much //as you like. But, please give me some credit for //starting you off on the right track. // //The file Bitmap.cpp goes along with this file // #include <iostream> #include <cstdio> #include <string> using namespace std; const short BITMAP_MAGIC_NUMBER=19778; const int RGB_BYTE_SIZE=3; #pragma pack(push,bitmap_data,1) typedef struct tagRGBQuad { char rgbBlue; char rgbGreen; char rgbRed; char rgbReserved; } RGBQuad; typedef struct tagBitmapFileHeader { unsigned short bfType; unsigned int bfSize; unsigned short bfReserved1; unsigned short bfReserved2; unsigned int bfOffBits; } BitmapFileHeader; typedef struct tagBitmapInfoHeader { unsigned int biSize; int biWidth; int biHeight; unsigned short biPlanes; unsigned short biBitCount; unsigned int biCompression; unsigned int biSizeImage; int biXPelsPerMeter; int biYPelsPerMeter; unsigned int biClrUsed; unsigned int biClrImportant; } BitmapInfoHeader; #pragma pack(pop,bitmap_data) class Bitmap { public: //variables RGBQuad *colours; char *data; bool loaded; int width,height; unsigned short bpp; string error; //methods Bitmap(void); Bitmap(char *); ~Bitmap(); bool loadBMP(char *); //private: //variables BitmapFileHeader bmfh; BitmapInfoHeader bmih; int byteWidth; //the width in bytes of the image int padWidth; //the width in bytes of the added image unsigned int dataSize; //size of the data in the file //methods void reset(void); bool convert24(char *); //convert to 24bit RGB bottom up data bool convert8(char *); //convert to 24bit RGB bottom up data }; #endif //_BITMAP_HWoher weiß ich denn, wie ich die Struktur übergeben muss, wenn das nicht immer so geht?
-
Hallo, ich hab mir jetzt ne zeitlang den Code des BMP-Laders angeguckt und meine den Fehler gefunden zu haben(bzw. den Fehler in meinem Verständnis des Codes).
Würde aber gerne Bestätigung meiner Vermutung bekommen.
Also ich denke es liegt an der Methode convert8.
Diese sieht wie folgt aus:bool Bitmap::convert8(char* tempData) { int offset,diff; diff=width*height*RGB_BYTE_SIZE; //allocate the buffer for the final image data data=new char[diff]; //exit if there is not enough memory if(data==NULL) { error="Not enough memory to allocate an image buffer"; delete[] data; return false; } if(height>0) { offset=padWidth-byteWidth; int j=0; //count backwards so you start at the front of the image for(int i=0;i<dataSize*RGB_BYTE_SIZE;i+=3) { //jump over the padding at the start of a new line if((i+1)%padWidth==0) { i+=offset; } //transfer the data *(data+i)=colours[*(tempData+j)].rgbRed; *(data+i+1)=colours[*(tempData+j)].rgbGreen; *(data+i+2)=colours[*(tempData+j)].rgbBlue; j++; } } //image parser for a forward image else { offset=padWidth-byteWidth; int j=dataSize-1; //count backwards so you start at the front of the image for(int i=0;i<dataSize*RGB_BYTE_SIZE;i+=3) { //jump over the padding at the start of a new line if((i+1)%padWidth==0) { i+=offset; } //transfer the data *(data+i)=colours[*(tempData+j)].rgbRed; *(data+i+1)=colours[*(tempData+j)].rgbGreen; *(data+i+2)=colours[*(tempData+j)].rgbBlue; j--; } } return true; }In der Schleife wird aus einem ehemaligen Pixel quasi 3 Verschiedene gemacht, jeweils mit dem Rot-,Grün- und Blauanteil.
Dies geschieht hier:*(data+i)=colours[*(tempData+j)].rgbRed; *(data+i+1)=colours[*(tempData+j)].rgbGreen; *(data+i+2)=colours[*(tempData+j)].rgbBlue;Dann muss ich natürlich vor dem Speichern in eine andere Datei diese 3 verschiedenen Pixel zu einem einzigen zusammenfügen.
Ist das richtig?
-
Hallo, Ich bins nochmal.
Also das war in der Tat der Fehler und nachdem ich die inverse Operation dazu ausgeführt hatte ging es.
JEDOCH:
Das Bild erscheint nicht als Symbol in den Windowsordnern, die erscheinen wenn man die Dateien mit großen bzw. kleinen Symbolen anzeigen lässt.
Woran könnte das liegen? Öffnen lässt sich das ganze ohne Probleme und Grafikfehler, nur das Symbol erscheint nicht?!
-
Vllt. liegt es an einem fehlerhaften BitmapHeader? Entweder erkennt der Windows-Thumbnailer nicht, dass das ein Bitmap sein soll, oder der holt sich den Thumb aus dem Bitmap (embedded Preview). Oder du hast Preview für .bmp deaktiviert

Kannst du nicht mal ein .bmp, bei dem die Vorschau klappt, im Hexeditor anschauen? Und dort mit einem deiner generierten Bitmaps vergleichen?