2010-05-10 19 views
12

मैं अपनी मूल एन्कोडिंग के साथ एक छवि कैसे सहेज सकता हूं?किसी छवि को अपने मूल प्रारूप में कैसे सहेजना है?

ऐसा लगता है कि एक छवि को बचाने के लिए एक ही रास्ता एक BitmapEncoder का उपयोग करना है, लेकिन मैं कैसे मैं छवि से सही स्वरूप प्राप्त कर सकते हैं पता नहीं है।

उदाहरण:

Clipboard.GetImage() एक InteropBitmap जो मूल स्वरूप के बारे में कोई जानकारी नहीं लगता है देता है।

मैं भी एक एक्सटेंशन विधि का उपयोग करने की कोशिश की:

public static void Save(this BitmapImage image, System.IO.Stream stream) 
{ 
    var decoder = BitmapDecoder.Create(image.StreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); 
    var encoder = BitmapEncoder.Create(decoder.CodecInfo.ContainerFormat); 
    foreach (var frame in decoder.Frames) 
    { 
     encoder.Frames.Add(BitmapFrame.Create(frame)); 
    } 
    encoder.Save(stream); 
} 

लेकिन समस्या यह है कि

  1. ImageSource हमेशा एक BitmapImage (Clipboard.GetImage()) उदाहरण के लिए और
  2. नहीं है image.StreamSource कुछ मामलों में अशक्त हो सकता है
(जब छवि एक रिश्तेदार उरी के माध्यम से भरी हुई है प्रतीत हो रहा है)

कोई सुझाव?

+0

आप संदर्भ में जो आप इस अनुभव कर रहे हैं के बारे में समझाएं कर सकते हैं? ऐसा लगता है कि यदि आप एक छवि को सहेज रहे हैं, तो बस इसे अपने इच्छित स्वरूप में सहेजें। बिटमैप छवि एक प्रारूप प्रतीत होता है, और मूल छवि को पहले से ही परिवर्तित कर दिया गया है। –

उत्तर

19

बुनियादी सवाल यहाँ है "मैं एक मनमाना ImageSource कैसे लेने के लिए और जानने के क्या प्रारूप यह मूल रूप में एन्कोड किया गया था करते हैं?"

उत्तर यह है कि आप हमेशा ऐसा नहीं कर सकते हैं, लेकिन अधिकांश व्यावहारिक उद्देश्यों के लिए एक कामकाज उपलब्ध है। जैसा कि उपर्युक्त आपका कोड दिखाता है, एक बार जब आप सीखा कि एक बार बाकी का उपयोग करने के लिए प्रारूप आसान है।

कारण आप मूल प्रारूप को हमेशा नहीं ढूंढ सकते हैं कि यह संभव है (कुछ बहुत मुश्किल कोड के साथ!) बिटमैपसोर्स को एक नया इमेजसोर्स बनाने के लिए उपclass करने के लिए जो आपके डेटा को कहीं से भी प्राप्त करता है। उदाहरण के लिए, मैं एक छद्म यादृच्छिक बिटमैप स्रोत लागू कर सकता हूं जो यादृच्छिक पिक्सल देता है। इस मामले में "मूल प्रारूप" शायद यादृच्छिक संख्या जनरेटर के लिए उपयोग किया जाने वाला बीज है।

आप ImageSource कक्षाओं में बनाया में से एक के साथ काम कर रहे हैं, तो जिस तरह से मूल एन्कोडिंग पता लगाने के लिए निर्भर करता है जिस पर सटीक वर्ग का उपयोग कर रहे:

  1. BitmapImage के लिए, आप StreamSource या UriSource उपयोग कर सकते हैं , जो भी सेट है। इनमें से कोई भी बिटमैप डीकोडर को पास किया जा सकता है। ओवरलोड लोड करें। आपका उदाहरण कोड दिखाता है कि स्ट्रीमसोर्स के लिए यह कैसे करें। यह यूरीसोर्स के लिए बिल्कुल वही है, सिवाय इसके कि आपको Uri(BaseUri, UriSource) की आवश्यकता है और इसे बिटमैप डिकोडर को पास करें। ओवरलोड करें जो उरी लेता है।

  2. ColorConvertedBitmap, CroppedBitmap, FormatConvertedBitmap, और TransformedBitmap के लिए वहाँ एक सार्वजनिक "स्रोत" संपत्ति है जिसे आप रिकर्सिवली इस कलन विधि का उपयोग अपने एन्कोडिंग जाँच, अंतर्निहित स्रोत प्राप्त करने के लिए उपयोग कर सकते हैं।

  3. कैशबिटमैप के लिए, आप केवल एक आंतरिक क्षेत्र के माध्यम से स्रोत बिटमैप प्राप्त कर सकते हैं। यदि आपके पास पर्याप्त विशेषाधिकार हैं, तो आप प्रतिबिंब का उपयोग कर सकते हैं, अन्यथा आप भाग्य से बाहर हैं।

  4. रेंडरटाइटल बिटमैप, लिखने योग्य बिटमैप, डी 3DImage, और DrawingImage के लिए कोई मूल एन्कोडिंग नहीं है क्योंकि छवि को वेक्टर प्रारूप या एल्गोरिदम से "फ्लाई पर" बनाया जा रहा है।

  5. बिटमैप फ्रेम के लिए, डिकोडर प्राप्त करने के लिए डिकोडर संपत्ति का उपयोग करें, फिर CodecInfo.ContainerFormat का उपयोग करें।

  6. InteropBitmap या UnmanagedBitmapWrapper के लिए यह बहुत ही जटिल है। मूल रूप से आप आंतरिक WicSourceHandle संपत्ति को पढ़ने के लिए प्रतिबिंब उपयोग करने की आवश्यकता है, तो एक IntPtr जो वास्तव में एक अप्रबंधित IUnkown है पाने के लिए DangerousGetHandle() कहते हैं। IWICBitmapDecoder के लिए अनधिकृत कोड का उपयोग, QueryInterface। यदि सफल हो तो आप प्रारूप GUID प्राप्त करने के लिए IWICBitmapDecoder.GetContainerFormat को कॉल कर सकते हैं (यह अभी भी अप्रबंधित कोड है)। यदि नहीं, तो मूल स्रोत के बारे में सारी जानकारी खो गई है।

जैसा कि आप देख सकते हैं, वहाँ काफी कुछ स्थितियों में, जहां आप स्रोत (जैसे एक पूरी तरह से डीकोड बिटमैप के लिए एक InteropBitmap) या जहाँ स्रोत हो रही विशेष तकनीक और विशेषाधिकार (के लिए अप्रबंधित कोड की आवश्यकता है नहीं प्राप्त कर सकते हैं InteropBitmap, या कैशबिटमैप के लिए आंतरिक फ़ील्ड पर प्रतिबिंब)।

क्योंकि यह मूल स्वरूप पाने के लिए अक्सर असंभव के लिए मुश्किल है, यह एक अच्छा विचार के रूप में यह अपने कोड में पारित हो जाता इस जानकारी की रक्षा करने के रास्तों की तलाश में है। आप छवि का स्रोत को नियंत्रित है, यह एक ImageSourceAndFormat वर्ग बनाने के रूप में सरल हो सकता है:

public class BitmapSourceAndFormat 
{ 
    public ImageSource Source { get; set; } 
    public Guid OriginalFormat { get; set; } 
} 

यह विशेष रूप से उपयोगी है जब आप क्लिपबोर्ड पर छवि दे रहे हैं। सामान्य रूप से DataObject में छवि जोड़ने के अलावा, आप एक बिटमैपसोर्स एंडफॉर्मेट ऑब्जेक्ट भी जोड़ सकते हैं। यदि आप ऐसा करते हैं, तो पेस्ट ऑपरेशन को इन दोनों प्रारूपों वाला डेटाऑब्जेक्ट प्राप्त होगा। आपके कोड को केवल पहले बिटमैपसोर्स एंडफॉर्मेट ऑब्जेक्ट की जांच करने की आवश्यकता है। यदि पाया जाता है तो यह मूल प्रारूप प्राप्त करने के लिए बस इसे एक्सेस कर सकता है। यदि नहीं, तो इसे ऊपर वर्णित साधनों का सहारा लेना चाहिए।

एक आखिरी नोट: क्लिपबोर्ड पेस्ट के लिए, आप उपलब्ध डेटा प्रारूप तारों की जांच कर सकते हैं। कुछ उपयोगी हैं: बिटमैप, डिब, टिफ़, गिफ, जेपीईजी, और फ़ाइल नाम। "टिफ", "गिफ" और "जेपीईजी" के लिए आप आवश्यक प्रारूप को हार्ड-कोड कर सकते हैं। "फ़ाइल नाम" के लिए आप बिटमैपडेकोडर को पास करने के लिए स्ट्रीम प्राप्त करने के लिए फ़ाइल खोल सकते हैं। किसी और चीज़ के बिना "डिब" या "बिटमैप" के लिए, आप जानते हैं कि मूल प्रारूप खो गया है।

+0

वाह - यह एक उत्कृष्ट जवाब है। आपको बहुत - बहुत धन्यवाद! प्रतिलिपि/पेस्ट के बारे में महान सुझाव! –

+0

+ केवल मुझे बता नहीं है कि मैं क्या जानना चाहता था, लेकिन यह भी मुझे बता क्या मेरी बुनियादी सवाल है के लिए धन्यवाद! मुझे इसे बेहतर वर्णन करना चाहिए था। –

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