AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Hilfe zu IThumbnailProvider

Ein Thema von Benmik · begonnen am 4. Nov 2022 · letzter Beitrag vom 7. Nov 2022
Antwort Antwort
Seite 1 von 2  1 2      
striderx

Registriert seit: 11. Feb 2007
Ort: Bergisch Gladbach
207 Beiträge
 
Delphi 10.4 Sydney
 
#1

AW: Hilfe zu IThumbnailProvider

  Alt 6. Nov 2022, 19:49
Ich mache das (m. E. wesentlich einfacher) mit GDI+:

Delphi-Quellcode:
function GDIPMakeThumbnail(sSourceFile, sTargetFile: String;
                           AWidth, AHeight: Word): Boolean;

var
  BM: tBitmap;
  GR: tGPGraphics;
  GDPImage: TGPImage;
  GDPThumbnail: TGPImage;
  H: Single;
  R1: Single;
  R2: Single;
  W: Single;

begin
  Result := False;
  {............................................................................}
  if not tFile.Exists(sSourceFile) then Exit;
  {............................................................................}
  if (sTargetFile = '') or (sTargetFile = sSourceFile) then Exit;
  {............................................................................}
  if (AWidth < 10) or (AHeight < 10) then Exit;
  {............................................................................}
  BM := tBitmap.Create;
  BM.Width := AWidth;
  BM.Height := AHeight;
  GR := tGPGraphics.Create(BM.Canvas.Handle);
  GDPImage := TGPImage.Create(sSourceFile);
  {............................................................................}
  R1 := AWidth / AHeight;
  H := GDPImage.GetHeight;
  W := GDPImage.GetWidth;
  if (H = 0) or (W = 0) then Exit;
  {............................................................................}
  R2 := W / H;
  if R1 > R2 then begin
     W := AHeight * R2;
     H := AHeight;
  end
  else begin
     W := AWidth;
     H := AWidth / R2;
  end;
  {............................................................................}
  GDPThumbnail := GDPImage.GetThumbnailImage(Round(W), Round(H), nil, nil);
  GR.DrawImage(GDPThumbnail, MakeRect((AWidth - W) / 2, (AHeight - H) / 2, W, H));
  try
    BM.SaveToFile(sTargetFile);
    Result := True
  except
    ShowMsg('Fehler beim Speichern der Thumbnail-Datei', ' Fehler', mb_OK,
            mb_IconError);
  end;
  {............................................................................}
  GR.Free;
  GDPImage.Free;
  GDPThumbnail.Free;
  BM.Free;
end;

Geändert von striderx ( 6. Nov 2022 um 20:21 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.339 Beiträge
 
Delphi 12 Athens
 
#2

AW: Hilfe zu IThumbnailProvider

  Alt 6. Nov 2022, 21:07
"Diese" Thumbnails sind nunmal vorwiegend für die Vorschau im Explorer und dort sind die Icons/Images nunmal Quadrate.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
570 Beiträge
 
Delphi 12 Athens
 
#3

AW: Hilfe zu IThumbnailProvider

  Alt 6. Nov 2022, 23:32
Ich mache das (m. E. wesentlich einfacher) mit GDI+:
GDI+ hatte ich gar nicht auf dem Schirm, obwohl ich das schon für das verlustfreie Drehen einsetze.
Welche GDI+-Unit verwendest du denn? Anscheinend nicht die von Erik van Bilsen.

@Himitsu: Ja, das habe ich ein bisschen spät bemerkt. Allerdings ging es mir dann immer mehr um den "sportlichen" Aspekt, ich wollte das Ganze zumindest einmal ans Laufen bringen und dabei auch noch verstehen.

@mytbo: Vielen Dank. Eine Eigenart dieser reinen Thumbnail-Prozessoren ist, dass sie bei JPG-Dateien nachschauen, ob es ein Thumbnail gibt und dann verwenden sie das. Für größere Miniaturbilder ist das von der Qualität her nicht akzeptabel. Meine gegenwärtige Lösung arbeitet mit IExtractImage aus Winapi.ShlObj und das funktioniert gut. Ich wollte unter anderem aber auch mal sehen, ob die neueren Methoden vielleicht schneller sind.

Geändert von Benmik ( 6. Nov 2022 um 23:47 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.339 Beiträge
 
Delphi 12 Athens
 
#4

AW: Hilfe zu IThumbnailProvider

  Alt 7. Nov 2022, 02:15
Vielleicht ist es einfacher, sich über IShellFolder und IShellIcon oder IExtractIcon das Vorschau-Icon zu besorgen?
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
venice2
(Gast)

n/a Beiträge
 
#5

AW: Hilfe zu IThumbnailProvider

  Alt 7. Nov 2022, 02:34
https://rmklever.com/?p=266
  Mit Zitat antworten Zitat
striderx

Registriert seit: 11. Feb 2007
Ort: Bergisch Gladbach
207 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Hilfe zu IThumbnailProvider

  Alt 7. Nov 2022, 05:57
Welche GDI+-Unit verwendest du denn? Anscheinend nicht die von Erik van Bilsen.

Das ist die von Prodigy.
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
570 Beiträge
 
Delphi 12 Athens
 
#7

AW: Hilfe zu IThumbnailProvider

  Alt 7. Nov 2022, 11:18
@Himitsu: Mein Fokus hat sich im Laufe der Recherche etwas verschoben, seit klar ist, dass IThumbnailProvider quadratische Bilder zurückliefert. Ich würde mittlerweile aus sportlichen Gründen gern wissen, wie man diese Sachen mit COM-Objekten und Factories bei IThumbnailProvider richtig handhabt und warum mein Code nicht funktioniert. Vielleicht erbarmt sich ja irgendwann einmal ein Wissender, der hier vorbeikommt, und erklärt es mir.

@striderx: Danke! Nie von gehört.

@venice2: Super-Link! Zum Lernen offenbar genau das Richtige!
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
570 Beiträge
 
Delphi 12 Athens
 
#8

AW: Hilfe zu IThumbnailProvider

  Alt 7. Nov 2022, 16:04
Ich vermute mal, dass wegen der Seltenheit des Suchwortes "IThumbnailProvider" im Laufe der Zeit noch so einige Leute über Google hierher kommen werden, von denen eine Reihe auch an der Extraktion von Vorschaubildern für ihre JPG interessiert sind.

Daher möchte ich hier erwähnen, welche Lösung ich für mich gefunden habe. Und zwar betten immer mehr Kameras in die JPG neben einem kleinen Thumbnail (APP1) auch noch ein weiteres großes Bild im Full-HD-Format ein, also 1920 x 1080 Pixel. Dies geschieht mittels MPF (Multi-Picture Format), einem Zusatz zur EXIF-Spezifikation, das im APP2 gespeichert wird. (Sogar die kleine Panasonic TZ101 tut das). Bei deutlich größeren Vorschaubildern als 120 Pixel Breite ist die Hochskalierung des eingebetteten Thumbnails keine Option, eine Vorschau größer als 1920 Pixel wird es aber wohl kaum geben. Es bietet sich also an, dieses Bild zu extrahieren und schlicht mit StretchDraw in der gewünschten Größe zu zeichnen.

Meine JPG haben mittlerweile locker 20 MB, während die MPF-Bilder meist zwischen 300 und 900 kB groß sind. Das Einlesen von so großen JPG und vor allem die Dekomprimierung verbrauchen enorme Zeit und Speicher. Dies bedeutet auch, dass nur relativ wenige JPG im Speicher gehalten und beim erneuten Einlesen direkt aus dem Speicher genommen werden können. Bei der MPF-Lösung werden jedoch nur die ersten 256 kB für das EXIF eingelesen (weniger als 256 kB liest Windows sowieso nicht) und dann nochmal die 300 - 900 kB für das MPF, wenn man sie selektiv aus dem Dateistream liest. Tatsächlich benötigt das Einlesen beim ersten Durchgang nur 10 msec je Datei, und ab dem zweiten nur 1 msec, und das auch bei 4.500 Dateien (16 GB Speicher).

Ich füge noch den Code bei, wie ich von TBytes zu TBitmap komme:
Delphi-Quellcode:
uses
  ...
  JpegImage,SynGDIPlus,...

var
  JpegImage:TJpegImage;
  BMP:TBitmap;
  TBMPF: TBytes;
  Breite, Höhe: integer;
If EXIF.ExtrahiereMPF(TBMPF) then begin
  JpegImage := TJpegImage.Create;
  JpegImage.CreateFromBuffer(TBMPF, Length(TBMPF));
  BMP := TBitmap.Create(Breite, Höhe);
  BMP.PixelFormat := pf24bit;
  BMP.Canvas.StretchDraw(BMP.Canvas.ClipRect,JpegImage.ToBitmap);
  JpegImage.Free;
end;
ExtrahiereMPF ist eine Methode aus meiner selbst geschriebenen EXIF-Unit, die das MPF-Bild aus dem Filestream in einen TBytes-Puffer kopiert. Ich füge noch ein Diagramm der relevanten MPF-Struktur bei, die unglaublich kompliziert und verwirrend gestaltet wurde. Die Spezifikation findet man hier. .CreateFromBuffer und .ToBitmap kommen aus SynGDIPlus von Synopse.

EDIT: Durch mein neues Vorgehen fällt plötzlich auf, dass keineswegs alle Bilder meiner Sony ein MPF haben, was mich total verblüfft. Eine Untersuchung zeigt, dass fast alle Bilder, die keins haben, Hochkantbilder sind. Eine Erklärung dafür könnte die sein, dass diese MPF damals eigentlich dazu eingeführt wurden, dass auf einem Fernseher ein besseres Vorschaubild gezeigt werden konnte. Da Hochkantbilder auf einem Fernseher viel kleiner dargestellt werden, wurde das bei ihnen wahrscheinlich weggelassen. Die Sony-Kameras werden in den Specs regelmäßig mit "MPF Baseline compliant" beworben. Es scheint so, als wäre eine alte Sache einfach immer weitergeführt worden. Verrückt.
Angehängte Grafiken
Dateityp: jpg MPF-Struktur.jpg (131,9 KB, 11x aufgerufen)

Geändert von Benmik ( 7. Nov 2022 um 18:16 Uhr) Grund: MPF Baseline compliant
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.339 Beiträge
 
Delphi 12 Athens
 
#9

AW: Hilfe zu IThumbnailProvider

  Alt 7. Nov 2022, 16:14
Problem an TJpegImage und Co. ist oft, dass selbst bei Zoom, oftmals die Bilder zuerst in ein TBitmap gezeichnet und anschließend gestrecht werden,
anstatt gleich gestrecht in das Temp-Bitmap gezeichnet zu werden.

Drum hat Delphi, z.B. im TImage, mit großen Bildern (JPEG,PNG,TIFF) oft Probleme.
z.B. siehe TWICImage, denn die WIC-API (Windows Imaging Component) ist eigentlich speziell für die stückchenweise Behandlung extrem großer Bilder sehr speichersparend optimiert .... man müsste nur die API richtig benutzen.

Ich hab hier einen netten Testfall, wo eine technische Zeichnug als TIFF nur wenige 100 KB groß ist, aber beim Versuch ein Vorschaubild zu bekommen, da rauchen die Delphi-Klassen bei ab, weil als Bitmap ist das Ding rießig.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
570 Beiträge
 
Delphi 12 Athens
 
#10

AW: Hilfe zu IThumbnailProvider

  Alt 7. Nov 2022, 17:55
Problem an TJpegImage und Co. ist oft, dass selbst bei Zoom, oftmals die Bilder zuerst in ein TBitmap gezeichnet und anschließend gestretcht werden,...
Das ist interessant, denn ich beobachte bei meiner Methode, dass die 16 GB bis an den Rand vollaufen, was so erstmal nicht verständlich ist. 1920 x 1080 müssten als Bitmap etwa 6 MB sein, das kann doch eigentlich 16.000 MB nicht auslasten, zumal sie ja nach dem Zeichnen sofort freigegeben werden.

Was käme denn als Alternative in Frage? Ich muss da wohl noch ein bisschen forschen.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:06 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz