Когда я копирую метаданные Exif из одного файла в другой, где исходный файл имеет миниатюру EXIF длиной 65173 байта, и добавляю несколько новых полей метаданных 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);
}
}
}
}
}
}