ImageList1.DrawingStyle := dsTransparent;
ImageList1.Handle := ImageList_LoadImage(MainInstance, 'MyBitmap32', 16, ImageList1.AllocBy,
CLR_NONE, IMAGE_BITMAP, LR_CREATEDIBSECTION or LR_LOADTRANSPARENT);
上述方法运行良好。因此,为了生成该位图,我从磁盘中加载带有Alpha通道的32位透明图标到ImageList中。
for i := 1 to 10 do ... ImageList2.AddIcon(AIcon)
现在,我该如何从这个图片列表中导出32位图(它将是透明的并且带有alpha通道),并将其保存为文件,使其看起来像这样:
![enter image description here](https://istack.dev59.com/X03cR.webp)
procedure PrepareBitmap(bmp: TBitmap);
var
pscanLine32: pRGBQuadArray;
i, j: Integer;
begin
for i := 0 to bmp.Height - 1 do
begin
pscanLine32 := bmp.Scanline[i];
for j := 0 to bmp.Width - 1 do
begin
pscanLine32[j].rgbReserved := 0;
end;
end;
end;
procedure TForm1.Button4Click(Sender: TObject);
var
bmp: TBitmap;
I: Integer;
IL: TImageList;
begin
IL := Imagelist10;
bmp := TBitmap.Create;
bmp.PixelFormat := pf32Bit;
bmp.Canvas.brush.Color := clNone;
bmp.Width := IL.Width * IL.Count;
bmp.Height := IL.Height;
//SetBkMode(bmp.Canvas.Handle, TRANSPARENT); //TRANSPARENT
PrepareBitmap(bmp);
for I := 0 to IL.Count - 1 do
begin
IL.Draw(bmp.Canvas, (I * 16), 0, I, True);
end;
bmp.SaveToFile('2.bmp');
end;
请注意,即使我成功使用了
GetImageBitmap
(我已经用24位图像列表实现了),输出的位图是垂直的,无法通过ImageList_LoadImage
加载:
![enter image description here](https://istack.dev59.com/nwJ28.webp)
带有alpha通道的良好位图,可以使用
ImageList_LoadImage
正常加载:
![enter image description here](https://istack.dev59.com/5XNlm.webp)
![enter image description here](https://istack.dev59.com/qaf9S.webp)
GdipCreateBitmapFromHICON
和GdipCreateBitmapFromHBITMAP
函数会破坏alpha通道-它们为每个像素写入alpha = 255)。procedure TForm1.Button3Click(Sender: TObject);
var
i, num_icons: Integer;
ico: TIcon;
icon: HICON;
encoderClsid: TGUID;
g: TGPGraphics;
in_img: TGPBitmap;
out_img: TGPImage;
begin
num_icons := 24;
out_img := TGPBitmap.Create(16 * num_icons , 16, PixelFormat32bppARGB);
for i := 1 to num_icons do
begin
// does not produce correct bitmap:
//ico := TIcon.Create;
//ImageList1.GetIcon(i - 1, ico);
//in_img := TGPBitmap.Create(ico.Handle);
in_img := TGPBitmap.Create('D:\Delphi\Projects\Icons\Icon_' + inttostr(i) + '.ico');
g := TGPGraphics.Create(out_img);
g.DrawImage(in_img, (i - 1) * 16, 0);
g.Free;
in_img.Free;
end;
GetEncoderClsid('image/bmp', encoderClsid);
out_img.Save('output.bmp', encoderClsid);
out_img.Free;
ImageList2.DrawingStyle := dsTransparent;
// Load from file:
ImageList2.Handle := ImageList_LoadImage(0, 'output.bmp', 16, ImageList2.AllocBy,
CLR_NONE, IMAGE_BITMAP, LR_CREATEDIBSECTION or LR_LOADTRANSPARENT
or LR_LOADFROMFILE);
end;
所有我直接从图像列表加载图标的尝试都失败了,并产生了反锯齿位图。请点击此处下载我正在使用的图标。以下是另一张图片,用于说明输出位图结果:
![enter image description here](https://istack.dev59.com/hrc9E.webp)
procedure CopyBitmapChannels(Src, Dst: TBitMap; DstOffset: Integer);
var
pscanLine32Src, pscanLine32Dst: pRGBQuadArray;
nScanLineCount, nPixelCount: Integer;
begin
with Src do
begin
for nScanLineCount := 0 to Height - 1 do
begin
pscanLine32Src := Scanline[nScanLineCount];
pscanLine32Dst := Dst.Scanline[nScanLineCount];
for nPixelCount := 0 to Width - 1 do
with pscanLine32Src[nPixelCount] do
begin
pscanLine32Dst[nPixelCount + DstOffset].rgbReserved := rgbReserved;
pscanLine32Dst[nPixelCount + DstOffset].rgbRed := rgbRed;
pscanLine32Dst[nPixelCount + DstOffset].rgbGreen := rgbGreen;
pscanLine32Dst[nPixelCount + DstOffset].rgbBlue := rgbBlue;
end;
end;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
h_Bitmap, h_Mask: HBITMAP;
bm_out, bm_ico: TBitmap;
hico : HICON;
icoInfo: TIconInfo;
i, icon_size, num_icons: Integer;
in_IL: TImageList;
begin
// in_IL := ImageList1; // imagelist ready with 32 bit icons
in_IL := nil; // from files
icon_size := 16;
num_icons := 24;
bm_out := TBitmap.Create;
bm_out.Width := icon_size * num_icons;
bm_out.Height := icon_size;
SetBitmapAlpha(bm_out, 0, 0, 0, 0); // no need to actually modify ScanLines but anyway
for i := 0 to num_icons - 1 do
begin
if in_IL = nil then
hico := LoadImage(0, PChar('D:\Delphi\Projects\Icons\Icon_' + inttostr(i + 1) + '.ico'), IMAGE_ICON, 0, 0,
LR_LOADFROMFILE or LR_LOADTRANSPARENT or LR_CREATEDIBSECTION)
else
hico := ImageList_GetIcon(in_IL.Handle, i, ILD_TRANSPARENT); // RGB is slightly changed - not 100% perfect but close enough!
// get icon info (hbmColor -> bitmap)
GetIconInfo(hico, icoInfo);
bm_ico := TBitmap.Create;
h_Bitmap := CopyImage(icoInfo.hbmColor, IMAGE_BITMAP, 0, 0, {LR_COPYDELETEORG or} LR_COPYRETURNORG or LR_CREATEDIBSECTION);
bm_ico.Handle := h_Bitmap;
CopyBitmapChannels(bm_ico, bm_out, i * icon_size);
DestroyIcon(hico);
DeleteObject(h_Bitmap);
bm_ico.Free;
end;
bm_out.SaveToFile('output.bmp');
bm_out.Free;
// output.bmp is now ready to load with ImageList_LoadImage
end;
顺便提一下,我可以像这样复制GetImageBitmap
的句柄:ImageList_GetImageInfo(ImageList1.Handle, 0, Info); h_Bitmap := CopyImage(Info.hbmImage, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG)
但无论如何,它都不能与ImageList_LoadImage
后续使用。
TImageList.GetImageBitmap
可以在这里帮助。 - Uwe RaabeTBitmap.Handle
,则位图和图像列表都认为它们拥有相同的位图。 - David HeffernanBitBlt
。这是老派的 GDI 编程。 - David Heffernan