2009-06-24 3 views
10

Я нашел различные коды и библиотеки для редактирования Exif..NET C# библиотека для без потерь перезаписи Exif?

Но они только без потерь, когда ширина и высота изображения кратен 16.

Ищу библиотеку (или даже способ сделать это сам), чтобы изменить только часть Exif в файле JPEG (или добавить данные Exif, если он еще не существует), оставив другие данные немодифицированными. Разве это невозможно?

До сих пор я мог только найти часть Exif (начинается с 0xFFE1), но я не понимаю, как читать данные.

+0

[Это звучит многообещающе] (http://www.nullskull.com/articles/20030706.asp) – TaW

ответ

8

Вот спецификации для формата обмена Exif, если вы планируете кодировать свою собственную библиотеку для редактирования тегов.

http://www.exif.org/specifications.html

Вот библиотека, написанная в Perl, который отвечает вашим потребностям, которые вы можете узнать из:

http://www.sno.phy.queensu.ca/~phil/exiftool/

Вот приличная библиотека .NET для оценки Exif из The Code Project:

http://www.codeproject.com/KB/graphics/exiftagcol.aspx

8

Вы можете сделать t его без каких-либо внешних Lib:

// 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), которые можно найти here.

Обновление: Согласовано, этот метод будет перекодировать изображение при сохранении. Но я вспомнил еще один метод, в WinXP SP2, а затем добавлены новые компоненты изображения - WIC, и вы можете использовать их для метаданных без потерь - How-to: Re-encode a JPEG Image with Metadata.

+2

Это перекодировано изображение. Существует временное решение не переуплотнять, дважды поворачивая изображение, но работает только в том случае, если ширина и высота кратные 16 – Aximili

+1

обновленная ссылка: http://msdn.microsoft.com/en-us/library/ee719794(v=VS +0,85) .aspx – BlackICE

4

exiv2net библиотека (оболочка .NET поверх exiv2) может быть тем, что вы ищете.

0

Я написал небольшой тест, где несколько раз сжимаю один файл, чтобы увидеть ухудшение качества, и вы можете увидеть его в третьем-четвертом сжатии, что очень плохо.

Но, к счастью, если вы всегда используете один и тот же 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); 
     } 
    } 
    } 
}