根据我同事使用Adobe Photoshop CS 6 13.0 x32进行的经验结果,使用以下测试代码表明,仅仅因为它不会复制alpha通道数据,所以无法保存从Adobe Photoshop复制的剪贴板图像而不丢失透明度。
Adobe Photoshop(至少在上述版本中)使用24位像素格式进行剪贴板图像数据传输。由于它是24位位图,因此不能有alpha通道。不知道是否有人使用Adobe Fireworks进行验证,但肯定他们正使用自己注册的剪贴板格式在他们的产品之间传输包括alpha通道在内的图像。
Adobe Photoshop剪贴板使用的CF_BITMAP
或CF_DIB
格式据说支持alpha通道,但只有32位像素格式才是真实的,而不是24位像素格式。唯一确定支持透明度的剪贴板格式是CF_DIBV5
,但像其他格式一样,图像必须以32位像素格式存储以保留alpha通道:
以下代码显示当前复制到剪贴板的内容信息:
uses
ActiveX;
function GetClipboardFormatString(Format: Word): string;
var
S: string;
begin
case Format of
1: S := 'CF_TEXT';
2: S := 'CF_BITMAP';
3: S := 'CF_METAFILEPICT';
4: S := 'CF_SYLK';
5: S := 'CF_DIF';
6: S := 'CF_TIFF';
7: S := 'CF_OEMTEXT';
8: S := 'CF_DIB';
9: S := 'CF_PALETTE';
10: S := 'CF_PENDATA';
11: S := 'CF_RIFF';
12: S := 'CF_WAVE';
13: S := 'CF_UNICODETEXT';
14: S := 'CF_ENHMETAFILE';
15: S := 'CF_HDROP';
16: S := 'CF_LOCALE';
17: S := 'CF_DIBV5';
$0080: S := 'CF_OWNERDISPLAY';
$0081: S := 'CF_DSPTEXT';
$0082: S := 'CF_DSPBITMAP';
$0083: S := 'CF_DSPMETAFILEPICT';
$008E: S := 'CF_DSPENHMETAFILE';
$0200: S := 'CF_PRIVATEFIRST';
$02FF: S := 'CF_PRIVATELAST';
$0300: S := 'CF_GDIOBJFIRST';
$03FF: S := 'CF_GDIOBJLAST';
else
begin
SetLength(S, 255);
SetLength(S, GetClipboardFormatName(Format, PChar(S), 255));
if Length(S) = 0 then
S := 'Unknown, unregistered clipboard format';
Result := S + ' (' + IntToStr(Format) + ')';
Exit;
end;
end;
Result := 'Standard clipboard format (' + S + ')';
end;
function GetClipboardFormats: string;
var
S: string;
FormatEtc: TFormatEtc;
DataObject: IDataObject;
EnumFormatEtc: IEnumFormatEtc;
begin
Result := '';
if Succeeded(OleGetClipboard(DataObject)) then
begin
if Succeeded(DataObject.EnumFormatEtc(DATADIR_GET, EnumFormatEtc)) then
begin
S := DupeString('-', 65) + sLineBreak +
'Clipboard data formats: ' + sLineBreak +
DupeString('-', 65) + sLineBreak;
while EnumFormatEtc.Next(1, FormatEtc, nil) = S_OK do
S := S + GetClipboardFormatString(FormatEtc.cfFormat) + sLineBreak;
Result := S;
end;
end;
end;
function GetClipboardInfoDIB: string;
var
S: string;
ClipboardData: HGLOBAL;
BitmapInfoHeader: PBitmapInfoHeader;
const
BI_JPEG = 4;
BI_PNG = 5;
begin
Result := '';
if OpenClipboard(0) then
try
ClipboardData := GetClipboardData(CF_DIB);
if ClipboardData <> 0 then
begin
BitmapInfoHeader := GlobalLock(ClipboardData);
if Assigned(BitmapInfoHeader) then
try
S := DupeString('-', 65) + sLineBreak +
'Clipboard data of CF_DIB format: ' + sLineBreak +
DupeString('-', 65) + sLineBreak +
'Width: ' + IntToStr(BitmapInfoHeader.biWidth) + ' px' + sLineBreak +
'Height: ' + IntToStr(BitmapInfoHeader.biHeight) + ' px' + sLineBreak +
'Bit depth: ' + IntToStr(BitmapInfoHeader.biBitCount) + ' bpp' + sLineBreak +
'Compression format: ';
case BitmapInfoHeader.biCompression of
BI_RGB: S := S + 'Uncompressed format (BI_RGB)';
BI_RLE8: S := S + 'RLE format for bitmaps with 8 bpp (BI_RLE8)';
BI_RLE4: S := S + 'RLE format for bitmaps with 4 bpp (BI_RLE4)';
BI_BITFIELDS: S := S + 'Not compressed with color masks (BI_BITFIELDS)';
BI_JPEG: S := S + 'Compressed using JPEG file format (BI_JPEG)';
BI_PNG: S := S + 'Compressed using PNG file format (BI_PNG)';
end;
S := S + sLineBreak;
Result := S;
finally
GlobalUnlock(ClipboardData);
end;
end;
finally
CloseClipboard;
end;
end;
function GetClipboardInfoDIBV5: string;
var
S: string;
ClipboardData: HGLOBAL;
BitmapInfoHeader: PBitmapV5Header;
const
BI_JPEG = 4;
BI_PNG = 5;
begin
Result := '';
if OpenClipboard(0) then
try
ClipboardData := GetClipboardData(CF_DIBV5);
if ClipboardData <> 0 then
begin
BitmapInfoHeader := GlobalLock(ClipboardData);
if Assigned(BitmapInfoHeader) then
try
S := DupeString('-', 65) + sLineBreak +
'Clipboard data of CF_DIBV5 format: ' + sLineBreak +
DupeString('-', 65) + sLineBreak +
'Width: ' + IntToStr(BitmapInfoHeader.bV5Width) + ' px' + sLineBreak +
'Height: ' + IntToStr(BitmapInfoHeader.bV5Height) + ' px' + sLineBreak +
'Bit depth: ' + IntToStr(BitmapInfoHeader.bV5BitCount) + ' bpp' + sLineBreak +
'Compression format: ';
case BitmapInfoHeader.bV5Compression of
BI_RGB: S := S + 'Uncompressed format (BI_RGB)';
BI_RLE8: S := S + 'RLE format for bitmaps with 8 bpp (BI_RLE8)';
BI_RLE4: S := S + 'RLE format for bitmaps with 4 bpp (BI_RLE4)';
BI_BITFIELDS: S := S + 'Not compressed with color masks (BI_BITFIELDS)';
BI_JPEG: S := S + 'Compressed using JPEG file format (BI_JPEG)';
BI_PNG: S := S + 'Compressed using PNG file format (BI_PNG)';
end;
S := S + sLineBreak;
Result := S;
finally
GlobalUnlock(ClipboardData);
end;
end;
finally
CloseClipboard;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
S: string;
begin
S := GetClipboardFormats;
if IsClipboardFormatAvailable(CF_DIB) then
S := S + sLineBreak + GetClipboardInfoDIB;
if IsClipboardFormatAvailable(CF_DIBV5) then
S := S + sLineBreak + GetClipboardInfoDIBV5;
ShowMessage(S);
end;
上述代码对由Adobe Photoshop CS 6 13.0复制到剪贴板的透明图像的输出(点击放大):
![Click to enlarge](https://istack.dev59.com/Gw6cL.webp)
有用的阅读材料:
这段代码
并告诉我,当你在剪贴板中有一个透明图像时,消息显示的是什么?你能使用从你提到的两个应用程序中复制的图像来执行吗? - TLamaLoadFromClipboardFormat
内部创建了一个位图,并尝试从剪贴板加载该位图。当您指定除CF_BITMAP
以外的格式时,就会引发异常。 - TLama这段代码
,我不记得我是否建议使用CF_BITMAP
。无论如何,这都行不通。从Photoshop复制时,无法粘贴精确的透明图像,因为32位位图(具有Alpha通道的格式)中每个像素由每个像素的4个字节组成。而Photoshop只复制红色、绿色和蓝色通道的3个值到剪贴板中。它不包括Alpha通道的值。 - TLama