Zła jakość ICO

0

Witam!
Mam problem..

Pobieram ikonę z pliku:

var
  Ico:TIcon;
  FileInfoz: SHFILEINFO;
  HIco:HIcon;
begin

  Ico:=TIcon.Create;
FillChar(FileInfoz, SizeOf(FileInfoz), #0);
SHGetFileInfo(PAnsichar(p2), 0, Fileinfoz, SizeOf(Fileinfoz), SHGFI_ICON or SHGFI_LARGEICON or SHGFI_SHELLICONSIZE or
             SHGFI_SYSICONINDEX or SHGFI_TYPENAME or SHGFI_DISPLAYNAME);
 Ico.Handle :=  Copyicon(Fileinfoz.hIcon);
               Form1.Image1.Picture.Icon := Ico;
 Form1.Image1.Picture.Icon.SaveToFile('c:\icon.ico');

I na Image1 jest ona wyświetlana prawidłowo - w dobrych kolorach etc. A gdy program zapiszę ją na dysku wygląda ona tak:
user image

Jest ktoś w stanie mi pomóc?</email>

0

<ort>Niebardzo </ort>wiem, jak Tobie pomóc. Sprawdziłem Twój kod dla mojego execa który posiada jako ikonkę faviconkę ze
strony chomikuj.pl. W oryginale ikonka ma zielone tło i zajmuje ponad 3 KB, po wydobyciu tym kodem co podałeś,
ma ona brzydkie kolory i zółte tło oraz zajmuje tyle co standardowa ikonka z mała ilością kolorów czyli 766 bajtów.
Jedyne co mogę doradzić to skorzystanie z poniższego kodu, ktory tworzy prawidłową ikonkę taką jak źródłowa z
pliku exe. W oryginale ta procedura była umieszczona chyba na swissdelphicenter, a wykorzystałem ją też w swoim
programie ktory konwertuje bitmapy na ikonki. Innego sposobu nie znam. Może ten będzie Tobie też odpowiadał :)

procedure HiBmpAsIcon(const Bmp : TBitmap; const Icon : string; const SmallIcon : Boolean;
  const Transparent : Boolean; const X, Y : Integer);

type
  TIconDirEntry = packed record
    bWidth : Byte;
    bHeight : Byte;
    bColorCount : Byte;
    bReserved : Byte;
    wPlanes : Word;
    wBitCount : Word;
    dwBytesInRes : DWord;
    dwImageOffset : DWord;
  end;

  TIcondir = packed record
    idReserved : Word;
    idType : Word;
    idCount : Word;
    IdEntries : array[1..20] of TIconDirEntry;
  end;

var
  PBI, MPBI : PBitmapInfo;
  IHS, MIHS, ImageSize, MImageSize : DWord;
  bmBuffer, MaskBuffer : Pointer;
  TID : TIconDir;
  TBIH : TBitmapInfoHeader;
  Bmx, Bmm : TBitmap;
  TranspCol : TColor;
  I, J : Integer;
begin
  Bmx := TBitmap.Create;
  Bmm := TBitmap.Create;
  try
    if SmallIcon then begin
      Bmx.Width := GetSystemMetrics(SM_CXSMICON);
      Bmx.Height := GetSystemMetrics(SM_CYSMICON);
    end else begin
      Bmx.Width := GetSystemMetrics(SM_CXICON);
      Bmx.Height := GetSystemMetrics(SM_CYICON);
    end;
    bmx.pixelformat := pf24bit;
    Bmx.Canvas.StretchDraw(Rect(0, 0, Bmx.Width, Bmx.Height), Bmp);
    TranspCol := Bmx.Canvas.Pixels[X, Y];
    Bmm.Assign(Bmx);
    Bmm.Mask(TranspCol);
    GetDIBSizes(Bmm.Handle, MIHS, MImageSize);
    GetDIBSizes(Bmx.Handle, IHS, ImageSize);
    MaskBuffer := AllocMem(MImageSize);
    bmBuffer := AllocMem(ImageSize);
    MPBI := AllocMem(MIHS);
    PBI := AllocMem(IHS);
    try
      if Transparent then begin
        for I := 0 to Bmx.Width - 1 do
          for J := 0 to Bmx.Height - 1 do
            if Bmx.Canvas.Pixels[I, J] = TranspCol then
              Bmx.Canvas.Pixels[I, J] := 0;
        with MPBI^.bmiHeader do begin
          biSize := SizeOf(TBitmapInfoHeader);
          biWidth := Bmm.Width;
          biHeight := Bmm.Height;
          biPlanes := 1;
          biBitCount := 1;
          biCompression := BI_RGB;
          biSizeImage := MImageSize;
          biXPelsPerMeter := 0;
          biYPelsPerMeter := 0;
          biClrUsed := 2;
          biClrImportant := 2;
        end;
        GetDIBits(Bmm.Canvas.Handle, Bmm.Handle, 0, Bmm.height, MaskBuffer, MPBI^, DIB_RGB_COLORS);
      end;
      with PBI^.bmiHeader do begin
        biSize := SizeOf(TBitmapInfoHeader);
        biWidth := Bmx.Width;
        biHeight := Bmx.Height;
        biPlanes := 1;
        biBitCount := 24;
        biCompression := BI_RGB;
        biSizeImage := ImageSize;
        biXPelsPerMeter := 0;
        biYPelsPerMeter := 0;
        biClrUsed := 0;
        biClrImportant := 0;
      end;
      GetDIBits(Bmx.Canvas.Handle, Bmx.Handle, 0, Bmx.Height, bmBuffer, PBI^, DIB_RGB_COLORS);
      with TBIH do begin
        biSize := 40;
        biWidth := Bmx.Width;
        biHeight := Bmx.Height * 2;
        biPlanes := 1;
        biBitCount := 24;
        biCompression := 0;
        biSizeImage := ImageSize;
        biXPelsPerMeter := 0;
        biYPelsPerMeter := 0;
        biClrUsed := 0;
        biClrImportant := 0;
      end;
      with TID do begin
        idReserved := 0;
        idType := 1;
        idCount := 1;
        with idEntries[1] do begin
          bWidth := bmx.width;
          bHeight := bmx.height;
          bColorCount := 0;
          bReserved := 0;
          wPlanes := 1;
          wBitCount := 24;
          dwBytesInRes := SizeOf(TBitmapInfoHeader) + TBIH.biSizeImage + MImageSize;
          dwImageOffset := 6 + TID.idCount * SizeOf(TIconDirEntry);
        end;
      end;
      with TFileStream.Create(Icon, fmCreate) do try
        Write(TID, 6 + TID.idCount * SizeOf(TIconDirEntry));
        Write(TBIH, SizeOf(TBitmapInfoheader));
        Write(bmBuffer^, TBIH.biSizeImage);
        Write(maskBuffer^, MImageSize);
      finally
        Free;
      end;
    finally
      FreeMem(MaskBuffer);
      FreeMem(bmBuffer);
      FreeMem(MPBI);
      FreeMem(PBI);
    end;
  finally
    Bmx.free;
    Bmm.free;
  end;
end;

Przykład użycia:

var
  Ico : TIcon;
  Bmp : TBitmap;
  FileInfoz : SHFILEINFO;
begin
  Ico := TIcon.Create;
  Bmp := TBitmap.Create;
  FillChar(FileInfoz, SizeOf(FileInfoz), #0);
  SHGetFileInfo(PAnsichar('D:\test.exe'), 0, Fileinfoz, SizeOf(Fileinfoz),
    SHGFI_ICON or SHGFI_LARGEICON or SHGFI_SHELLICONSIZE or SHGFI_SYSICONINDEX or
    SHGFI_TYPENAME or SHGFI_DISPLAYNAME);
  Ico.Handle := Copyicon(Fileinfoz.hIcon);
  Image1.Picture.Icon := Ico;
  Bmp.Height := Ico.Height;
  Bmp.Width := Ico.Width;
  Bmp.Canvas.Draw(0, 0, Ico);
  HiBmpAsIcon(Bmp, 'D:\testowa_ikonka.ico', False, True, 0, 0);
  Bmp.Free;
  Ico.Free;
end;
0

a czy to <ort>zahowa </ort>przezroczystosc w ikonkach? i ogolnie kanal alpha jesli ikonka 32bit?

0

Nie znam się na grafice cimak, ale z moich testów wynika że po konwersji tą funkcją, ikona jest taka
jaką była wcześniej w exe i raczej zachowa przeźroczystość, nie wiem tylko czy dla wszystkich ikon.

0

W sumie już jest prawie OK, teraz wychodzi taka ikonka:

user image (otoczka)
gdy pobieram to tak:
ico.Handle:= ExtractIcon(application.handle,PAnsiChar(g), 0) ;
lub tak:

SHGetFileInfo(PAnsichar(g), 0, Fileinfoz, SizeOf(Fileinfoz), SHGFI_SYSICONINDEX );
Wie ktoś jakie parametry stwaić po 'SizeOf(Fileinfoz),' żeby wyszło bez otoczki? Trochę mi się zdaje jednak, że ten twój skrypt wstawia otoczke.

(oczywiście z użyciem twojej procedurki)

btw. Wielkie thx za odpowiedź!

0

ta otoczka to wlasnie brak obslugi kanalu alpha (przezroczystosci).
jest to wina konwersji ico>bmp>ico, wiec ja bym powrocil do tego pierwszego kodu i szukal rozwiazania.
ikonki zapisywane sa w 16 kolorach zamiast 32bit koloru (lub 16bit).

a i jeszcze jedno... to nie jest KU#$%*@ SKRYPT!

0
cimak napisał(a)

ta otoczka to wlasnie brak obslugi kanalu alpha (przezroczystosci).
jest to wina konwersji ico>bmp>ico, wiec ja bym powrocil do tego pierwszego kodu i szukal rozwiazania.
ikonki zapisywane sa w 16 kolorach zamiast 32bit koloru (lub 16bit).

a i jeszcze jedno... to nie jest KU#$%*@ SKRYPT!

sorki za ten skrypt ale koduje dużo w php i już takie przyzwyczajenie, że mówie skrypt ; )

0

Może spróbuj zapisać to do PNG (operować na PNG).

ico>png>ico

0

w tym drugim linku mówią, żeby walnąć to do TImage.

ico.Handle:= ExtractIcon(application.handle,PAnsiChar(g), 0) ;


Image1.Picture.Icon:=ico;
  Image1.Picture.Icon.SaveToFile('c:\icone.ico');

i niestety dalej icone.ico jest w 16 bitach =/ zaraz popróbuje z PNG.- jednak trudno znalezc kod ktory konwertuje ico->png

0

na Twoim miejsu bym jeszcze poszukaj jakiegos komponentu albo czegos.
bardzo mozliwe ze ktos juz napisal procedurke do zapisywania ico, z pominieciem TIcon.
a jak nie to mozna samemu napisac.

0

nawet nie mam pojęcia co wpisać w google ;/ "32bit ico delphi component"/"32bit ico delphi" wymięka

1 użytkowników online, w tym zalogowanych: 0, gości: 1