Datein einlesen...
-
Hallo,
ja das habe ich mir schon angeschaut, und bin demnach gerade dabei die Auflösung aus zu lesen.
Damit wir einmal konkret werden, sende ich hier einfach mal den einfachen Code, bin wie ihr gemerkt habt noch neu auf dem Gebiet.
#include <iostream> //#include <string> #include <fstream> using namespace std; int main () { int length; char * buffer; ifstream heightmap; heightmap.open ("heightmap.bmp", ios::binary ); if(!heightmap) { cerr << "FEHLER: Datei \"heightmap.bmp\" konnte nicht geöffnet werden!" << endl; return -1; } // get length of file: heightmap.seekg (0, ios::end); length = heightmap.tellg(); heightmap.seekg (0, ios::beg); // allocate memory: buffer = new char [length]; // read data as a block: heightmap.read (buffer,length); heightmap.close(); cout.write (buffer,length); delete buffer; return 0; }Für die breite muß ich einfach 18 Byte nach vorne kommen, weiß noch nicht wie, und in lesbaren Zahlen das auslesen, das selbe für die anderen Informationen.
Arbeite unter Linux, und bin wie gesagt noch Neuling bei dem ganzen.
lg
Darian
-
seekg zum vorschieben ... ehm und dann einfach my_file.read(reinterpret_cast<char*>(&my_integer), sizeof(int)); bsw. um einen Integer auszulesen.
-
Eigentlich habe ich schon einen fetten Text geantwortet, abe keine Ahnung wo der jetzt hin ist.
Also heightmap.seekg (18, ios::beg); => zum 18 Byte nach vorne schieben (konnte ich jetzt noch nicht testen)
Und das nächste ist mir nicht klar. sizeof(int). Int hat ja normalerweise 32 Byte, aber wenn ich "cout << sizeof(int);" schreibe, gibt es genau 4 aus...? (von dem her wäre es ok, weil die Breite laut Wiki mit 4 Bytes gespeichert ist)
Und bitte noch um einer genauer Erklärung für das:
reinterpret_cast<char*>(&length)Ist mir eher weniger, bis gar nicht klar

lg
Darian
-
Darian schrieb:
Und das nächste ist mir nicht klar. sizeof(int). Int hat ja normalerweise 32 Byte, aber wenn ich "cout << sizeof(int);" schreibe, gibt es genau 4 aus...?
Wenn dann 32 Bit
Und bitte noch um einer genauer Erklärung für das:
reinterpret_cast<char*>(&length)read will nen char* wo die daten hingeschrieben werden sollen. du nimmst die adresse wo dein length im speicher liegt und tust so, als ob diese 4 bytes, auf die die adresse, zeigt ein char* wären, indem du castest. ist aber ein bisschen gefährlich, weil int nicht immer 4 bytes sein müssen, aber auf den meisten 32 bit systemen sind es 4, auf 64 bit system sind es wahrscheinlich 8. also nimm lieber nen anderen datentyp der immer 4 byte groß ist.
-
Ah ja stimmt, das mit dem Bit und Byte habe ich da jetzt ein bisschen durcheinander gebracht.
Das mit dem reinterpret_cast ist mir jetzt klar, ich Frage mich nur ob einfach so zu casten so eine gute Idee ist, ist es egal wenn man sowas macht?
Ich kriege nur eine große negative Zahl zurück.
#include <iostream> #include <fstream> using namespace std; int main () { char * buffer; int breite; int hoehe; ifstream heightmap; heightmap.open ("heightmap.bmp", ios::binary ); if(!heightmap) { cerr << "FEHLER: Datei \"heightmap.bmp\" konnte nicht geöffnet werden!" << endl; return -1; } //vorschieben zum breiten Bereich heightmap.seekg (18, ios::beg); //Auslesen und schliessen aus dem Str heightmap.read(reinterpret_cast<char*>(breite), sizeof(int)); heightmap.close(); //Ausgabe der Breite cout << breite << endl; return 0; }Was stimmt da jetzt wieder nicht, bitte um konkrete Infos, wäre super wenn mir da verständlich jemand weiter helfen könnte.
lg Darian
-
Du mußt den Zeiger auf die int-Variable casten und nicht die Variable selbst.
heightmap.read(reinterpret_cast<char*>(&breite), sizeof(breite));
-
Mah stimmt, so ist es richtig, jetzt hat es funktioniert, und sogar die richtige Breite wurde ausgegeben.
Nachdem das jetzt passt, kann ich mal gemütlich versuchen das alles dementsprechend zu verarbeiten. Jetzt wo ich die Basics habe.
lg und danke für diesen Tipp, habe ich wohl übersehen
Darian
-
Habe jetzt einmal den Header eingelesen, und stehe jetzt bei dem auslesen der ersten Pixel, da scheint es irgendwie wieder weniger zusammen zu passen.
Muß ich jetzt ersteinmal die Farbpalette in einen Array laden?
Hier er Code:
http://nopaste.info/94d173b2b5.htmlWäre super wenn ich noch ein paar Infos kriege.
Ach ja, hätte ich den Header auch irgendwie mit einer Schleife laden können, anstatt alles manuell aus zu schreiben?? (mir ist da irgendwie nichts eingefallen!)lg
Darian
-
Darian schrieb:
Habe jetzt einmal den Header eingelesen, und stehe jetzt bei dem auslesen der ersten Pixel, da scheint es irgendwie wieder weniger zusammen zu passen.
Muß ich jetzt ersteinmal die Farbpalette in einen Array laden?
Wenn das Bild eine Farbepalette hat, vermutlich ja. Andernfalls kann es sein, daß zwischen Header und Bilddaten noch Müll steht - im Header steht auch drin, wo die Nutzdaten beginnen.
-
Ach ja, hätte ich den Header auch irgendwie mit einer Schleife laden können, anstatt alles manuell aus zu schreiben?? (mir ist da irgendwie nichts eingefallen!)
hättest auch ne struct machen können die genau die selben variablen mit selber größe hat und da alles auf einmal reinkopieren.
-
Hallo,
ja habe ich sogar, aber wie hätte ich das aufeinmal rüber kopieren können?
struct Bitmap_Header { // BITMAPFILEHEADER word bfType; dword bfSize; dword bfReserved; dword bfOffBits; //BITMAPINFOHEADER dword biSize; long biWidth; long biHeight; word biPlanes; word biBitCount; dword biCompression; dword biSizeImage; long biXPelsPerMeter; long biYPelsPerMeter; dword biClrUsed; dword biClrImportant; };Wäre interessant, damit ich es das nächste mal brauchbarer mache, und es nicht wieder soviel Arbeit für mich ist.
lg Darian
-
na, so wie du breite und höhe eingelesen hast nur mit struct adresse und sizeof Bitmap_Header
-
Hallo, habe das jetzt probiert, gibt dann aber nicht das richtig aus!
Meinst du so:
heightmap.seekg(0, ios::beg);
heightmap.read(reinterpret_cast<char*>(&header), sizeof(Bitmap_Header));Stimmt das so??
Na ja, das wäre doch sehr interessant für mich für die Zukunft, also bitte noch um die nötigen Infos für das praktische einlesen.
lg Darian
-
Wenn die struct aus PODs besteht, kannst du durch:
file_stream.read(reinterpret_cast<char*>(&my_struct), sizeof(my_struct));die Daten einlesen, jap. Ehm dabei musst du aber einiges beachten. Das zu erklären, überlasse ich anderen, weil ich jetzt in die Haia gehe :xmas1:
-
Na ja, habe ich eh so gemacht, oder meinst du es anders?
Aber es werden wenn ich zum Beispiel die Höhe Ausgeben will, nur komische zahlen ausgegeben, aber nicht die, die es sein sollten.
Wäre echt super wenn mir das noch jemand erklären könnte.
lg Darian
-
(D)Evil schrieb:
Ehm dabei musst du aber einiges beachten. Das zu erklären, überlasse ich anderen, weil ich jetzt in die Haia gehe :xmas1:
Das wichtigste, was du dabei beachten solltest ist, daß die verwendete Struktur "dicht" im Speicher steht - d.h. du solltest das Padding ausschalten (frag mal deine Compiler-Doku, wie das geht). Sonst landen einige der Nutzdaten in den Füllbytes, mit denen der Compiler dafür sorgt, daß die Elemente an vernünftigen Speicheradressen ausgerichtet werden.
Und du solltest dich bei den Datentypen nicht auf die Built-ins verlassen - deren exakte Größe ist nämlich nicht standardisiert (nur Mindestgrößen).
-
Na ja, nachdem man da extra wieder beim Compiler herum stellen muß, wäre es wohl besser man codet es doch gleich aus? Oder wie wird das sonst so gemacht?
Das mit dem padding muß ich mir wirklich dann mal genauer durchlesen benutzte übrigends g++ unter Linux.
Sorry, aber was meinst du mit Built-ins?
lg
Darian
-
Darian schrieb:
Sorry, aber was meinst du mit Built-ins?
Die eingebauten Datentypen von C++ - char, short, int etc. Wenn du mit WORD und DWORD arbeitest, kannst du mit einigen Präprozessor-Einstellungen oder Templates sicherstellen, daß diese IMMER die erforderliche Größe haben.
PS: Und das typische Vorgehen ist tatsächlich, dort für die Strukturen das Padding auszuschalten (nicht unbedingt für's gesamte Programm). Unter VC sieht das z.B. so aus:
#pragma pack(push,1) struct bitmap_header {...}; #pragma pack(pop)
-
Hallo,
ich dachte dass int und short auf einem 32Bit CPU immer gleich viel haben.
und daher mit folgendem Code, müßten word und dword auch die selben haben. (dachte ich bis jetzt zumindest so)//Define Datatypes
typedef unsigned short int word;
typedef unsigned int dword;Bezügich padding habe ich jetzt im manual von g++ nichts gefunden. Ich konnte nur raus lesen dass ein paar Sachen nicht kompatibel sind mit anderen, und was falsch ist zu machen. Aber wie man padding selbst macht, stand nicht da. (und natürlich auch dass die binarys möglicherweise mit binarys von anderen Compilern nicht kompatibel sind)
Werde wohl mal genauer suchen, oder irgendwo nachfragen müßen...
lg und danke für die Infos
Darian
-
Darian schrieb:
Hallo,
ich dachte dass int und short auf einem 32Bit CPU immer gleich viel haben.
und daher mit folgendem Code, müßten word und dword auch die selben haben. (dachte ich bis jetzt zumindest so)Der Ansi Standard legt nur fest, daß beide Typen mindestens 16 Bit groß sein müssen - nach oben ist das keine Grenze vorgeschrieben. Deine Probleme werden vermutlich dann beginnen, wenn ein Compiler anderer Meinung ist als dein aktueller (mit typedef reicht es, das an einer Stelle zu korrigieren, wenn du int direkt verwendet hast, mußt du den gesamten Code danach absuchen).