Einzelnen Beitrag anzeigen

Thebe

Registriert seit: 26. Jul 2004
Ort: Wedel
78 Beiträge
 
Delphi 6 Enterprise
 
#10

Re: TBitmap.Pixelformat = pfDevice! Check auf 32Bit ?

  Alt 6. Sep 2005, 10:44
Hihoooo

@Dizzy:
Es ist anscheinend tatsächlich so, daß 24bit Bitmaps auch 32Bpp belegen. Der Alphakanal bei den 24bit Bitmaps ist natürlich leer, weil diese Informationen nicht abgespeichert werden im jeweiligen Icon. Ich bin gestern zur ca. der gleichen Zeit wie Du auf die Idee gekommen, den Alphakanal einfach auszulesen ob der ungleich 0 ist.

Die Maske ist leider immer existend, die kann ich nicht auslesen um zu bestimmen was es fürn Icon ist. Schätze ma das sind auch wieder solche Kompatibilitätszwecke, weil nen Win98 Rechner mit den Icons ja auch was anfangen muss, würde da die Maske fehlen wärs ziemlich schlimm.

@Flocke:
Ich hab ja leider nur das Handle von den Icons und keine Datei, das is das Problem. Deswegen nutz ich schon Ansatz 1 mit GetIconInfo (s.o. im Code), nur leider sind die ja DeviceDependentBitmaps, sprich PixelFormat = pfDevice.

Lösung 2: Auslesen des Alphakanals des ColorBitmaps.
Ist nicht wirklich mein Favorit, da ich nicht weiß wie ne 1,4ghz Maschine damit klar kommt, aber bei mir funktioniert es in recht kurzer Zeit. Es schmeckt mir nur nicht wirklich, um rauszukriegen ob eine Bitmap 24 oder 32bittig ist, gleich die komplette Bitmap per Scanline analysieren zu müssen, man sollte meinen das wäre mit nem Performance-schonenderem "if 32bit then HauReinUndTuWas();" möglich.

Hier erstma der Code bis dato

Delphi-Quellcode:
function IconToBitmap(const IconHandle: HIcon):TBitmap;
var
        IcoInfo: TIconInfo; // Icon Info mit beiden Bitmaps
        mask: TBitmap; // TBitmap für Maskierungsbitmap
// result: TBitmap; // TBitmap für das Farbinformationsbitmap
        x, y: word; // Zählvariablen
        AnSL, AnSL2: pRGBALine; // Scanline Arrays für Color BMP und für Mask BMP
        xp: boolean; // Boolean Wert ob bei der Analysierung ein XP Icon entdeckt wurde
begin
// Aus dem Icon Handle die beiden Bitmaps - Color und Mask - rauskriegen. Wenn nicht, dann gleich Ende
        result := nil;
        if NOT GetIconInfo(IconHandle, IcoInfo) then
                exit;

        try
                try
                        result := TBitmap.Create;
                        result.Handle := IcoInfo.hbmColor;
                        result.PixelFormat := pf32bit;

                        mask := TBitmap.Create;
                        mask.Handle := IcoInfo.hbmMask;
                        mask.PixelFormat := pf32bit;

// Color Bitmap analysieren, ob alle Alphawerte = 0 sind. Wenn ja, dann bleibt xp = false. Wenn nur ein Wert != 0 gefunden wurde, dann ist ein XP Icon gefunden worden und die Schleife bricht ab.
                        xp := false;
                        AnSL := result.ScanLine[result.Height-1];
                        x := 0;

                        while ((x < (result.Height*result.Width)) and (xp = false)) do
                        begin
                                xp := xp or (AnSL^[x].rgbReserved <> 0);
                                inc(x);
                        end;

// Wenn kein XP Icon gefunden wurde, dann die Maskierungsinformationen aus der Mask BMP in den Alphakanal des Color Bitmaps reinkopieren. Da die Maskierung entweder Weiß oder Schwarz ist (sprich alle RGB Werte gleich), wird stellvertretend für den Maskierungswert Rot genommen
                        if not xp then
                        begin
                                for y := 0 to result.Height-1 do
                                begin
                                        AnSL := result.Scanline[y];
                                        AnSL2 := mask.ScanLine[y];
                                        for x := 0 to result.Width-1 do
                                                AnSL^[x].rgbReserved := NOT AnSL2^[x].rgbRed;
                                end;
                        end
// Eigener Hack: AlphaBlend() zeigt bei mir ein merkwürdiges Verhalten. Wenn von einem Pixel der Alpha Wert 0 ist und die Pixelfarbe in den helleren Bereich wie weiß, helles gelb etc. geht, dann wird trotz Alpha=0 das weiße Pixel bei AlphaBlend in ein anderes Bitmap kopiert. Als Fix dafür werden alle Pixel schwarz gemacht, die einen Alphawert von kleiner 100 haben, sprich eigentlich sowieso nur für den obligatorischen Schlagschatten zuständig sind und der immer schwarz ist.
                        else
                        begin
                                for x := 0 to (result.Height*result.Width)-1 do
                                        if AnSL^[x].rgbReserved < 100 then
                                        begin
                                                AnSL^[x].rgbRed := 0;
                                                AnSL^[x].rgbGreen := 0;
                                                AnSL^[x].rgbBlue := 0;
                                        end;
                        end;
                except
                        FreeAndNil(result);
                end;
        finally
                if Assigned(mask) then
                        mask.Free;
        end;
end;
Das funkt soweit, nur finde ich schaut das eher aus als wenn ich mit Kannonen auf Spatzen schießen würde, statt adäquat der Situation entsprechend einen Wert auszulesen.

Ich suche noch weiter nach Methoden dieses Analysieren zu umgehen, sowas muss ja nicht sein.

Vielen Dank wieder mal für Eure Antworten!

- Thebe
  Mit Zitat antworten Zitat