2009-11-18 15 views
15

Bir JPEG görüntünün özellik penceresinde, 'Özet' adlı bir sekme vardır. Bu sekmede, 'Yorumlar' denilen bir alan var. Bu alana belirli bir string ekleyeceğim C# kodu yazmak istiyorum, örn. "Bu bir fotoğraftır".C# kullanarak bir JPEG dosyasına 'Yorumlar' ekleme #

Dışarıdaki bazı ruhlar bunun nasıl yapılacağını biliyor mu?

Çok teşekkürler.

cevap

11

aşağıdaki kod benim sorunu çözer ve belirli bir JPEG görüntüsüne yorum ekler:

public void addImageComment(string imageFlePath, string comments) 
    { 
     string jpegDirectory = Path.GetDirectoryName(imageFlePath); 
     string jpegFileName = Path.GetFileNameWithoutExtension(imageFlePath); 

     BitmapDecoder decoder = null; 
     BitmapFrame bitmapFrame = null; 
     BitmapMetadata metadata = null; 
     FileInfo originalImage = new FileInfo(imageFlePath); 

     if (File.Exists(imageFlePath)) 
     { 
      // load the jpg file with a JpegBitmapDecoder  
      using (Stream jpegStreamIn = File.Open(imageFlePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) 
      { 
       decoder = new JpegBitmapDecoder(jpegStreamIn, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad); 
      } 

      bitmapFrame = decoder.Frames[0]; 
      metadata = (BitmapMetadata)bitmapFrame.Metadata; 

      if (bitmapFrame != null) 
      { 
       BitmapMetadata metaData = (BitmapMetadata)bitmapFrame.Metadata.Clone(); 

       if (metaData != null) 
       { 
        // modify the metadata 
        metaData.SetQuery("/app1/ifd/exif:{uint=40092}", comments); 

        // get an encoder to create a new jpg file with the new metadata.  
        JpegBitmapEncoder encoder = new JpegBitmapEncoder(); 
        encoder.Frames.Add(BitmapFrame.Create(bitmapFrame, bitmapFrame.Thumbnail, metaData, bitmapFrame.ColorContexts)); 
        //string jpegNewFileName = Path.Combine(jpegDirectory, "JpegTemp.jpg"); 

        // Delete the original 
        originalImage.Delete(); 

        // Save the new image 
        using (Stream jpegStreamOut = File.Open(imageFlePath, FileMode.CreateNew, FileAccess.ReadWrite)) 
        { 
         encoder.Save(jpegStreamOut); 
        } 
       } 
      } 
     } 
    } 

Bu aslında Konamiman nazikçe verilen bağlantısı altında bulunan bir kod hafifçe değiştirilmiş versiyonu.

Eğer PresentationCore ve WindowsBase için .NET başvuruları eklemek gerekir bu işi yapmak için lütfen unutmayın. Visual Studio 2008 kullanıyorum, bu aşağıdaki yoluyla elde edilebilir: aşağıya açılan listede Solution Explorer

  • daki proje üzerinde

    1. Sağ tıklama, ekleme seçeneğini 'başvurusu ...'

      , '.net' sekmesi yukarıdaki ve her belirtilen iki referanslar

    2. Scroll seçmek açılan yeni kutusundan

    3. ok tıklayın

    Bu konudaki yardımlarınız için hem danbystrom hem de Konamiman'a çok teşekkürler. Hızlı yanıtı gerçekten takdir ediyorum.

  • +0

    Yararlı bulursanız, oy vermeli ve/veya cevaplarını kabul etmelisiniz. Şerefe! – RickL

    +0

    Oops, Yukarıdaki çözümümde küçük bir hata yaptım. Sana PresentationCore referansı değil System.Core Ps eklemem gerekiyor söyledi gerekirdi. Baştaki Rick için teşekkürler! Bunu hemen yapacağım. –

    +3

    jpeg, kayıplı bir formattır Bu yöntemi kullanarak meta verileri ekleyerek kalitesini kaybetmeye beklenebilir, yoksa sadece resmi etkilemeden meta verileri değiştirebilir olmadığını göz önüne alındığında? –

    0

    kolay kısmı:

    bu özellik öğesi ekleyin: Image'ın PropertItems koleksiyonu için

    var data = System.Text.Encoding.UTF8.GetBytes("Some comments"); 
    PropertyItem pi; 
    *** create an empty PropertyItem here 
    pi.Type = 2; 
    pi.Id = 37510; 
    pi.Len = data.Length; 
    pi.Value = data; 
    

    .

    Biraz daha hantal bölüm: Ortak bir kurucusu olmadığı için nasıl yeni bir PropertyItem oluşturursunuz?

    Yaygın "hile", etrafında bir PropertyItem çalabildiğiniz boş bir görüntüye sahip olmaktır. iç çekiş

    +1

    ve çalınan PropertyItem'i gerçek görüntüyle nasıl ilişkilendiriyorsunuz? Okuma-yazma özelliği/değişkeni midir? –

    +0

    realImage.PropertyItems.Add (emptyImage.PropertyItems [0]); –

    +1

    Sinir bozucu. msdn From: "Bir PropertyItem tek başına bir nesne olarak kullanılmak üzere tasarlanmamıştır Bir PropertyItem nesnesi Image türetilen sınıflar tarafından kullanılmak üzere tasarlanmıştır Bir PropertyItem nesnesi almak ve mevcut görüntünün meta verileri değiştirme için kullanılır.. Bu nedenle, meta veri oluşturmak için değil, dolayısıyla PropertyItem sınıfının tanımlanmış bir ortak kurucusu yoktur ve bir PropertyItem nesnesinin bir örneğini oluşturamazsınız. " – JYelton

    1

    Önceki ipuçlarımız sayesinde aşağıdakileri bir araya getirebildim. Test ettim ve işe yaradı. En büyük engel oluşturan bloklardan biri, atamak istediğiniz alan için gereken Kimliği belirliyordu.

    public static Image SetImageComment(Image image, string comment) { 
        using (var memStream = new MemoryStream()) { 
        image.Save(memStream, ImageFormat.Jpeg); 
        memStream.Position = 0; 
        var decoder = new JpegBitmapDecoder(memStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad); 
        BitmapMetadata metadata; 
        if (decoder.Metadata == null) { 
         metadata = new BitmapMetadata("jpg"); 
        } else { 
         metadata = decoder.Metadata; 
        } 
    
        metadata.Comment = comment; 
    
        var bitmapFrame = decoder.Frames[0]; 
        BitmapEncoder encoder = new JpegBitmapEncoder(); 
        encoder.Frames.Add(BitmapFrame.Create(bitmapFrame, bitmapFrame.Thumbnail, metadata, bitmapFrame.ColorContexts)); 
    
        var imageStream = new MemoryStream(); 
        encoder.Save(imageStream); 
        imageStream.Position = 0; 
        image.Dispose(); 
        image = null; 
        return Image.FromStream(imageStream); 
        } 
    } 
    

    bu yöntemle döndürülen görüntü imha etmeyi unutmayın: Burada cevaplara

    string fileName = "c:/SomeImage.jpg"; 
    // Retrieve the Image 
    System.Drawing.Image originalImage = System.Drawing.Image.FromFile(fileName); 
    
    // Get the list of existing PropertyItems. i.e. the metadata 
    PropertyItem[] properties = originalImage.PropertyItems; 
    
    // Create a bitmap image to assign attributes and do whatever else.. 
    Bitmap bmpImage = new Bitmap((Bitmap)originalImage); 
    
    // Don't need this anymore 
    originalImage.Dispose(); 
    
    // Get/setup a PropertyItem 
    PropertyItem item = properties[0]; // We have to copy an existing one since no constructor exists 
    
    // This will assign "Joe Doe" to the "Authors" metadata field 
    string sTmp = "Joe DoeX"; // The X will be replaced with a null. String must be null terminated. 
    var itemData = System.Text.Encoding.UTF8.GetBytes(sTmp); 
    itemData[itemData.Length - 1] = 0;// Strings must be null terminated or they will run together 
    item.Type = 2; //String (ASCII) 
    item.Id = 315; // Author(s), 315 is mapped to the "Authors" field 
    item.Len = itemData.Length; // Number of items in the byte array 
    item.Value = itemData; // The byte array 
    bmpImage.SetPropertyItem(item); // Assign/add to the bitmap 
    
    // This will assign "MyApplication" to the "Program Name" field 
    sTmp = "MyApplicationX"; 
    itemData = System.Text.Encoding.UTF8.GetBytes(sTmp); 
    itemData[itemData.Length - 1] = 0; // Strings must be null terminated or they will run together 
    item.Type = 2; //String (ASCII) 
    item.Id = 305; // Program Name, 305 is mapped to the "Program Name" field 
    item.Len = itemData.Length; 
    item.Value = itemData; 
    bmpImage.SetPropertyItem(item); 
    
    // Save the image 
    bmpImage.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg); 
    
    //Clean up 
    bmpImage.Dispose(); 
    
    1

    sayesinde, yalnızca bir yorum kullanarak hafızayı ayarlamak için bir çözüm kodlu ettik.(Bir dosyaya resmi kaydetmiş Örneğin) diğer cevaplar dayanarak

    14

    Çeşitli meta manipülasyonlar sağlar aşağıdaki sınıfını yazdı. Bunu şu şekilde kullanırsınız:

    var jpeg = new JpegMetadataAdapter(pathToJpeg); 
    jpeg.Metadata.Comment = "Some comments"; 
    jpeg.Metadata.Title = "A title"; 
    jpeg.Save();    // Saves the jpeg in-place 
    jpeg.SaveAs(someNewPath); // Saves with a new path 
    

    Çözümüm ve diğerleri arasındaki farklar büyük değil. Esas olarak, daha temiz olmak için bunu yeniden düzenledim. Ayrıca SetQuery yönteminden ziyade BitmapMetadata'un daha yüksek düzey özelliklerini kullanıyorum.

    İşte the MIT licence altında lisanslanmıştır tam koddur. Sen PresentationCore, WindowsBase ve System.Xaml başvuruları eklemeniz gerekir.

    public class JpegMetadataAdapter 
    { 
        private readonly string path; 
        private BitmapFrame frame; 
        public readonly BitmapMetadata Metadata; 
    
        public JpegMetadataAdapter(string path) 
        { 
         this.path = path;    
         frame = getBitmapFrame(path); 
         Metadata = (BitmapMetadata)frame.Metadata.Clone(); 
        } 
    
        public void Save() 
        { 
         SaveAs(path); 
        } 
    
        public void SaveAs(string path) 
        { 
         JpegBitmapEncoder encoder = new JpegBitmapEncoder(); 
         encoder.Frames.Add(BitmapFrame.Create(frame, frame.Thumbnail, Metadata, frame.ColorContexts)); 
         using (Stream stream = File.Open(path, FileMode.Create, FileAccess.ReadWrite)) 
         { 
          encoder.Save(stream); 
         } 
        } 
    
        private BitmapFrame getBitmapFrame(string path) 
        { 
         BitmapDecoder decoder = null; 
         using (Stream stream = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) 
         { 
          decoder = new JpegBitmapDecoder(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad); 
         } 
         return decoder.Frames[0]; 
        } 
    } 
    
    +1

    Bu fantastik ve tam olarak neye ihtiyacım vardı temiz bir şekilde. Çok teşekkür ederim! –

    +3

    System.Xaml başvuru aynı zamanda System.Windows.Media.Imaging kullanarak gereken – Ben

    +1

    olan –

    İlgili konular