2012-06-24 13 views
21

यहाँ एक सरल ड्राइंगUIBezierPath स्ट्रोक 1px लाइन और 1px चौड़ाई आयताकार भरें - अलग-अलग परिणाम।

 

- (void)drawRect:(CGRect)rect 
{ 
    //vertical line with 1 px stroking 
    UIBezierPath *vertLine = [[UIBezierPath alloc] init]; 
    [vertLine moveToPoint:CGPointMake(20.0, 10.0)]; 
    [vertLine addLineToPoint:CGPointMake(20.0, 400.0)]; 
    vertLine.lineWidth = 1.0; 
    [[UIColor blackColor] setStroke]; 
    [vertLine stroke]; 

    //vertical rectangle 1px width 
    UIBezierPath *vertRect= [UIBezierPath bezierPathWithRect:CGRectMake(40.0, 10.0, 1.0, 390.0)]; 
    [[UIColor blackColor] setFill]; 
    [vertRect fill]; 

} 

पर गैर रेटिना 3GS और सिम्युलेटर पहली पंक्ति धुंधली है और व्यापक से कम 1 पिक्सल लग रहा है, लेकिन दूसरी पंक्ति कुरकुरा है।

दुर्भाग्यवश मेरे पास न तो आईफोन 4 है और न ही नया आईपैड परीक्षण करने के लिए है, लेकिन रेटिना सिम्युलेटर पर दोनों लाइनें समान दिखती हैं।

प्रश्न: स्ट्रेट के बजाय आयत आयताकार और रेटिना उपकरणों के लिए एक ही परिणाम प्राप्त करने का एकमात्र तरीका है?

उत्तर

51

आप आयताकार के अंदर भर रहे हैं लेकिन आप केंद्र से रेखा का पीछा कर रहे हैं। चूंकि दोनों मामलों में समन्वय (आयत के कोनों और रेखा में प्रारंभ और अंत समन्वय) को पूर्ण संख्या मान (कोई अंश नहीं) के रूप में परिभाषित किया जाता है, निर्देशांक सटीक बिंदु सीमाओं पर स्थित होते हैं।

मैंने स्क्रीन के बिंदुओं के बारे में बात करने के लिए लाइन के बिंदुओं के बारे में बात करते समय उपरोक्त "निर्देशांक" कहा। मैंने उसी कारण से "पिक्सेल सीमाओं" के बजाय "बिंदु सीमाएं" भी कहा। आईओएस अपने निर्देशांक और सभी बिंदुओं को परिभाषित करता है जिसे पिक्सल के बजाय "अंक" कहा जाता है। एक बिंदु एक संकल्प स्वतंत्र माप है। रेटिना और गैर-रेटिना उपकरणों दोनों में स्क्रीन पर समान अंक हैं, यह सिर्फ एक वास्तविक संख्या के वास्तविक पिक्सेल से मेल खाता है।

नीचे चित्र में मैं एक लाइन पथपाकर कर रहा हूँ: एक आयत जहां कोनों बिंदु सीमाओं पर झूठ भरने की तुलना में एक लाइन है कि (अपने प्रश्न में) की तरह बिंदु सीमाओं पर झूठ पथपाकर पर

आइए नज़र गैर-रेटिना स्क्रीन और रेटिना स्क्रीन दोनों पर नारंगी के साथ एक आयताकार भरकर और आयताकार भरना। मैंने रेखा और आयताकार को नीले रंग के रूप में भी रेखांकित किया है। दोनों मामलों में आप उस संकल्प के लिए एक बिंदु का आकार देख सकते हैं और इसे वास्तविक पिक्सेल ग्रिड से तुलना कर सकते हैं।

गैर-रेटिना मामले में, आप देख सकते हैं कि केंद्र से लाइन को 1 बिंदु रेखा के साथ स्ट्रोक करने की कोशिश कर रहा है (इस मामले में 1 पिक्सेल लाइन चौड़ाई के अनुरूप) शीर्ष पर पिक्सेल के आधे हिस्से को भर देगा और नीचे पिक्सेल पर आधा। चूंकि पिक्सल केवल आधा भरा है, इसलिए उन पिक्सेल के लिए अस्पष्टता 50% है। इसका परिणाम हल्का रंग (सफेद पृष्ठभूमि पर) होता है। चूंकि ऊपर और नीचे दोनों पिक्सेल पार्टी भर चुके हैं, दोनों पिक्सल को ऊपर और नीचे भरते हैं। यह रेखा को दिखता है जैसे कि यह एक के बजाय 2 पिक्सल चौड़ा है।

आप जल्दी से उस आयत से तुलना कर सकते हैं जो अंदर भर जाता है।

non retina

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

हम यह भी देख सकते हैं कि भरा आयताकार समान दिखता है।

retina


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

नीचे दिए गए चित्रण में (रेटिना के लिए) मैंने पॉइंट ग्रिड और पिक्सेल ग्रिड दोनों को दिखाया है।

half pixel non-retina half pixel retina

2

कारण आप स्ट्रोक के साथ अलग अलग परिणाम प्राप्त और भरने कि तर्क की अपनी व्याख्याओं अलग है।

स्ट्रोक समन्वय के प्रत्येक तरफ रेखा की आधा चौड़ाई जोड़ता है। तो, आपका बिंदु 20.0 है और रेखा की चौड़ाई 1px है। परिणाम सैद्धांतिक रूप से (1 9 .5-20.5) के बीच 1 पिक्सेल काली रेखा होगी। चूंकि डिवाइस स्क्रीन पर कोई nonintegral पिक्सेल नहीं है, इसलिए इसे 2 पिक्सेल ग्रे/धुंधली रेखा (1 9 -21) के बीच परिवर्तित कर दिया जाएगा। इसे रोकने के लिए, आपको अपने प्रत्येक समन्वयक को 0.5 के साथ जोड़ना होगा (जैसा कि CGPointMake (20.5, 10.5) में) ताकि चौड़ाई पिक्सल के बीच अब विभाजित न हो।

हालांकि, भरने के तर्कों को क्षेत्र की सीमाओं को भरने के लिए उपयोग किया जाता है, सीजीआरईटीएमके (40.0, 10.0, 1.0, 3 9 0.0) (40 - 41) के बीच एक क्षेत्र का तात्पर्य है। नतीजतन धुंधला दिखने के लिए पिक्सेल पर कोई अंश भाग नहीं पड़ता है।