首页 > 解决方案 > JPEG 位图元数据保存失败,EXIF 缩略图较大

问题描述

当我将 Exif 元数据从一个文件复制到另一个文件时,源文件具有长度为 65173 字节的 EXIF 缩略图并添加一些新的 EXIF 元数据字段,JPEGBitMapEncoder 保存操作

destinationEncoder.Save(destinationStream);

失败并显示消息“提交失败,因为更改了太多元数据”。如果 Exif 缩略图的长度较短(约 7000 字节),则复制后保存和添加元数据工作正常。

如果我尝试通过取消注释该行来删除 EXIF 缩略图

//sourceMetadata.RemoveQuery("/app1/ifd/exif:{uint=20507}"); // remove thumbnail data

我仍然收到“提交失败”消息。

如何添加 EXIF 元数据字段而不收到此错误消息?

public void CopyMetadata(string sourceFile, string destinationFile, string sXPTitle, string sXPSubject,
            string sXPComment, bool bAspectRatioNotSet, int Width, int Height, bool bShowErrors = false)
{
    string tempFile = destinationFile + ".tmp3";
    uint paddingAmount = 2048;

    // from http://www.dustyfish.com/blog/copying-jpeg-metadata-using-c-and-windows-imaging-component
    //BitmapCreateOptions createOptions = BitmapCreateOptions.PreservePixelFormat | BitmapCreateOptions.IgnoreColorProfile;    // Create backup of the file so you can read and write to different files
    BitmapCreateOptions createOptions = new BitmapCreateOptions();
    System.IO.File.Copy(destinationFile, tempFile, true);    // Open the source file
    //System.IO.File.Copy(sourceFile, tempFile, true);    // Open the source file
    using (Stream sourceStream = System.IO.File.Open(sourceFile, FileMode.Open, FileAccess.Read))
    {
       BitmapDecoder sourceDecoder = BitmapDecoder.Create(sourceStream, createOptions, BitmapCacheOption.None);       // Check source is has valid frames
       if (sourceDecoder.Frames[0] != null && sourceDecoder.Frames[0].Metadata != null)
       {
           // Get a clone copy of the metadata
           BitmapMetadata sourceMetadata = sourceDecoder.Frames[0].Metadata.Clone() as BitmapMetadata;
           // modify values
           sourceMetadata.SetQuery("/app1/ifd/PaddingSchema:Padding", paddingAmount);
           sourceMetadata.SetQuery("/app1/ifd/exif/PaddingSchema:Padding", paddingAmount);
           sourceMetadata.SetQuery("/xmp/PaddingSchema:Padding", paddingAmount);

           sourceMetadata.SetQuery("/app1/ifd/exif:{uint=256}", Width);
           sourceMetadata.SetQuery("/app1/ifd/exif:{uint=257}", Height);

           Encoding _Encoding = Encoding.UTF8;

           sourceMetadata.SetQuery("/app1/ifd/exif:{uint=40091}", _Encoding.GetBytes(sXPTitle + '\0'));// uint=40091
           sourceMetadata.SetQuery("/app13/irb/8bimiptc/iptc/object name", sXPTitle);
           sourceMetadata.SetQuery("/xmp/Description:Description", (sXPTitle + " " + sXPSubject).Replace(Environment.NewLine, " ").ToCharArray());// XMP Description

           sourceMetadata.SetQuery("/app1/ifd/exif:{uint=40095}", _Encoding.GetBytes(sXPSubject + '\0')); // uint 40095
           sourceMetadata.SetQuery("/app13/irb/8bimiptc/iptc/Caption", sXPSubject.Replace(Environment.NewLine, " "));
           sourceMetadata.SetQuery("/xmp/Description:Description", (sXPTitle + " " + sXPSubject).Replace(Environment.NewLine, " ").ToCharArray());// XMP Description

           sourceMetadata.SetQuery("/app1/ifd/exif:{uint=40092}", _Encoding.GetBytes(sXPComment + '\0')); // uint 40092

           if (!bAspectRatioNotSet)
               sourceMetadata.SetQuery("/app1/ifd/exif:{uint=274}", (ushort)1);

           //sourceMetadata.RemoveQuery("/app1/ifd/exif:{uint=20507}"); // remove thumbnail data)
           using (Stream tempStream = System.IO.File.Open(tempFile, FileMode.Open, FileAccess.Read))
           {
               BitmapDecoder tempDecoder = BitmapDecoder.Create(tempStream, createOptions, BitmapCacheOption.None);             // Check temp file has valid frames
               if (tempDecoder.Frames[0] != null && tempDecoder.Frames[0].Metadata != null)
               {
                   // Open the destination file
                   using (Stream destinationStream = System.IO.File.Open(destinationFile, FileMode.Open, FileAccess.ReadWrite))
                   {
                       // Create a new jpeg frame, replacing the destination metadata with the source
                       BitmapFrame destinationFrame = BitmapFrame.Create(tempDecoder.Frames[0],
                             tempDecoder.Frames[0].Thumbnail,
                             sourceMetadata,
                             tempDecoder.Frames[0].ColorContexts);                   // Save the file
                       JpegBitmapEncoder destinationEncoder = new JpegBitmapEncoder();
                       destinationEncoder.Frames.Add(destinationFrame);
                       destinationEncoder.Save(destinationStream);
                   }
               }
           }
       }
    }
}

标签: c#metadata

解决方案


推荐阅读