Bitmaps parsen mit Streams: Zeichen werden übersprungen?
-
Zur Behebung der Strukturenoptimierung in VS-C++:
#pragma pack( 1 ) struct peter { }; #pragma pack( )Außerdem: Die 4Bytes sind unzuverlässig.
-
Ja, das mit der Unzuverlässigkeit ist auch so ne Sache. Gibt es irgendwelche sicheren und compiler- sowie bs-unabhängigen Typen für 4 Byte usw.?
Ich les dann einzeln ein, glaub ich.

-
ein binärer filestream und op>> wären denke ich am elegantesten...
zum 1. gibts hier scho was:
der 3.letzte Beitrag von Werner
ist zwar die ausgabe-variante, aber geht mit sicherheit auch umzuschreiben2. sollte np sein
bb
-
> liest immer entsprechend so viel Byte, wie der rechtsseitige Datentyp lang ist?
-
Eisflamme schrieb:
Ich les dann einzeln ein, glaub ich.

Genau.
Das geht dann überall.
Wenn du dir ein paar Hilfsfunktionen bastelst, ist das auch halbwegs erträglich.Und vergiss nicht dass du die Endianness berücksichtigen solltest, falls du es wirklich portabel hinbekommen willst.
-
Hm, wo gibt es denn little und wo big endian?
-
Eisflamme schrieb:
> liest immer entsprechend so viel Byte, wie der rechtsseitige Datentyp lang ist?
ja - allerdings meinte ich, dass du deinem struct einen solchen operator spendierst und dort sinnvollerweise genau das machst, was du beim speichern (dann mit op<<) machst...
weil du das Alignment ja nicht unbedingt mit speichern musst... ^^bb
-
Eisflamme schrieb:
Hm, wo gibt es denn little und wo big endian?
Guckst du Wikipedia???
-
unskilled:
Ok, das wäre eine Variante. Aber im Endeffekt macht das ja keinen wirklichen Unterschied dazu alles einzeln zu setzen, nur dass es mehr nach Streams aussieht, oder?
hustbaer:
Grundsätzlich sind mir die Begriffe schon klar. Mir ging es jetzt darum, wo das hier im Einzelnen zutrifft. Ich meine, ich operiere auf Byte-Ebene und wüsste jetzt auch gar nicht, wo ich das auf einem Little-Endian-system anders umsetzen müsste bzw. wie ich es jetzt noch plattformunabhängiger gestalten könnte.
Lg
-
Eisflamme schrieb:
wo das hier im Einzelnen zutrifft. Ich meine, ich operiere auf Byte-Ebene und wüsste jetzt auch gar nicht, wo ich das auf einem Little-Endian-system anders umsetzen müsste
Die Daten in der Bitmap-Datei sind in Little-Endian abgelegt. Wenn dein System mit Big-Endian läuft, musst alle Datentypen mit >1 Byte um-modeln.
-
Ok, das wäre eine Variante. Aber im Endeffekt macht das ja keinen wirklichen Unterschied dazu alles einzeln zu setzen, nur dass es mehr nach Streams aussieht, oder?
struct data { int a; float b; long c; }; //->weiß nich, ob du das hier jemals brauchst, aber ich schreibs ma mit Tout_stream& operator<< (Tout_stream &s, const data &these) { s << these.a << these.b << these.c; return s; } //<- Tin_stream& operator>> (Tin_stream &s, data &these) { s >> these.a >> these.b >> these.c; return s; } Tin_stream stream("./save.dat"); data buf; stream >> buf;wie es mit read und write aussieht, weist du ja selber - und wenn ich statt einer Zeile pro member nur ne hand voll Zeichen brauch, sollte ja wohl klar sein, was ich schöner find...
das du die beiden streamklasen davor noch schreiben musst, ist dann zwar nen Nachteil, aber imho lohnt es sich trotzdem - zu mal du ja schon eine klasse komplett hast (mein 1. link).
aber die probleme von wegen little/big endian bleibt - nur musst du es eben nur noch einmal im code iwo unterscheiden...
falls du hier allerdings nur bhf verstehst, solltest du den ansatz vll vergessen, da es nicht ganz trivial sein wird, die stream-klasse zu schreiben - aber dann solltest du wahrscheinlich allg. bevor du das Problem zu lösen versuchst, noch ein wenig lernen...
bb
-
Schon ok, kann alles nachvollziehen. Finde die Idee auch ganz schön und werde sie wohl auch umsetzen. Vielen Dank

-
Ok, neues Problem. header.read(c, 12); mit c = char[12] liefert mir etwas anderes als header >> c.
Problem ist wohl, dass zero1 und zero2 innerhalb der Datei halt \0 sind und >> da abzubrechen scheint. Der Stream ist binary und ich habe auch versucht Manipulatoren wie std::ws, std::noskipws usw. zu nutzen. Leider war das nicht so erfolgreich.
Welchen Manip müsste ich dafür denn benutzen?
-
Du hast doch nen eigenen Stream-Typen gebaut - dann kannst du also auch so etwas machen:
struct TinputStream { typedef size_t size_type; /*...*/ template <typename T> friend TinputStream& operator>> (TinputStream& s, T& these) { return s.read(reinterpret_cast<char*>(&these), sizeof(T)); } } template <typename T, size_type len> friend TinputStream& operator>> (TinputStream& s, T& (these[len])) { return s.read(reinterpret_cast<char*>(&these), sizeof(T)*len); } };bin ich mir allerdings nicht ganz sicher, ob das geht... und vor allem geht es nicht mehr, wenn irgend ne länge nicht zur compilezeit bekannt ist...
ich würd std::tr1::array oder std::vector nehmen und dann nen op>> für die zu speziallisieren - du musst halt davor die länge setzen und dann liest der op>> so viel ein, wie der vector/das array lang ist...bb
-
Na ja, ich hab einfach in meinem operator>> nicht den operator>> des übergebenen is benutzt, sondern auch da das read benutzt. Das funktioniert natürlich, gerade, da die Daten auch fix sind:
inline std::istream& operator>>(std::istream& is, BitmapFileHeader& bfh) { is.read(reinterpret_cast<char*>(bfh.type), 2); is.read(reinterpret_cast<char*>(&bfh.size), 4); is.read(reinterpret_cast<char*>(&bfh.zero1), 2); is.read(reinterpret_cast<char*>(&bfh.zero2), 2); is.read(reinterpret_cast<char*>(&bfh.offsetToData), 4); return is; }Ist halt auch nicht so besonders schön, verlagert den Code im Endeffekt ja nur. Außerdem ist der operator nicht Mal mehr wirklich inline...
Bei deiner Variante hätte ich Probleme mit char*, ich könnte natürlich auch nen optionalen Template-Parameter für die Größe übergeben, aber das wäre ja auch hässlich.
-
du hast mich nich ganz verstanden ^^
aber dann lass es halt so ;o)