首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 產生 24 位真彩色圖標(ICO):解析 ICO 檔案結構與 BMP 轉換完整流程

     編輯:Delphi

ICO 檔案格式解析

ICO 實為多圖像容器,結構:

  1. ICONDIR (6 bytes):idReserved=0, idType=1 (圖標), idCount (圖像數)。
  2. ICONDIRENTRY x N (16 bytes each):bWidth, bHeight (0=256), bColorCount (0=256+), bReserved=0, wPlanes, wBitCount (色深), dwBytesInRes, dwImageOffset。
  3. 圖像資料:每張為 BMP 格式(含 BITMAPINFOHEADER),但 biHeight = 2×實際高度(含 XOR 與 AND 遮罩),biBitCount=24 真彩色無調色盤。

Delphi 轉換核心流程

  1. 任意圖片 → 24-bit BMP:
    procedure Pic2BMP(Picture: TPicture);
    var Bmp: TBitmap;
    begin
      if not (Picture.Graphic is TBitmap) then
      begin
        Bmp := TBitmap.Create;
        try Bmp.Width := Picture.Width; Bmp.Height := Picture.Height;
          Bmp.Canvas.Draw(0, 0, Picture.Graphic);
          Picture.Graphic := Bmp;
        finally Bmp.Free; end;
      end;
    end;
  2. 縮放至目標尺寸 (≤255):
    procedure PicToMiniature(Src, Dst: TBitmap; W, H: Integer);
    var Tmp: TBitmap;
    begin
      Tmp := TBitmap.Create;
      try Tmp.Assign(Src); Tmp.Width := Min(W,255); Tmp.Height := Min(H,255);
        Tmp.PixelFormat := pf24bit;
        Tmp.Canvas.StretchDraw(Rect(0,0,Tmp.Width,Tmp.Height), Src);
        Dst.Assign(Tmp);
      finally Tmp.Free; end;
    end;
  3. 建立 ICONDIR + ICONDIRENTRY:
    function MakeICOHead(const Mem: TStream): Boolean;
    var BMPH: TBitmapFileHeader; BMPInfo: TBitmapInfoHeader; Sz: DWORD;
    begin
      Result := False;
      Mem.Position := 0;
      Mem.Read(BMPH, SizeOf(BMPH)); Mem.Read(BMPInfo, SizeOf(BMPInfo));
      if (BMPInfo.biCompression = BI_RGB) and (BMPInfo.biWidth <= 255) and (BMPInfo.biHeight <= 255) then
      begin
        with IconDir.idEntries do
        begin
          bWidth := Byte(BMPInfo.biWidth); bHeight := Byte(BMPInfo.biHeight);
          wBitCount := 24; wPlanes := 1;
          Sz := (Mem.Size - SizeOf(BMPH)) * 2 + SizeOf(BMPInfo); // *2 含 AND 遮罩
          dwBytesInRes := Sz; dwImageOffset := SizeOf(ICONDIR);
        end;
        Result := True;
      end;
    end;
  4. 組裝圖像資料(XOR + AND 遮罩):
    function MakeICOData(const Mem: TStream): Boolean;
    var M1, M2: TMemoryStream; BMPInfo: TBitmapInfoHeader;
    begin
      Result := False;
      M1 := TMemoryStream.Create; M2 := TMemoryStream.Create;
      try
        M1.SetSize(Mem.Size - SizeOf(TBitmapFileHeader));
        Mem.Position := SizeOf(TBitmapFileHeader);
        M1.CopyFrom(Mem, M1.Size); // 複製 BMPInfo + 像素資料
    
        M1.Position := 0; M1.Read(BMPInfo, SizeOf(BMPInfo));
        BMPInfo.biHeight := BMPInfo.biHeight * 2; // 雙倍高度含遮罩
        BMPInfo.biSizeImage := M1.Size * 2;
        M1.Position := 0; M1.Write(BMPInfo, SizeOf(BMPInfo));
    
        M2.SetSize(M1.Size - SizeOf(BMPInfo)); // 遮罩區填 0 (白色透明)
        FillChar(M2.Memory^, M2.Size, 0);
    
        Mem.Size := 0;
        Mem.Write(IconDir, SizeOf(ICONDIR));
        Mem.Write(M1.Memory^, M1.Size);
        Mem.Write(M2.Memory^, M2.Size);
        Result := True;
      finally M1.Free; M2.Free; end;
    end;
  5. 儲存 .ico 檔:Mem.SaveToFile('output.ico')。

多解析度 ICO

重複上述流程產生 16×16、32×32、48×48、256×256 等多組 ICONDIRENTRY 與圖像資料,依序寫入同一檔案,Windows 會自動選取最適合解析度顯示。

驗證與應用

  • Delphi/VB/VC++ 專案圖示直接載入 .ico。
  • 檔案關聯、快捷方式、工作列圖示皆正常顯示真彩色含 Alpha 通道(若需 Alpha 需使用 32-bit BMP + PNG 壓縮,Vista+ 支援)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved