How to save PngImage from clipboard

后端 未结 3 1317
日久生厌
日久生厌 2021-02-10 05:25

How can i save the pngimage to file copied form AdobeFirewoks(Clipboard) or Photoshop without losing the transparency.

i am using delphi2009.

thank you in advan

3条回答
  •  眼角桃花
    2021-02-10 05:56

    Based on empirical results confirmed by my colleague having Adobe Photoshop CS 6 13.0 x32 using the following test code points out that it's not possible to save the image from clipboard copied by the Adobe Photoshop without losing transparency simply because it doesn't copy the alpha channel data.

    Adobe Photoshop (at least in the version mentioned above) uses 24-bit pixel format for clipboard image data transfer. And, since it is the 24-bit bitmap there can't be an alpha channel. Don't know anyone who has the Adobe Fireworks to verify, but for sure they're using own registered clipboard format to transfer images including the alpha channel between their products.

    The CF_BITMAP or CF_DIB formats used by Adobe Photoshop clipboard supposedly supports alpha channel, as some people says (I haven't tried) but that would be true only for 32-bit pixel format, not for the 24-bit pixel format. The only clipboard format, that surely supports transparency, is the CF_DIBV5 but as the others, the image have to be stored in 32-bit pixel format to preserve the alpha channel:

    The following code shows the information about the currently copied clipboard content:

    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;
    

    Output of the above code for transparent image copied into a clipboard by Adobe Photoshop CS 6 13.0 (click to enlarge):

    Something useful to read:

    • How to copy an image to clipboard keeping its transparency
    • How to copy & paste images using CF_DIBV5 format preserving transparency

提交回复
热议问题