Delphi-PRAXiS
Seite 3 von 5     123 45      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Objekte einer TObjectList direkt aus dem Speicher lesen / in ihn schreiben (https://www.delphipraxis.net/187797-objekte-einer-tobjectlist-direkt-aus-dem-speicher-lesen-ihn-schreiben.html)

HolgerX 7. Jan 2016 13:27

AW: Objekte einer TObjectList direkt aus dem Speicher lesen / in ihn schreiben
 
Hmm..

Anscheinend wird bei dem Bitmap, welches per ExtractThumbnail geholt wird etwas bei SaveToStream anders gemacht, wie bei Draw..

Wenn Du zunächst das Thumbnail mit einem 2. Bitmap holts und es dann auf dein eigentliches Bitmap malst (.Draw) dann gehts..

Delphi-Quellcode:
 
// Thumbnail aus JPG-Datei
  Bmp := TBitmap.Create;
  Bmp2:= TBitmap.Create;
  try
    ExtractThumbnail(Bmp2,Verz + JPGDatei,400,0);
    // Auf Form zeichnen
    Self.Canvas.Draw(450,10,Bmp2);

    Bmp.Assign(bmp2);
    Bmp.Canvas.Draw(0,0,bmp);

  ..

  finally
    Bmp2.Free;
    Bmp.Free;
  end;
So ist dann das Bitmap in bmp mit der korrekten Orientierung.

Uwe Raabe 7. Jan 2016 14:47

AW: Objekte einer TObjectList direkt aus dem Speicher lesen / in ihn schreiben
 
Zitat:

Zitat von HolgerX (Beitrag 1326286)
Hmm..

Anscheinend wird bei dem Bitmap, welches per ExtractThumbnail geholt wird etwas bei SaveToStream anders gemacht, wie bei Draw..

Wie schon erwähnt, hat das nichts mit dem
Delphi-Quellcode:
SaveToStream
zu tun. Ein simples
Delphi-Quellcode:
bmp.Dormant
, was lediglich ein neues GDI-Objekt forciert, zeigt schon den Fehler. Vielleicht hat man den verlinkten Bug in der Implementation des IExtractImage Interfaces nicht mit gefixt.

HolgerX 7. Jan 2016 18:51

AW: Objekte einer TObjectList direkt aus dem Speicher lesen / in ihn schreiben
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1326305)
Zitat:

Zitat von HolgerX (Beitrag 1326286)
Hmm..

Anscheinend wird bei dem Bitmap, welches per ExtractThumbnail geholt wird etwas bei SaveToStream anders gemacht, wie bei Draw..

Wie schon erwähnt, hat das nichts mit dem
Delphi-Quellcode:
SaveToStream
zu tun. Ein simples
Delphi-Quellcode:
bmp.Dormant
, was lediglich ein neues GDI-Objekt forciert, zeigt schon den Fehler. Vielleicht hat man den verlinkten Bug in der Implementation des IExtractImage Interfaces nicht mit gefixt.

Schon klar, mir ging es nur um einen Workarround, damit der TE seine Bitmaps speichern kann, ohne dass Sie gedreht werden..

Benmik 7. Jan 2016 20:25

AW: Objekte einer TObjectList direkt aus dem Speicher lesen / in ihn schreiben
 
Danke an euch alle. Ich bin natürlich froh, dass ich jetzt nicht als Depp dastehe.

Die Lösung von HolgerX ist ziemlich schräg, funktioniert aber (und warum?).
Das doppelte Zeichnen ist unter Umständen verschmerzbar, weil ja nur die sichtbaren Vorschaubilder gezeichnet werden, das ist überschaubar.

Übrigens war es bei mir so, dass nicht immer alle Bilder auf dem Kopf standen, sondern nur die Hochkantbilder, während die querkantigen richtig herum waren. Ich werde mal sehen, ob HolgerX' Lösung auch hier wirkt.

@Perlsau: Danke für deine Mühe. Ich möchte natürlich alle Bilder in einer einzigen Datei speichern. Das könnte ich natürlich auch in die Klasse der Objectlist integrieren. Der direkte Speicherzugriff war ja doch nur wegen der Rotationsproblematik.

Benmik 8. Jan 2016 20:51

AW: Objekte einer TObjectList direkt aus dem Speicher lesen / in ihn schreiben
 
Die Implementierung von HolgerX' Idee hat nicht funktioniert und sie war mir ohnehin nicht so geheuer, weil ich nicht nachvollziehen konnte, warum sie überhaupt manchmal funktioniert.

Ich bin jetzt den Weg gegangen, einfach biHeight manuell negativ zu setzen, denn die Bitmap muss doch gar nicht gedreht, sondern es müssen nur die Scanlines in anderer Richtung ausgelesen werden. Das funktioniert prima. Dabei bin auch auch gleich Perlsaus Rat gefolgt, die Funktion in die Klasse zu verlegen.
Wird hier noch Verbesserungspotenzial gesehen (bis auf die Sünde, Umlaute zu verwenden)? Dieses doppelte "Free" zum Beispiel stört mich immer.

Zur Erläuterung der PosBiHeight: Die Größe des FileHeaders ist immer fix bei 14 Bytes. Beim nachfolgenden DIB header gibt es 7 Größen, aber alle fangen mit 3 x 4 Byte an. Die hartkodierte numerische Angabe erscheint mir sicherer als so etwas wie SizeOf(BitmapFileHeader) + SizeOf(InfoHeader.biSize) + SizeOf(InfoHeader.biWidth).
Delphi-Quellcode:
function TBilderListe.LeseVSBAusDatei(Dateiname: string): Boolean;
var BildNr,AnzDS:integer; Stream,VSBStream:TMemoryStream; VSBBmp:TBitMap; VSBHöhe:integer;
const PosBiHeight = 14 + 4 + 4;
begin
  Result := False;
  If not FileExists(Dateiname)
    then exit;
  Stream := TMemoryStream.Create;
  Try
    Stream.LoadFromFile(Dateiname);
  Except
    Stream.Free;
    exit;
  End;
  Stream.Position := 0;
  Stream.ReadData(AnzDS);
  If AnzDS <> BilderListe.Count
    then exit;
  VSBStream := TMemoryStream.Create;
  Try
    For BildNr := 0 to AnzDS - 1 do begin
      VSBBmp := TBitMap.Create;
      VSBBmp.LoadFromStream(Stream);
      VSBStream.Clear;
      VSBBmp.SaveToStream(VSBStream);
      VSBStream.Position := PosBiHeight;
      VSBStream.ReadData(VSBHöhe,SizeOf(VSBHöhe));
      VSBStream.Position := PosBiHeight;
      VSBStream.WriteData(-Abs(VSBHöhe));
      VSBStream.Position := 0;
      VSBBmp.LoadFromStream(VSBStream);
      Self[BildNr].VSB := VSBBmp;
    end;
    Stream.Free;
    VSBStream.Free;
  Except
    Stream.Free;
    VSBStream.Free;
    exit;
  End;
  Result := True;
end;

Sir Rufo 8. Jan 2016 21:47

AW: Objekte einer TObjectList direkt aus dem Speicher lesen / in ihn schreiben
 
Dann schau dir mal
Delphi-Quellcode:
try finally
an, denn dafür ist das da.

Benmik 8. Jan 2016 22:29

AW: Objekte einer TObjectList direkt aus dem Speicher lesen / in ihn schreiben
 
Ja. Nur dass dann bei einer Exception der Code durchläuft und Result damit True ist.
Ich habe jetzt zu einem Sprunglabel gegriffen. Bei dem "exit" da oben kommt es ja auch zu einem Speicherleck.

Sir Rufo 8. Jan 2016 22:42

AW: Objekte einer TObjectList direkt aus dem Speicher lesen / in ihn schreiben
 
Nein, tut er nicht.

http://www.delphi-treff.de/tutorials.../exceptions/5/

Perlsau 8. Jan 2016 22:55

AW: Objekte einer TObjectList direkt aus dem Speicher lesen / in ihn schreiben
 
Zitat:

Zitat von Benmik (Beitrag 1326458)
Ja. Nur dass dann bei einer Exception der Code durchläuft und Result damit True ist.
Ich habe jetzt zu einem Sprunglabel gegriffen. Bei dem "exit" da oben kommt es ja auch zu einem Speicherleck.

In diesem Fall verwendet man die Try-Finally-Variante:
Delphi-Quellcode:
function TBilderListe.LeseVSBAusDatei(Dateiname: string): Boolean;
var BildNr,AnzDS:integer; Stream,VSBStream:TMemoryStream; VSBBmp:TBitMap; VSBHöhe:integer;
const PosBiHeight = 14 + 4 + 4;
begin
  Result := False;
  If not FileExists(Dateiname)
    then exit;
  Stream := TMemoryStream.Create;
  Try
    Stream.LoadFromFile(Dateiname);
    Result := True;
  Finally
    Stream.Free;
  End;
  If Not Result Then Exit;
  ...
Wenn das Laden der Datei in den Stream schiefläuft, bleibt Result = False und somit wird die Methode nach dem Try-Finally-Block mit Exit verlassen. Normalerweise kann hier nichts schieflaufen, da ja die Existenz der Datei zuvor abgefragt wird. Einzige Fehlerquelle, die mir jetzt noch einfällt: Die Datei ist zu groß für den verfügbaren Arbeitsspeicher. Ich verwende daher immer noch einen Try-Except-Block innerhalb des Try-Finally-Blocks, um die Fehlermeldung zu erhalten, die in eine globale Fehlervariable geschrieben wird. Aber das kannst du letztendlich halten, wie du willst ...

BUG 8. Jan 2016 23:30

AW: Objekte einer TObjectList direkt aus dem Speicher lesen / in ihn schreiben
 
Zitat:

Zitat von Perlsau (Beitrag 1326461)
Einzige Fehlerquelle, die mir jetzt noch einfällt: Die Datei ist zu groß für den verfügbaren Arbeitsspeicher.

Mir fallen noch einige ein: die Datei wurde zwischendurch gelöscht, umbenannt, der USB-Stick wurde gezogen; oder es fehlen die nötigen Zugriffsrechte.


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:09 Uhr.
Seite 3 von 5     123 45      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz