Hilfe bei Bitmap-Loader
-
aVoX schrieb:
KN4CK3R schrieb:
im Debugger geschaut ob die ausgelesenen Werte auch stimmen?
Eigentlich prüfe ich bei jeder Debugging-Session die Werte, die bis dato immer korrekt waren, (weshalb ich mir das wahrscheinlich unbewusst abgewöhnt habe).
Bei der letzten Session (Breakpoint direkt an der Zeile mit der Array-Initialisation)Name Value Type this 0x00000010 {m_iWidth=??? m_iHeight=??? m_pData=???} CBitmap * const -m_iWidth C*XX0030: Error: expression cannot be evaluated -m_iHeight C*XX0030: Error: expression cannot be evaluated -m_pData C*XX0030: Error: expression cannot be evaluated strFileName "terrain.bmp" std::basic_string<char,std::char_traits<char>,std::allocator<char>> offset -858993460 int stream [ganz viel Gedöns, das ziemlich richtig aussieht] std::basic_ifstream<char,std::char_traits<char>>'strFileName' ist richtig. 'offset' ist auch richtig, da die Variable erst später benutzt wird, stream sollte auch richtig sein, da ich keine Lesefehler bekomme, aber was mit 'this' los ist würde ich selbst gerne wissen (zumal this ja automatisch generiert wird)
Ich bin verwirrt.Wie erstellst du den deine Bitmap Instanz... Zeig mal den Code wo du CBitmap erstellst.
-
@Thorgrim:
Danke für die Antwort. Wie gesagt, der Bitmap-Loader soll ganz minimalistisch ausfallen, d.h. 24 bit Farbtiefe und nur BMPs (DIBs sind uncool). Auf die Idee, das Bild mit 2 Vektoren zu beschreiben bin ich auch schon gekommen, nur dachte ich mir, dass es einfacher wäre, alles in ein 2-dimensionales Array zu speichern (als ob)@Tobias Gerg:
Der BMP-Loader wird von einer anderen Klasse namens CMesh aufgerufen.
Relevante Ausschnitte:// Mesh.h #pragma once #include <WinDef.h> #include "Bitmap.h" class CMesh { public: CMesh( void ) { m_bmp = CBitmap(); }; ~CMesh( void ); bool LoadHeightMap( char *szFile, float flScale, float flResolution = (4.0f) ); // noch ein paar unwichtige Funktions- und Variablendeklarationen CBitmap m_bmp; }; // Mesh.cpp bool CMesh::LoadHeightMap( char *szFile, float flScale, float flResolution ) { if ( !m_bmp.Load(string(szFile)) ) // <- Crash { g_error.szErrMsg = t( "Error loading height map." ); return false; } // Ende des bmp-relevanten Abschnitts }
-
Ist das CMesh Objekt ein Pointer der noch nicht initialisiert wurde wenn du die Loadfunktion aufrufst?
-
Tobias Gerg schrieb:
Ist das CMesh Objekt ein Pointer der noch nicht initialisiert wurde wenn du die Loadfunktion aufrufst?
Ja. Verdammt, ich könnt' mich echt manchmal selbst auslachen. Sowas banales und dafür 2 Seiten voll mit Fachsimplereien! Es tut richtig leid um eure Zeit. (wobei ich mich wundere, dass das Programm nicht schon früher abgestürzt ist)
Jetzt funktioniert alles soweit, bis auf einen Debug Error ("Invalid allocation size"), was wohl am scheinbar komplett falsch geschriebenen Lade-Code liegt.
Danke an alle PosterInnen!
aVoX
-
Wegen dem nicht Absturz, dass ist einfach undefined behavior, da darf alles passieren...
Ansonsten würde ich mal einen Breakpoint in deinen CMesh Konstruktor setzen. Schau im Debugger einfach was passiert, dann findest du den Fehler... :xmas1:
Greets
Tobi
-
@Tobias: Fehler bereits behoben, Danke für alles

@Topic:
Das hoffentlich letzte Problem (auch Grund für die invalid allocation size): stream << var lest keine Daten aus der Datei aus.
Aktueller Code:bool CBitmap::Load( string strFileName ) { ifstream stream( strFileName, ios_base::binary | ios_base::in ); // Breakpoint 1: m_iWidth und m_iHeight sind beide 0 (im Konstruktor so zugewiesen) if ( stream.fail() || stream.bad() || !stream.is_open() ) { g_error.szErrMsg = t("Error loading heightmap!"); return false; } stream.seekg( 18, ios_base::beg ); // Offset 18: 4 Byte speichern die Bildbreite. stream >> m_iWidth; // 4 Byte (int) einlesen. // Cursor steht bei 22. // Offset 22: 4 Byte speichern die Bildhöhe. stream >> m_iHeight; // 4 Byte (int) einlesen. m_pData = new int *[m_iWidth]; // Breakpoint 2: Laut Debugger sind iWidth und m_iHeight noch immer 0.Wenn ich die Bitmap in einem Hexeditor öffne und zum Offset 18 springe, steht dort 0400 (1024 dezimal - also richtiger Wert), selbiges gilt für Offset 22.
Sollten ebenjene Werte nicht auch in den entsprechenden Variablen stehen?
-
Du musst die Datei binär öffnen (std::ios::binary angeben).
-
hat er doch?
greetz KN4CK3R
-
@KN4CK3R: Sorry, hab das irgendwie übersehen

Ich würde es dennoch anders machen:
class CBitmap { .... private: std::vector<unsigned char> m_data; // Daten std::vector<unsigned char*> m_rows; // Adresse jeder Rasterzeile BITMAPINFOHEADER m_infoHeader; } bool Bitmap::Load(const char* file) { std::ifstream stream(file,std::ios::binary); if(!stream.is_open()) return false; BITMAPFILEHEADER fileHeader; stream.read(reinterpret_cast<char*>(&fileHeader),sizeof(BITMAPFILEHEADER)); stream.read(reinterpret_cast<char*>(&m_infoHeader),sizeof(BITMAPINFOHEADER)); if(m_infoHeader.biBitCount!=24 || bmi.biHeight<0) // return false; stream.seekg(fileHeader.bfOffBits); // eigentlich unnötig, Daten sollten direkt anfangen unsigned rowlen = 4*((m_infoHeader.biWidth*m_infoHeader.biBitCount+31)/32); unsigned size = m_infoHeader.biHeight*rowlen; m_data.resize(size); m_rows.resize(m_infoHeader.biHeight); stream.read(reinterpret_cast<char*>(&m_data[0]),m_data.size()); for(unsigned y=0;y<m_rows.size();++y) // Zeilen liegen von unten nach oben im Speicher m_rows[y] = &m_data[0] + (m_infoHeader.biHeight - y - 1)*rowlen; }Natürlich sollte die Fehlerüberprüfung noch verbessert werden (z.B. überprüfen, ob es sich überhaupt um eine bmp-Datei handelt, den stream nach jedem Lesen prüfen etc.).
Wenn dir die Strukturen BITMAPFILEHEADER und BITMAPINFOHEADER nicht zur Verfügung stehen, kannst du sie nachbauen (zu finden bei MSDN), musst allerdings unbedingt das Padding des Compilers auf 2 Byte setzen.Achja, der Code nur kurz angetestet.
-
@Thorgrim: OK, du hast mich endgultig von den Vektoren überzeugt!

Danke an alle für's Mithelfen, auch wenn das eigentliche Problem mein eigener Fehler war. :xmas1: