簡體   English   中英

如何從剪貼板類中獲取圖像格式?

[英]How to get the image format from Clipboard class?

我正在用 C# 制作圖像查看器。 該功能是在 C# 上使用剪貼板類的復制和粘貼功能。

我成功獲得了 BitmapSource 的圖像。 但它不能檢查圖像格式(jpeg、png、bmp)。

這是來自 C# BitmapSource source = Clipboard.GetImage();的支持源

這些是我想要使用的。 byte[] image = Clipboard.GetImage("image/png") byte[] image = Clipboard.GetImage("image/bmp")

我會說,如何從 BitmapSource 或剪貼板檢查圖像格式?

簡單地說,你不能。

圖像作為原始位圖保存在剪貼板上。 一些應用程序也將其以 png 格式放置,但這不是為了保留原始文件,而只是為了更好地支持 alpha-transparency

但是,一般來說,剪貼板根本不包含該圖像來自何處或它最初具有什么格式的指示。 您還必須意識到剪貼板上的圖像可能根本就不是文件。 這就像假設任何復制的文本必須是一個完整的文本文件,帶有文件名。 該圖像可能是直接從某個編輯器復制的,甚至可能是直接的 [PrintScreen] 按鈕屏幕截圖。

然而...

注意到,當我從 Chrome 復制圖像並將其粘貼到 Discord 中時,Discord 不知何故知道它在 Chrome 中的文件名。 這是因為您可以同時將多種格式的數據放在剪貼板上。

該系統通常旨在確保每個應用程序都可以讀取最適合它的內容。 例如,對於從網頁復制的內容,記事本更喜歡純文本版本,而 Microsoft Word 將使用 HTML(如果可用)。 同樣,正如我提到的,應用程序經常以位圖和 png 格式復制圖像,以確保接收支持透明度的應用程序可以采用支持透明度的 PNG 版本,而不了解使用 PNG 的新趨勢的應用程序可以采用經典位圖.

但是很多應用程序也使用它來將元數據添加到復制的內容中。 當我在 Chrome 中復制您頭像的 32x32 縮略圖時,剪貼板中的其中一件事是這個被標識為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>

(我相信指定 HTML 片段信息的標頭可能是標准格式。不過,從未研究過。)

如您所見,這包含文件名,並且從中,您通常會得到一個擴展名,可用於確定文件的原始格式。

但該文件不再是那種格式。 因為,它只是剪貼板上的數據,而不是實際文件。 復制圖像后 Chrome 剪貼板的完整轉儲包含以下格式:

  • System.Drawing.Bitmap (.Net Bitmap 對象。這可能在 WPF 上以不同方式公開)
  • Bitmap (我認為與System.Drawing.Bitmap相同)
  • HTML Format (如上圖所示)
  • DeviceIndependentBitmap (包含 DIB v1 圖像字節的字節流;在剪貼板上傳輸圖像的最常見方式;由於它是 32 位 RGB,因此經常被濫用為 alpha-capable
  • Format17 (包含 DIB v5 圖像字節的字節流;比 v1 稍先進,並正式支持 alpha。“17”指舊 Windows 版本中使用的舊數字剪貼板格式)

如您所見,那里沒有 jpeg 文件。 因為當您處於剪貼板級別時,永遠不會假定原始文件格式會被保留。 即使是設法讀取和保留文件名的 Discord,也會將粘貼的文件另存為 png,並在需要時調整文件擴展名。

在這種特定情況下,您當然可以實際從該 url 下載圖像,而不是獲取剪貼板版本。 但從技術上講,這永遠不能保證是相同的圖像。

請注意,這正是 Chrome 的做法。 無法保證來自其他應用程序甚至來自其他瀏覽器的剪貼板副本將發送元數據,如果他們這樣做,如果它是稍微可比的格式。


我用來分析剪貼板數據的代碼:

(注意,這是 Windows 窗體代碼。我不知道它的 WPF 等效項)

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

    // ...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM