How to get the image format from Clipboard class?

谁说我不能喝 提交于 2020-01-15 11:19:07

问题


I'm making a image viewer in C#. that feature is copy and paste function using Clipboard class on C#.

And I succeeded to get image of BitmapSource. but it can not check image formats (jpeg, png, bmp).

This is supported source from C# BitmapSource source = Clipboard.GetImage();

These are what i want to use. byte[] image = Clipboard.GetImage("image/png") byte[] image = Clipboard.GetImage("image/bmp")

I will say, How do I check image format from BitmapSource or Clipboard?


回答1:


Simply put, you can't.

Images are saved on the clipboard as raw bitmap. Some applications also put it on in png format, but that's not to preserve the original, but just to better support alpha-transparency.

But, in general, the clipboard contains no indication at all of where that image came from, or what format it originally had. You also have to realize that that image on the clipboard might never have been a file at all. That's like assuming any copied piece of text must have been a complete text file, with a filename. That image might've been copied straight from some editor, or might even be a direct [PrintScreen]-button screenshot.

I have noticed that when I copy an image from Chrome and paste it in Discord, Discord somehow knows the file name it had in Chrome. This is because you can put data on the clipboard in multiple formats simultaneously.

This system is generally meant to make sure that every application can read the content that's most optimally suited for it. For example, for content copied from a web page, Notepad will prefer the plain text version, while Microsoft Word will take HTML if available. Likewise, as I mentioned, applications often copy images in bitmap and png to make sure receiving applications that support transparency can take the transparency-supporting PNG version, while applications that are not aware of the rather new trend to use PNG can take the classic bitmap.

But a lot of applications also use this to add metadata to the copied content. When I copy the 32x32 thumbnail of your avatar in Chrome, one of the things in the clipboard was this text snippet identified as HTML Format:

Version:0.9
StartHTML:0000000105
EndHTML:0000000238
StartFragment:0000000141
EndFragment:0000000202
<html>
<body>
<!--StartFragment--><img src="https://i.stack.imgur.com/Eql2x.jpg?s=32&amp;g=1"/><!--EndFragment-->
</body>
</html>

(I believe that the header specifying the HTML Fragment information might be a standard format. Never looked into that, though.)

As you see, this contains the file name, and from that, you usually got an extension that can be used to determine the original format the file was in.

But the file is no longer in that format. Because, it's just data on the clipboard, not an actual file. The full dump of the Chrome clipboard after copying an image contained the following formats:

  • System.Drawing.Bitmap (a .Net Bitmap object. This might be exposed differently on WPF)
  • Bitmap (Same as System.Drawing.Bitmap I think)
  • HTML Format (the snippet shown above)
  • DeviceIndependentBitmap (A byte stream containing bytes for a DIB v1 image; the most common way of transferring images on the clipboard; often abused as alpha-capable because it's 32 bit RGB)
  • Format17 (A byte stream containing bytes for a DIB v5 image; slightly more advanced than v1, and officially supports alpha. The '17' refers to the old numeric clipboard formats used in old windows versions)

As you see, there's no jpeg file in there. Because the original file format is never assumed to be preserved when you're at clipboard level. Even Discord, which manages to read and preserve the filename, will save the pasted file as png, adjusting the file extension if needed.

Do note that this is just how Chrome does it. There are no guarantees that the clipboard copy from other applications, or even from other browsers, will send metadata, and if they do, if it is in an even slightly comparable format.


The code I used to analyse the clipboard data:

(Note, this is Windows Forms code. I have no idea about its WPF equivalents)

DataObject retrievedData = (DataObject)Clipboard.GetDataObject();
if (retrievedData == null)
    return;
String[] formats = retrievedData.GetFormats();
foreach (String format in formats)
{
    Object contents = retrievedData.GetData(format);
    MemoryStream ms = contents as MemoryStream;
    Byte[] bContents = ms == null ? null : ms.ToArray();
    String sContents = contents as String;

    // Check if bContents and sContents are null here, and analyse their contents

    // ...
}


来源:https://stackoverflow.com/questions/57263058/how-to-get-the-image-format-from-clipboard-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!