2009-06-24 11 views
10

He encontrado varios códigos y bibliotecas para editar Exif..NET C# library para la reescritura Exif sin pérdida?

Pero sólo son sin pérdidas cuando el ancho de la imagen y la altura es múltiplo de 16.

Busco a una biblioteca (o incluso una manera de hacerlo yo mismo) para editar sólo la parte de Exif en un archivo JPEG (o agregue datos Exif si aún no existe), dejando los otros datos sin modificar. ¿No es eso posible?

Hasta ahora solo pude localizar la parte Exif (comienza con 0xFFE1) pero no entiendo cómo leer los datos.

+0

[Esto suena prometedor] (http://www.nullskull.com/articles/20030706.asp) – TaW

Respuesta

8

Aquí están las especificaciones para el formato de intercambio Exif, si planea codificar su propia biblioteca para editar etiquetas.

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

Aquí es una biblioteca escrita en Perl que se adapte a sus necesidades que pueda ser capaz de aprender a partir de:

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

Aquí es una biblioteca .NET decente para la evaluación Exif de The Code Project:

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

8

Puedes hacer t sin su lib externa:

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

lista de todos los posibles identificadores de PropertyItem (incluyendo EXIF) que se encuentran here.

Actualización: De acuerdo, este método recodificará la imagen al guardar. Pero he recordado otro método, en WinXP SP2 y más tarde hay nuevos componentes de imágenes agregados - WIC, y puede usarlos para metadate write sin pérdida - How-to: Re-encode a JPEG Image with Metadata.

+2

Esto recomprime la imagen. Hay una solución para no volver a comprimir, al rotar la imagen dos veces, pero solo funciona si el ancho y la altura son múltiplos de 16 – Aximili

+1

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

4

exiv2net biblioteca (un .NET contenedor encima de exiv2) puede ser lo que estás buscando.

0

Escribí una pequeña prueba donde comprime un archivo varias veces para ver la degradación de la calidad y se puede ver en la compresión del tercer cuarto, lo cual es muy malo.

Pero afortunadamente, si siempre utiliza el mismo QualityLevel con JpegBitmapEncoder, no hay degradación.

En este ejemplo reescribo palabras clave 100x en metadatos y la calidad parece no cambiar.

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