2010-10-25 8 views
7

पर तेज़ ग्राफिक्स ऑपरेशन लागू करें मैं WPF C# में एक साधारण ग्राफिक्स एप्लिकेशन बनाने की कोशिश कर रहा हूं। इसका उद्देश्य 10000 * 10000 आयताकार आकार 4 पिक्सेल प्रत्येक को आकर्षित करना है।WPF कैनवास

मैंने आयतों को आकर्षित करने के लिए कैनवास की ऑनरेंडर विधि को संशोधित किया है। चित्रों को छोटे आयतों के लिए किया जाता है (प्रत्येक 50 पिक्सेल के 50 * 50 या 100 * 100 आयतों का कहना है) लेकिन यह धीमा हो रहा है क्योंकि मैं संख्या बढ़ा रहा हूं। आयताकारों का।

protected override void OnRender(DrawingContext dc) 
    { 
     base.OnRender(dc); 

     FillCells(dc); 

     if (_ShowGrids) 
     { 
      DrawGrid(dc); // draw grid lines 
     } 
    } 
void FillCells(DrawingContext dc) 
    { 

     int cellSize=4; 

     for (int i = 0; i < MaxRow; i++) 
     { 
      for (int j = 0; j < MaxColumn; j++) 
      { 
       dc.DrawRectangle(GetRectBrush(i,j), GetRectPen(i,j), new Rect(j * cellSize , i * cellSize , cellSize - 1, cellSize - 1)); 

      } 
     } 
    } 

ऊपर कोड 1000 * 1000 आयतों आकर्षित करने के लिए एक मिनट से भी अधिक समय लगता है:

बाद

मेरी कोड है।

क्या इस प्रक्रिया को तेज़ी से बनाने के लिए कोई तरीका है? क्या इस जगह पर कोई और चीज मैं उपयोग कर सकता हूं?

धन्यवाद।

+0

क्या आपने विजुअल ब्रश का उपयोग करने पर विचार किया है? – TerrorAustralis

+0

नहीं मैंने नहीं किया। क्या आप मुझे विजुअल ब्रश के कुछ उदाहरण दे सकते हैं? –

+0

क्या आप स्मृति में प्रत्येक rectangel के लिए रंग भंडार कर रहे हैं? यदि नहीं, GetRectBrush (i, j) क्या कर रहा है? – TerrorAustralis

उत्तर

11

उद्देश्य 10000 * 10000 आकार 4 पिक्सल के आयतों को आकर्षित करना है।

उन्हें आकर्षित न करें। यह सरल है। यह 40k से 40k पिक्सल होगा।

अधिकतर दिखाई नहीं देंगे। तो उन्हें मधुमक्खियों को नहीं खींचा जाना चाहिए। असल में केवल उन लोगों को आकर्षित करें जो कैनवास में दिखाई दे रहे हैं। जब भी आप आकार बदलते या स्क्रॉल करते हैं, वही करते हैं, तो वही करें - केवल उन लोगों को आकर्षित करें जो दिखाई दे रहे हैं।

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

अगला विकल्प कैनवास का उपयोग नहीं करना होगा। बिटमैप आज़माएं इसे एक अलग थ्रेड पर तैयार करें, फिर इसे एक बार में खीचें।

+0

यह मेरे द्वारा किए गए प्रदर्शन को बढ़ाने का एकमात्र तरीका है। मैंने यह तंत्र भी आकर्षित करने के लिए लागू किया लेकिन दृश्यों की गणना करने में सक्षम नहीं था कैनवास के। मैंने यहां इस समस्या के लिए एक प्रश्न भी पूछा, गुग हो गया लेकिन भाग्य नहीं मिला। –

+1

+1। कुछ भी 100 एम ड्राइंग पागल है। – alxx

+0

+1 @alxx। लेकिन, जब डेटाग्रिड या कुछ जैसे नियंत्रणों की बात आती है जंजीर ग्रिड नियंत्रण। यह बिल्कुल ठीक है। कुछ मामलों में इसे 100 एम से भी अधिक की आवश्यकता हो सकती है। –

0

शायद विजुअल ब्रश के साथ कैनवास को ओवरले करने का प्रयास करें।
इस दृश्य के लिए ब्रश बस 4 * 4 आयताकार जोड़ें और इसे टाइल मोड में दोहराएं। वैकल्पिक रूप से आप केवल लाइनों को जोड़ सकते हैं ताकि यह आयत के किनारों को ओवरलैप न कर सके ... आपकी पसंद :)

आपकी समस्या ब्रश के निर्माण में है ... एक परीक्षण रन से संकेत मिलता है कि यह कोड

int limit = 10000 * 10000; 
var converter = new BrushConverter(); 
for (int i = 0; i < limit; i++) 
{ 
    var blueBrush = converter.ConvertFromString("Blue") as Brush; 
} 

चलाने के लिए 53 सेकंड लग गए। आप 100,000,000 ब्रश बनाने की कोशिश कर रहे हैं :) यदि यह पैटर्न योग्य है, तो पैटर्न पैटर्न वाले ब्रश का उपयोग करें, यदि यह पैटर्न योग्य नहीं है ... किसी अन्य समाधान के लिए perhapse देखो। स्मृति में है कि कई ब्रश भंडारण की भूमि के ऊपर गीगाबाइट में है

+0

दृश्य ब्रश उद्देश्य को पूरा नहीं करेगा क्योंकि आयत अलग-अलग रंगों का हो सकता है। दृश्य ब्रश किसी भी दृश्य तत्व की प्रतिलिपि बनाता है। –

+0

आप आयतों को रंग कैसे बना रहे हैं? यह आपके उदाहरण में दिखता है जैसे वे सभी नीले होंगे :) – TerrorAustralis

+0

मैंने रीक्ट्स के रंग को पाने के लिए कोड को अभी संशोधित किया है। –

2

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

SolidColorBrush blueBrush = new SolidColorBrush(Colors.Blue) 
SolidColorPen bluePen = new SolidColorPen(blueBrush) 

for (int i = 0; i < MaxRow; i++) 
{ 
    for (int j = 0; j < MaxColumn; j++) 
    { 
     dc.DrawRectangle(blueBrush, bluePen, 1), new Rect(j * cellSize , i * cellSize , cellSize - 1, cellSize - 1)); 
    } 
} 

यह लूप को थोड़ा सा बढ़ा सकता है।

+0

थोड़ा तेज़ लेकिन अभी भी धीमा :( –

+0

वास्तविक समस्या नहीं है, लेकिन अच्छी सलाह है। –

3

आपको स्ट्रीमजीमेट्री का प्रयास करना चाहिए। http://msdn.microsoft.com/en-us/library/system.windows.media.streamgeometry.aspx

जटिल geometries उसके बाद वे बनाई गई हैं संशोधित करने की जरूरत नहीं है के लिए, आप के बजाय StreamGeometry एक प्रदर्शन अनुकूलन के रूप में PathGeometry उपयोग करने पर विचार करना चाहिए। StreamGeometry पथजीमेट्री की तरह काम करता है, सिवाय इसके कि यह केवल प्रक्रियात्मक कोड के माध्यम से भरा जा सकता है। इसकी अजीब नाम एक कार्यान्वयन विस्तार को दर्शाता है: कम स्मृति (और सीपीयू की कम) का उपयोग करने के लिए, अपनी PathFigures और PathSegments एक कॉम्पैक्ट बाइट धारा बल्कि नेट वस्तुओं की एक ग्राफ से के रूप में जमा कर रहे हैं।

एडम नाथन की पुस्तक WPF Unleashed से उद्धृत।

+0

WHOW - जो मेरे लिए अनसुना था। कुछ पढ़ने के लिए। WPF Unleashed के लिए – TomTom

+0

+1। बहुत बढ़िया किताब प्रदर्शन में – Grozz

2

प्रत्येक व्यक्ति जो पहले से ही कहता है, उसके ऊपर एक और युक्ति है, सुनिश्चित करें कि पेन और ब्रश जमे हुए हैं - यदि आप ब्रश कॉल फ्रीज़ को इसका उपयोग करने से पहले बनाते हैं (ब्रश क्लास (ब्रश। व्हाइट) से ब्रश पहले ही जमे हुए हैं)।

+0

+1। धन्यवाद! –

1

बिटमैप दृष्टिकोण अधिक तेज़ी से बढ़ सकता है - बिटमैपसोर्स में एक ऐसी विधि है जो कच्चे डेटा को या तो सरणी या असुरक्षित स्मृति के सूचक के रूप में लेती है। वास्तविक आयताकारों को चित्रित करने के बजाय यह सरणी में मान सेट करने के लिए थोड़ा तेज़ होना चाहिए - हालांकि आपको व्यक्तिगत पिक्सेल को सही ढंग से सेट करने के लिए पिक्सेलफॉर्म को चेकआउट करना होगा।