2009-06-24 6 views
10

Ho trovato vari codici e librerie per la modifica di Exif.Libreria .NET C# per la riscrittura di Exif senza perdita di dati?

Ma sono solo senza perdita di dati quando la larghezza e l'altezza dell'immagine è multiplo di 16.

Sto cercando una libreria (o anche un modo per farlo io stesso) per modificare solo la porzione Exif in un file JPEG (o aggiungere dati Exif se ancora non esiste), lasciando gli altri dati non modificati. Non è possibile?

Finora ho potuto individuare solo la parte Exif (inizia con 0xFFE1) ma non capisco come leggere i dati.

+0

[Sembra promettente] (http://www.nullskull.com/articles/20030706.asp) – TaW

risposta

8

Di seguito sono riportate le specifiche per il formato di interscambio Exif, se si intende codificare la propria libreria per la modifica dei tag.

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

Ecco una libreria scritta in Perl che soddisfi le vostre esigenze che si può essere in grado di imparare da:

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

Ecco una libreria .NET decente per la valutazione Exif da The Code Project:

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

8

Si può fare t la sua senza alcun lib esterna:

// 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); 

Elenco di tutti i possibili ids PropertyItem (tra cui EXIF) è possibile trovare here.

Aggiornamento: D'accordo, questo metodo ricodifica l'immagine al salvataggio. Ma ho ricordato un altro metodo, in WinXP SP2 e in seguito sono stati aggiunti nuovi componenti di imaging - WIC, e puoi usarli per metadate di scrittura senza perdita di dati - How-to: Re-encode a JPEG Image with Metadata.

+2

Questo ricomprime l'immagine. C'è una soluzione alternativa per non ricomprimere, ruotando l'immagine due volte, ma funziona solo se la larghezza e l'altezza sono multipli di 16 collegamento aggiornato – Aximili

+1

: http://msdn.microsoft.com/en-us/library/ee719794(v=VS .85) aspx – BlackICE

4

exiv2net libreria (un wrapper .NET in cima a exiv2) potrebbe essere quello che stai cercando.

0

Ho scritto un piccolo test in cui comprimo un file più volte per vedere il degrado della qualità e lo si può vedere nella compressione del terzo quarto, che è molto brutta.

Ma fortunatamente, se si utilizza sempre lo stesso QualityLevel con JpegBitmapEncoder, non si verifica alcun degrado.

In questo esempio, riscrivo le parole chiave 100x nei metadati e la qualità sembra non cambiare.

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); 
     } 
    } 
    } 
}