gpt4 book ai didi

c# - 如何以原始格式保存图像?

转载 作者:可可西里 更新时间:2023-11-01 08:20:41 26 4
gpt4 key购买 nike

如何使用原始编码保存图像?

似乎保存图像的唯一方法是使用 BitmapEncoder,但我不知道如何从图像中获取正确的格式。

示例:

Clipboard.GetImage() 返回一个 InteropBitmap,它似乎不包含有关原始格式的任何信息。

我也尝试使用扩展方法:

public static void Save(this BitmapImage image, System.IO.Stream stream)
{
var decoder = BitmapDecoder.Create(image.StreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
var encoder = BitmapEncoder.Create(decoder.CodecInfo.ContainerFormat);
foreach (var frame in decoder.Frames)
{
encoder.Frames.Add(BitmapFrame.Create(frame));
}
encoder.Save(stream);
}

但问题是
  • 例如,ImageSource 并不总是一个 BitmapImage (Clipboard.GetImage()) 和
  • image.StreamSource 在某些情况下可以为 null(似乎是通过相对 Uri 加载图像时)

  • 有什么建议吗?

    最佳答案

    这里的基本问题是“我如何获取任意 ImageSource 并了解它最初编码的格式?”

    答案是你不能总是这样做,但对于大多数实际目的,有一个可用的解决方法。正如你上面的代码所示,一旦你学会了使用什么格式,剩下的就很容易了。

    您不能总是找出原始格式的原因是可以(使用一些非常棘手的代码!)子类 BitmapSource 以创建一个新的 ImageSource,从您喜欢的任何地方获取其数据。例如,我可以实现一个返回随机像素的 PseudoRandomBitmapSource。在这种情况下,“原始格式”可能是用于随机数生成器的种子。

    如果您正在处理内置的 ImageSource 类之一,则找出原始编码的方法取决于您使用的确切类:

  • 对于 BitmapImage,您可以使用 StreamSource 或 UriSource,以设置的为准。其中任何一个都可以传递给 BitmapDecoder.Create 重载。您的示例代码显示了如何为 StreamSource 执行此操作。除了您需要新 Uri(BaseUri, UriSource) 外,UriSource 完全相同。并将其传递给采用 Uri 的 BitmapDecoder.Create 重载。
  • 对于 ColorConvertedBitmap、CroppedBitmap、FormatConvertedBitmap 和 TransformedBitmap,有一个公共(public)“Source”属性,您可以使用它来获取基础源,然后使用此算法递归检查其编码。
  • 对于 CachedBitmap,您只能通过内部字段获取源位图。如果你有足够的权限,你可以使用反射访问,否则你就不走运了。
  • 对于 RenderTargetBitmap、WritableBitmap、D3DImage 和 DrawingImage,没有原始编码,因为图像是从矢量格式或算法“动态”构建的。
  • 对于 BitmapFrame,使用 Decoder 属性获取解码器,然后使用 CodecInfo.ContainerFormat。
  • 对于 InteropBitmap 或 UnmanagedBitmapWrapper,它非常复杂。基本上你需要使用反射来读取内部的 WicSourceHandle 属性,然后调用 DangerousGetHandle() 来获取一个 IntPtr,它实际上是一个非托管的 IUnkown。使用非托管代码,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”,您可以硬编码所需的格式。对于“FileName”,您可以自己打开文件以获取要传递给 BitmapDecoder 的流。对于没有任何其他内容的“Dib”或“Bitmap”,您知道原始格式已丢失。

    关于c# - 如何以原始格式保存图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2800812/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com