AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Code-Bibliothek Library: Grafik / Sound / Multimedia Delphi PNG in 32bit Icon (alpha blended) wandeln (ohne GDI+)
Thema durchsuchen
Ansicht
Themen-Optionen

PNG in 32bit Icon (alpha blended) wandeln (ohne GDI+)

Ein Thema von chaosben · begonnen am 27. Apr 2006
Antwort Antwort
Benutzerbild von chaosben
chaosben

Registriert seit: 27. Apr 2005
Ort: Görlitz
1.358 Beiträge
 
Delphi XE2 Professional
 
#1

PNG in 32bit Icon (alpha blended) wandeln (ohne GDI+)

  Alt 27. Apr 2006, 19:19
Sinn:
-ein PNG-Bild in ein 32bit Icon mit Alphablending konvertieren und das Ganze ohne Nutzung von GDI+

Benötigte zusätzliche Units:
-PNGImage

Basierend auf:
-einem MSDN-Artikel

Delphi-Quellcode:
function PNGtoIcon(const APNG : TPNGObject;
                      ACursor : Boolean = false;
                      AHotSpotX : Integer = 0;
                      AHotSpotY : Integer = 0) : HICON;
var
  Width, Height : Integer;
  BitmapHeader : PBitmapV5Header;
  hNewBitmap,
  hMonoBitmap : HBITMAP;
  Bits : Pointer;
  x,
  y : Integer;
  DC : HDC;
  IconInfo : _ICONINFO;
  Pixel : ^Integer;
  ScanLine : PRGBTriple;
  AlphaScanline : pByteArray;
begin

  //Die Höhe und die Breite brauchen wir später noch ein paar Mal
  Width := APNG.Width;
  Height := APNG.Height;

  //So ein Icon hat einen "Bitmap Version 5 Header"
  //(Wichtig: Als Pointer, damit er später vom CreateDIBSection "genommen" wird)
  New(BitmapHeader);

  //Die Größe der Struktur setzen, damit Windows weiß, "wie weit es gehen kann" :)
  BitmapHeader.bV5Size := sizeof(BITMAPV5HEADER);

  BitmapHeader.bV5Width := Width;
  //Wichtig: negative Höhe angeben, sonst ist das Ergebniss an der X-Achse gespiegelt
  // ... bzw. der Ursprung des Bildes an der falschen Stelle (technisch richtiger)
  BitmapHeader.bV5Height := -Height;

  //Wir haben eine Ebene
  BitmapHeader.bV5Planes := 1;
  // ... und 32bit pro Bixel
  BitmapHeader.bV5BitCount := 32;

  //Das Bild wird nicht komprimiert
  BitmapHeader.bV5Compression := BI_BITFIELDS;
  //Und nun müssen wir noch sagen, wo sich die Farben und der Alpha-Wert innerhalb
  // ... der 32bit eines Pixels befinden
  BitmapHeader.bV5RedMask := $00FF0000;
  BitmapHeader.bV5GreenMask := $0000FF00;
  BitmapHeader.bV5BlueMask := $000000FF;
  BitmapHeader.bV5AlphaMask := $FF000000;


  DC := GetDC(0);
  //Ein neues Bitmap anlegen
  hNewBitmap := CreateDIBSection( DC,
                                PBitmapInfo(BitmapHeader)^, //Hier ein wenig tricksen
                                                            // ... damit der V5Header "reinpasst"
                                DIB_RGB_COLORS, //wir haben RGB-Farben
                                Bits, //eine Pointer auf das erste Pixel
                                0, //bedeutet, das wir das Bitmap im RAM haben wollen
                                0); // ... und deswegen brauchen wir auch kein Offset
  Dispose(BitmapHeader); //der Header hat seine Schuldigkeit getan
  ReleaseDC(0,dc); // ... und auch unser DC

  //man nehme ein Bitmap, welches wir später als Maske "verkaufen"
  hMonoBitmap:=CreateBitmap(Width,Height,1,1,nil);

  //Und los gehts beim ersten Pixel
  Pixel := Bits;
  for y := 0 to Height-1 do
  begin
    //aus dem PNG die Farbwerte einer Zeile holen
    ScanLine := APNG.Scanline[y];
    // ... und dazu die Alpha-Werte
    AlphaScanline := APNG.AlphaScanline[y];
    for x := 0 to Width - 1 do
    begin
      //ein Pixel-Wert setzt sich aus ...
      Pixel^ := AlphaScanLine[x]; // ... dem Alpha-Wert, ...
      Pixel^ := Pixel^ shl 8;
      Inc(Pixel^, Scanline^.rgbtRed); // ... einem Rot-Anteil, ...
      Pixel^ := Pixel^ shl 8;
      Inc(Pixel^, Scanline^.rgbtGreen); // ... einem Grün-Anteil, ...
      Pixel^ := Pixel^ shl 8;
      Inc(Pixel^, Scanline^.rgbtBlue); // ... und einem Blau-Anteil zusammen

      //weiter gehts mit dem nächsten Pixel innerhalb unseres RAM-Bitmaps
      Inc(Pixel);

      //und auch ein neues Pixel von unserem PNG währe nicht schlecht
      Inc(ScanLine);
    end;
  end;

  //Mit der IconInfo-Struktur können wir einige Eigenschaften des Icons setzen

  // ... z.B. ob es ein Cursor ...
  IconInfo.fIcon := not ACursor;
  if ACursor then
  begin
    // ... mit einem Hotspot ist
    IconInfo.xHotspot := AHotSpotX;
    IconInfo.yHotspot := AHotSpotY;
  end;
  //Aber auf jeden Fall brauchen wir ein Bitmap das als Maske dient
  IconInfo.hbmMask := hMonoBitmap;
  // ... und natürlich ein Bitmap mit dem eigentlichen Bild
  IconInfo.hbmColor := hNewBitmap;

  //Et voila ... ein schönes neues Icon
  Result := CreateIconIndirect(IconInfo);

  //natürlich räumen wir nachher auf
  DeleteObject(hNewBitmap);
  DeleteObject(hMonoBitmap);
 
  //Wichtig: Das Icon, das zurückgegeben wird muss auch mit DestroyIcon
  // ... freigegeben werden, wenn wir es nicht mehr brauchen.
end;
[edit=Chakotay1308]SourceCode korrigiert. Mfg, Chakotay1308[/edit]
[edit=Chakotay1308]DeleteObject DestroyIcon. Mfg, Chakotay1308[/edit]
Benjamin Schwarze
If I have seen further it is by standing on the shoulders of Giants. (Isaac Newton)
  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 22:18 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