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

Delphi 實作 24 位真彩色圖標 (ICO) 產生器

     編輯:Delphi

前言

Delphi 內建的 Image Editor 直到 Delphi 7 仍不支援真彩色圖標編輯,這是一大遺憾。本文深入分析 ICO 檔案格式與 BMP 位圖結構,實現從 JPEG、BMP 等 24 位真彩色圖片產生圖標檔的完整方案。

ICO 檔案格式深度解析

一個 ICO 檔可包含多個不同尺寸/色深的圖標影像。檔案結構包含:

  • 檔案標頭 (tagIconDir):6 位元組,含保留欄位、資源類型(1=圖標)、圖標數量
  • 目錄項目陣列 (tagIconDirEntry):每個圖標 16 位元組,記錄寬、高、色數、色深、資料大小、資料偏移位置
  • 影像資料區 (tagIconImage):實際位圖資料,含 TBitmapInfoHeader、調色盤、XOR 遮罩、AND 遮罩

關鍵點:圖標顯示時使用雙重遮罩機制(XOR 切出區域、AND 繪製圖形),因此 biHeight 等於兩張位圖高度之和。

BMP 位圖檔案格式回顧

標準 BMP 包含四段:

  1. 檔案標頭 (tagBITMAPFILEHEADER):14 位元組,標識 "BM"、檔案大小、資料偏移
  2. 資訊標頭 (tagBITMAPINFOHEADER):40 位元組,寬高、色深、壓縮類型、解析度等
  3. 調色盤 (RGBQUAD 陣列):1/4/8 位色深時分別有 2/16/256 色;24 位真彩色無調色盤
  4. 像素資料

核心轉換流程

// 1. 非 BMP 格式先轉為 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. 調整尺寸至規格 (不超過 255x255)
procedure PicToMiniature(SourceBMP, DestBMP: TBitmap; H, W: Integer);
var Bmp: TBitmap;
begin
  Bmp := TBitmap.Create;
  try
    Bmp.Assign(SourceBMP);
    if W > 255 then W := 255;
    if H > 255 then H := 255;
    Bmp.Width := W; Bmp.Height := H;
    Bmp.PixelFormat := pf24bit;
    Bmp.Canvas.StretchDraw(Rect(0,0,W,H), SourceBMP);
    DestBMP.Assign(Bmp);
  finally Bmp.Free; end;
end;

// 3. 建立 ICO 檔案標頭
function MakICOHead(const Mem: TStream): Boolean;
var BMPHead1: tagBITMAPFILEHEADER;
    BMPHead2: TBitmapInfoHeader;
    BitsTotal: DWORD;
begin
  Result := False;
  Mem.Position := 0;
  Mem.Read(BMPHead1, SizeOf(tagBITMAPFILEHEADER));
  Mem.Read(BMPHead2, SizeOf(TBitmapInfoHeader));
  if (BMPHead2.biCompression = 0) and (BMPHead2.biWidth <= 255) and (BMPHead2.biHeight <= 255) then begin
    IconHead.idEntries.bWidth := Byte(BMPHead2.biWidth);
    IconHead.idEntries.bHeight := Byte(BMPHead2.biHeight);
    BitsTotal := (Mem.Size - 54) * 2 + 40; // *2 含 XOR 遮罩
    IconHead.idEntries.dwBytesInRes := BitsTotal;
    IconHead.idEntries.dwImageOffset := $16;
    Result := True;
  end;
  Mem.Position := 0;
end;

// 4. 產生 ICO 完整資料 (含遮罩)
function MakICOData(Mem: TStream): Boolean;
var Mem1, Mem2: TMemoryStream;
    Size: Longint;
    BMIH2: TBitmapInfoHeader;
begin
  Mem1 := TMemoryStream.Create;
  Mem2 := TMemoryStream.Create;
  try
    Size := Mem.Size - 14; Mem.Position := 14;
    Mem1.SetSize(Size);
    Mem.Read(Mem1.Memory^, Size); // 複製 BMP 資料 (含資訊頭)
    Mem1.Read(BMIH2, SizeOf(TBitmapInfoHeader));
    
    Mem2.SetSize(Size - 40); // 跳過資訊頭
    FillChar(Mem2.Memory^, Size - 40, 0); // 遮罩填 0 = 白色背景
    BMIH2.biHeight := IconHead.idEntries.bHeight * 2; // 雙倍高度
    BMIH2.biSizeImage := Mem2.Size * 2;
    Mem1.Seek(0, soFromBeginning);
    Mem1.Write(BMIH2, SizeOf(TBitmapInfoHeader)); // 更新資訊頭
    
    Mem.Size := 0;
    Mem.Write(IconHead, SizeOf(tagIconDir)); // 寫 ICO 標頭
    Mem.Write(Mem1.Memory^, Mem1.Size);       // 寫 XOR 影像
    Mem.Write(Mem2.Memory^, Mem2.Size);       // 寫 AND 遮罩
    Result := True;
  finally
    Mem1.Free; Mem2.Free;
  end;
end;

擴充性與測試環境

Delphi 支援豐富圖片格式(加入 uses jpeg 即支援 JPEG),若安裝第三方圖形元件亦可擴展。產出的 ICO 可供 VB、Delphi 等直接使用。測試環境:Delphi 7 + Windows XP SP2。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved