AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi TBitmap.Pixelformat = pfDevice! Check auf 32Bit ?
Thema durchsuchen
Ansicht
Themen-Optionen

TBitmap.Pixelformat = pfDevice! Check auf 32Bit ?

Ein Thema von Thebe · begonnen am 2. Mai 2005 · letzter Beitrag vom 6. Sep 2005
Antwort Antwort
Thebe

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

TBitmap.Pixelformat = pfDevice! Check auf 32Bit ?

  Alt 2. Mai 2005, 19:36
Mahlzeit

Ich hab ein TBitmap aus einem Icon rausgezogen, nur leider liegt die ColorMask eines Icons nicht so vor wie ich möchte.
Und zwar ist bei diesem Bitmap das PixelFormat pfDevice, was ja auch eigentlich alles sein könnte. Wenn ich das PixelFormat auf 32bit setze, hab ich dann ja auch 32bit Information in dieser Bitmap wie Alpha Channel z.B. Nur manchmal ist so ein Bitmap eben nicht im 32bit Modus sondern z.b. nur 8 oder 16bit, nur das Pixelformat bleibt gleich beim TBitmap, nämlich pfDevice.

Wie kann ich nun rauskriegen ob die Bitmap die ich bearbeite im 32bit Modus ist oder nicht, allerdings ohne das ich mich auf TBitmap.Pixelformat stützen muss ?

Schon mal Danke im Vorraus.

- Thebe
  Mit Zitat antworten Zitat
Thebe

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

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

  Alt 3. Mai 2005, 15:05
Sooo... *schieb*

Ich hab nun herausgefunden das ich da mit dem FormatDescriptor vom Bitmap was anfangen kann.
Und zwar:

Delphi-Quellcode:
var
   pfd: PixelFormatDescriptor
begin
    DescribePixelFormat(result.Canvas.Handle, GetPixelFormat(result.Canvas.Handle), sizeof(PixelFormatDescriptor), pfd);

    if pfd.iPixelType = PFD_TYPE_RGBA then
        ShowMessage('Es ist 32BIT!');
end;
Es funkt tatsächlich, nur es gibt ein riesen Manko bei dem Teil:
Um ca. 6 Bitmaps damit abzuchecken, braucht mein Rechner (P4 2,6Ghz, 1G Ram, WinXP) ma so locker 2-3 Sekunden. Und das ist mir zuviel, besonders da ich die Funktion benutzen will wo auch mal 20 Bitmaps abgecheckt werden müssen. Dann sitzt der Benutzer 7-10 Sekunden doof rum, was ich absolut nicht befürworten kann.

Habt ihr ne Ahnung wie ich diese langsame Funktion (DescribePixelFormat, GetPixelFormat) durch andere ersetzen kann ??

- Thebe
  Mit Zitat antworten Zitat
Thebe

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

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

  Alt 5. Sep 2005, 21:34
Ich muss leider den Thread wieder aussem Grab heraus befördern, weil ich immer noch in dieser Hinsicht Probleme hab. Am besten beschreibe ich mal alles haargenau was ich mache, vielleicht kann man dann besser das Problem nachvollziehen.

Also:
Ich möchte Icons in eine 32bit Bitmap umwandeln und je nachdem ob ich ein neues XP Icon oder ein altes Icon mit 24bit Farbe umwandle, muss ich da anders ran. Jedes Icon hat ja einmal eine BMP, in der die Farbinformationen (und bei XP Icons, der Alphakanal) enthalten ist.
Dann hat das Ding eine Maskierungs BMP, in der (auch bei XP Icons, zwecks Kompatibilitätsgründen schätz ich ma) eine 1bit Maskierung abgespeichert is, die bestimmt welcher Pixel vom Icon durchsichtig is und welcher nicht.

Wenn ich also ein XP Icon umwandeln möchte, dann ist die BMP mit dem Farbinformationen eine 32bit Bitmap, in der auch der Alphakanal drinne ist, sprich ich muss einfach nur diese BMP weiterverwenden und gut ist.
Wenn ich nun aber ein altes Icon umwandle, dann is die BMP mit den Farbinformationen nur max. 24bit, sprich ich muss die BMP mit dem Farbinformationen zu 32bit umwandeln und dort selbstständig den Alphakanal reinspeichern, der sich aus der Maskierungs Bitmap ergibt.

Problem: Ich benutze bei den Bitmaps die Klasse TBitmap. Deren Eigenschaft PixelFormat ist leider vom Typ pfDevice (und nicht pf32bit wie ich erhofft hatte), das bedeutet das das PixelFormat vom jeweiligen anzeigendem Device abhängig ist. Leider sind ALLE Farbbitmaps von Icons, egal ob XP, 24bit oder 256 bzw. 16 Farben, beim PixelFormat vom Typ pfDevice. Sprich ich kann nicht unterscheiden ob ich nen XP Icon habe oder nicht, folglich kann ich nicht entscheiden ob ich die Bitmap mit den Farbinformationen noch bearbeiten muss oder nicht und wenn ich das Ding bearbeite obwohl ichs nicht soll, dann sehen XP Icons ziemlich dämlich aus.

erster Lösungversuch: Über den PixelFormatDescriptor rauskriegen von welchem Typ das Bitmap ist.

Folgender Code:
Delphi-Quellcode:
function IconToBitmap(const IconHandle: HIcon):TBitmap;
var
        IcoInfo: TIconInfo;
        mask: TBitmap;
        x, y: word;
        ColorSL, MaskSL: pRGBALine;
        pfd: PixelFormatDescriptor;
begin
        result := nil;
        if NOT GetIconInfo(IconHandle, IcoInfo) then
                exit;

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

                        mask := TBitmap.Create;
                        mask.Handle := IcoInfo.hbmMask;
                        mask.PixelFormat := pf32bit;
                        
                        DescribePixelFormat(result.Canvas.Handle, 1, sizeof(PixelFormatDescriptor), pfd); // Tiiiiiiiiiiierisch laaaaaaaaaaaaaaahm

                        if pfd.iPixelType <> PFD_TYPE_RGBA then
                        begin
                                result.PixelFormat := pf32bit;

                                for y := 0 to result.Height-1 do
                                begin
                                        ColorSL := result.Scanline[y];
                                        MaskSL := mask.ScanLine[y];
                                        for x := 0 to result.Width-1 do
                                                ColorSL^[x].rgbReserved := NOT MaskSL^[x].rgbRed;
                                end;
                        end;

                except
                        FreeAndNil(result);
                end;
        finally
                if Assigned(mask) then
                        mask.Free;
        end;
end;
Wie schon im Code am Kommentar ersichtlich, ist die Funktion DescribePixelFormat saulahm, sprich für ca. 6 Bitmaps braucht mein Rechner 2-3 Sekunden, da das Ganze eigntlich eher so ca. 20 Bitmaps aufeinma abchecken muss, kann das nicht einfach mal 7-10 Sekunden dauern.

Habt ihr noch ne Ahnung was man da machen könnte, was auch einigermaßen schnell ist ?

Danke schon mal im Vorraus

- Thebe
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#4

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

  Alt 5. Sep 2005, 21:38
Bisr du sicher, dass es nicht eher an deiner Schleife liegt:
Delphi-Quellcode:
for y := 0 to result.Height-1 do
                                begin
                                        ColorSL := result.Scanline[y];
                                        MaskSL := mask.ScanLine[y];
                                        for x := 0 to result.Width-1 do
                                                ColorSL^[x].rgbReserved := NOT MaskSL^[x].rgbRed;
                                end;
Was ist das eigentlich für eine kranke Einrückung mit Tabulatoren?
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Thebe

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

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

  Alt 5. Sep 2005, 22:25
Ich kann Dir definitiv versichern, das es nicht an dem rüberkopieren des Alphakanals liegt. Die Frage hat sich mir nämlich beim PixelFormatDescriptor auch gestellt und ich habe die komplette Bedingung (in der herumkopiert wird) auskommentiert und das Zeug war immernoch so saumäßig lahm.

Kommentiere ich hingegen DescribePixelFormat aus und ersetze die Bedingung durch eine wie "if true = true then ..." geht es ziemlich schnell und das obwohl der AlphaKanal immer rüberkopiert wird.
  Mit Zitat antworten Zitat
SMO

Registriert seit: 20. Jul 2005
178 Beiträge
 
Delphi XE6 Professional
 
#6

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

  Alt 5. Sep 2005, 22:49
Zitat von Thebe:
Und zwar ist bei diesem Bitmap das PixelFormat pfDevice, was ja auch eigentlich alles sein könnte. Wenn ich das PixelFormat auf 32bit setze, hab ich dann ja auch 32bit Information in dieser Bitmap wie Alpha Channel z.B. Nur manchmal ist so ein Bitmap eben nicht im 32bit Modus sondern z.b. nur 8 oder 16bit, nur das Pixelformat bleibt gleich beim TBitmap, nämlich pfDevice.

Wie kann ich nun rauskriegen ob die Bitmap die ich bearbeite im 32bit Modus ist oder nicht, allerdings ohne das ich mich auf TBitmap.Pixelformat stützen muss ?
Ein Bitmap mit PixelFormat pfDevice ist ein Device-Dependent Bitmap (DDB), seine Farbtiefe also abhängig vom Gerät (z.B. Bildschirm). Eine kurze Suche führt zu dieser MSDN Seite. Dort steht, dass die Farbtiefe des Geräts mit GetDeviceCaps ermittelt werden kann. Für pfDevice Bitmaps also mit GetDeviceCaps(Bitmap.Canvas.Handle, BITSPIXEL). Ich hoffe das hilft.
  Mit Zitat antworten Zitat
Thebe

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

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

  Alt 5. Sep 2005, 23:18
Wunderbare Idee, daran hab ich gar nicht gedacht die DeviceCaps vom Bild abzufragen, nur leider hab ich das Problem das eben jene Bilder die ich per GetIconInfo() erhalte, so ziemlich gleiche Werte liefern.

Ich hab 5 Icons abgefragt, 3 sind 32bit Icons, 2 sind 24bit Icons.

GetDeviceCaps(Handle, BITSPIXEL) liefert jedesmal 32 (auch bei den 24bit Icons).
GetDeviceCaps(Handle, COLORRES) liefert jedesmal 24. (Kann ich leider auch nit zur Unterscheidung nutzen)

Sprich, zurück ans Zeichenbrett *gnarf*

Aber war schonma ne gute Idee, Danke Dir!
  Mit Zitat antworten Zitat
Benutzerbild von dizzy
dizzy

Registriert seit: 26. Nov 2003
Ort: Lünen
1.932 Beiträge
 
Delphi 7 Enterprise
 
#8

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

  Alt 6. Sep 2005, 03:13
Hm, Schnellschuss :

Es gibt:
a) Bitmap 24Bit mit 1Bit Maske
b) Bitmap 32Bit mit 1Bit Maske, aber auch mit Alpha im höchsten Byte der Farbwerte

Nun wäre interessant ob die 24-Bitter wegen des Alignments nicht auch mit 32Bit pro Pixel gespeichert werden. Wäre dem nicht so, wärst du mit einem Vergleich "Bildgrößeateigröße" dabei -> der 24-Bitter wäre in Bytes ausgedrückt kleiner.

Sollte es aber doch so sein dass die 24er 32bpp belegen, so wäre interessant was dort im höchsten Byte steht. Mal angenommen wir haben Glück und sie sind immer $00:
Dann kannst du zunächst mal alle als 32er ansehen. Wenn sich auch nur eines dieser Bytes findet dass nicht 0 ist, wäre anzunehmen du hast ein echtes 32bpp Bitmap, und die 1Bit-Maske hat keine Bedeutung. Sind jedoch alle 0, wäre beides möglich, aber es macht keinen Unterschied mehr - du kannst die 1Bit-Maske blind anwenden. Damit wird ein 24er korrekt maskiert, und beim 32er ist die Maske eh komplett leer, so dass sie nichts am Bild ändert.
(Das setzt jedoch voraus, dass die 1Bit-Makse bei den 32ern am Alpha-Byte orientiert ist, und nicht separat davon "schrott" enthalten kann. Das weiss ich nicht.)

Ich hoffe dieser nächtliche Gedankenanflug ist nicht allzu abwegig


Gruss,
Fabian
Fabian K.
INSERT INTO HandVonFreundin SELECT * FROM Himmel
  Mit Zitat antworten Zitat
Benutzerbild von Flocke
Flocke

Registriert seit: 9. Jun 2005
Ort: Unna
1.172 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#9

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

  Alt 6. Sep 2005, 07:08
1. Ansatz: benutze GetIconInfo - das liefert dir die beiden Bitmaps (Maske und Bild) als separate Bitmaps. Die sind (so meine ich) DIB-Sections, also geräteunabhängig. Wenn die Masken-Bitmap 0 ist (also leer), dann benutzt die Bild-Bitmap Alphablending (und sonst die Maske).

2. Ansatz: Wenn du die Icons als Dateien vorliegen hast, kannst du auch alle Informationen direkt daraus lesen. Ich habe mal zwei Units von mir angehängt mit denen das ansatzweise geht (unfertig, Work in Progress). Bitmaps extrahieren geht aber schon.
Angehängte Dateien
Dateityp: zip iconcursor_974.zip (7,5 KB, 18x aufgerufen)
Volker
Besucht meine Garage
Aktuell: RtfLabel 1.3d, PrintToFile 1.4
  Mit Zitat antworten Zitat
Thebe

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

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

  Alt 6. Sep 2005, 09: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
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 23:42 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