本文介绍了JpegBitmapEncoder.Save()元数据写入图像时的MemoryStream抛出异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图建立在JPG图像元数据什么没有它。你不能在这种情况下使用就地作家(InPlaceBitmapMetadataWriter)辩论,因为有在图像元数据没有地方

I am trying to set up metadata on JPG image what does not have it. You can't use in-place writer (InPlaceBitmapMetadataWriter) in this case, cuz there is no place for metadata in image.

如果我使用的FileStream作为输出 - 一切正常精细。但是,如果我尝试使用的MemoryStream作为输出 - JpegBitmapEncoder.Save()抛出(从HRESULT异常:0000005)异常。
经过一番调查,我还发现了什么编码器可以将图片保存到内存流,如果我提供空,而不是元数据。

If I use FileStream as output - everything works fine. But if I try to use MemoryStream as output - JpegBitmapEncoder.Save() throws an exception (Exception from HRESULT: 0xC0000005).After some investigation I also found out what encoder can save image to memory stream if I supply null instead of metadata.

我做了一个非常简单的和例如短再现什么问题:

I've made a very simplified and short example what reproduces the problem:

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文件没有元数据(或使用)。

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

Ofc I can just save image to temporary file first, close it, then open and copy to MemoryStream, but its too dirty and slow workaround.Any ideas about getting this working are welcome :)

推荐答案

在万一有人会遇到同样的问题,这里是解决方案:

In case someone will encounter same issue, here is the solution:

如果您尝试对.save()从主应用程序线程JPEG,添加[STAThread]之前的主()

If you try to .Save() jpeg from main application thread, add [STAThread] before Main().

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

If not, call .SetApartmentState(ApartmentState.STA) for the thread calling JpegBitmapEncoder.Save()

WinXP以及WinVista版本不重入,因此,如果您将使用默认的MTA模型(这是因为.NET Framework 2.0的缺省值)线程调用JpegBitmapEncoder.Save()函数,它可以运行异常,并抛出异常描述。
windowscodecs.dll的Win7的版本没有这个问题。

WinXP and WinVista versions of windowscodecs.dll are not reenterable, so if you will use default MTA model (it is default since .NET framework 2.0) for threads calling JpegBitmapEncoder.Save() function, it can behave strangely and throw described exception.Win7 version of windowscodecs.dll does not have this issue.

这篇关于JpegBitmapEncoder.Save()元数据写入图像时的MemoryStream抛出异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-18 22:30