AGB  ·  Datenschutz  ·  Impressum  







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

Änderung: PNG in 32bit Icon (alpha blended) wandeln

Ein Thema von Biergeneral · begonnen am 5. Jan 2008
Antwort Antwort
Biergeneral

Registriert seit: 12. Jul 2006
1 Beiträge
 
#1

Änderung: PNG in 32bit Icon (alpha blended) wandeln

  Alt 5. Jan 2008, 03:04
Hallo!

Ich habe einen Änderungsvorschlag für die folgende Methode:
(orig. Artikel : PNG in 32bit Icon (alpha blended) wandeln (ohne GDI+)
http://www.delphipraxis.net/internal...t.php?p=539759)

Die aktuelle Methode macht große Schwierigkeiten bei der Konvertierung von dem BitmapV5Header in die BitmapInfo.
Bei der aktuellen Variante wird nicht der komplette Header übergeben sondern nur die ersten 44 Bytes.
Das kann aus welchen Grund auch immer bei Delphi zufällig auftauchende, absolut irrsinnige Fehler erzeugen(Vergleichbar mit den Fehlern, wenn man über die Arraygrenzen hinausschreibt). Bei mir kam hin und wieder mal der Fehler "Division durch Null".
Das lässt sich aber durch eine kleine Änderung beheben. (Getestet mit Delphi 2007 Ent.)


Delphi-Quellcode:
uses
  Windows,
  [...]

{Header mit BitmapV5Header}
{$EXTERNALSYM CreateDIBSection}
function CreateDIBSection(DC: HDC; const p2: TBitmapV5Header; p3: UINT;
  var p4: Pointer; p5: THandle; p6: DWORD): HBITMAP; stdcall;

implementation

function CreateDIBSection; external gdi32 name 'CreateDIBSection';


function PNGtoIcon(const APNG : TPNGObject;
                      ACursor : Boolean = false;
                      AHotSpotX : Integer = 0;
                      AHotSpotY : Integer = 0) : HICON;
var
  Width, Height : Integer;
  BitmapHeader : TBitmapV5Header; //TBitmapV5Header statt 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); Nicht mehr notwendig }

  //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,

{***                                                          Genau an dieser Stelle liegt die Ursache für das Problem...
                                PBitmapInfo(BitmapHeader)^, //Hier ein wenig tricksen
                                                            // ... damit der V5Header "reinpasst" }


                                BitmapHeader, { Statt der alten Methode passt jetzt der komplette Header rein }
                                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;
  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:54 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