TMemoryStream verketten
-
Hallo,
Ich versuche eine bestimmte Bit-folge einem TMemoryStream voranzustellen, leider ohne erfolg.
Mein Hintergrund ist das ich versuche den "OLE-Header" einer BMP Datei zu entfernen, die in einer MS-Access Datenbank archiviert ist. Das klappt bis hierhin problemlos.
Lediglich ein "BMP-Header" lässt sich nicht mehr nachträglich anfügen.Die Datei wie sie mit dem "OLE-Header" in Access liegt:
15 1C 1A 00 03 00 00 00 05 00 01 00 14 00 19 00 FF FF FF FF 42 69 6C 64 00 00 01 05 00 00 03 00 00 00 04 00 00 00 44 49 42 00 DB 67 00 00 36 BC FF FF A8 30 1E 00 28 00 00 00 ED 03 00 00 90 02 00 00 01 00 18 00 00 00 00 00 00 00 00 00 C4 0E 00 00 C4 0E .. .. .. .. .. .. .. .. .. .. .. ..
Der "OLE-Header" kann mit Stream->Position = 54; "weggeschnitten" werden:
28 00 00 00 ED 03 00 00 90 02 00 00 01 00 18 00 00 00 00 00 00 00 00 00 C4 0E 00 00 C4 0E .. ..
Damit das Bild als BMP erkannt wird muss eine BMP Notation angefügt werden:
42 4D B6 30 1E 00 00 00 00 00 36 00 00 00 .. ..
Doch ich konnte bisher keine Möglichkeit finden die BMP Notation der "gesäuberten" Version ohne OLE-Header vorzustellen.
Das Resultat sollte ebenfalls vom Typ Stream sein damit es einem DBImage angefügt werden kann.Ist der "BMP-Header" nicht vorhanden wird keine Exception ausgeworfen aber das Bild kann auch nicht auf dem DBImage angezeigt werden.
-
- neues
TMemoryStream
Objekt erzeugen - Bitmap Header in Stream schreiben (woher bekommst du die Daten wie Breite/Höhe/Fabrbtiefe?)
- Bitmap-Daten aus db Stream in neuen Stream übertragen
- neues
-
Danke für die schnelle Antwort DocShoe.
Wie schreibe ich den direkt in einen Stream?
Mir ist nur bekannt das ich eine Datei in einem Stream verfügbar machen kann um diesen zu bearbeiten.Woher ich die Daten wie Breite/Höhe/Fabrbtiefe bekomme?
Die benötige ich Extra nicht noch einmal. Ich entferne lediglich den "OLE-Header"
und möchte einen allgemeinen "BMP-Header" einsetzen.Hier der aufbau des BMP Formates:
http://upload.wikimedia.org/wikipedia/commons/c/c4/BMPfileFormat.pngBreite/Höhe/Fabrbtiefe sind nicht mitglieder des Dateikopfes.
Der Dateikopf beinhaltet lediglich 14 Byte zur Angabe der Notation:42 4D 76 7D 09 00 00 00 00 00 36 00 00 00
-
Schau mal bei
Stream->CopyFrom
-
Danke für deinen Hinweis Burkhi, CopyFrom ist mir bekannt.
Ich benutze CopyFrom bereits um die ersten 54 Stellen also den "OLE-Header" abzuscheiden:
//Bild wird aus Access gelesen static_cast<TBlobField*>(ADOQuery1->FieldByName("Bild"))->SaveToStream(Stream); //Position wird auf 54 gesetzt und zeigt somit auf das ende des OLE Headers Stream->Position = 54; //Kopieren in den neuen Stream ab Stelle 54 DEStream->CopyFrom(Stream, Stream->Size-54); //Die BMP Datei steht jetzt im DEStream OHNE BMP Dateikopf zur Verfügung /*Hier müsste jetzt der BMP-Header angefügt werden*/ //Es wird keine Exception ausgelöst aber das Bild wird auch nicht angezeigt DBImage1->Picture->Bitmap->LoadFromStream(DEStream);
Der BMP Header liegt in keiner Datei sondern steht mir als diese Zeichenfolge zur verfügung:
42 4D 76 7D 09 00 00 00 00 00 36 00 00 00
Mir fehlt jetzt also die Möglichkeit diese Zeichenfolge an den Stream anzufügen.
CopyFrom kann Streams kopieren ich aber habe einen Stream und einen String.
Ich hoffe jemand hat noch eine andere Lösung für dieses Problem.
-
Du hast doch alles was du brauchst, du musst es nur richtig zusammenbauen.
Ich vermute außerdem, dass du den Bitmapheader nicht nach den Bitmapdaten anhängen willst, sondern davor.
Jetzt guck´ dir doch bitte mal die API vonTStream
(und deren Erben) an, da wirst du sicher Methoden finden, mit denen sich dein Problem lösen lässt.
-
Die passende eigenschaft habe ich gefunden:
//Schreibt die in Count angegebene Anzahl Bytes aus Buffer //in den Stream und verschiebt die aktuelle Position im Stream um diese Anzahl Bytes. DEStream->WriteBuffer(const void *Buffer, int Count);
Ich verstehe nicht wie ich Zugriff auf "const void *Buffer" bekomme,
bzw. wie ich meinen String "const void *Buffer" zuweise oder ihn dahin verschiebe.In der Hilfe der Entwicklungsumgebung finde ich keine weiteren Informationen zu diesem Thema.
-
Hi,
ich gehe davon aus, TImage, bzw. TBitmap keine Exception auslößt, da du den Stream DEStream nach CopyFrom in der Position nicht zurücksetzt.Hier am Beispiel einer Datei der Vorgang
TMemoryStream *ms = new TMemoryStream(); //Bild laden ms->LoadFromFile("C:\\lastimage.bmp"); //Empfangstream TMemoryStream *ms1 = new TMemoryStream(); //Headerstream TMemoryStream *msHead = new TMemoryStream(); //Bildstream zurücksetzen (eigentlich nicht nötig) ms->Position = 0; //Header kopieren -> bzw. mit Write schreiben, wenn mit Write entfällt CopyFrom natürlich //b mit dem festen Header füllen /* BYTE b[54]; memset(&b, 0, sizeof(b)); ms->Read(&b, 54); msHead->Write(&b, 54); */ msHead->CopyFrom(ms, 54); //Bildstream Position setzen (wird eigentlich auch von CopyFrom erledigt) ms->Position = 54; //Header zurücksetzen msHead->Position = 0; //Header in Empfang einlesen ms1->CopyFrom(msHead, msHead->Size); //Restliches Bitmap von 54er Position einlesen ms1->CopyFrom(ms, ms->Size-54); //Empfang zurücksetzen ms1->Position = 0; //Bildübergeben Image1->Picture->Bitmap->LoadFromStream(ms1); //Aufräumen delete ms; delete ms1; delete msHead;
P.S.: Ich finde es ein bißchen windig einfach einen festcoiderten Header zu verwenden.
-
Machello schrieb:
//Schreibt die in Count angegebene Anzahl Bytes aus Buffer //in den Stream und verschiebt die aktuelle Position im Stream um diese Anzahl Bytes. DEStream->WriteBuffer(const void *Buffer, int Count);
Ist nicht dein Ernst, oder?
Machello schrieb:
42 4D 76 7D 09 00 00 00 00 00 36 00 00 00
Wenn da nix klingelt solltest du dir ein Grundlagenbuch besorgen und Grundlagen büffeln.
-
Nachtrag:
Hast du dir eigentlich schon die CreateBlobStream Methode angeschaut?
When you are ready to read you bitmap back out, use the built in TBitmap method and you are set.
Blobfield := FieldbyName('picturefield');
BS := CreateBlobStream(BlobField,bmReadWrite);
MyFavoriteBitmap.LoadFromStream(BS);http://edn.embarcadero.com/article/27462
Hatte so im Hinterkopf, dass das doch einfacher geht.
Ich weiß zwar nicht, für was du das Bitmapfeld in deiner MDB verwendest und wie groß die Bitmaps im Durchschnitt sind. Aber ich würde dir raten die Bilder lieber auf der Platte und nicht in der DB zu speichern.