2015-03-13 6 views
6

दोनों को मेटाडेटा लिखें, मुझे अपलोड की गई छवियों में मेटाडेटा टैग (विवरण) जोड़ने की आवश्यकता है।दोनों jpg और png

मुझे यह जवाब मिला है: https://stackoverflow.com/a/1764913/6776 जो जेपीजी फाइलों के लिए बहुत अच्छा काम करता है, लेकिन पीएनजी के लिए नहीं।

private string Tag = "test meta data"; 

private static Stream TagImage(Stream input, string type) 
{ 
    bool isJpg = type.EndsWith("jpg", StringComparison.InvariantCultureIgnoreCase) || type.EndsWith("jpeg", StringComparison.InvariantCultureIgnoreCase); 
    bool isPng = type.EndsWith("png", StringComparison.InvariantCultureIgnoreCase); 

    BitmapDecoder decoder = null; 

    if (isJpg) 
    { 
     decoder = new JpegBitmapDecoder(input, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad); 
    } 
    else if (isPng) 
    { 
     decoder = new PngBitmapDecoder(input, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad); 
    } 
    else 
    { 
     return input; 
    } 

    // modify the metadata 
    BitmapFrame bitmapFrame = decoder.Frames[0]; 
    BitmapMetadata metaData = (BitmapMetadata)bitmapFrame.Metadata.Clone(); 
    metaData.Subject = Tag; 
    metaData.Comment = Tag; 
    metaData.Title = Tag; 

    // get an encoder to create a new jpg file with the new metadata.  
    BitmapEncoder encoder = null; 
    if (isJpg) 
    { 
     encoder = new JpegBitmapEncoder(); 
    } 
    else if (isPng) 
    { 
     encoder = new PngBitmapEncoder(); 
    } 

    encoder.Frames.Add(BitmapFrame.Create(bitmapFrame, bitmapFrame.Thumbnail, metaData, bitmapFrame.ColorContexts)); 

    // Save the new image 
    Stream output = new MemoryStream(); 
    encoder.Save(output); 

    output.Seek(0, SeekOrigin.Begin); 

    return output; 
} 

यह जब मैं एक jpg अपलोड अच्छा काम करता है, लेकिन एक png साथ, metaData.Subject = Tag लाइन में, यह एक System.NotSupportedException फेंकता है (इस कोडेक निर्दिष्ट संपत्ति का समर्थन नहीं करता)।

अद्यतन

ऐसा लगता है मैं एक अलग तरीके छवि प्रारूप के आधार पर उपयोग करने के लिए:

if (isJpg) 
{ 
    metaData.SetQuery("/app1/ifd/exif:{uint=270}", Tag); 
} 
else 
{ 
    metaData.SetQuery("/tEXt/{str=Description}", Tag); 
} 

पर the available formats' queries आधार पर पहले दोनों प्रारूपों के लिए काम करना चाहिए। दूसरा वास्तव में काम नहीं करता है (यह छवि में मेटाडेटा बनाता है लेकिन इसका मूल्य नहीं बचाता है)।

यदि मैं encoder.Save लाइन पर पीएनजी के लिए पहली विधि (/app1/ifd/exif) का उपयोग करने का प्रयास करता हूं, तो मुझे कोई अपवाद नहीं है, "कोई इमेजिंग घटक उपयुक्त नहीं है"।

+0

अपने प्रश्न के लिए प्रासंगिक नहीं है, लेकिन मुझे लगता है कि आपके isJpg = कथन में कोई गलती है। मुझे लगता है कि आप ".jpg" या ".jpeg" के लिए परीक्षण करना चाहते हैं, लेकिन आप दो बार ".jpg" के लिए परीक्षण करते हैं। – RenniePet

+0

हां तब से कोड में तय किया गया है, लेकिन सवाल में नहीं। धन्यवाद! – thomasb

उत्तर

-1

पीएनजी प्रारूप का समर्थन नहीं करता मेटाडाटा :(

लेकिन XMP करता है, जो मदद की जब JPEGs के बीच परिवर्तित करने, EXIF-मेटाडाटा के साथ, और PNG हो सकता है।

+0

विकिपीडिया पर [पोर्टेबल नेटवर्क ग्राफिक्स] (https://en.wikipedia.org/wiki/Portable_Network_Graphics#Ancillary_chunks) विषय के अनुसार, पीएनजी मेटाडेटा स्टोर कर सकता है। तो मुझे यकीन नहीं है कि आप ऐसा क्यों नहीं सोच सकते हैं। –

+1

मुझे संदेह है कि ऐसा इसलिए है क्योंकि 'PngBitmapEncoder' का मेटाडाटा सदस्य अनसेट नहीं है। विशेष रूप से 'एन्कोडर। मेटाडाटा = नया बिटमैप मेटाडेटा (" पीएनजी "); 'अपवाद उत्पन्न करता है" नामित बिटमैप एन्कोडर वैश्विक मेटाडेटा का समर्थन नहीं करता है। " – Eponymous

2

मैं इसे pngcs लाइब्रेरी का उपयोग कर हल (आप "pngcs.dll" करने के लिए डाउनलोड dll नाम बदलने की आवश्यकता)

यहाँ है मैं इसे कैसे लागू किया:

using Hjg.Pngcs; // https://code.google.com/p/pngcs/ 
using Hjg.Pngcs.Chunks; 
using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.IO; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace MarkerGenerator.Utils 
{ 
    class PngUtils 
    { 

     public string getMetadata(string file, string key) 
     { 

      PngReader pngr = FileHelper.CreatePngReader(file); 
      //pngr.MaxTotalBytesRead = 1024 * 1024 * 1024L * 3; // 3Gb! 
      //pngr.ReadSkippingAllRows(); 
      string data = pngr.GetMetadata().GetTxtForKey(key); 
      pngr.End(); 
      return data; ; 
     } 


     public static void addMetadata(String origFilename, Dictionary<string, string> data) 
     { 
      String destFilename = "tmp.png"; 
      PngReader pngr = FileHelper.CreatePngReader(origFilename); // or you can use the constructor 
      PngWriter pngw = FileHelper.CreatePngWriter(destFilename, pngr.ImgInfo, true); // idem 
      //Console.WriteLine(pngr.ToString()); // just information 
      int chunkBehav = ChunkCopyBehaviour.COPY_ALL_SAFE; // tell to copy all 'safe' chunks 
      pngw.CopyChunksFirst(pngr, chunkBehav);   // copy some metadata from reader 
      foreach (string key in data.Keys) 
      { 
       PngChunk chunk = pngw.GetMetadata().SetText(key, data[key]); 
       chunk.Priority = true; 
      } 

      int channels = pngr.ImgInfo.Channels; 
      if (channels < 3) 
       throw new Exception("This example works only with RGB/RGBA images"); 
      for (int row = 0; row < pngr.ImgInfo.Rows; row++) 
      { 
       ImageLine l1 = pngr.ReadRowInt(row); // format: RGBRGB... or RGBARGBA... 
       pngw.WriteRow(l1, row); 
      } 
      pngw.CopyChunksLast(pngr, chunkBehav); // metadata after the image pixels? can happen 
      pngw.End(); // dont forget this 
      pngr.End(); 
      File.Delete(origFilename); 
      File.Move(destFilename, origFilename); 

     } 

     public static void addMetadata(String origFilename,string key,string value) 
     { 
      Dictionary<string, string> data = new Dictionary<string, string>(); 
      data.Add(key, value); 
      addMetadata(origFilename, data); 
     } 


    } 
} 
संबंधित मुद्दे