Delphi 如何从剪贴板保存PngImage
如何在不丢失透明度的情况下将图像保存到复制的文件ADOBEFIREWKS(剪贴板)或Photoshop 我正在使用delphi2009 先谢谢你 @特拉马 我试过这个代码,但没有透明度。我也不知道我是否做对了Delphi 如何从剪贴板保存PngImage,delphi,png,transparency,clipboard,Delphi,Png,Transparency,Clipboard,如何在不丢失透明度的情况下将图像保存到复制的文件ADOBEFIREWKS(剪贴板)或Photoshop 我正在使用delphi2009 先谢谢你 @特拉马 我试过这个代码,但没有透明度。我也不知道我是否做对了 png := TPngimage.Create; try png.LoadFromClipboardFormat(CF_BITMAP, Clipboard.GetAsHandle(CF_BITMAP), CF_BITMAP); image1.Pictur
png := TPngimage.Create;
try
png.LoadFromClipboardFormat(CF_BITMAP,
Clipboard.GetAsHandle(CF_BITMAP), CF_BITMAP);
image1.Picture.Assign(png);
finally
png.Free;
end;
根据我的同事使用以下测试代码对Adobe Photoshop CS 6 13.0 x32进行测试所证实的实证结果,我指出,保存Adobe Photoshop复制的剪贴板中的图像而不丢失透明度是不可能的,因为它不复制alpha通道数据 Adobe Photoshop(至少在上述版本中)使用24位像素格式传输剪贴板图像数据。而且,因为它是24位位图,所以不可能有alpha通道。不知道谁有Adobe Fireworks需要验证,但可以肯定的是,他们使用自己注册的剪贴板格式在产品之间传输图像,包括alpha通道 Adobe Photoshop剪贴板使用的or格式应该支持alpha通道,正如一些人所说(我没有尝试过),但这只适用于32位像素格式,而不适用于24位像素格式。唯一的剪贴板格式当然支持透明度,但与其他格式一样,图像必须以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;
使用
ActiveX;
函数GetClipboardFormatString(格式:Word):string;
变量
S:字符串;
开始
案例格式
1:S:='CF_TEXT';
2:S:=“CF_位图”;
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_调色板”;
10:S:=“CF_PENDATA”;
11:S:=“CF_RIFF”;
12:S:=‘CF_波’;
13:S:='CF_unicodext';
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_gdiobjast';
其他的
开始
设定长度(S,255);
SetLength(S,GetClipboardFormatName(格式,PChar,255));
如果长度=0,则
S:=“未知、未注册的剪贴板格式”;
结果:=S+'('+IntToStr(格式)+');
出口
结束;
结束;
结果:='标准剪贴板格式('+S+');
结束;
函数GetClipboardFormats:字符串;
变量
S:字符串;
FormatEtc:TFormatEtc;
数据对象:IDataObject;
EnumFormatEtc:IEnumFormatEtc;
开始
结果:='';
如果成功(OleGetClipboard(DataObject)),则
开始
如果成功(DataObject.EnumFormatEtc(DATADIR\u GET,EnumFormatEtc)),则
开始
S:=双列('-',65)+滑动断裂+
'剪贴板数据格式:'+sLineBreak+
双股('-',65)+滑裂;
而EnumFormatEtc.Next(1,FormatEtc,nil)=S_OK do
S:=S+GetClipboardFormatString(FormatEtc.cfFormat)+sLineBreak;
结果:=S;
结束;
结束;
结束;
函数getClipboardInfo:string;
变量
S:字符串;
剪贴簿数据:HGLOBAL;
BitMapInfo头:PBITMapInfo头;
常数
BI_JPEG=4;
biu PNG=5;
开始
结果:='';
如果打开剪贴板(0),则
尝试
剪贴簿数据:=获取剪贴簿数据(CF_DIB);
如果剪贴板数据为0,则
开始
BitMapInfo头:=GlobalLock(剪贴板数据);
如果已分配(BitMapInfo标头),则
尝试
S:=双列('-',65)+滑动断裂+
“CF_DIB格式的剪贴板数据:”+sLineBreak+
双圈('-',65)+滑环+
'宽度:'+IntToStr(bitmapinfo.biWidth)+'px'+sLineBreak+
'高度:'+IntToStr(bitmapinfo.biHeight)+'px'+sLineBreak+
'位深度:'+IntToStr(BitMapInfo头文件.biBitCount)+'bpp'+sLineBreak+
'压缩格式:';
大小写为BitMapInfo的Header.b压缩
BI_RGB:S:=S+“未压缩格式(BI_RGB)”;
BI_RLE8:S:=S+“用于8 bpp位图的RLE格式(BI_RLE8)”;
BI_RLE4:S:=S+“用于4bpp位图的RLE格式(BI_RLE4)”;
BI_位字段:S:=S+'未使用颜色掩码(BI_位字段)进行压缩';
BI_JPEG:S:=S+‘使用JPEG文件格式(BI_JPEG)压缩’;
BI_PNG:S:=S+'使用PNG文件格式(BI_PNG)进行压缩';
结束;
S:=S+sLineBreak;
结果:=S;
最后
GlobalUnlock(剪贴板数据);
结束;
结束;
最后
关闭剪贴板;
结束;
结束;
函数getClipboardInfo:string;
变量
S:字符串;
剪贴簿数据:HGLOBAL;
BitMapInfo头:PBITMAPV5头;
常数
BI_JPEG=4;
biu PNG=5;
开始
结果:='';
如果打开剪贴板(0),则
尝试
剪贴簿数据:=获取剪贴簿数据(CF_DIBV5);
如果剪贴板数据为0,则
开始
BitMapInfo头:=GlobalLock(剪贴板数据);
如果已分配(BitMapInfo标头),则
尝试
S:=双列('-',65)+滑动断裂+
“CF_DIBV5格式的剪贴板数据:”+sLineBreak+
双圈('-',65)+滑环+
'Width:'+IntToStr(BitMapInfo.bV5Width)+'px'+sLineBreak+
'Height:'+IntToStr(BitMapInfo.bV5Height)+'px'+sLineBreak+
'位深度:'+IntToStr(BitMapInfo头文件.bV5BitCount)+'bpp'+sLineBreak+
'压缩格式:';
案例BitmapInfoHeader.BV5压缩
BI_RGB:S:=S+“未压缩格式(BI_RGB)”;
BI_RLE8:S:=S+“用于8 bpp位图的RLE格式(BI_RLE8)”;
BI_RLE4:S:=S+“用于4bpp位图的RLE格式(BI_RLE4)”;
BI_位字段:S:=S+'未使用颜色m压缩
unit EG_ClipboardBitmap32;
{
Author William Egge. egge@eggcentric.com
January 17, 2002
Compiles with ver 1.2 patch #1 of Graphics32
This unit will copy and paste Bitmap32 pixels to the clipboard and retain the
alpha channel.
The clipboard data will still work with regular paint programs because this
unit adds a new format only for the alpha channel and is kept seperate from
the regular bitmap storage.
}
interface
uses
ClipBrd, Windows, SysUtils, GR32;
procedure CopyBitmap32ToClipboard(const Source: TBitmap32);
procedure PasteBitmap32FromClipboard(const Dest: TBitmap32);
function CanPasteBitmap32: Boolean;
implementation
const
RegisterName = 'G32 Bitmap32 Alpha Channel';
GlobalUnlockBugErrorCode = ERROR_INVALID_PARAMETER;
var
FAlphaFormatHandle: Word = 0;
procedure RaiseSysError;
var
ErrCode: LongWord;
begin
ErrCode := GetLastError();
if ErrCode <> NO_ERROR then
raise Exception.Create(SysErrorMessage(ErrCode));
end;
function GetAlphaFormatHandle: Word;
begin
if FAlphaFormatHandle = 0 then
begin
FAlphaFormatHandle := RegisterClipboardFormat(RegisterName);
if FAlphaFormatHandle = 0 then
RaiseSysError;
end;
Result := FAlphaFormatHandle;
end;
function CanPasteBitmap32: Boolean;
begin
Result := Clipboard.HasFormat(CF_BITMAP);
end;
procedure CopyBitmap32ToClipboard(const Source: TBitmap32);
var
H: HGLOBAL;
Bytes: LongWord;
P, Alpha: PByte;
I: Integer;
begin
Clipboard.Assign(Source);
if not OpenClipboard(0) then
RaiseSysError
else
try
Bytes := 4 + (Source.Width * Source.Height);
H := GlobalAlloc(GMEM_MOVEABLE and GMEM_DDESHARE, Bytes);
if H = 0 then
RaiseSysError;
P := GlobalLock(H);
if P = nil then
RaiseSysError
else
try
PLongWord(P)^ := Bytes - 4;
Inc(P, 4);
// Copy Alpha into Array
Alpha := Pointer(Source.Bits);
Inc(Alpha, 3); // Align with Alpha
for I := 1 to (Source.Width * Source.Height) do
begin
P^ := Alpha^;
Inc(Alpha, 4);
Inc(P);
end;
finally
if (not GlobalUnlock(H)) then
if (GetLastError() <> GlobalUnlockBugErrorCode) then
RaiseSysError;
end;
SetClipboardData(GetAlphaFormatHandle, H);
finally
if not CloseClipboard then
RaiseSysError;
end;
end;
procedure PasteBitmap32FromClipboard(const Dest: TBitmap32);
var
H: HGLOBAL;
ClipAlpha, Alpha: PByte;
I, Count, PixelCount: LongWord;
begin
if Clipboard.HasFormat(CF_BITMAP) then
begin
Dest.BeginUpdate;
try
Dest.Assign(Clipboard);
if not OpenClipboard(0) then
RaiseSysError
else
try
H := GetClipboardData(GetAlphaFormatHandle);
if H <> 0 then
begin
ClipAlpha := GlobalLock(H);
if ClipAlpha = nil then
RaiseSysError
else
try
Alpha := Pointer(Dest.Bits);
Inc(Alpha, 3); // Align with Alpha
Count := PLongWord(ClipAlpha)^;
Inc(ClipAlpha, 4);
PixelCount := Dest.Width * Dest.Height;
Assert(Count = PixelCount,
'Alpha Count does not match Bitmap pixel Count,
PasteBitmap32FromClipboard(const Dest: TBitmap32);');
// Should not happen, but if it does then this is a safety catch.
if Count > PixelCount then
Count := PixelCount;
for I := 1 to Count do
begin
Alpha^ := ClipAlpha^;
Inc(Alpha, 4);
Inc(ClipAlpha);
end;
finally
if (not GlobalUnlock(H)) then
if (GetLastError() <> GlobalUnlockBugErrorCode) then
RaiseSysError;
end;
end;
finally
if not CloseClipboard then
RaiseSysError;
end;
finally
Dest.EndUpdate;
Dest.Changed;
end;
end;
end;
end.
On Error Resume Next
Set Ps = CreateObject("Photoshop.Application")
Set Shell = CreateObject("WScript.Shell")
Set FileSystem = CreateObject("Scripting.FileSystemObject")
Dim PNGFileName
PNGFileName = Shell.CurrentDirectory & "\psClipboard.png"
If FileSystem.FileExists(PNGFileName) Then
FileSystem.DeleteFile PNGFileName
End If
Set Doc = Ps.Documents.Add(1,1,72,"psClipboard",,3)
Doc.Paste()
Doc.RevealAll()
If Err.Number = 0 Then
set PNGSaveOptions = CreateObject("Photoshop.PNGSaveOptions")
doc.saveAs PNGFileName, PNGSaveOptions
End If
doc.Close()