2012-02-16 15 views
35

मुझे WPF में बिटमैप्स हैंडलिंग को अनुकूलित करने के लिए कई पैटर्न मिले। हालांकि, मैं समझ नहीं पा रहा हूं कि प्रत्येक पैटर्न का उपयोग कब करें। जैसा कि मुझे लगता है कि यह एक आम समस्या है, मैंने सारांशित किया कि मैं क्या समझता हूं और मुझे क्या लगता है और आपकी मदद के लिए पूछता है। आप पैटर्न जोड़ सकते हैं, कि वे किस तरह भिन्न होते हैं, की व्याख्या करता है, तो वे CPU या GPU का उपयोग समझाने, और जब उपयोग करने के लिए सिखाने प्रत्येक और उन्हें गठबंधन करने के लिए कैसे, यह एक जबरदस्त मदद होगी !बिटमैप प्रदर्शन-अनुकूलन पैटर्न

प्रसंग - छवियाँ "ग्रिड" परिदृश्य:

मेरा आवेदन कई बिटमैप छवियों को प्रदर्शित करने की है। छवियों को पंक्तियों और कॉलम ग्रिड जैसी संगठन में स्क्रीन पर प्रदर्शित किया जाता है (आवश्यक रूप से ग्रिड या यूनिफॉर्मग्रिड कक्षाएं नहीं, विंडो मीडिया प्लेयर के एल्बम दृश्य को सोचें)। छवियां विभिन्न ग्रिड कोशिकाओं के बीच स्थानांतरित हो सकती हैं। मनमानी कोशिकाओं पर कुछ छवियों को दूसरों द्वारा प्रतिस्थापित किया जा सकता है। छवियों को क्लिक करने योग्य होना चाहिए, एक संदर्भ मेनू प्रदान करना चाहिए, चयन योग्य, ड्रैग-सक्षम आदि होना चाहिए। दूसरे शब्दों में, "छोटे बगर्स को एक बड़े बिटमैप में गठबंधन करें" लागू नहीं है, कम से कम निष्क्रिय नहीं है।

पैटर्न 0: हैक

एक बिटमैप में छोटे buggers गठबंधन है, और पृष्ठभूमि के रूप में उपयोग (कैसे संदर्भ ड्राइंग??)। खाली सामग्री वाली छवियों के साथ इसे ओवरले करें जो हिट, संदर्भ मेनू, इवेंट इत्यादि को संभालेगा।

लाभ यह है कि हम केवल दो बिटमैप बोल रहे हैं: वर्तमान में प्रदर्शित एक और जिसे इसे प्रतिस्थापित करना चाहिए। यह वास्तव में तेज़ होना चाहिए। हालांकि, मेरे वर्षों के अनुभव खतरे के लाल झंडे को बढ़ाते हैं। आपकी टिप्पणी?

पैटर्न 1: कम छवि का आकार

यह एक नहीं brainer है जब आप छवि आकार के आकार बदलने के लिए पहले से पता है, और होता है जब आप प्रदर्शन के लिए विवरण (रंग) कम करने के लिए तैयार हैं:

  1. BitmapImage.DecodePixelWidth
  2. का उपयोग कर FormatConvertedBitmap.DestinationFormat का उपयोग कर रंग जानकारी
  3. सेट कम बिटमैप आकार कम नियंत्रण के स्केलिंग व्यवहार रों इमेटिंग इमेज। स्ट्रेच को स्ट्रेच करें।
  4. छवि के लिए SetBitmapScalingMode को निम्न गुणवत्ता में सेट करें।
  5. मैथुन

देखें कोड here फ्रीज।

पैटर्न 2: पृष्ठभूमि प्री-फ़ेच

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

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

इस काम के लिए आपको बिटमैप इमेज के कैशऑप्शन को ऑनलोड पर सेट करना होगा, ताकि काम पृष्ठभूमि कार्यकर्ता से ऑफ-लोड हो।

पैटर्न 3: आरेखण संदर्भ

यह MSDN WPF मंच here पर Microsoft समर्थन से शेल्डन ziao द्वारा सुझाव दिया गया था। आदम नाथन के डब्ल्यूपीएफ 4 में पेज 4 9 4, अध्याय 15 "2 डी ग्राफिक्स" देखें DrawingContext के विवरण के लिए खुलासा। मैं नहीं कह सकता कि मैं इसे समझता हूं। here के उत्तर के अनुसार, मुझे लगता है कि यह ज्यामिति चित्रों को संभालने में सुधार करेगा, बिटमैप्स नहीं। इसके बाद, मुझे नहीं लगता कि यह छवियों के लिए फोकस और घटनाओं की आवश्यकताओं का समर्थन करेगा (फोरम में बेहतर आवश्यकताओं को समझाने के लिए मेरा बुरा) इसके अलावा, मैं पुस्तक की सारांश वाक्य से चिंतित हूं: "ध्यान दें कि DrawingContext का उपयोग इस तथ्य को नहीं बदलेगा कि आप एक बनाए रखा मोड सिस्टम के भीतर काम कर रहे हैं। निर्दिष्ट चित्र तुरंत नहीं होता है; आदेशों को WPF द्वारा तब तक जारी रखा जाता है जब तक उनकी आवश्यकता न हो। "इसका मतलब है कि एक बार हमारे हैंडलर फिर भी हम" बैकग्राउंड प्री-फ़ेच "जैसे समांतरता का लाभ नहीं उठा सकते हैं।

पैटर्न 4: लेखनीय बिटमैप

MSDN प्रलेखीकरण here एक दोहरी बफर प्रणाली के रूप में वर्णन: अपने यूआई धागा बफर अद्यतन करता है; डब्ल्यूपीएफ का रेंडर थ्रेड इसे वीडियो मेमोरी में ले जाता है।

इच्छित उपयोग (here देखें) बिटमैप्स के लिए है जो वीडियो मूवी जैसे प्रदर्शन में बहुत कुछ बदलता है। मुझे यकीन नहीं है, लेकिन संभव है कि इसे हैक किया जा सके और बैकग्राउंड प्री-फ़ेच पैटर्न के साथ जोड़ा जा सके और ग्रिड परिदृश्य में उपयोग किया जा सके।

पैटर्न 5: कैश्ड बिटमैप

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

पैटर्न 6: RenderTargetBitmap

RenderTargetBitmap एक बिटमैप करने के लिए एक दृश्य बदल देता है। मुझे यकीन नहीं है कि यह यहां प्रासंगिक है या नहीं। here देखें।

संपादित: पॉल Hoenecke प्रश्न के बारे में: मैं लिखा है कि "मेरा आवेदन कई बिटमैप iages प्रदर्शित करने के लिए है।" मैं उल्लेख करने में असफल रहा कि मुझे 800 छवियों को समवर्ती प्रदर्शित करने की आवश्यकता है।

एक मेरी अतः सवाल पर शामिल प्रदर्शन के मुद्दों WPF Bitmap performance और How can I make displaying images on WPF more “snappy”?

मैं पैटर्न 1 के वर्णन में बदलाव कर दिया है अवधारणा है कि छवि नियंत्रण बनाया या नष्ट कर दिया (जब तक कि हम चाहते हैं नहीं कर रहे हैं उजागर करने के लिए के बारे में पढ़ सकते हैं एक बड़ा या छोटा ग्रिड प्रदर्शित करने के लिए)। केवल उनके स्रोत अलग-अलग, नए या शून्य बिटमैप स्रोत पर सेट हैं।

संपादित करें: This question as posted on the WPF support forum, एमएस कर्मियों के कुछ उत्तरों के साथ।

+1

आप कितनी छवियों की उम्मीद कर रहे हैं? मैंने एक ऐप बनाया है जो पहले हजारों छवियों का ग्रिड दिखाता है। हमने वर्चुअल-मोड सूचीबॉक्स का उपयोग किया; चूंकि उपयोगकर्ता नीचे स्क्रॉल करता है, छवियों को पृष्ठभूमि थ्रेड में लोड किया जाता है, जमे हुए और छवि के स्रोत पर सेट किया जाता है। जाहिर है, आपने इसमें बहुत कुछ सोचा है ... लेकिन, शायद आप जो कुछ हासिल करना चाहते हैं उसके बारे में अधिक जानना बेहतर होगा। उदाहरण के लिए, आपके पास ऐसी समस्याएं हैं जो ऐसी प्राथमिकता को अनुकूलित करने में सक्षम हैं? –

+0

@PaulHoenecke हाय पॉल, आपके उत्तर के लिए धन्यवाद। जब आप बड़े संग्रह से छोटी संख्या में आइटम प्रदर्शित करना चाहते हैं तो आभासी संग्रह आपकी सहायता करते हैं। यहां, मैं समवर्ती रूप से लगभग 1 के आइटम प्रदर्शित करना चाहता हूं। इसके अतिरिक्त, मुझे यकीन नहीं है कि वर्चुअलाइजिंग ग्रिड मौजूद है। अंत में, पैटर्न 1 अनिवार्य रूप से वर्चुअलाइजिंग है - मैं एन संपादित कर दूंगा। – Avi

+0

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

उत्तर

17

मैं नीचे दिए गए दृष्टिकोणों पर टिप्पणियों के अलावा अन्य पोस्ट में एक विशिष्ट प्रश्न नहीं ढूंढ पा रहा हूं। मैं ऊपर सबकुछ जानने का दावा नहीं करूंगा लेकिन मैं आपको बताऊंगा कि डब्ल्यूपीएफ और सिल्वरलाइट का उपयोग करके उच्च प्रदर्शन वाले यूआई विकसित करने के दौरान मुझे क्या पता चला है।

पैटर्न 0: हैक। सभी को एक छवि में जोड़ना

यदि संभव हो तो मैं इससे बचूंगा। ऐसा लगता है कि आप हजारों छोटी छवियों का एक बड़ा लपेट-पैनल प्रदर्शित करना चाहते हैं। इसलिए प्रत्येक छवि एक थंबनेल है (क्योंकि आप एक साथ कई बड़ी छवियों को प्रदर्शित नहीं कर सकते हैं)। नतीजतन, मैं संयोजन पर कैशिंग/आकार बदलने का समर्थन करता हूं।

पैटर्न 1: कम छवि का आकार

आप एक बार में स्क्रीन पर 1,000 चित्रों का प्रदर्शन कर रहे हैं, उपलब्ध स्क्रीन अचल संपत्ति पर विचार करें। औसत मॉनिटर 1280x1024 पिक्सल है, या केवल 1.3 एमपीिक्स से अधिक है। 1000 छवियां बताती हैं कि आपको प्रति छवि 1300 पिक्सेल का अधिकतम आकार, या 36 * 36 मिलेगा। आइए कहें कि आपकी छवियां 32 * 32 आकार में हैं। आपको निश्चित रूप से स्क्रीन पर प्रस्तुत करने के लिए उस छवि आकार का थंबनेल बनाना चाहिए, फिर क्लिक (या अन्य क्रिया) पर पूर्ण आकार की छवि दिखाएं।

न केवल एक बड़ी छवि का आकार बदलने के लिए ओवरहेड प्रस्तुत करना, बल्कि जीपीयू को आकार बदलने के लिए एक बड़ी छवि भेजने पर विचार करें। उस डेटा को बैंडविड्थ भेजने की आवश्यकता है। एक बड़ी छवि कई मेगाबाइट हो सकती है जबकि आकार 32 * 32 का थंबनेल कुछ किलोबाइट हो सकता है।

यदि आपको गतिशील आकार की आवश्यकता है, तो ठीक है, लेकिन आपको एकाधिक थंबनेल बनाने या उन्हें फ्लाई पर उत्पन्न करने के साथ प्रयोग करने की आवश्यकता होगी।

पैटर्न 2: पृष्ठभूमि प्री-फ़ेच

यह एक तकनीक है मैं के बारे में सुना नहीं किया है, लेकिन यह प्रशंसनीय लगता है। आपके आवेदन में ओवरहेड क्या है? क्या यह Image.Source प्रॉपर्टी को अद्यतन कर रहा है या एक नई छवि, टेस्सेलिंग, लेआउट प्रदर्शन कर रहा है और इसे GPU को प्रस्तुत करने के लिए जानकारी भेज रहा है?

अंतिम उपरोक्त को छोड़कर सभी उपरोक्त CPU पर होते हैं। सीपीयू पक्ष पर ओवरहेड को कम करके और स्रोत को अपडेट करके आप कुछ पर हो सकते हैं। इसे लिखने योग्य बिटमैप के साथ एक स्रोत के रूप में संयोजित करें और आप एक प्रदर्शन सुधार प्राप्त कर सकते हैं (नीचे देखें)।

पैटर्न 3: आरेखण संदर्भ

ठीक है, यह सब करता है आप एक "OnPaint" शैली वाक्य रचना जो पुराने GDI OnPaint की तरह कुछ भी नहीं है का उपयोग कर कॉल ड्राइंग बनाए रखा मोड अप कतार करने की अनुमति है।मेरे अनुभव में ऑनरेंडर प्रदर्शन में सुधार नहीं करता है, लेकिन यह खींचा जाने पर और कब पर अच्छी तरह से दागदार लचीलापन की अनुमति देता है। ऑनरेंडर आपको एक संदर्भ प्रदान करता है, जिसमें एक ड्राइमेज फ़ंक्शन होता है, जिससे बिटमैप स्रोत को छवि नियंत्रण की आवश्यकता के बिना प्रतिपादन पाइपलाइन पर खींचा जा सकता है। यह अच्छा है क्योंकि यह कुछ ओवरहेड को हटा देता है, हालांकि पैटर्न 0 में दिखाई देने वाली समस्याओं के समान समस्याएं पेश करता है (आप लेआउट खो देंगे और अपनी सभी छवियों की स्थिति की गणना करनी होगी)। यदि आप ऐसा करते हैं, तो आप पैटर्न 0 को भी बुला सकते हैं, जिसे मैंने सलाह दी थी।

पैटर्न 4: लेखनीय बिटमैप

WriteableBitmaps WPF के भीतर एक छोटे से अधिक इस्तेमाल किया और असाधारण शक्तिशाली सबसिस्टम हैं। मैं रीयल-टाइम में बड़ी मात्रा में डेटा प्रस्तुत करने में सक्षम चार्टिंग घटक बनाने के लिए उन्हें बहुत प्रभावशाली उपयोग करता हूं। मैं लिखने योग्य बिटमैपएक्स कोडप्लेक्स प्रोजेक्ट प्रकटीकरण की जांच करने का सुझाव दूंगा, मैंने इसे में एक बार योगदान दिया है और यह देखकर कि क्या आप इसे अन्य पैटर्न के साथ जोड़ सकते हैं। विशेष रूप से ब्लिट फ़ंक्शन जो आपको एक छवि पर बिटमैप स्रोत पर कैश किए गए बिटमैप लिखने देगा।

उदाहरण के लिए, एक अच्छी तकनीक पैटर्न हो सकता है 1 + 2 + 4.

आप एक ग्रिड नियंत्रण में सेट स्थानों पर स्क्रीन पर एन छवि नियंत्रण का एक ग्रिड हो सकता था। इनमें से प्रत्येक स्थिर है और दृश्य से बाहर नहीं निकलता है इसलिए कोई रचना/हटाना नहीं चल रहा है। अब, इसके शीर्ष पर, अपनी छवि का आकार बदलें और एक लिखने योग्य बिटमैप को लिखें जो प्रत्येक छवि पर स्रोत प्रॉपर्टी के रूप में सेट है। जैसे ही आप स्क्रॉल करते हैं, अगले/पिछले थंबनेल प्राप्त करें और WriteableBitmapEx.Blit का उपयोग करके स्रोत अपडेट करें। पाउ! आभासी, कैश, बहु थ्रेडेड इमेजिंग भलाई।

पैटर्न 5: कैश्ड बिटमैप

यह माइक्रोसॉफ्ट द्वारा एक प्रयास के रूप में मैं ऊपर चर्चा की 1 + 2 + 4 करना है। यह करने की कोशिश करता है कि लेआउट (सीपीयू साइड), टेस्सेलेशन (सीपीयू साइड) के बाद, जीपीयू (सीपीयू साइड) और प्रतिपादन (जीपीयू पक्ष) को बनाए रखा मोड रेंडर निर्देश भेजकर यह प्रस्तुत तत्व की रास्टर छवि को कैश करता है जो पुनः- अगले प्रतिपादन पास पर प्रयोग किया जाता है। हां, डब्ल्यूपीएफ के बारे में थोड़ा ज्ञात तथ्य यह है कि अद्भुत जीपीयू संचालित इंजन बहुत धीमा है क्योंकि यह सीपीयू पर अधिकांश काम करता है: पी

मैं बिटमैप कैश के साथ प्रयोग करता हूं और देखता हूं कि यह कैसा प्रदर्शन करता है। चेतावनी हैं, और वे हैं कि जब आप अपना UIElement अपडेट करते हैं तो इसे कैश को फिर से बनाना होता है ताकि स्थैतिक तत्व गतिशील से कहीं बेहतर प्रदर्शन कर सकें। इसके अलावा मैंने इसका उपयोग करने से प्रदर्शन में महत्वपूर्ण सुधार नहीं देखा है, जबकि लिखित योग्य बिट शैली शैली तकनीक परिमाण सुधार का क्रम दे सकती है।

पैटर्न 6: RenderTargetBitmap

इस अंतिम तकनीक आप एक बिटमैप के लिए एक UIElement प्रस्तुत करना की सुविधा देता है - आप जानते हैं - लेकिन क्या दिलचस्प है यह एक गरीब-मनुष्य थंबनेल जनरेटर प्रदर्शन (या आकार परिवर्तन) कर सकते हैं । उदाहरण के लिए, अपनी पूर्ण आकार छवि के बिटमैप स्रोत के साथ एक छवि सेट करें। अब छवि नियंत्रण का आकार 32 * 32 पर सेट करें और बिटमैप को प्रस्तुत करें। देखा! आपके पास बिटमैपसोर्स थंबनेल कुछ स्वैपिंग (पैटर्न 2) और/या लिखने योग्य बिटमैप्स के संयोजन के साथ उपयोग करने के लिए है।

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

जैसा कि मैंने कहा था कि मेरी सिफारिश 1 + 2 + 4 है। आपको एक थंबनेल का आकार बदलना होगा, जिसमें मुझे कोई संदेह नहीं है। छवि नियंत्रणों का स्थिर ग्रिड रखने और स्रोतों को अद्यतन करने का विचार बहुत अच्छा है। स्रोतों को अद्यतन करने के लिए WriteableBitmap (विशेष रूप से WriteableBitmapEx ब्लिट फ़ंक्शन) का उपयोग करने का विचार भी एक लायक है।

शुभकामनाएं!

+0

आपके उत्तर के लिए धन्यवाद! एक प्राचीन यहूदी फसह की कहानी चार बेटों का वर्णन करती है: बुद्धिमान, बुराई, मूर्ख और वह जो यह भी नहीं जानता कि कौन से प्रश्न पूछना है। मुझे लगता है कि मैं पृष्ठभूमि में इतनी कमी कर रहा हूं कि मैं सही प्रश्न पूछने में भी सक्षम नहीं हूं: "tessellating"? क्या आप WPF में (2 डी) ग्राफिक्स "पाइपलाइन" का वर्णन करने वाली किसी पुस्तक या आलेख से अवगत हैं? गतिविधियां क्या हैं, सीपीयू क्या करता है, जीपीयू क्या करता है? – Avi

+1

हाँ मैं करता हूँ! यह आलेख देखें: http://jeremiahmorrill.com/2011/02/14/a- क्रिटिकल- डीप- डीव-into-the-wpf-rendering-system/ यह बहुत गूढ़ चीजें है, बुरा मत मानो। अधिकांश आपको प्रदर्शन के लिए "ऑनरेंडर ओवरराइड" बताएंगे, या "डब्ल्यूपीएफ जीपीयू का उपयोग करता है", लेकिन यह गलत जवाब है। जब आपको एहसास होता है कि डब्ल्यूपीएफ अपने अधिकांश काम सीपीयू पक्ष (लंग !!) करता है तो आप प्रदर्शन के लिए अनुकूलित करना शुरू कर सकते हैं। –

+0

जिस ट्रेल को आपने मुझे भेजा है, उसके माध्यम से जाना, मुझे यह महसूस हो रहा है कि डब्ल्यूपीएफ स्वाभाविक रूप से धीमा है और उसे डायरेक्ट 2 डी या विनआरटी के लिए इंतजार करना चाहिए ... – Avi

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