Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi x Bilder einheitlich skaliert auf drittes Bild zeichen (https://www.delphipraxis.net/174386-x-bilder-einheitlich-skaliert-auf-drittes-bild-zeichen.html)

QStorm 19. Apr 2013 10:38

x Bilder einheitlich skaliert auf drittes Bild zeichen
 
Hallo,

Vorab, verzeiht mir, falls das Thema schon aufkam. Ich habe mit Hilfe der Suche kein passendes Thema gefunden. Folgendes Problem beschäftigt mich:

Ich habe Bilder in verschiedenen Formaten vorliegen (BMP, JPEG, PNG, GIF, ...). Die Bilder kommen teilweise aus einer Datenbank, aber auch aus anderen Quellen. Nun möchte ich diese Bilder proportional korrekt auf eine gemeinsame Größe skalieren und in einem Raster (NxM) auf ein drittes Bild zeichnen. Dabei soll die Transparenz der einzelnen Bilder berücksichtigt werden. Einige Bilder haben halb-transparente Farben (Alphakanal). Zudem haben die Ausgangsbilder unterschiedliche "Transparentfarben". Der Hintergrund, des Zielbildes (auf den die Bilder gezeichnet werden sollen) soll ebenfalls transparent sein.

Ich habe es mit verschiedenen Ansätzen versucht. Leider bin ich auf die folgenden Probleme gestoßen:
- "Canvas.StretchDraw" liefert eine sehr schlechte Qualität (die Skalierung eines TBitmaps habe ich schlussendlich auf andere Weise in akzeptabler Qualität hinbekommen)
- die Standardimplementierung von TBitmap unterstützt so wie es aussieht keine halb-transparenten Farben und auch nur BMP
- nachdem ich Bilder mit unterschiedlichen "Transparentfarben" auf das Zielbild gezeichnet habe, gab es Probleme mit der Transparenz

Habt ihr eine Idee/Ansatz, wie man das Problem lösen könnte?
Wenn möglich:
- ohne TImage
- ohne externe Lib

Vielen Dank im Voraus :)

Grüße
QStorm

DeddyH 19. Apr 2013 10:44

AW: x Bilder einheitlich skaliert auf drittes Bild zeichen
 
Für das Skalieren hätte ich da was, aber dabei geht wohl die Transparenz flöten.

QStorm 19. Apr 2013 11:49

AW: x Bilder einheitlich skaliert auf drittes Bild zeichen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe mal einen sehr einfachen Beispielcode implementiert. Bitte beachtet die Dateipfade anzupassen bevor ihr ihn ausführt.

Bummi 19. Apr 2013 13:09

AW: x Bilder einheitlich skaliert auf drittes Bild zeichen
 
Liste der Anhänge anzeigen (Anzahl: 2)
Um das ganze in guter Qualität hinzubekommen könntest Du auf GDI+ zurückgreifen,da Du aber nichts externes wolltest und TImage vermeiden willst, hätte ich folgendes anzubieten.
Delphi-Quellcode:
unit Demop;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  ENotImplemeted=Class(Exception);

  TForm3 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form3: TForm3;

implementation

{$R *.dfm}

uses Math, pngImage, GifImg,jpeg;

Procedure SetCanvasZoomAndRotation(ACanvas: TCanvas; Zoom: Double; Angle: Double; CenterpointX, CenterpointY: Double);
var
  form: tagXFORM;
  Winkel: Double;

begin
  Winkel := DegToRad(Angle);
  SetGraphicsMode(ACanvas.Handle, GM_ADVANCED);
  SetMapMode(ACanvas.Handle, MM_ANISOTROPIC);
  form.eM11 := Zoom * cos(Winkel);
  form.eM12 := Zoom * Sin(Winkel);
  form.eM21 := Zoom * (-Sin(Winkel));
  form.eM22 := Zoom * cos(Winkel);
  form.eDx := CenterpointX;
  form.eDy := CenterpointY;
  SetWorldTransform(ACanvas.Handle, form);
end;

Procedure LoadAndPaint(FileName: String; C: TCanvas; x, y, BH: Integer;BitMapTransparent:Boolean=false);
var
  G: TGraphic;
  SC: Integer;
begin
  if UpperCase(ExtractFileExt(FileName)) = '.PNG' then
    G := TPngImage.Create
  else if UpperCase(ExtractFileExt(FileName)) = '.BMP' then
    begin
      G := TBitMap.Create;
      if BitMapTransparent then TBitMap(G).Transparent := true;
    end
  else if UpperCase(ExtractFileExt(FileName)) = '.GIF' then
    G := TGifImage.Create
  else if (UpperCase(ExtractFileExt(FileName)) = '.JPG') or (UpperCase(ExtractFileExt(FileName)) = '.JPEG') then
    G := TJpegImage.Create
  else raise ENotImplemeted.Create('Nicht berücksichtigtes Dateiformat');

  try
    G.LoadFromFile(FileName);
    SC := G.Width;
    if G.Height > G.Width then
      SC := G.Height;
    SetCanvasZoomAndRotation(C, BH / SC, 0, x, y);
    C.Draw(0, 0, G);
    SetCanvasZoomAndRotation(C , 1, 0, 0,0);
  finally
    G.Free;
  end;
end;

procedure TForm3.Button1Click(Sender: TObject);
Const
  C_Raster = 40;
var
  x, y: Integer;
  Path: String;
begin
  Path := IncludeTrailingBackSlash(ExtractFilePath(Paramstr(0)));
  x := 0;
  y := 0;
  LoadAndPaint(Path + '01.png', Canvas, x, y, C_Raster);
  Inc(x, C_Raster);
  LoadAndPaint(Path + '02.png', Canvas, x, y, C_Raster);
  Inc(x, C_Raster);
  LoadAndPaint(Path + '01.bmp', Canvas, x, y, C_Raster);
  Inc(y, C_Raster);
  Inc(x, C_Raster);
  LoadAndPaint(Path + '01.gif', Canvas, x, y, C_Raster);
  Inc(y, C_Raster);
  Inc(x, C_Raster);
  LoadAndPaint(Path + 'bbok.bmp', Canvas, x, y, C_Raster,true);

end;

end.

QStorm 22. Apr 2013 08:14

AW: x Bilder einheitlich skaliert auf drittes Bild zeichen
 
Zitat:

Zitat von Bummi (Beitrag 1212111)
Um das ganze in guter Qualität hinzubekommen könntest Du auf GDI+ zurückgreifen,da Du aber nichts externes wolltest und TImage vermeiden willst, hätte ich folgendes anzubieten.

Vielen Dank für die Antworten.

@Bummi: Ich habe dein Beispiel ausprobiert. Es funktioniert wunderbar, mit einer Einschränkung: Wenn man die PNGs rotiert (z.B.: um 25°) dann wird die Transparenzfarbe auf das Canvas gezeichnet (die Transparenz geht verloren). Hast du eine Idee woran das liegen könnte?

/QStorm

Bummi 22. Apr 2013 09:26

AW: x Bilder einheitlich skaliert auf drittes Bild zeichen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Darauf hatte ich gar nicht geachtet, da von Rotation ursprünglich keine Rede war.
Mit einem Umweg über ein Bitmap geht es:

Delphi-Quellcode:
Procedure LoadAndPaint(FileName: String; C: TCanvas; x, y, BH: Integer;BitMapTransparent:Boolean=false);
var
  G,G2: TGraphic;
  SC: Integer;
begin
  if UpperCase(ExtractFileExt(FileName)) = '.PNG' then
  begin
    G := TPngImage.Create;
  end
  else if UpperCase(ExtractFileExt(FileName)) = '.BMP' then
    begin
      G := TBitMap.Create;
      if BitMapTransparent then TBitMap(G).Transparent := true;
    end
  else if UpperCase(ExtractFileExt(FileName)) = '.GIF' then
    G := TGifImage.Create
  else if (UpperCase(ExtractFileExt(FileName)) = '.JPG') or (UpperCase(ExtractFileExt(FileName)) = '.JPEG') then
    G := TJpegImage.Create
  else raise ENotImplemeted.Create('Nicht berücksichtigtes Dateiformat');

  G2 := TBitmap.Create;
  try
    G.LoadFromFile(FileName);
    G2.Assign(G);
    G2.Transparent := BitMapTransparent;
    SC := G.Width;
    if G.Height > G.Width then
      SC := G.Height;
    SetCanvasZoomAndRotation(C, BH / SC, 0, x, y);
    C.Draw(0, 0, G2);
    SetCanvasZoomAndRotation(C , 1, 0, 0,0);
  finally
    G.Free;
    G2.Free;
  end;
end;

QStorm 23. Apr 2013 07:46

AW: x Bilder einheitlich skaliert auf drittes Bild zeichen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Bummi (Beitrag 1212308)
Darauf hatte ich gar nicht geachtet, da von Rotation ursprünglich keine Rede war.
Mit einem Umweg über ein Bitmap geht es:

Die Rotation ist in den meisten Fällen auch nicht nötig, daher hatte ich sie nicht erwähnt. Mit dieser Lösung funktioniert es. Ich habe jetzt nur noch ein Problem:

Das Ergebnis der "Bilderzusammenstellung" soll ein TBitmap sein (oder ein anderer Untertyp von TGraphic). Das TBitmap muss ich in einigen Fällen einen TPicture zuweisen (pic.Bitmap.Assign(bit)), um es in bestimmten Komponenten (z.B.: cxGrid) nutzen zu können. Ich habe mal dein Beispiel dahingehend angepasst. Leider habe ich dann wieder Probleme mit der Transparenz. Dazu kommt, dass sich die Transparenz bei verschiedenen Komponenten (TPaintBox, TImage, TForm) unterschiedlich verhält.

Vermutlich liegt es an irgendeiner Einstellung. Leider finde ich sie nicht. :(

Noch eine allgemeine Frage:
Welche externe Bildverarbeitungs-Bibliothek könnt ihr empfehlen? Wenn möglich eine kommerzielle. Ich habe hier schon von GDI+ gehört. Graphics32 und ImageEn habe ich mal kurz überflogen. Leider hat Graphics32 keine geeignete Lizenz.
Wichtig ist, dass die Bibliothek ohne Probleme in kommerziellen Produkten einsetzbar/integrierbar ist.

Vielen Dank nochmal!

/QStorm

Bummi 23. Apr 2013 10:01

AW: x Bilder einheitlich skaliert auf drittes Bild zeichen
 
Ja, hier kommen wir jetzt an den Punkt wo man mit reinen GDI-Routinen Probleme bekommt.
Ich meine ich hatte in meiner ersten Antwort auf GDI+ hingewiesen, hier entfallen alle Basteleien ...
Ich verwende noch die anscheinend nicht erhältliche Api von http://www.progdigy.com/.
Eine freie Implementierung, mit der ich noch keine Erfahrung habe gibt es unter http://www.bilsen.com/gdiplus/index.shtml, hier sind auch weitere Downloadadressen angegeben.


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:09 Uhr.

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