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