2009-06-24 36 views
10

Tôi đã tìm thấy nhiều mã và thư viện khác nhau để chỉnh sửa Exif.Thư viện .NET C# dành cho việc ghi đè không cần thiết Exif?

Nhưng họ chỉ lossless khi chiều rộng hình ảnh và chiều cao là bội số của 16.

Tôi đang tìm kiếm một thư viện (hoặc thậm chí là một cách để làm điều đó bản thân mình) để chỉnh sửa chỉ là phần Exif trong một tập tin JPEG (hoặc thêm dữ liệu Exif nếu nó chưa tồn tại), để lại các dữ liệu khác chưa được sửa đổi. Không phải là có thể?

Cho đến nay tôi chỉ có thể tìm phần Exif (bắt đầu bằng 0xFFE1) nhưng tôi không hiểu cách đọc dữ liệu.

+0

[Điều này nghe có vẻ hứa hẹn] (http://www.nullskull.com/articles/20030706.asp) – TaW

Trả lời

8

Dưới đây là các thông số kỹ thuật cho định dạng trao đổi Exif, nếu bạn có kế hoạch mã hóa thư viện của riêng bạn để chỉnh sửa thẻ.

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

Dưới đây là một thư viện viết bằng Perl đáp ứng nhu cầu của bạn mà bạn có thể học hỏi từ:

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

Dưới đây là một thư viện .NET đàng hoàng để đánh giá Exif từ The Code Project:

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

8

Bạn có thể làm t mà không cần bất kỳ lib bên ngoài của mình:

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

Danh sách tất cả các id PropertyItem thể (bao gồm cả exif), bạn có thể tìm thấy here.

Cập nhật: Đồng ý, phương pháp này sẽ mã hóa lại hình ảnh khi lưu. Nhưng tôi đã nhớ một phương pháp khác, trong WinXP SP2 và sau đó có các thành phần hình ảnh mới được thêm vào - WIC, và bạn có thể sử dụng chúng để ghi không mất chỉ số - How-to: Re-encode a JPEG Image with Metadata.

+2

Thao tác này sẽ nén lại hình ảnh. Có một giải pháp không giải nén, bằng cách xoay hình ảnh hai lần, nhưng chỉ hoạt động nếu chiều rộng và chiều cao là bội số của 16 – Aximili

+1

liên kết được cập nhật: http://msdn.microsoft.com/en-us/library/ee719794(v=VS .85) .aspx – BlackICE

4

exiv2net thư viện (trình bao bọc .NET trên đầu trang của exiv2) có thể là những gì bạn đang tìm kiếm.

0

Tôi đã viết một bài kiểm tra nhỏ, nơi tôi nén một tệp nhiều lần để xem sự xuống cấp chất lượng và bạn có thể thấy nó ở lần nén thứ ba, rất tệ.

Nhưng may mắn thay, nếu bạn luôn sử dụng cùng một QualityLevel với JpegBitmapEncoder thì không có sự xuống cấp.

Trong ví dụ này tôi viết lại từ khóa 100x trong siêu dữ liệu và chất lượng dường như không thay đổi.

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