2010-08-02 5 views
7

सी # में कैसे करें?बिटमैप में फ़ाइल लोड हो रहा है लेकिन मूल फ़ाइल को

अगर मैं Bitmap.FromFile() का उपयोग, मूल फ़ाइल बंद है।

अगर मैं Bitmap.FromStream() का उपयोग, मूल फ़ाइल अवरोधित किया गया है नहीं है, लेकिन प्रलेखन कहते हैं, "आप धारा छवि के जीवन भर के लिए खुला रखना चाहिए।" इसका शायद मतलब है कि फ़ाइल अभी भी छवि ऑब्जेक्ट से जुड़ी हुई है, (उदाहरण के लिए, शायद अगर फ़ाइल बदलती है तो ऑब्जेक्ट या इसके विपरीत)।

मुझे क्या करना सिर्फ बिटमैप पढ़ रहे हैं और एक वस्तु पर सहेजें है चाहते हैं और फ़ाइल और छवि वस्तु के बीच कोई लिंक है कि वहाँ के बाद

उत्तर

25

इस व्यवहार पर कुछ पृष्ठभूमि जानकारी: बिटमैप बिटमैप में पिक्सल पहुँचने के लिए एक स्मृति-मैप की गई फ़ाइल का उपयोग करता है। विंडोज एपीआई में यह एक बहुत ही बुनियादी सुविधा है, यह डेटा को फाइल करने के लिए स्मृति के बहुत कुशल मैपिंग की अनुमति देता है। डेटा केवल फ़ाइल से पढ़ा जाता है जब प्रोग्राम मेमोरी पढ़ता है, वर्चुअल मेमोरी पेज विंडोज पेजिंग फ़ाइल में कोई स्थान नहीं लेते हैं।

सटीक उसी तंत्र का उपयोग .NET असेंबली को लोड करने के लिए किया जाता है। यह स्मृति मैपिंग है जो फ़ाइल पर लॉक रखती है। जो मूल रूप से एक .NET प्रोग्राम में उपयोग किए जाने पर असेंबली लॉक हो जाती है। Image.Dispose() विधि लॉक जारी करती है। लॉक से लड़ने से अक्सर संकेत मिलता है कि आप अपने बिटमैप्स का निपटान करना भूल रहे हैं। बहुत महत्वपूर्ण बात यह है कि निपटान करना भूलना() अक्सर बिटमैप को छोड़कर .NET कक्षाओं के लिए समस्याएं उत्पन्न नहीं करता है क्योंकि इसे बहुत अधिक (अप्रबंधित) स्मृति की आवश्यकता हो सकती है।

हां, FromStream() कक्षा को इस अनुकूलन से रोकता है। लागत महत्वपूर्ण है, बिटमैप लोड होने पर आपको स्मृति को दोगुनी करने की आवश्यकता होगी। बिटमैप बड़ा होने पर यह एक समस्या होगी, जब आप थोड़ी देर के लिए चल रहे हैं (पता स्थान को खंडित कर रहे हैं) और यह 64-बिट ऑपरेटिंग सिस्टम पर नहीं चल रहा है, तो आप ओओएम स्कर्ट कर रहे हैं। निश्चित रूप से ऐसा करने से बचें यदि बिटमैप की चौड़ाई x ऊंचाई x 4> = 45 एमबी, दे या ले लो।

कुछ कोड, आप CopyStream घेरा के माध्यम से कूद करने की जरूरत नहीं है:

public static Image LoadImageNoLock(string path) { 
     var ms = new MemoryStream(File.ReadAllBytes(path)); // Don't use using!! 
     return Image.FromStream(ms); 
    } 

ध्यान दें कि आप MemoryStream निपटान के लिए नहीं करना चाहते हैं, तो आप एक कठिन "सामान्य त्रुटि" निदान करने के लिए मिल जाएगा जब आप करते हैं तो बिटमैप का उपयोग किया जाता है। छवि वर्ग आलसी-स्ट्रीम पढ़ने के कारण।

+0

आपको बिटमैप प्राप्त करने के लिए भी इसकी आवश्यकता है। बिटमैप बिटमैप = नया बिटमैप (लोड इमेज नॉकॉक (पथ)); – Harris

+2

मेमोरीस्ट्रीम डिस्पोजेबल है, जो इस समाधान में इसे निपटाने का ख्याल रखेगा? – kwesolowski

4

एक FileStream से कॉपी करके स्मृति में फ़ाइल पढ़ें MemoryStream में। (कैसे है कि सुरक्षित रूप से। असल में पाश करने के लिए है, जबकि पढ़ने स्मृति धारा करने के लिए प्रत्येक हिस्सा लिखने के उदाहरण के बहुत खोजने के लिए स्टैक ओवरफ़्लो में CopyStream के लिए खोज, वहाँ कोई और अधिक डेटा है जब तक पढ़ने के लिए।) इसके बाद रिवाइंड MemoryStream (Position = 0 सेट) और फिर Bitmap.FromStream पर पास करें।

4

आदेश फ़ाइल ताला लगा के बिना एक छवि बनाने के लिए, आप छवि के FileStream की एक प्रति बनाना होगा। स्ट्रीम को कॉपी करने के लिए इस पृष्ठ को Best way to copy between two Stream instances - C# देखें।

बाद में बस की नकल की धारा से अपनी छवि बना सकते हैं और आप जाने के लिए तैयार कर रहे हैं।

+0

+1 हमारे लिए खोज करने के लिए जो जॉन ने सुझाव दिया कि हमें करना चाहिए ... आपको इसके लिए एक बहुत अच्छी पोस्ट मिली है। – awe

0

मैंने मेमोरीस्ट्रीम पर प्रतिलिपि बनाने की इस तकनीक का उपयोग किया है और फिर मेमोरीस्ट्रीम को बिटमैप में खिलाया है। बहुत बार बार से स्ट्रीम करें। हालांकि, इस तकनीक के साथ एक गोचा भी है।

यदि आप बिटमैप में से किसी एक का उपयोग करने की योजना बना रहे हैं। बाद में लोड की गई छवि पर विधियों को सहेजें, तो आपको स्ट्रीम को जीवित रखना होगा (यानी।, छवि लोड होने के बाद इसे निपटान नहीं करें), अन्यथा आपको डरावना "एक सामान्य जीडीआई + त्रुटि हुई" अपवाद मिलेगा!

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