AGB  ·  Datenschutz  ·  Impressum  







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

PNG zur Laufzeit in ImageList einfügen

Ein Thema von bezarre · begonnen am 1. Mai 2010 · letzter Beitrag vom 12. Feb 2011
Antwort Antwort
David Martens

Registriert seit: 29. Sep 2003
205 Beiträge
 
Delphi XE Enterprise
 
#1

AW: PNG zur Laufzeit in ImageList einfügen

  Alt 10. Feb 2011, 14:58
Wir haben auf Delphi XE umgestellt. Leider habe ich das Problem der Transparenz von PNGs in Imagelisten.

Folgende Situation:

PNGs sind in einer ImageDLL gespeichert:

Auszug auf der rc Datei:
cut RCDATA "cut.png"
Um diese Dll habe ich eine Klasse geschrieben die die Bilder dann als TPngImage zurückgibt:
Delphi-Quellcode:
function TImageDll.GetPNG(Name: string): TPngImage;
var
  hLib : THandle;
begin
  try
    hLib := LoadLibrary(PChar(fImageDll));

    Result := TPngImage.Create;
    Result.LoadFromResourceName(hLib, Name);
  except
  end;
end;
Das wird dann wiederum in eine TImagelist gespeichert:
  ilStandard.Add(sImageDll.GetPNG('cut'), nil); ilStandard ist eine von mir erweiterte TImagelist, die zusätzlich beim Add ein GrayscaleImage in die Imagelist für die deaktivierten Bilder packt.
Delphi-Quellcode:
function TMyImageList.Add(Image, Mask: TBitmap): Integer;
begin
  Result := inherited Add(Image, Mask);

  if Assigned(FDisabledImages) then
  begin
    ConvertColors(Image);

    if Assigned(Mask) then
      ConvertColors(Mask);

    FDisabledImages.Add(Image, Mask);
  end;
end;
Ich habe schon mit Transparenz hin und her probiert, aber nichts funktioniert.


Bisher habe ich die PNGs gleich in Bitmaps umgewandelt, aber dabei geht ja die Transparenz verloren. Ich habe mich da mit TransperentColor = clBtnFace beholfen, aber das sieht im Menü leider nicht so gut aus. Die Bilder werden in TMainMenu und in TControlBar benutzt. Die TToolButtons sehen dann gut aus, aber leider ist im Menü der Hintergrund nicht (immer) clBtnFace.

Delphi-Quellcode:
function TImageDll.LoadPNG(Name: string; TransperentColor : TColor): Graphics.TBitmap;
var
  hLib : THandle;
  PNGImage : TPngImage;
begin
  Result := Graphics.TBitmap.Create;
  try
    hLib := LoadLibrary(PChar(fImageDll));

    PNGImage := TPngImage.Create;
    PNGImage.LoadFromResourceName(hLib, Name);
    PNGImage.Transparent := true;

    Result.Canvas.Brush.Color := TransperentColor;
    Result.Width := PNGImage.Width;
    Result.Height := PNGImage.Height;
    Result.Canvas.StretchDraw(Rect(0, 0, PNGImage.Width, PNGImage.Height), PNGImage);

    PNGImage.Free;
  except
    On E : EPNGCouldNotLoadResource do
      ShowMessageFmt(rcDLLFailure, [sDLLPath + rcImgDll]);
  end;
end;
Ich hoffe ich hab mich verständlich ausgedrückt. Hier nochmal eine kurze Zusammenfassung was ich machen will:
1. PNGs als Resource in eine DLL
2. PNGs mit LoadFromResourceName laden
3. PNGs in einer TImageList speichern UND dabei nicht den Alphachannel verlieren
3b. möglicherweise gleich GrayscaleImage erstellen und in eine zweite TImageList speichern
4. Bilder korrekt in TMainMenu, TToolButtons, ... anzeigen MIT richtigem Alphachannel

Mein Knackpunkt ist Nummer 3.

Vielen dank schon mal für die Antworten

David

P.S.: Uwes Vorschlag hat leider nicht geklappt.

Geändert von David Martens (10. Feb 2011 um 15:01 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: PNG zur Laufzeit in ImageList einfügen

  Alt 10. Feb 2011, 15:13
Ganz spontan geantwortet: delphis TImageList kennt keine derartige Transparenz (Alpha-Kanal), wie sie im PNG verbaut ist.

TImageList kennt nur RGB-Bitmap mit zusätzlichem Schwarz/Weiß-Masken-Bitmap (wür ein ICON also ein Bitmap mit den Farben und Nocheines mit einer Maske für die volltranzparenten Pixel)
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (10. Feb 2011 um 15:15 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.234 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: PNG zur Laufzeit in ImageList einfügen

  Alt 10. Feb 2011, 15:20
Im Downloadberech zu Delphi müsste es doch ein PNGImageListe geben? Damit bleibt semitransparenz erhalten.

Ansonsten schau dir mal die Kompos von LMD an. Dort gibt es auch eine PNG-Imageliste.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.785 Beiträge
 
Delphi 12 Athens
 
#4

AW: PNG zur Laufzeit in ImageList einfügen

  Alt 10. Feb 2011, 15:31
Vielleicht macht die TPngImageList der PngComponents das ja besser. Da kann man direkt ein TPngImage in die Liste einfügen. Habe ich aber jetzt nicht ausprobiert.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#5

AW: PNG zur Laufzeit in ImageList einfügen

  Alt 10. Feb 2011, 15:32
Du kannst über einen umweg die PNG's mit GDI+ laden und zu TBitmap umwandeln
ohne den Alphachannel zu verlieren.

Schau mal mein Sample GDIClock_v14 an.
Delphi-Quellcode:
var
  hbmReturn : HBITMAP;
Delphi-Quellcode:
      
hbmReturn := LoadSourceImage('xxx.png');
if hbmReturn <> 0 then
begin
  xxxImg := TBitmap.Create;
  xxxImg.Handle := hbmReturn;
end;
Delphi-Quellcode:
// This function is used to load PNG file which has alpha channel and
// returns the handle to bitmap.
// The rgbReserved element of bitmap gets the data of alpha channel.
function LoadSourceImage(ImgFile : WideString) : HBITMAP;
var
   img: cardinal;
   hbmReturn: HBITMAP;
   format : integer;
begin
   Result := 0;

   if not GDIReady then
      exit;
   if not FileExists(ImgFile) then
      exit;

   GdipLoadImageFromFile(PWideChar(ImgFile), img);

   if img <> 0 then
   begin
     GdipGetImagePixelFormat(img, format);
     if format = PixelFormat32bppARGB then // Accept files with alpha channel
     begin
       GdipCreateHBITMAPFromBitmap(pointer(img), hbmReturn, $000000);
       if hbmReturn <> 0 then
          Result := hbmReturn;
     end;

     GdipDisposeImage(img);
   end;
end;
gruss

Geändert von EWeiss (10. Feb 2011 um 15:45 Uhr)
  Mit Zitat antworten Zitat
David Martens

Registriert seit: 29. Sep 2003
205 Beiträge
 
Delphi XE Enterprise
 
#6

AW: PNG zur Laufzeit in ImageList einfügen

  Alt 10. Feb 2011, 17:12
Danke erstmal an alle.

Ich habe es fast hinbekommen. Die TToolButtons haben nicht mehr hingehauen, aber das konnte ich mit dem TAdvDockPanel von TMS erschlagen. ABER

Ich habe Text auf einige Bilder geschrieben:
Delphi-Quellcode:
  Image.Canvas.Brush.Style := bsClear;

  Image.Canvas.Font. Name := 'Small Fonts';
  Image.Canvas.Font. Size := 5;
  Image.Canvas.Font. Color := Color;

  Image.Canvas.TextOut(16 - Image.Canvas.TextWidth(Text), - 2, Text);
Leider hat der bei einem PNG den Alphachannel vom Untergrund. Kann ich denn den Text direkt auf das PNGImage schreiben ohne den Umweg über den Canvas?

Das wäre SUPER dann hab ich es genau so wie es es wollte.

Danke
David

P.S.: es hat übrigens mit TPNGImageList geklappt.
@EWeiss: sorry, aber eine weitere DLL an alle Benutzer ausliefern wollte ich dann doch nicht.
  Mit Zitat antworten Zitat
Thom

Registriert seit: 19. Mai 2006
570 Beiträge
 
Delphi XE3 Professional
 
#7

AW: PNG zur Laufzeit in ImageList einfügen

  Alt 10. Feb 2011, 17:14

Ähm... Worin besteht das Problem?
Wird einem Bitmap ein PNG-Bild zugewiesen, wird automatisch (falls vorhanden) die Transparenz übergeben und das Bitmap hat 32 Bit Farbtiefe (RGBA). Wird das Bitmap jetzt zur Image-Liste hinzugefügt, wird auch dabei die Transparenz berücksichtigt. Einzige Bedingung dabei: TImageList.ColorDepth muß auf cd32Bit stehen.

Delphi-Quellcode:
procedure TForm1.FormShow(Sender: TObject);
var
  Bmp: TBitmap;
begin
  Bmp:=TBitmap.Create;
  try
    //Die Übergabe der Bilddaten erfolgt dabei von
    //TPNGImage.AssignTo(Bmp):
    Bmp.Assign(Image1.Picture.Graphic);
    //Die Maske ist egal, weil der Alpha-Kanal schon
    //im Bitmap enthalten ist:
    ImageList1.Add(Bmp,nil);
  finally
    Bmp.Free;
  end;
end;
Weshalb also die ganzen Kopfstände mit GDI+, TPngImageList und Co.?

P.S.:
Text wird nun einmal ohne Hintergrund gerendert. Willst Du das nicht, setze
Delphi-Quellcode:
Canvas.TextFlags:=Canvas.TextFlags or ETO_OPAQUE;
//...
Thomas Nitzschke
Google Maps mit Delphi

Geändert von Thom (10. Feb 2011 um 17:22 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: PNG zur Laufzeit in ImageList einfügen

  Alt 10. Feb 2011, 17:18
Sicher daß TBitmap Transparenz kann?

Ich dachte das hätte im 32-Bit-Modus RGBP und nicht RGBA?
(Red, Green, Blue, Palette/Alpha)
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Antwort Antwort


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 11:34 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