.NET С# библиотека для без потерь перезаписи Exif?
Я нашел различные коды и библиотеки для редактирования Exif.
Но они являются только без потерь, когда ширина и высота изображения кратно 16.
Я ищу библиотеку (или даже способ сделать это сам), чтобы редактировать только часть Exif в файле JPEG (или добавить данные Exif, если она еще не существует), оставив другие данные без изменений. Разве это невозможно?
До сих пор я мог только найти часть Exif (начинается с 0xFFE1), но я не понимаю, как читать данные.
Ответы
Ответ 1
Вот спецификации для формата обмена Exif, если вы планируете закодировать свою собственную библиотеку для редактирования тегов.
http://www.exif.org/specifications.html
Здесь библиотека, написанная на Perl, которая соответствует вашим потребностям, с которыми вы можете научиться:
http://www.sno.phy.queensu.ca/~phil/exiftool/
Здесь достойная библиотека .NET для оценки Exif от Проект кода:
http://www.codeproject.com/KB/graphics/exiftagcol.aspx
Ответ 2
Вы можете сделать это без внешней библиотеки:
// Create image.
Image image1 = Image.FromFile("c:\\Photo1.jpg");
// Get a PropertyItem from image1. Because PropertyItem does not
// have public constructor, you first need to get existing PropertyItem
PropertyItem propItem = image1.GetPropertyItem(20624);
// Change the ID of the PropertyItem.
propItem.Id = 20625;
// Set the new PropertyItem for image1.
image1.SetPropertyItem(propItem);
// Save the image.
image1.Save("c:\\Photo1.jpg", ImageFormat.Jpg);
Список всех возможных идентификаторов PropertyItem (включая exif) можно найти здесь.
Обновление: Согласовано, этот метод будет повторно кодировать изображение при сохранении. Но я вспомнил еще один метод, в WinXP SP2, а затем добавлены новые компоненты изображения - WIC, и вы можете использовать их для метаданных без потерь - How-to: Перекодируйте изображение JPEG с метаданными.
Ответ 3
exiv2net библиотека (оболочка .NET поверх exiv2) может быть тем, что вы ищете.
Ответ 4
Я написал небольшой тест, где несколько раз сжимаю один файл, чтобы увидеть ухудшение качества, и вы можете увидеть его в третьем-четвертом сжатии, что очень плохо.
Но, к счастью, если вы всегда используете один и тот же QualityLevel с JpegBitmapEncoder, то нет деградации.
В этом примере я переписываю ключевые слова 100x в метаданных, и качество, похоже, не изменяется.
private void LosslessJpegTest() {
var original = "d:\\!test\\TestInTest\\20150205_123011.jpg";
var copy = original;
const BitmapCreateOptions createOptions = BitmapCreateOptions.PreservePixelFormat | BitmapCreateOptions.IgnoreColorProfile;
for (int i = 0; i < 100; i++) {
using (Stream originalFileStream = File.Open(copy, FileMode.Open, FileAccess.Read)) {
BitmapDecoder decoder = BitmapDecoder.Create(originalFileStream, createOptions, BitmapCacheOption.None);
if (decoder.CodecInfo == null || !decoder.CodecInfo.FileExtensions.Contains("jpg") || decoder.Frames[0] == null)
continue;
BitmapMetadata metadata = decoder.Frames[0].Metadata == null
? new BitmapMetadata("jpg")
: decoder.Frames[0].Metadata.Clone() as BitmapMetadata;
if (metadata == null) continue;
var keywords = metadata.Keywords == null ? new List<string>() : new List<string>(metadata.Keywords);
keywords.Add($"Keyword {i:000}");
metadata.Keywords = new ReadOnlyCollection<string>(keywords);
JpegBitmapEncoder encoder = new JpegBitmapEncoder {QualityLevel = 80};
encoder.Frames.Add(BitmapFrame.Create(decoder.Frames[0], decoder.Frames[0].Thumbnail, metadata,
decoder.Frames[0].ColorContexts));
copy = original.Replace(".", $"_{i:000}.");
using (Stream newFileStream = File.Open(copy, FileMode.Create, FileAccess.ReadWrite)) {
encoder.Save(newFileStream);
}
}
}
}