将带有元数据的图像写入 MemoryStream 时,JpegBitmapEncoder.Save() 抛出异常

2024-04-04

我正在尝试在 JPG 图像上设置没有元数据的元数据。在这种情况下,您不能使用就地编写器(InPlaceBitmapMetadataWriter),因为图像中没有元数据的位置。

如果我使用 FileStream 作为输出 - 一切正常。但如果我尝试使用 MemoryStream 作为输出 - JpegBitmapEncoder.Save() 会引发异常(来自 HRESULT 的异常:0xC0000005)。 经过一番调查后,我还发现如果我提供 null 而不是元数据,什么编码器可以将图像保存到内存流。

我做了一个非常简单且简短的示例来重现该问题:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Media.Imaging;

namespace JpegSaveTest
{
    class Program
    {
        public static JpegBitmapEncoder SetUpMetadataOnStream(Stream src, string title)
        {
            uint padding = 2048;
            BitmapDecoder original;
            BitmapFrame framecopy, newframe;
            BitmapMetadata metadata;
            JpegBitmapEncoder output = new JpegBitmapEncoder();
            src.Seek(0, SeekOrigin.Begin);
            original = JpegBitmapDecoder.Create(src, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
            if (original.Frames[0] != null) {
                framecopy = (BitmapFrame)original.Frames[0].Clone();
                if (original.Frames[0].Metadata != null) metadata = original.Frames[0].Metadata.Clone() as BitmapMetadata;
                else metadata = new BitmapMetadata("jpeg");
                metadata.SetQuery("/app1/ifd/PaddingSchema:Padding", padding);
                metadata.SetQuery("/app1/ifd/exif/PaddingSchema:Padding", padding);
                metadata.SetQuery("/xmp/PaddingSchema:Padding", padding);
                metadata.SetQuery("System.Title", title);
                newframe = BitmapFrame.Create(framecopy, framecopy.Thumbnail, metadata, original.Frames[0].ColorContexts);
                output.Frames.Add(newframe);
            }
            else {
                Exception ex = new Exception("Image contains no frames.");
                throw ex;
            }
            return output;
        }

        public static MemoryStream SetTagsInMemory(string sfname, string title)
        {
            Stream src, dst;
            JpegBitmapEncoder output;
            src = File.Open(sfname, FileMode.Open, FileAccess.Read, FileShare.Read);
            output = SetUpMetadataOnStream(src, title);
            dst = new MemoryStream();
            output.Save(dst);
            src.Close();
            return (MemoryStream)dst;
        }

        static void Main(string[] args)
        {
            string filename = "Z:\\dotnet\\gnom4.jpg";
            MemoryStream s;
            s = SetTagsInMemory(filename, "test title");
        }
    }
}

这是简单的控制台应用程序。 要运行它,请将文件名变量内容替换为任何不带元数据的 .jpg 文件的路径(或使用mine http://lr.gameimg.ru/gnom4.jpg).

Ofc 我可以先将图像保存到临时文件,关闭它,然后打开并复制到 MemoryStream,但它太肮脏且缓慢的解决方法。 欢迎任何关于让它工作的想法:)


如果有人遇到同样的问题,解决方案如下:

如果您尝试从主应用程序线程 .Save() jpeg,请在 Main() 之前添加 [STAThread]。

如果没有,请为调用 JpegBitmapEncoder.Save() 的线程调用 .SetApartmentState(ApartmentState.STA)

WinXP 和 WinVista 版本的 windowscodecs.dll 不可重新输入,因此如果您对调用 JpegBitmapEncoder.Save() 函数的线程使用默认 MTA 模型(自 .NET Framework 2.0 起默认),它可能会表现得很奇怪并抛出所描述的异常。 Win7版本的windowscodecs.dll没有这个问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将带有元数据的图像写入 MemoryStream 时,JpegBitmapEncoder.Save() 抛出异常 的相关文章

  • strtok() 使用安全吗[重复]

    这个问题在这里已经有答案了 我读到了很多负面的东西strtok 有人说它已经过时 有人说它不是线程安全的 等等 那么真相是什么 我可以使用吗strtok 它是线程安全的吗 Note 我正在使用 Visual C 您可以使用它 它是标准库的一
  • Boost MPI 在监听列表时不会释放资源?

    这是一个后续问题如何释放 boost mpi request https stackoverflow com questions 44078901 how do i free a boostmpirequest 我在监听列表而不是单个项目时
  • C# 异步任务比同步慢

    你知道为什么同步斐波那契方法比异步 等待更快并且比异步任务更快吗 我在每个项目方法上都使用了异步 所以主要是这是一个非常糟糕的方法 Code static int FibonacciSync int number if number 0 r
  • Winform DatagridView 数字列排序

    我只使用一个简单的 DataGridView 来保存一堆数据 有趣的是 我在特定列中有小数 但是当按小数列排序时 它的排序是错误的 例如 起始顺序可能是 0 56 3 45 500 89 20078 90 1 56 100 29 2 39
  • 如何使用c#从数据桶中获取所有文档?

    如何获取数据桶中的所有文档 我尝试过一个示例 但我只能获得一个特定的文档 这是我的代码 CouchbaseClient oclient oclient new CouchbaseClient vwspace data bucket name
  • 如何通过 libwebsocket 发送异步数据?

    我正在将 Warmcat 的 libwebsocket C 库用于小型 Websocket 服务器 我已经启动并运行了这些示例 并且可以发送数据以响应从 websocket 接收数据 例如回显发送的反向字节 但是 我无法弄清楚如何在不使用
  • 从内存流播放视频文件

    只是好奇看看这是否可能 我有一个 Windows 应用程序 它从我的电脑上的 avi 文件读取所有字节 然后将其存储在 byte 中 现在我的内存中有 avi 文件 我想直接从内存将其加载到某种视频播放器控件中 我尝试过使用 wmplaye
  • 为什么像 BindingList 或 ObservableCollection 这样的类不是线程安全的?

    我一次又一次发现自己必须编写 BindingList 和 ObservableCollection 的线程安全版本 因为当绑定到 UI 时 这些控件无法从多个线程更改 我想理解的是why情况就是这样 这是设计错误还是故意的 问题是设计一个线
  • 如何使用 CUDA/Thrust 对两个数组/向量根据其中一个数组中的值进行排序

    这是一个关于编程的概念问题 总而言之 我有两个数组 向量 我需要对一个数组 向量进行排序 并将更改传播到另一个数组 向量中 这样 如果我对 arrayOne 进行排序 则对于排序中的每个交换 arrayTwo 也会发生同样的情况 现在 我知
  • asp.net core http 如果没有内容类型标头,则删除 `FromBody` 忽略

    我在 http 中使用 bodyDELETE要求 我知道目前删除主体是非标准的 但是允许的 使用时出现问题HttpClient它不允许删除请求的正文 我知道我可以使用SendAsync 但我宁愿让我的 API 更加灵活 我希望这个机构是可选
  • ASP.net WebForms - 在标记中使用 GetRouteUrl

    我一直在尝试弄清楚如何将路由功能与 ASP net 4 0 WebForms 一起使用 我将一条路线添加到我的路线集合中 void Application Start RegisterRoutes RouteTable Routes voi
  • 本地时间的内存需要释放吗?

    void log time t current time 0 tm ptm localtime current stuf 只是想确定 我是否需要在方法结束时释放 tm 指针分配的内存 不 你不应该释放它 该结构是静态分配的 检查文档 htt
  • 从 C# 调用时无法识别 Powershell 命令

    这是这个的延续Question https stackoverflow com questions 66280000 powershell object returns null 66280138 noredirect 1 comment1
  • 在 C# .NET 中对非 ASCII 字符进行编码

    我想向我的应用程序发送的电子邮件添加自定义标头 标头名称只能包含 ASCII 字符 但对于值和用户可能会输入 UTF 8 字符 我必须对它们进行 Base64 编码 此外 我还必须将它们解码回 UTF 8 以便在 UI 中向用户显示它们 最
  • 使用 cmake 将两种解决方案合二为一

    我有两个单独的 Visual Studio 2013 解决方案 我想将它们迁移到一个解决方案中 因为第一个解决方案 使用 Qt 充当第二个解决方案的 GUI 最后 我希望有一个结构如下的单一解决方案 Solution All Build P
  • 如何释放字符串未使用的容量

    我正在程序中处理很多字符串 这些字符串数据在读入我的程序后的整个生命周期内都不会改变 但由于 C 字符串保留了容量 因此浪费了大量肯定不会被使用的空间 我尝试释放这些空间 但没有成功 以下是我尝试过的简单代码 string temp 123
  • 基础设施 - 同步和异步接口和实现? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 在实现库 基础设施时 并且该 API 的用户希望同步和异步使用代码 我读到混合同步和异步并不是一个好主意 例如 同步实现包括等待异步实现 显然
  • Unity - 在生成时获取随机颜色

    我有一个小问题 我想在我的场景中生成四边形 它们都应该有红色或绿色作为材质 但 Random Range 函数只能是 int 我该如何解决它 void SpawningSquadsRnd rndColor 0 Color red rndCo
  • 在 LP2844Z(Zebra 打印机)上的收据中包含 PNG [重复]

    这个问题在这里已经有答案了 我正在致力于创建一个基于 HTML5 画布的签名 绘图框 目前我们在服务器上将画布保存为PNG 但可以轻松地将base64字符串保存在数据库中 现在的问题是我们如何在打印的收据上添加签名 目前我们使用 GF 字段
  • 如何通过API退出Win32应用程序?

    我有一个使用 Win32 API 编写的 C Win32 应用程序 我希望强制它在其中一个函数中退出 有没有类似的东西Exit or Destroy or Abort 类似的东西会终止它吗 哎呀呀呀呀呀呀 不要做任何这些事情 exit 和

随机推荐