Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将带有元数据的图像写入MemoryStream时,JpegBitmapEncoder.Save()引发异常_C#_Wpf_Metadata_Exif - Fatal编程技术网

C# 将带有元数据的图像写入MemoryStream时,JpegBitmapEncoder.Save()引发异常

C# 将带有元数据的图像写入MemoryStream时,JpegBitmapEncoder.Save()引发异常,c#,wpf,metadata,exif,C#,Wpf,Metadata,Exif,我正在尝试设置JPG图像上没有的元数据。在这种情况下不能使用就地编写器(InPlaceBitmapMetadataWriter),因为映像中没有元数据的位置 如果我使用FileStream作为输出,一切都正常。但是,如果我尝试使用MemoryStream作为输出,JpegBitmapEncoder.Save()会抛出一个异常(来自HRESULT:0xC0000005的异常)。 经过一些调查,我还发现,如果我提供空值而不是元数据,什么编码器可以将图像保存到内存流中 我已经做了一个非常简单和简短的例

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

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

我已经做了一个非常简单和简短的例子,再现了这个问题:

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");
        }
    }
}
这是一个简单的控制台应用程序。 要运行它,请将filename变量内容替换为任何不带元数据的.jpg文件的路径(或使用)

Ofc我可以先将图像保存到临时文件中,关闭它,然后打开并复制到MemoryStream,但它太脏,解决方法也太慢。
欢迎您提出任何让这项工作正常进行的想法:)

我运行了您的代码,没有进行任何修改,也没有抛出错误。 我甚至试着将修改后的数据保存到磁盘上,并且图像本身没有损坏

string filename = "e:\\a.jpg";
        MemoryStream s;
        s = SetTagsInMemory(filename, "test title");
        FileStream fs = new FileStream("e:\\b.jpg", FileMode.CreateNew, FileAccess.ReadWrite);
        BinaryWriter sw = new BinaryWriter(fs);
        s.Seek(0, SeekOrigin.Begin);
        while (s.Position < s.Length)
       {
            byte[] data = new byte[4096];
            s.Read(data, 0, data.Length);
            sw.Write(data);
       }

        sw.Flush();
        sw.Close();
        fs.Close();
string filename=“e:\\a.jpg”;
记忆流;
s=设置标记内存(文件名,“测试标题”);
FileStream fs=newfilestream(“e:\\b.jpg”,FileMode.CreateNew,FileAccess.ReadWrite);
BinaryWriter sw=新的BinaryWriter(fs);
s、 Seek(0,SeekOrigin.Begin);
而(s.位置
除了我在下面添加的s=SetTagsInMemory(…)以写入磁盘之外,其余代码都是未修改的


编辑:哦,metadeta最终出现在新文件中,之前的文件没有我看到的任何元数据。

如果有人会遇到相同的问题,下面是解决方案:

如果试图从主应用程序线程中保存.Save()jpeg,请在main()之前添加[StatThread]

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

WinXP和WinVista版本的windowscodecs.dll不可重传,因此,如果您将默认MTA模型(自.NET framework 2.0以来是默认的)用于调用JpegBitmapEncoder.Save()函数的线程,它可能会表现得异常,并引发所述异常。
Win7版本的windowscodecs.dll没有这个问题。

这有点神秘。你能存档你的整个解决方案(包括所有VS文件)并发邮件给我吗?mephisto123[在]gmail[网站]我会尝试运行你的,看看会发生什么。谢谢。也把你的a.jpg寄给我。或者测试程序是否和我在第一篇文章中链接的jpg一起工作。是的。当然,你正在运行什么版本的VS?我做了一个2010年的项目,但如果它更适合你的话,我可以做一个2008年的项目。我也试着用你的形象来运行它,结果成功了。无论如何,我会压缩它,并发送给你所有的东西,包括你的图像和元数据。我用的是2008。事实上,我想知道它是否会在2008年对你起作用,这不是我第一次错了。对不起!Nps,谢谢你的帮助。