2009-02-20 13 views
11

मैं एक हल्के वजन वाली छवि देखने के आवेदन लिखने की कोशिश कर रहा हूं। हालांकि, .NET के साथ सिस्टम मेमोरी सीमाएं हैं।मैं .NET में बड़े बिटकैप्स का उपयोग कैसे करूं?

जब बड़े बिटमैप (9000 x 9000 पिक्सल या बड़ा, 24-बिट) लोड करने की कोशिश, मैं एक System.OutOfMemoryException मिलता है। यह विंडोज 2000 पीसी पर 2 जीबी रैम है (जिसमें से 1.3 जीबी का उपयोग किया जाता है)। फ़ाइलों को लोड करने का प्रयास करने में भी बहुत समय लगता है। इस कोड को करता है

Image image = new Bitmap(filename); 
using (Graphics gfx = this.CreateGraphics()) 
{ 
    gfx.DrawImage(image, new Point(0, 0)); 
} 

:

निम्नलिखित कोड इस त्रुटि उत्पन्न

Bitmap bitmap = new Bitmap(filename); 
IntPtr handle = bitmap.GetHbitmap(); 

उत्तरार्द्ध कोड:

Stream stream = (Stream)File.OpenRead(filename); 
Image image = Image.FromStream(stream, false, false); 
using (Graphics gfx = this.CreateGraphics()) 
{ 
    gfx.DrawImage(image, new Rectangle(0, 0, 100, 100), 4000, 4000, 100, 100, GraphicsUnit.Pixel); 
} 

इसके अलावा, यह सिर्फ ऐसा करने के लिए पर्याप्त है जीडीआई के साथ उपयोग के लिए इरादा था। इस पर शोध करते समय, मुझे पता चला कि यह वास्तव में एक स्मृति समस्या है जहां .NET स्मृति की एक भीड़ ब्लॉक में जितनी आवश्यक हो उतनी बार आवंटित करने की कोशिश करता है।

http://bytes.com/groups/net-c/279493-drawing-large-bitmaps

मैं जानता हूँ कि अन्य अनुप्रयोगों से (इंटरनेट एक्सप्लोरर, एमएस पेंट आदि) है कि यह बड़ी छवियों को खोलने के लिए संभव है, और नहीं बल्कि जल्दी से। मेरा सवाल है, मैं .NET के साथ बड़े बिटमैप्स का उपयोग कैसे करूं?

क्या उन्हें स्ट्रीम करने के लिए वैसे भी है, या गैर-स्मृति उन्हें लोड करता है?

उत्तर

8

यह दो भाग प्रश्न है।पहला सवाल यह है कि आप मेमोरी (1) से बाहर किए बिना बड़ी छवियों को कैसे लोड कर सकते हैं, दूसरा लोडिंग प्रदर्शन (2) में सुधार करने पर है।

(1) फ़ोटोशॉप जहां विशाल छवियों फाइल सिस्टम पर gigabites लेने के साथ काम करने की क्षमता है की तरह एक आवेदन पर विचार। पूरी छवि को स्मृति में रखते हुए और अभी भी संचालन (फ़िल्टर, छवि प्रसंस्करण और इतने पर, या यहां तक ​​कि केवल परत जोड़ने) करने के लिए पर्याप्त मुफ्त मेमोरी है, अधिकांश सिस्टम (यहां तक ​​कि 8 जीबी x64 सिस्टम) पर भी असंभव होगा।

यही कारण है कि इस तरह के अनुप्रयोग स्वैप फ़ाइलों की अवधारणा का उपयोग करते हैं। आंतरिक रूप से मैं यह मान रहा हूं कि फ़ोटोशॉप एक मालिकाना फ़ाइल प्रारूप का उपयोग करता है, जो उनके अनुप्रयोग डिज़ाइन के लिए उपयुक्त है और स्वैप से आंशिक भार का समर्थन करने के लिए बनाया गया है, जिससे उन्हें फ़ाइल के हिस्सों को संसाधित करने के लिए स्मृति में लोड करने में सक्षम बनाता है।

(2) प्रदर्शन फ़ाइल प्रत्येक फ़ाइल प्रारूप के लिए कस्टम लोडर लिखकर (काफी कुछ) में सुधार किया जा सकता है। इसके लिए आपको फाइल हेडर और फ़ाइल स्वरूपों की संरचना पर पढ़ने की आवश्यकता है, जिनके साथ आप काम करना चाहते हैं। एक बार जब आप इसे प्राप्त कर लेते हैं तो यह **** नहीं है **** कठिन है, लेकिन यह एक विधि कॉल करने के रूप में तुच्छ नहीं है।

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

 [StructLayout(LayoutKind.Sequential, Pack = 1)] 
     public struct BITMAPFILEHEADER 
     { 
      public Int16 bfType; 
      public Int32 bfSize; 
      public Int16 bfReserved1; 
      public Int16 bfReserved2; 
      public Int32 bfOffBits; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     public struct BITMAPINFO 
     { 
      public BITMAPINFOHEADER bmiHeader; 
      public RGBQUAD bmiColors; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     public struct BITMAPINFOHEADER 
     { 
      public uint biSize; 
      public int biWidth; 
      public int biHeight; 
      public ushort biPlanes; 
      public ushort biBitCount; 
      public BitmapCompression biCompression; 
      public uint biSizeImage; 
      public int biXPelsPerMeter; 
      public int biYPelsPerMeter; 
      public uint biClrUsed; 
      public uint biClrImportant; 
     } 

संभवतः एक डीआईबी (http://www.herdsoft.com/ti/davincie/imex3j8i.htm) बनाने के साथ काम के रूप में structues और विषमताएं को परिभाषित करने की आवश्यकता होगी "एक बिटमैप है जो आप को ध्यान में रखना करने की आवश्यकता है या जब यू इसे खोलने :-)

अब जब कि सिर्फ बिटमैप्स के लिए है कि आप एक आईना छवि देखेंगे में। मान लें कि आप पीएनजी करना चाहते हैं तो आपको समान सामान करना होगा लेकिन पीएनजी हेडर को डीकोड करना होगा, जो कि इसके सबसे सरल रूप में मुश्किल नहीं है, लेकिन यदि आप पूर्ण पीएनजी विनिर्देश समर्थन प्राप्त करना चाहते हैं तो आप एक मजेदार सवारी के लिए हैं: -)

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

string[] chunks = 
new string[] {"?PNG", "IHDR","PLTE","IDAT","IEND","tRNS", 
"cHRM","gAMA","iCCP","sBIT","sRGB","tEXt","zTXt","iTXt", 
"bKGD","hIST","pHYs","sPLT","tIME"}; 

तुम भी PNG फ़ाइलें के लिए Adler32 चेकसम के बारे में जानने के लिए जा रहे हैं था। इसलिए प्रत्येक फ़ाइल प्रारूप जो आप करना चाहते हैं वह चुनौतियों का एक अलग सेट जोड़ देगा।

मैं वास्तव में चाहता हूं कि मैं अपने उत्तर में अधिक संपूर्ण स्रोत कोड उदाहरण दे सकता हूं लेकिन यह एक जटिल विषय है, और ईमानदार होने के लिए मैंने स्वयं को एक स्वैप लागू नहीं किया है, इसलिए मैं बहुत अधिक ठोस सलाह नहीं दे पाऊंगा उस।

संक्षिप्त उत्तर यह है कि बीसीएल में छवि प्रसंस्करण क्षमताओं को गर्म नहीं है। मध्यम उत्तर यह कोशिश करना और खोजना होगा कि किसी ने एक छवि लाइब्रेरी लिखी है जो आपकी मदद कर सकती है और लंबा जवाब आपकी आस्तीन खींचने और अपने आवेदन के मूल को लिखने के लिए होगा।

जब से तुम मुझे वास्तविक जीवन में पता है कि तुम जहां मुझे लगता है पता है;)

0

के बारे में क्या:

Image image = new Bitmap(filename); 
using (Graphics gfx = Graphics.FromImage(image)) 
{  
// Stuff 
} 
+0

मुझे नहीं लगता है कि यह एक 32 बिट सीमाएं – WiiMaxx

0

बस एक त्वरित फिक्स, मैं एक ही समस्या थी, मैं एक दूसरे बिटमैप उदाहरण बनाया और निर्माता में बिटमैप पारित कर दिया।

0

क्या आप एक ही आयाम और रंग गहराई का एक नया, खाली, बिटमैप बना सकते हैं? यदि ऐसा है, तो आप कम से कम जानते हैं कि आपका पर्यावरण छवि को संभाल सकता है। फिर समस्या छवि लोडिंग उपप्रणाली में रहती है, बेशक आपका लिंक संकेत दिया जा सकता है।

मुझे लगता है कि आप अपना खुद का बिटमैप लोडर लिख सकते हैं, लेकिन यह गैर-तुच्छ प्रारूपों के लिए बहुत काम है, इसलिए मैं इसका सुझाव नहीं दूंगा।

शायद प्रतिस्थापन पुस्तकालय उपलब्ध हैं जो मानक लोडर के साथ इन मुद्दों के आसपास काम करते हैं?

0

तो आप कह रहे हैं कि यह बिटमैप की लोडिंग नहीं है लेकिन प्रतिपादन जो स्मृति से बाहर निकलता है?

यदि हां, तो क्या आप पिक्सेल को पकड़ने के लिए बिटमैप.लॉकबिट का उपयोग कर सकते हैं और मूल छवि पुनर्विक्रेता स्वयं लिख सकते हैं?

3

वास्तव में व्यापक उत्तर के लिए, मैं पेंट.नेट (http://www.getpaint.net/) के स्रोत कोड को देखने के लिए परावर्तक का उपयोग करूंगा; सी # में लिखा एक उन्नत ग्राफिक्स संपादन कार्यक्रम।

(जैसा कि टिप्पणी में बताया गया है, Paint.NET खुला स्रोत होता था लेकिन अब बंद स्रोत है)।

+0

Paint.net पर आधारित प्रणाली पर काम करेंगे है के 2007 (http छोर से एक बंद स्रोत कार्यक्रम है।नेट/2007/12/04/फ्रीवेयर-लेखक- सावधान रहें-% E2% 80% 9 कैबस्पेसवेयर% ई 2% 80% 9 डी /) – zihotki

+0

यह बहुत बुरा है। मैंने आपकी टिप्पणी को दर्शाने के लिए संपादित किया। – ine

0

एक बात सिर्फ मुझे मारा। क्या आप पूरी छवि खींच रहे हैं न केवल दृश्यमान भाग? आपको अपने आवेदन में दिखाए जाने से छवि का एक बड़ा हिस्सा नहीं खींचा जाना चाहिए, खींचे गए क्षेत्र को प्रतिबंधित करने के लिए एक्स, वाई, चौड़ाई और हेगथ ​​पैरामीटर का उपयोग करें। //blog.getpaint:

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