這裏最根本的問題是「我如何取一個任意的ImageSource並學習它最初編碼的格式?」
答案是,你不能總是這樣做,但對於大多數實際目的來說,有一個解決方法可用。如上面的代碼所示,一旦你瞭解了使用哪種格式,其餘部分都很容易。
你不能總能找出原始格式的原因是,它有可能(用一些非常棘手的代碼!)來子類化BitmapSource來創建一個新的ImageSource,從你喜歡的任何地方獲取它的數據。例如,我可以實現一個返回隨機像素的PseudoRandomBitmapSource。在這種情況下,「原始格式」可能是用於隨機數生成器的種子。
如果你正在處理的內置的ImageSource類之一,找出原來的編碼方式取決於它的確切類,你正在使用:
對於BitmapImage的,你可以使用的StreamSource或UriSource ,無論哪一個設置。其中任何一個都可以傳遞給BitmapDecoder.Create重載。您的示例代碼顯示瞭如何爲StreamSource執行此操作。這與UriSource完全相同,除非您需要新的Uri(BaseUri, UriSource)
並將其傳遞給需要Uri的BitmapDecoder.Create過載。
對於ColorConvertedBitmap,CroppedBitmap,FormatConvertedBitmap和TransformedBitmap,可以使用公共「Source」屬性獲取底層源代碼,然後使用此算法遞歸檢查其編碼。
對於CachedBitmap,您只能通過內部字段獲取源位圖。如果您擁有足夠的權限,則可以使用反射訪問,否則您的運氣不佳。
對於RenderTargetBitmap,WritableBitmap,D3DImage和DrawingImage,由於圖像是從矢量格式或算法「實時」構建的,因此沒有原始編碼。
對於BitmapFrame,使用Decoder屬性獲取解碼器,然後使用CodecInfo.ContainerFormat。
對於InteropBitmap或UnmanagedBitmapWrapper,它非常複雜。基本上你需要使用反射來讀取內部的WicSourceHandle屬性,然後調用DangerousGetHandle()來獲得一個實際上是非託管IUnkown的IntPtr。 IWICBitmapDecoder使用非託管代碼,QueryInterface。如果成功,您可以調用IWICBitmapDecoder.GetContainerFormat獲取格式Guid(這仍然是非託管代碼)。如果沒有,關於原始來源的所有信息都已丟失。
正如你所看到的,還有相當,你不能得到源(例如,對於完全解碼位圖的InteropBitmap),或者獲得源需要專門的技術和特權(對於非託管代碼少數情況下InteropBitmap或CachedBitmap內部字段的反射)。
因爲通常很難不可能獲得原始格式,所以尋找保存這些信息的方法是一個好主意,因爲它會傳遞到您的代碼中。如果控制圖像的源,其可以是作爲創建ImageSourceAndFormat類如簡單:
public class BitmapSourceAndFormat
{
public ImageSource Source { get; set; }
public Guid OriginalFormat { get; set; }
}
此,如果要放置在圖像上剪貼板是特別有用的。通常,除了將圖像添加到DataObject之外,您還可以添加一個BitmapSourceAndFormat對象。如果這樣做,則粘貼操作將接收包含這兩種格式的DataObject。您的代碼只需要首先檢查BitmapSourceAndFormat對象。如果發現它可以簡單地訪問它以獲得原始格式。如果不是,它必須訴諸於上述手段。
最後一個注意事項:對於剪貼板粘貼,您可以檢查可用的數據格式字符串。一些有用的是:Bitmap,Dib,Tiff,Gif,Jpeg和FileName。對於「Tiff」,「Gif」和「Jpeg」,您可以硬編碼所需的格式。對於「文件名」,您可以自己打開文件以獲取流傳遞給BitmapDecoder。對於沒有其他任何東西的「Dib」或「Bitmap」,您知道原始格式已丟失。
你能解釋一下你正在經歷的情況嗎?在我看來,如果您要保存圖像,只需將其保存爲所需的格式即可。 BitmapImage似乎是一種格式,原始圖像已被轉換。 – 2010-08-04 22:16:11