【问题标题】:How to save C# .NET WriteableBitmap that is 32767 x 32767 in resolution as JPG or PNG如何将分辨率为 32767 x 32767 的 C# .NET WriteableBitmap 保存为 JPG 或 PNG
【发布时间】:2015-03-21 18:58:46
【问题描述】:

这适用于在具有 32GB 内存的 64 位 Windows 8 系统上运行的 .NET 4.5 控制台应用程序。该应用程序面向 64 位平台并启用了 gcAllowVeryLargeObjects 标志,它允许应用程序创建大于 .NET 限制的 2Gb 的对象。所以,我可以创建一个 15GB 的整数数组。

我使用以下构造函数创建了一个 32,767 x 32,767 像素的 System.Windows.Media.Imaging.WriteableBitmap,它使用 WIC(Windows 成像组件而不是 GDI+,因为 WIC 可以处理比 GDI+ 更高的分辨率)

WriteableBitmap wbit = new WriteableBitmap(32767, 32767, 300, 300, PixelFormats.Bgra32, null);

我尝试使用以下代码将其保存为 JPG 格式

using (FileStream stream = new FileStream("c:\\test.jpg",FileMode.Create))
{
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(wbit));
encoder.Save(stream);
}

我也尝试使用以下代码将其保存为 PNG

using (FileStream stream = new FileStream("c:\\test.png",FileMode.Create))
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(wbit));
encoder.Save(stream);
}

对于 JPG 和 PNG,我可以将分辨率提高到 23,170 x 23,170,并且工作正常,但提高到 23,171 x 23,171 会引发以下异常

System.AccessViolationException:试图读取或写入受保护的内存。这通常表明其他内存已损坏。在 MS.Wind32.PresentationCore.UnsafeNativeMethods.WICBitmapFrameEncode.WriteSource(SafeMILHandle THIS_PTR, SafeMILHandle pIBitmapSource, Int32Rect& r) 在 System.Windows.Media.Imaging.BitmapEncoder.Save(Stream 流)

有谁知道这个异常的原因,以及我如何能够绕过它,以便将完整的最大分辨率保存为 32,767 x 32,767?也许我必须使用另一个编码器,甚至开始寻找 .NET 框架之外的东西。理想情况下,我希望能够处理 JPEG 最大分辨率为 65,535 x 65,535 的图像,或者在 PNG 中以 100,000 x 100,000 像素甚至更高的分辨率处理图像。对于此事或朝着正确方向提出的建议,我将不胜感激。谢谢。

【问题讨论】:

  • "因为 WIC 可以处理比 GDI+ 更高的分辨率" 您从哪里发现的?我在文档中找不到任何关于此的内容。
  • @ScottChamberlain 没有关于这些的任何文档,它基于我过去几天对 Bitmap 和 WriteableBitmap 的测试。位图在“大约”22000 x 22000 像素处开始中断,这不是一个硬数字,因为它的限制基于 2GB 虚拟内存限制。因此,22000 x 22000 有时有效,有时无效。 WriteableBitmap 有一个硬限制,最高可达 32,767 x 32,767,但总是在 32,768 x 32,768 处中断。见this post
  • 平铺不是一个选项? IE。 Google 地图也不是由一张巨大的图像组成的。
  • 我已经做了平铺,然后再做,以便像 Goodle Maps 一样在网络上提供图像,但在那个阶段之前,我仍然需要生成单个 JPG 或 PNG 文件整件事。
  • 我不是 Microsoft API 的专家,但错误中的“Wind32”位是可疑的。它表明编码器 API 正在调用 32 位非托管代码,然后该代码会落在您的大图像上。如果这是特定于编码器的,您可以在 System.Windows.Media 库中查找另一个编码器(BMP?)。或者,查找第三方 64 位编码器。 (System.Drawing.Bitmap.Save 会做得更好吗?)

标签: c# .net bitmap jpeg writeablebitmap


【解决方案1】:

关于支持更高分辨率的 JPEG 格式本身是对的。我使用大小为 40,000 x 33,000 像素的巨大 JPEG 图像进行了测试。 JPEG 无法使用 System.Drawing.Bitmap 加载,但它使用至少 2 个不同的程序正确打开:

  1. Windows 7 照片查看器,可能是因为它使用 WIC,而不是 GDI+。
  2. IrfanView 64 位,但将其大小调整为半宽半高 加载过程中。

这表明测试 JPEG 图像确实有效,即使 GDI+ 无法加载它。 由于这不是 JPEG 规范的限制,因此它必须是 Microsoft 实施中的限制。他们的编码器不太可能在这里解决问题。如果您必须有更高的分辨率(并且您表示有),您最好的解决方案可能是找到一个不同的库来进行编码。

【讨论】:

    猜你喜欢
    • 2020-12-16
    • 1970-01-01
    • 2012-06-27
    • 1970-01-01
    • 2011-03-07
    • 1970-01-01
    • 1970-01-01
    • 2020-09-14
    • 1970-01-01
    相关资源
    最近更新 更多