Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   PNG zur Laufzeit in ImageList einfügen (https://www.delphipraxis.net/150954-png-zur-laufzeit-imagelist-einfuegen.html)

bezarre 1. Mai 2010 12:04


PNG zur Laufzeit in ImageList einfügen
 
Hallo,

diesmal möchte ich eine PNG Datei einlesen lassen und sie dann in eine ImageList einfügen.

Delphi-Quellcode:
procedure build_imagelist(ImageList:TImageList);
  var
  image : TBitmap;
  PNG : TPNGOBject;
  i :Integer;
  begin
   
        png.Create;
        image.create;
        png.LoadFromFile('images\bild1.png');
        image.Assign(png);
        Imagelist.Add(image,nil);
        png.Destroy;
        image.Destroy;

  end;
Ich habe mir das jetzt irgendwie so gedacht, kriege aber leider immer eine Fehlermeldung, dass eine Speicherverletzung auftritt. Was genau fehlt mir noch bzw. was ist richtig an dem, was ich gemacht habe?

Gruß
Micha

PS nochmal danke für eure bisherige Hilfe.

mkinzler 1. Mai 2010 12:07

Re: PNG zur Laufzeit in ImageList einfügen
 
In welcher (Code-)Zeile?

bezarre 1. Mai 2010 12:10

Re: PNG zur Laufzeit in ImageList einfügen
 
Hallo,

in garkeiner Zeile. Compilieren und erzeugen passt beides.
Aber beim Starten kommt dann folgende Meldung:

Zugriffsverletzung bei Adresse {blabla} im Modul start.exe. Lesen von Adresse {blabla}.

Ich lasse die Funktion übrigens bei onShow starten.

Gruß
Micha

Andreas L. 1. Mai 2010 12:13

Re: PNG zur Laufzeit in ImageList einfügen
 
Delphi-Quellcode:
  //falsch
      png.Create;
        image.create;

  //richtig
      png := TPNGObject.Create;
        image := TBitmap.create;

Uwe Raabe 1. Mai 2010 12:14

Re: PNG zur Laufzeit in ImageList einfügen
 
png := TPngObject.Create;
image := TBitmap.create;

png.LoadFromFile('images\bild1.png');
image.Assign(png);
Imagelist.Add(image,nil);
png.Free;
image.Free;

bezarre 1. Mai 2010 12:16

Re: PNG zur Laufzeit in ImageList einfügen
 
Hallo,

dankeschön :-)

Funktioniert.

Und wie sorge ich dafür, dass die Hintergründe Transparent bleiben?

Gruß
Micha

mkinzler 1. Mai 2010 12:22

Re: PNG zur Laufzeit in ImageList einfügen
 
Zitat:

Aber beim Starten kommt dann folgende Meldung:
Beschäftige dich mal mit dem Thema Debugger.
Zitat:

Und wie sorge ich dafür, dass die Hintergründe Transparent bleiben?
So nicht, da Bitmaps keine Transparenz kennen

Andreas L. 1. Mai 2010 12:28

Re: PNG zur Laufzeit in ImageList einfügen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Jetzt frag ich nochmal: Welche Delphi-Version hast du? (Das kannst du auch in deinem Profil eintragen damit es jeder sehen kann)

Ab Delphi 2009 (oder ab 2007?) unterstützt die IDE von Haus aus PNG-Bilder. Es sollte also auch eine Möglichkeit geben der ImageList ein PNG hinzu zufügen ohne es vorher in ein Bitmap oder ähnliches umzuwandeln.

Da ich aber auch schon jede Menge Probleme mit der ImageList hatte, verwende ich nur noch die X²GraphicList (siehe Anhang). Da kann man alles rein laden 8-)

David Martens 10. Feb 2011 14:58

AW: PNG zur Laufzeit in ImageList einfügen
 
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:
Delphi-Quellcode:
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:
Delphi-Quellcode:
  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.

himitsu 10. Feb 2011 15:13

AW: PNG zur Laufzeit in ImageList einfügen
 
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)

Bernhard Geyer 10. Feb 2011 15:20

AW: PNG zur Laufzeit in ImageList einfügen
 
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.

Uwe Raabe 10. Feb 2011 15:31

AW: PNG zur Laufzeit in ImageList einfügen
 
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.

EWeiss 10. Feb 2011 15:32

AW: PNG zur Laufzeit in ImageList einfügen
 
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

David Martens 10. Feb 2011 17:12

AW: PNG zur Laufzeit in ImageList einfügen
 
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.

Thom 10. Feb 2011 17:14

AW: PNG zur Laufzeit in ImageList einfügen
 
:gruebel:
Ä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;
//...

himitsu 10. Feb 2011 17:18

AW: PNG zur Laufzeit in ImageList einfügen
 
Sicher daß TBitmap Transparenz kann?

Ich dachte das hätte im 32-Bit-Modus RGBP und nicht RGBA?
(Red, Green, Blue, Palette/Alpha)

Thom 10. Feb 2011 17:36

AW: PNG zur Laufzeit in ImageList einfügen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ja, TBitmap unterstütz den Alpha-Kanal.
Ich hatte das vor einigen Tage getestet, als ich eigene Marker-Icons für Google Maps erstellen wollte.
Anhang 33333
Gezeichnet wird dabei in ein TPNGImage, was für sich genommen noch nichts besonderes ist. Erst bei der Erstellung des Schattenbildes wird es interessant:
Dabei wird das PNG-Bild als Maske samt Transparenz in ein Bitmap kopiert, perspektivisch verzerrt, gefiltert und wieder zurück in ein (neues) PNG-Image kopiert - und das alles unter Beibehaltung der Transparenz.

David Martens 10. Feb 2011 17:38

AW: PNG zur Laufzeit in ImageList einfügen
 
Also ich hab folgendes probiert, aber geht noch nicht:

Delphi-Quellcode:
      Image := TPngImage.Create;
      Image.Transparent := true;
      Image := GetPNG('ABC');

      if Image <> nil then
      begin
        if Color <> clNone then
        begin
          Image2 := TPngImage.CreateBlank(COLOR_GRAYSCALE, 1, 16, 16);

          Image2.Canvas.Brush.Style := bsClear;

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

          Image2.Canvas.TextOut(16 - Image.Canvas.TextWidth(Text), - 2, Text); // HIER schreibe ich den Text ins Image2

          for y := 0 to Image2.Height - 1 do
          begin
            for x := 0 to Image2.Width - 1 do
            begin
              // HIER wird der Text ins Image "kopiert"
              if Image2.Canvas.Pixels[x, y] = clBlack then
                Image.Pixels[x, y] := clBlack;
            end;
          end;
        end;
      end;

      with Image do
      begin
        for y := 0 to Height - 1 do
        begin
          pb := AlphaScanline[y];
          for x := 0 to Width - 1 do
          begin
            ColorRGBToHLS(ImageColor, NewHue, NewLuminance, NewSaturation);

            // HIER soll der Text im Image nicht überschrieben werden
            if Pixels[x, y] <> clBlack then
              Pixels[x, y] := ColorHLSToRGB(NewHue, Trunc((pb^[x] + NewLuminance) / 2), NewSaturation);
          end;
        end;
      end;
Lieder sehe ich noch keinen Text. Wenn ich TextOut dierekt auf Image mache, sehe ich nur dort Text wo im Ursprungsimage keine Transparenz vorhanden ist.

P.S.: ach so mit ColorHLSToRGB(NewHue, Trunc((pb^[x] + NewLuminance) / 2), NewSaturation); wird das PNG (hat nur den Alphachannel) in der "neuen" Farbe eingefärbt.

David Martens 10. Feb 2011 17:39

AW: PNG zur Laufzeit in ImageList einfügen
 
@Thom: und das Ganze funktioniert auch noch mit TImageList?

EWeiss 10. Feb 2011 17:46

AW: PNG zur Laufzeit in ImageList einfügen
 
Zitat:

EWeiss: sorry, aber eine weitere DLL an alle Benutzer ausliefern wollte ich dann doch nicht.
He?
Was für eine DLL?
GDI+ ist auf allen Systemen enthalten.

Zitat:

Weshalb also die ganzen Kopfstände mit GDI+, TPngImageList und Co.?
Weil GDI+ und das ist Fakt einfach das beste ist wenn es um PNG Dateien geht.
Zumindest meine Erfahrung.

gruss

Thom 10. Feb 2011 18:21

AW: PNG zur Laufzeit in ImageList einfügen
 
Liste der Anhänge anzeigen (Anzahl: 2)
Zitat:

Zitat von David Martens (Beitrag 1080891)
@Thom: und das Ganze funktioniert auch noch mit TImageList?

Ja. Hier der Beweis:
Anhang 33334
Das rechte obere Smiley ist ein TImage mit dem Original-PNG-Bild. Im FormShow-Event wird dieses Bild in eine normale Image-Liste kopiert (siehe erstes Beispiel). Diese Image-Liste wird vom Button zur Darstellung des Icons genutzt (ohne jeglichen eigenen Quelltext). Das Quadrat unteren ist ein TShape-Objekt, das in seiner rechten oberen Ecke von einer kleinen PaintBox überlagert ist und in die mit
Delphi-Quellcode:
procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  ImageList1.Draw(PaintBox1.Canvas,0,0,0);
end;
gezeichnet wird. Mehr ist das nicht: Keine Magie, keine Tricks...
Eine Vergrößerung zeigt, das der Alpha-Kanal wirklich vorhanden ist:
Anhang 33335

Zitat:

Zitat von EWeiss (Beitrag 150954)
GDI+ ist auf allen Systemen enthalten.

Nein. Zum Beispiel auf Windows 98 und Windows 2000 noch nicht.

EWeiss 10. Feb 2011 18:25

AW: PNG zur Laufzeit in ImageList einfügen
 
Ich möchte bezweifeln das der AlphaChannel korrekt angezeigt wird..
Schon mal den AlphaChannel auf 75% Durchsichtigkeit verändert und dann anzeigen lassen ?

es sollte ja dann Transparent über deinen Panel liegen (Durchscheinend)

So in der art .. Siehe Pic
Hintergrundbild mit aufgesetztem PNG AlphaChannel 50%

gruss

Thom 10. Feb 2011 18:49

AW: PNG zur Laufzeit in ImageList einfügen
 
Liste der Anhänge anzeigen (Anzahl: 1)
OK - Hier der Versuch mit Geister-Smileys:
Anhang 33337
Die Transparenz ist gut zu erkennen. Allerdings wird auch sichtbar, daß die Objekte (TImage und TButton) offenbar etwas unterschiedliche Zeichenalgorithmen verwenden, da die Farbsättigung differiert.

P.S.:
@EWeiss: Dein Bild sieht natürlich besser aus! 8-)

EWeiss 10. Feb 2011 18:52

AW: PNG zur Laufzeit in ImageList einfügen
 
Zitat:

Zitat von Thom (Beitrag 1080919)
OK - Hier der Versuch mit Geister-Smileys:
Anhang 33337
Die Transparent ist gut zu erkennen. Allerdings wird auch sichtbar, daß die Objekte (TImage und TButton) offenbar etwas unterschiedliche Zeichenalgorithmen verwenden, da die Farbsättigung differiert.

Supi..
Danke das du mich überzeugen konntest.
Denke damit kann man leben :)

Zitat:

P.S.:
@EWeiss: Dein Bild sieht natürlich besser aus! 8-)
Jo denke auch ;)
hehehehe

gruss

Thom 10. Feb 2011 19:04

AW: PNG zur Laufzeit in ImageList einfügen
 
Zitat:

Zitat von EWeiss (Beitrag 1080921)
Danke das du mich überzeugen konntest.

Keine Ursache - gern geschehen! :thumb:

P.S.:
Dein Bild wird ja immer besser! 8-)
Gefällt mir!

himitsu 10. Feb 2011 20:23

AW: PNG zur Laufzeit in ImageList einfügen
 
Zitat:

Zitat von Thom (Beitrag 1080888)
Ja, TBitmap unterstütz den Alpha-Kanal.

Gut, wenn man es über in ein TBitmap reinquetzt und keine delphieigenen Komponenten/Befehle verwendet, um es anzuzeigen oder zu bearbeiten, dann mag es gehen, wenn man das PalettenByte als Alphakanal mißbraucht und das TBitmap quasi nur als Speichermedium verwendet. Von den "normalen" Delphi/Windows-Funktionen würde der "Alpha"-Kanal aber bestimmt nur als Palette behandelt.


Hab nochmal schnell nachgeguck:
Zitat:

Zitat von OH:TColor
Hat das höchstwertige Byte den Wert Null, erhalten Sie eine Farbe, die derjenigen in der Systempalette am ähnlichsten ist. Ist das höchstwertige Byte Eins ($01 bzw. 0x01), ergibt das eine Farbe, die derjenigen in der aktiven Palette am ähnlichsten ist. Wenn Sie das höchstwertige Byte auf Zwei ($02 bzw. 0x02) setzen, wird der Wert an die ähnlichste Farbe in der logischen Palette des aktuellen Gerätekontexts angepasst.

Und dann noch:
Delphi-Quellcode:
clSystemColor = $FF000000;
clNone = TColor($1FFFFFFF);
clDefault = TColor($20000000);

Genauso kann ich ja Binärdaten in einem (Ansi)String zwischenspeichern und es ist dennoch nicht sofort ein lesbarer/anzeigbarer "Text".

David Martens 11. Feb 2011 11:21

AW: PNG zur Laufzeit in ImageList einfügen
 
Es geht :dp:

So um nur noch mein Ergebnis zu präsentieren:

1. Mit TImageList hat es NICHT geklappt. Was wohl auch an mir liegt. Ich hatte vergessen zu sagen das Bild selbst hat unterschiedliche Transparenz ich will das Bild nicht mit eine Gesamttransparenz zeichnen.

Hier der Code mit dem es geht und unten dann die Erklärung dazu:
Delphi-Quellcode:
      if Image <> nil then
      begin
        if Color <> clNone then
        begin
          Image2 := TPngImage.CreateBlank(COLOR_GRAYSCALE, 1, 16, 16);

          Image2.Canvas.Brush.Style := bsClear;

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

          Image2.Canvas.TextFlags := Image2.Canvas.TextFlags or ETO_OPAQUE;
          Image2.Canvas.TextOut(16 - Image2.Canvas.TextWidth(Text), - 2, Text);
        end;
      end;

      with Image do
      begin
        for y := 0 to Height - 1 do
        begin
          pb := AlphaScanline[y];
          for x := 0 to Width - 1 do
          begin
            ColorRGBToHLS(ImageColor, NewHue, NewLuminance, NewSaturation);

            if Image2.Pixels[x, y] = clWhite then
            begin
              Pixels[x, y] := clBlack;
              pb^[x] := 255;
            end
            else
              Pixels[x, y] := ColorHLSToRGB(NewHue, Trunc((pb^[x] + NewLuminance) / 2), NewSaturation);
          end;
        end;
      end;

      if Image <> nil then
      begin
        Liste.AddPng(Image);
      end;
1.
Delphi-Quellcode:
TPngImage.CreateBlank(COLOR_GRAYSCALE, 1, 16, 16);
erzeugt ein SCHWARZES Bild, ergo muß ich Weiß als Textfarbe nehmen.
2.
Delphi-Quellcode:
            if Image2.Pixels[x, y] = clWhite then
            begin
              Pixels[x, y] := clBlack;
              pb^[x] := 255;
            end
Das ist der eigentliche Knackpunkt, hier muß ich den Alphachannel auch noch setzen.

Vielen Dank an alle
David

Thom 11. Feb 2011 15:49

AW: PNG zur Laufzeit in ImageList einfügen
 
Liste der Anhänge anzeigen (Anzahl: 2)
Sind hier nur Skeptiker unterwegs!? :wink:
Zitat:

Zitat von himitsu (Beitrag 1080944)
Gut, wenn man es über in ein TBitmap reinquetzt und keine delphieigenen Komponenten/Befehle verwendet, um es anzuzeigen oder zu bearbeiten, dann mag es gehen, wenn man das PalettenByte als Alphakanal mißbraucht und das TBitmap quasi nur als Speichermedium verwendet. Von den "normalen" Delphi/Windows-Funktionen würde der "Alpha"-Kanal aber bestimmt nur als Palette behandelt.

Im Bitmap kann die Farbtiefe über die Eigenschaft PixelFormat eingestellt werden. pf1bit erzeugt zum Beispiel ein Schwarz-Weiß-Bild. In einem Byte sind also (Windows-)intern (!!!) 8 nebeneinanderliegende Pixel enthalten. Kannst Du gern über ScanLine überprüfen. Wenn Du da mit der 32-Bit-TColor-Keule draufhauen würdest, würdest du dem Tapferen Schneiderlein Konkurrenz machen und auf einmal sogar 32 Pixel erschlagen! Die Methoden GetPixel und SetPixel des Windows API's (gekapselt in der Eigenschaft Canvas.Pixels[x,y]) rechnen die tatsächlich im Bitmap enthaltenen Werte um. Bei einem Schwarz-Weiß-Bild könnte ich natürlich ohne Fehlermeldung den Wert clRed übergeben - darf mich aber dann natürlich nicht wundern, wenn das nicht im Bitmap ankommt!

Ich habe irgendwie den Eindruck, daß Du nach dem Motto gehts: Was nicht sein darf, das kann nicht sein.
Probier's doch einfach aus: Lade ein beliebiges PNG-Bild in eine TImage-Komponente, kopiere zur Laufzeit das Bild in ein temporäres Bitmap und laß es in einer PaintBox anzeigen. Du wirst sehen: Die Transparenz des PNG-Bildes bleibt erhalten. Und jetzt kommt die (rhetorische) Frage: Wer hat das Bitmap auf den Bildschirm gezaubert? Das war Windows. Also kommt Windows (unter Berücksichtigung einiger Bedingungen) tatsächlich mit Alpha-Werten in Bitmaps zurecht!

Damit Du's und alle anderen, die es nicht glauben (wollen/können) habe ich eine kleine Demo fertig gemacht:
Anhang 33345

Der Kern des Ganzen:
Delphi-Quellcode:
procedure TForm2.PaintBox1Paint(Sender: TObject);
var
  Bmp: TBitmap;
begin
  Bmp:=TBitmap.Create;
  try
    Bmp.Assign(Image1.Picture.Graphic);
    PaintBox1.Canvas.Draw(0,0,Bmp);
  finally
    Bmp.Free;
  end;
end;
Der Alpha-Kanal wird vom PNG-Bild korrekt in das Bitmap übernommen und von Windows wiederum richtig auf den Bildschirm dargestellt.
w.z.b.w.
q.e.d.

Sowohl die PaintBox als auch das Image sind auf dem Hintergrund verschiebbar. Wer's dann immer noch nicht glaubt, dem kann ich auch nicht mehr helfen... :roll:

EWeiss 11. Feb 2011 16:37

AW: PNG zur Laufzeit in ImageList einfügen
 
Zitat:

Wer's dann immer noch nicht glaubt, dem kann ich auch nicht mehr helfen...
Ich bin nicht gläubig.
Aber in dem Fall schon ;)

Dafür muss ich das nicht extra laden..

Thom 11. Feb 2011 17:32

AW: PNG zur Laufzeit in ImageList einfügen
 
Etwas OT:
Zitat:

Zitat von EWeiss (Beitrag 1081095)
Ich bin nicht gläubig.

Ich auch nicht... :lol: Deshalb finde ich Matthias Eissing's Berufsbezeichnung auch immer etwas befremdlich, wenn ich wieder einmal darüber stolpere: National Evangelist Germany. :gruebel: Ich weiß: Das ist wohl eher im Sinne eines Technology Evangelisten gemeint - aber trotzdem hat es für mich einen merkwürdigen Beigeschmack. Tja, ja - die Ammis (Embarcadero) mit ihrem Sendungsbewußtsein...8-)

Mal sehen, was himitsu dazu meint... (Damit meine ich nicht die Glaubensfrage sondern die Transparenzfähigkeit von Bitmaps.) :zwinker:

David Martens 12. Feb 2011 02:58

AW: PNG zur Laufzeit in ImageList einfügen
 
Nur um es nochmal zum bekräftigen:

mit TImageList hat es nicht geklappt.

Meine Schritte:
1. PNG in einer separaten DLL
2. mit TPngImage.LoadFromResourceName(hLib, Name); laden
3. mit ImageList.Add(Image, Mask); Bild speichern
4. Toolbuttons, Menüs die ImageList zuweisen und Bilder anzeigen lassen

Das funktioniert leider so nicht, weil Punkt 3 den Alphakanal anscheinen schluckt.

Also benutze ich die PNGComponents. Das hat PngImageList.AddPng(PngImage); und behält alles bei.
Außerdem kann mit der PngImageList auch gleich die Disabled Version erzeugt werden. Dafür sind auch gleich PngSpeedButtons und PngBitButtons vorhanden.

Es gibt noch ein/zwei Spezialfälle die ich hier auch noch erwähnen will.

Eins der Bilder besteht nur aus dem Alphakanal und soll entsprechend eingefärbt werden. Danach werden in das Bild noch ein paar Buchstaben geschrieben.
Ein paar Bilder werden aus der installierten Excel/Word Version extrahiert (Programmicons) und genauso das Notepadicon.

Bei all diesen Funktionen mußte ich bei ImageList/TBitmap einem Trick anwenden. Die tranzparenten Teile des Bildes mußte ich mit clButtonFace einfärben. Das hatte jedoch unter anderem den Nachteil, das die Bilder im Menü immer diesen "Hintergrund" haben, auch wenn man drüber geht.

@Thom: Wenn die Tranzparenz mit normalen ImageList/TBitmap funktioniert würde ich das sofort benutzen, aber ich habe es nicht hinbekommen. Wenn ich die Bilder zur Design-Time lade dann geht es, aber nicht zur Laufzeit.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:33 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