Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Icon pixelfrei (https://www.delphipraxis.net/107796-icon-pixelfrei.html)

Nils_13 2. Feb 2008 10:53


Icon pixelfrei
 
Hi,

ich lese mit einer Funktion Icons von Programmen aus und zeichne sie mit Canvas. Nun habe ich aber ziemlich viele Pixel. Kann man das irgendwie wegbekommen ?

Ich habe bis jetzt zu dem Thema nur einen brauchbaren (so schien es am Anfang...) Thread gefunden, der aber keine Lösung enthielt. AntiAliasing wird wohl nötig sein. Habe zu dem Thema aber wirklich fast nichts gefunden.

Lossy eX 2. Feb 2008 11:21

Re: Icon pixelfrei
 
Nun ja. Wenn du Icon/Bilder ausliest es wohl zu erwarten, dass du Pixel bekommst, oder? Den konnte ich mir nicht verkneifen. :P

Ich kann mir darunter allerdings gerade nicht viel vorstellen. Evtl solltest du mal ein Bild posten wo man das Problem sehen kann.

phXql 2. Feb 2008 11:23

Re: Icon pixelfrei
 
Was er will ist Kantenglättung... Bei Antialiasing wird das Bild erst z.b. 2x so groß gerechnet und dann auf Zielgröße verkleinert. Damit verschwinden die Pixelkanten.

Lossy eX 2. Feb 2008 11:35

Re: Icon pixelfrei
 
Dessen bin ich mir durchaus bewusst. Aber mir stellt sich die Frage was das mit Icons zu tun hat? Außer höchsten 32x32 Icons auf 16x16 zu rechnen. Was aber kein AntiAliasing ist. Das ist aber genau das was ich in Erfahrng bringen wollte.

CalganX 2. Feb 2008 11:38

Re: Icon pixelfrei
 
AntiAliasingAntiAliasing liefert mir u.A. das hier

Christopher

Nils_13 2. Feb 2008 12:01

Re: Icon pixelfrei
 
Liste der Anhänge anzeigen (Anzahl: 2)
AntiAliasing hat hier aber nicht viel gebracht. Schaut euch vorallem die beiden obersten Icons an, der weiße Mist in der Mitte muss auf jeden Fall weg. Habe zwei verschiedene Algos getestet:

Gausi 2. Feb 2008 12:24

Re: Icon pixelfrei
 
Das sieht für mich eher danach aus, als gäbe es da ein Problem mit der Transparenz bzw. dem Alpha-Kanal in den Icons.

Nils_13 2. Feb 2008 12:28

Re: Icon pixelfrei
 
Delphi-Quellcode:
function GetIcon(filename : String; IconIndex: Integer) : TBitmap;
var NumberOfIcons : Integer;
    Ico          : TIcon;
begin
  NumberOfIcons := ExtractIcon(hInstance, PChar(Filename), UINT(-1));

  Ico := TIcon.Create;
  if (Ico <> nil) and (NumberOfIcons > -1) then
    Ico.Handle := ExtractIcon(hInstance, PChar(Filename), IconIndex);
  Result := TBitmap.Create;
  with Result do
  begin
    Width := Ico.Width;
    Height := Ico.Height;
    Canvas.Draw(0, 0, Ico);
  end;
  Ico.Free;
end;
So hole ich mir das Icon. Das Bild auf das ich es zuweise hat Transparent auf True.

Lossy eX 2. Feb 2008 12:40

Re: Icon pixelfrei
 
Bitte nicht AntiAliasing mit stumpfen Weichzeichnem verwechseln. Nur weil die Methode Antialiasing heiß bedeutet das nicht, dass die auch gleiches tut. Das ist ein Trugschluss. Und in den Fall könnte es von richtigem AntiAlising nicht weiter entfernt sein. Okay die Kanten sind weich aber der Recht ist auch matschig.

Nils_13: Das Zauberwort heißt Alphakanal. Seit Windows XP können Icons 24 Bit Farbtiefe enthalten und einen 8Bit Alphakanal. In deinem Fall wird aus dem 8 Bit Alphakanal eine 1 Bit Maske. Das ist aber nicht so gut, denn dadurch entstehen eben solche Kanten. Wie beim FF.

Schau dir mal die Funktion GetIconInfo an. Du musst du das Handle des Icons übergeben und bekommst eine Struktur in der 2 Bitmaps enthalten sind. Ein mal das Normale RGB Bild und ein Mal die Maske. Die Maske sollte richtige 8Bit Transparenz enthalten. Diese muss du beim Zeichnen des Icons berücksichtigen.

Und dabei darfst du eigenschaft Tranzparent des TBitmaps nicht benutzen. Du musst das Bild richtig blenden. Dann werden sie auch so aussehen wie sie sollen.

Nils_13 2. Feb 2008 13:13

Re: Icon pixelfrei
 
Habe eine Funktion gefunden. Das Ergebnis sieht zwar besser aus, aber nicht gut genug. Es werden die weiten Pixel geschwärzt. Könnte man anstelle von Schwarz nicht einfach die Hintergrundfarbe nehmen und es wäre alles flüssig ?
Delphi-Quellcode:
function IconToBitmap(const IconHandle : HIcon) : TBitmap;
var IcoInfo : TIconInfo;
    Mask   : TBitmap;
    X, Y   : Word;
begin
  Mask  := nil;
  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;

      for X := 0 to Result.Width-1 do
        for Y := 0 to Result.Height-1 do
          pRGBALine(Result.Scanline[Y])^[X].rgbReserved := not pRGBALine(Mask.Scanline[Y])^[X].rgbRed;
    except
      FreeAndNil(Result);
    end;
  finally
    if Assigned(Mask) then
      Mask.Free;
  end;
end;

function GetIcon(filename : String; IconIndex: Integer) : TBitmap;
var NumberOfIcons : Integer;
    Ico          : TIcon;
begin
  NumberOfIcons := ExtractIcon(hInstance, PChar(Filename), UINT(-1));

  Ico := TIcon.Create;
  if (Ico <> nil) and (NumberOfIcons > -1) then
    Ico.Handle := ExtractIcon(hInstance, PChar(Filename), IconIndex);
  Result := IconToBitmap(Ico.Handle);
  Result.Canvas.Draw(0, 0, Ico);
  Ico.Free;
end;

turboPASCAL 2. Feb 2008 14:48

Re: Icon pixelfrei
 
1. Das Windows-Bitmap Format was u.A. Delphi verwendet ist Äusserst bescheiden wenn es um die
Verwendung von Transparenzen geht.

2. Warum bleibst du nicht einfach bei Icons, zum Zeichnen dieser aber nur DrawIconEx() der Windows-API nutzen sonst wirds es wieder nix richtiges.

3. Willst du doch Bitmaps dan nutze die GR32 - Bitmaps die den Alphakanak unterstützen

4. Was du willst gnau machen mit die Icons ?

Lossy eX 2. Feb 2008 16:26

Re: Icon pixelfrei
 
Kommt drauf an was man vor hat. Wenn man das Icon selber zeichnen kann, dann ist sicherlich DrawIconEx die beste Wahl. Allerdings wenn das ein Icon in einer Komponente sein soll, dann kommt man um Bitmaps teilweise nicht herum, da diese leider nur mit Bitmaps arbeiten. So war es zu mindest bei mir immer.

Ich hatte gerade noch mal in Quellen von mir geschaut. Dort mache ich komischer weise nichts anderes als das Icon auf ein weißes Bitmap zu zeichnen. Und dabei wurde die Transparenz automatisch mit reingerechnet. Das was du im ersten Code gemacht hattest. Nur eben direkt weißer Hintergrund und Pixelformat war pf24Bit. Allerdings dort hatte es funktioniert. Was ich etwas komisch finde.

Bei dem zweiten Code müsstest du den Alphakanal direkt mit verrechnen. Denn Windows Bitmap können eigentlich kein Alphakanal. Verrechnen kannst du das in dem du für jedes Pixel die resultierende Farbe berechnest. Der Wert aus der Maske spiegelt dann die Sichtbarkeit wieder. Entweder die Hintergrundfarbe oder die des Pixels aus dem Icon. Natürlich musst du jeden Kanal seperat berechnen.

Nils_13 2. Feb 2008 17:19

Re: Icon pixelfrei
 
Hm, DrawIconEx dürfte wohl richtig sein.
Mit folgendem Code wird allerdings kein Icon mehr gezeichnet, seht ihr den Grund ?
Delphi-Quellcode:
function GetIcon(filename : String; IconIndex: Integer) : TBitmap;
begin
  Result := TBitmap.Create;
  DrawIconEx(Result.Handle, 0, 0, ExtractIcon(hInstance, PChar(Filename), IconIndex), 0, 0, 0, 0, DI_NORMAL);
end;

turboPASCAL 2. Feb 2008 18:18

Re: Icon pixelfrei
 
:wiejetzt:

Ja.

Zitat:

BOOL DrawIconEx(

HDC hdc, // handle to device context <---<<<
int xLeft, // x-coordinate of upper left corner
int yTop, // y-coordinate of upper left corner
HICON hIcon, // handle to icon to draw
int cxWidth, // width of the icon
int cyWidth, // height of the icon
UINT istepIfAniCur, // index of frame in animated cursor
HBRUSH hbrFlickerFreeDraw, // handle to background brush
UINT diFlags // icon-drawing flags
);
Code:
    DrawIconEx([color=#ff0000]Result.Canvas.Handle[/color], 0, 0, ..., 0, 0, 0, DI_NORMAL);
Sicher ist dein Code aber nicht und ob das so hinnhaut ?!

Nils_13 2. Feb 2008 18:21

Re: Icon pixelfrei
 
Habe dabei wohl gepennt. Ändert aber nichts an der Ausgabe. Meinst du mit unsicher, dass ich nicht prüfe, ob die Funktion fehlschlägt ?

Lossy eX 2. Feb 2008 19:06

Re: Icon pixelfrei
 
Hmmm. So kann das nicht gehen. Denn dein Bitmap hat gar keine Größe. Außerdem so wird das Icon gar nicht wieder freigegeben, da du das Handle ein Mal an eine Funktion übergibst und sofort vergisst.

Du solltest also wohl das Handle des Icons einem TIcon zuweisen. Mit der Größe dieses das Bitmap initialisieren. Und dann mit DrawIconEx das Icon auf das Bitmap zeichnen.

PS: Bitmap als Rückgabewert halte ich persönlich auch für nicht unproblematisch. Da eine andere Stelle das Bitmap freigeben muss als die bei der es erzeugt wurde. Also ich würde es erzeigen und per const an die Methode übergeben.

Nils_13 2. Feb 2008 20:22

Re: Icon pixelfrei
 
Ich habe es gerade zusammengebaut, es wird nun wieder gezeichnet aber genauso pixelig wie vorher:
Delphi-Quellcode:
procedure GetIcon(filename : String; IconIndex: Integer; var Result : TBitmap);
var Ico : TIcon;
begin
  Ico := TIcon.Create;
  Ico.Handle := ExtractIcon(hInstance, PChar(Filename), IconIndex);
  Result := TBitmap.Create;
  with Result do
  begin
    Width := Ico.Width;
    Height := Ico.Height;
    DrawIconEx(Canvas.Handle, 0, 0, Ico.Handle, 0, 0, 0, 0, DI_NORMAL);
  end;
  Ico.Free;
end;

Lossy eX 2. Feb 2008 23:47

Re: Icon pixelfrei
 
Benutzt du rein zufällig etwas anderes als Windows XP? Also zum Beispiel Windows 2000. Denn Windows 2000 kann noch keine Transparenzen.

Evtl schau dir auch mal an was du für Bitmaps bekommst. Also die mit GetIconInfo. Einfach mal auf Platte schreiben oder in Images darstellen. Vielleicht sind die Bilder ja schon falsch.

Denn sonst sieht der Code für mich zu mindest nicht falsch aus.

MuTzE 3. Feb 2008 09:54

Re: Icon pixelfrei
 
Wenn ich das richtig verstanden habe, gibts Probleme mit dem Alpha Channel.
Probier mal das hier: Advanced Icon

Klappt super.


MfG

MuTzE

Nils_13 3. Feb 2008 12:45

Re: Icon pixelfrei
 
Hi,

das Ergebnis sieht gut aus, aber ich verstehe nicht, was ich mit dem Ergebnis Icon.Images.Image anfangen soll. Das ist nämlich TIconImage und lässt sich nicht via Canvas zeichnen.

Habe mich nochmal genauer damit beschäftigt:
Delphi-Quellcode:
procedure GetIcon(filename : String; IconIndex: Integer; var Result : TBitmap);
var NumberOfIcons : Integer;
    Ico          : TIcon;
    Icon   : TAdvancedIcon;
    IconLib : TIconLibrary;
    Image  : TIconImage;
begin
  NumberOfIcons := ExtractIcon(hInstance, PChar(Filename), UINT(-1));

  Ico := TIcon.Create;
  if (Ico <> nil) and (NumberOfIcons > -1) then
    Ico.Handle := ExtractIcon(hInstance, PChar(Filename), IconIndex);

  Icon   := TAdvancedIcon(Ico);
  IconLib := TIconLibrary.Create;
  Image  := Icon.Images.Image[1];

  Result := TBitmap.Create;
  Image.Draw(Result.Canvas, 0, 0);
  Ico.Free;

  Icon.Free;
  IconLib.Free;
end;
Nun gibt es eine AV in der markierten Zeile der AdvancedIcon.pas:
Delphi-Quellcode:
function TIconImageList.GetIconImage(Index : Word) : TIconImage;
begin
  Result:=nil;
  IF Index>FCapacity Then exit; <--
  Result:=FList^[Index];
end;
Ich gehe davon aus, dass oben TAdvancedIcon(Ico) falsch ist, was müsste anstelle davon hin ? So habe ich es zumindest im Beispielcode gesehen.

Medium 4. Feb 2008 08:49

Re: Icon pixelfrei
 
Zitat:

Zitat von turboPASCAL
Alphakanak

Sorry fürs totale OT, aber ich kann nicht mehr :lol:
Ist das sowas wie der türkische Vorarbeiter aufm Bau?

(Hab nix gegen Imigranten, fands nur spaßig - um evtl. Missverständnissen gleich vorzubeugen!)

Nils_13 4. Feb 2008 09:13

Re: Icon pixelfrei
 
:lol: :lol:

Ist mir gar nicht aufgefallen.

Zum Thema:
Hat noch jemand irgendwelche Ideen ?

Sunlight7 5. Feb 2008 05:35

Re: Icon pixelfrei
 
Liste der Anhänge anzeigen (Anzahl: 1)
Moin!

Also ich hab mir echt Mühe gegeben, aber mir ist der Effekt mit den weißen Randpixeln gar nicht gelungen :mrgreen:

Beim Zeichnen von Icons mach ich generell einen Bogen um VCL, aber ich habs mal mit versucht^^
Das Ergebnis meiner Spielerei, hoffe es is was brauchbares bei.

MFG Sun

Delphi-Quellcode:
function IconToBitmap(const Icon:HIcon; const Color:TColor; BMP:TBitmap):Boolean;
   var II:TIconInfo;
begin
   Result:=False;
   If BMP=nil then Exit;
   If not GetIconInfo(Icon, II) then Exit;

   try
      BMP.Handle:=II.hbmColor;
      BMP.Canvas.Brush.Color:=Color;
      BMP.PixelFormat:=pf24bit;

      Result:=DrawIconEx(BMP.Canvas.Handle, 0, 0, Icon, BMP.Width, BMP.Height, 0, BMP.Canvas.Brush.Handle, DI_NORMAL);
   except
   end;
end;

procedure TForm1.FormPaint(Sender: TObject);
   var MyIconH:HIcon;
       MyIcon:TIcon;
       MyBMP:TBitmap;
begin
   MyIconH:=ExtractIcon(0, 'F:\Programme\Mozilla Firefox\Firefox.exe', 0);
   If MyIconH<=1 then Exit;

   DrawIconEx(Canvas.Handle, 10, 10, MyIconH, 32, 32, 0, Brush.Handle, DI_NORMAL);

   MyIcon:=TIcon.Create;
   MyIcon.Handle:=MyIconH;
   Canvas.Draw(42, 10, MyIcon);

   MyBMP:=TBitmap.Create;
   IconToBitmap(MyIconH, Self.Color, MyBMP);
   Canvas.Draw(74, 10, MyBMP);

   MyIcon.Free;
   MyBMP.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   Randomize;
   Color:=Random(16777216);
end;

Nils_13 5. Feb 2008 12:26

Re: Icon pixelfrei
 
In OnPaint funktioniert es, aber kann man das nicht auch in eine Funktion verpacken ?
Habe es probiert, ich sehe kein Icon:
Delphi-Quellcode:
GetIcon(Pfade[Akt], 0, Bmp);
Img.Picture.Bitmap := Bmp;
Bmp.Free;

procedure GetIcon(filename : String; IconIndex: Integer; var Result : TBitmap);
var MyIconH : HIcon;
    MyIcon : TIcon;
    MyBMP  : TBitmap;
begin
   MyIconH := ExtractIcon(0, PChar(Filename), 0);
   if MyIconH <= 1 then
     Exit;

   Result := TBitmap.Create;

   DrawIconEx(Result.Handle, 10, 10, MyIconH, 32, 32, 0, Result.Canvas.Brush.Handle, DI_NORMAL);

   MyIcon       := TIcon.Create;
   MyIcon.Handle := MyIconH;
   Result.Canvas.Draw(42, 10, MyIcon);

   MyBMP := TBitmap.Create;
   IconToBitmap(MyIconH, clGreen, MyBMP);
   Result.Canvas.Draw(74, 10, MyBMP);

   MyIcon.Free;
   MyBMP.Free;
end;

Sunlight7 5. Feb 2008 13:44

Re: Icon pixelfrei
 
Das Du das Icon nicht siehst liegt daran, das in GetIcon mit MyIcon.Free; (auch MyIconH) freigegeben wird.

Es scheint so, als hättest Du meinen QT nicht richtig interpretiert, denn das sind 3 Möglichkeiten, von der jede einzelne funktionieren würde.

Wenn Du nur vor hast die Icons irgendwo drauf zu malen, dann würd' ich mir einfach das IconHandle wo sichern um es mit DrawIconEx zu zeichnen.
Somit kann man auch ganz lässig die Hintergrundfarbe ändern :mrgreen:

Delphi-Quellcode:
...
  private
    { Private-Deklarationen }
    Icons:Array[0..255] of HIcon;
  public
    { Public-Deklarationen }
    procedure FreeIcons;
    procedure LoadIcons;
...

procedure TForm1.FormCreate(Sender: TObject);
begin
   Randomize;
   Color:=Random(16777216);

   LoadIcons;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
   FreeIcons;
end;

procedure TForm1.FormPaint(Sender: TObject);
   var i:Byte;
begin
   // Icons zeichnen
   For i:=0 to High(Icons) do
      if Icons[i]>1 then
         DrawIconEx(Canvas.Handle, 10+(i * 32), 10, Icons[i], 32, 32, 0, Brush.Handle, DI_NORMAL);
end;

procedure TForm1.FormClick(Sender: TObject);
begin
   Color:=Random(16777216);
end;



procedure TForm1.FreeIcons;
   var i:Byte;
begin
   // Icons freigeben
   For i:=0 to High(Icons) do
      if Icons[i]>1 then
         DeleteObject(Icons[i]);

   ZeroMemory(@Icons, SizeOf(Icons));
end;

procedure TForm1.LoadIcons;
   var i:Byte;
begin
   FreeIcons;

   // Icons laden
   For i:=0 to High(Icons) do begin
      Icons[i]:=ExtractIcon(0, '%WinDir%\Explorer.exe', i);
      If Icons[i]<=1 then Break;
   end;
end;

Nils_13 5. Feb 2008 15:49

Re: Icon pixelfrei
 
Ah danke. Hatte dich vorhin missverstanden. Danke! :)

Hab eine Schnapszahl (2222 Beiträge) :mrgreen:

turboPASCAL 5. Feb 2008 15:51

Re: Icon pixelfrei
 
( ot: tja, da muss er nu einen usgebe. :mrgreen: )

larsf 23. Sep 2008 12:32

Re: Icon pixelfrei
 
Hallo,

ich habe es jetzt endlich auch geschafft ein Icon in ein Image32 zu malen :D
dafür benutze ich diesen code:

Code:
DrawIconEx(image321.Canvas.Handle, 10+(1 * 32), 10, Icons[0], 32, 32, 0, Brush.Handle, DI_NORMAL);
Jetzt habe ich aber das Problem das ich damit nichts machen kann.
Wenn ich das Bild speichern möchte kommt ein 0 kB Bild heraus, wenn ich die Form verschiebe ist das Bild auch weg.

kann mir jemand helfen??

Blup 24. Sep 2008 14:45

Re: Icon pixelfrei
 
Zitat:

Zitat von larsf
Hallo,

ich habe es jetzt endlich auch geschafft ein Icon in ein Image32 zu malen :D

Nein, das ist dir nicht gelungen.
Du hast tatsächlich nur auf den Bereich des Bildschirms gemalt, der für die Darstellung dieses Steuerelements vorgesehen ist.
Sobald das Steuerelement von Windows die Nachricht bekommt sich neu zu zeichnen, wird es deine Darstellung übermalen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05: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