2009-06-24 13 views
10

Znalazłem różne kody i biblioteki do edycji Exif..NET C# biblioteki do bezstratnego przepisywania Exif?

Ale są tylko bezstratna, gdy szerokość i wysokość obrazu jest wielokrotnością 16.

szukam biblioteki (lub nawet sposób zrobić to sam), aby edytować tylko część Exif w pliku JPEG (lub dodaj dane Exif, jeśli jeszcze nie istnieje), pozostawiając inne dane niezmodyfikowane. Czy to nie możliwe?

Do tej pory mogłem zlokalizować tylko część Exif (zaczyna się od 0xFFE1), ale nie rozumiem, jak odczytać dane.

+0

[To brzmi obiecująco] (http://www.nullskull.com/articles/20030706.asp) – TaW

Odpowiedz

8

Możesz zrobić Jego bez lib zewnętrzny:

// 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 wszystkich możliwych identyfikatorów PropertyItem (łącznie z Exif) można znaleźć here.

Aktualizacja: Uzgodniono, ta metoda ponownie zakoduje obraz przy zapisie. Ale przypomniałem sobie inną metodę, w WinXP SP2 i później dodano nowe komponenty do obrazowania - WIC, i można ich używać do bezstratnego metadanika zapisu - How-to: Re-encode a JPEG Image with Metadata.

+2

ta ponownie kompresuje obraz. Istnieje obejście, którego nie można ponownie skompresować, obracając obraz dwukrotnie, ale działa tylko wtedy, gdy szerokość i wysokość są wielokrotnościami 16 – Aximili

+1

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

4

Biblioteka exiv2net (a .NET na szczycie exiv2) może być tym, czego szukasz.

0

Napisałem mały test, w którym kompresuję jeden plik wiele razy, aby zobaczyć pogorszenie jakości i widać go w trzeciej czwartej kompresji, co jest bardzo złe.

Ale na szczęście, jeśli zawsze używasz tego samego QualityLevel z JpegBitmapEncoder, nie ma degradacji.

W tym przykładzie przepisuję słowa kluczowe 100x w metadane, a jakość wydaje się nie zmieniać.

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