2012-05-16 19 views
5

मैक ओएस एक्स 10.7.4मैक ओएस एक्स: CGContextRef C फ़ंक्शंस का उपयोग करते हुए एक ऑफस्क्रीन NSGraphicsContext में चित्रण का कोई प्रभाव नहीं पड़ता है। क्यूं कर?

मैं +[NSGraphicsContext graphicsContextWithBitmapImageRep:] के माध्यम से बनाए गए ऑफस्क्रीन ग्राफिक्स संदर्भ में आ रहा हूं।

जब मैं NSBezierPath कक्षा का उपयोग करके इस ग्राफिक्स संदर्भ में आकर्षित करता हूं, तो सब कुछ अपेक्षित काम करता है।

हालांकि, जब मैं CGContextRef सी फ़ंक्शन का उपयोग करके इस ग्राफिक्स संदर्भ में आकर्षित करता हूं, तो मुझे अपने चित्र का कोई परिणाम नहीं दिखता है। कुछ भी काम नहीं करता है।

कारणों से मैं अंदर नहीं जाऊंगा, मुझे वास्तव में CGContextRef फ़ंक्शंस (कोको NSBezierPath कक्षा के बजाए) का उपयोग करने की आवश्यकता है।

मेरा कोड नमूना नीचे सूचीबद्ध है। मैं एक साधारण "एक्स" खींचने का प्रयास कर रहा हूं। NSBezierPath का उपयोग करके एक स्ट्रोक, CGContextRef सी फ़ंक्शंस का उपयोग करके एक स्ट्रोक। पहला स्ट्रोक काम करता है, दूसरा नहीं करता है। मैं क्या गलत कर रहा हूं?

NSRect imgRect = NSMakeRect(0.0, 0.0, 100.0, 100.0); 
NSSize imgSize = imgRect.size; 

NSBitmapImageRep *offscreenRep = [[[NSBitmapImageRep alloc] 
    initWithBitmapDataPlanes:NULL 
    pixelsWide:imgSize.width 
    pixelsHigh:imgSize.height 
    bitsPerSample:8 
    samplesPerPixel:4 
    hasAlpha:YES 
    isPlanar:NO 
    colorSpaceName:NSDeviceRGBColorSpace 
    bitmapFormat:NSAlphaFirstBitmapFormat 
    bytesPerRow:0 
    bitsPerPixel:0] autorelease]; 

// set offscreen context 
NSGraphicsContext *g = [NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]; 
[NSGraphicsContext setCurrentContext:g]; 

NSImage *img = [[[NSImage alloc] initWithSize:imgSize] autorelease]; 

CGContextRef ctx = [g graphicsPort]; 

// lock and draw 
[img lockFocus]; 

// draw first stroke with Cocoa. this works! 
NSPoint p1 = NSMakePoint(NSMaxX(imgRect), NSMinY(imgRect)); 
NSPoint p2 = NSMakePoint(NSMinX(imgRect), NSMaxY(imgRect)); 
[NSBezierPath strokeLineFromPoint:p1 toPoint:p2]; 

// draw second stroke with Core Graphics. This doesn't work! 
CGContextBeginPath(ctx); 
CGContextMoveToPoint(ctx, 0.0, 0.0); 
CGContextAddLineToPoint(ctx, imgSize.width, imgSize.height); 
CGContextClosePath(ctx); 
CGContextStrokePath(ctx); 

[img unlockFocus]; 

उत्तर

22

आप यह निर्दिष्ट नहीं करते कि आप परिणामों को कैसे देख रहे हैं। मुझे लगता है कि आप NSImageimg पर देख रहे हैं और NSBitmapImageRepoffscreenRep पर नहीं देख रहे हैं।

जब आप [img lockFocus] फोन, आप वर्तमान NSGraphicsContext बदल रहे हैं img में आकर्षित करने के लिए एक संदर्भ किया जाना है। तो, NSBezierPath ड्राइंग img में जाता है और यह वही है जो आप देखते हैं। सीजी ड्राइंग offscreenRep में जाती है जिसे आप नहीं देख रहे हैं।

इसके बजाय एक NSImage पर फोकस ताला लगा है और इसे में ड्राइंग का, एक NSImage बना सकते हैं और offscreenRep अपने प्रतिनिधि के रूप में जोड़ें।

NSRect imgRect = NSMakeRect(0.0, 0.0, 100.0, 100.0); 
NSSize imgSize = imgRect.size; 

NSBitmapImageRep *offscreenRep = [[[NSBitmapImageRep alloc] 
    initWithBitmapDataPlanes:NULL 
    pixelsWide:imgSize.width 
    pixelsHigh:imgSize.height 
    bitsPerSample:8 
    samplesPerPixel:4 
    hasAlpha:YES 
    isPlanar:NO 
    colorSpaceName:NSDeviceRGBColorSpace 
    bitmapFormat:NSAlphaFirstBitmapFormat 
    bytesPerRow:0 
    bitsPerPixel:0] autorelease]; 

// set offscreen context 
NSGraphicsContext *g = [NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]; 
[NSGraphicsContext saveGraphicsState]; 
[NSGraphicsContext setCurrentContext:g]; 

// draw first stroke with Cocoa 
NSPoint p1 = NSMakePoint(NSMaxX(imgRect), NSMinY(imgRect)); 
NSPoint p2 = NSMakePoint(NSMinX(imgRect), NSMaxY(imgRect)); 
[NSBezierPath strokeLineFromPoint:p1 toPoint:p2]; 

// draw second stroke with Core Graphics 
CGContextRef ctx = [g graphicsPort];  
CGContextBeginPath(ctx); 
CGContextMoveToPoint(ctx, 0.0, 0.0); 
CGContextAddLineToPoint(ctx, imgSize.width, imgSize.height); 
CGContextClosePath(ctx); 
CGContextStrokePath(ctx); 

// done drawing, so set the current context back to what it was 
[NSGraphicsContext restoreGraphicsState]; 

// create an NSImage and add the rep to it  
NSImage *img = [[[NSImage alloc] initWithSize:imgSize] autorelease]; 
[img addRepresentation:offscreenRep]; 

// then go on to save or view the NSImage 
+0

धन्यवाद कर्ट। हां, आप अपनी धारणा में सही थे, मैं 'img' diaplay करने का प्रयास कर रहा हूं। इसके अलावा: आपका फिक्स सही है और समस्या को हल करता है। इसे साफ़ करने के लिए धन्यवाद! –

3

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

init विधि

- (instancetype)initWithSize:(NSSize)aSize 

जो MacOS 10.0 के बाद से मौजूद है और अभी भी अमान्य नहीं है के प्रलेखन, स्पष्ट रूप से कहते हैं:

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

तो यहाँ है कि कैसे मुझे लगता है कि कोड लिखा होता:

NSRect imgRect = NSMakeRect(0.0, 0.0, 100.0, 100.0); 
NSImage * image = [[NSImage alloc] initWithSize:imgRect.size]; 

[image lockFocus]; 
// draw first stroke with Cocoa 
NSPoint p1 = NSMakePoint(NSMaxX(imgRect), NSMinY(imgRect)); 
NSPoint p2 = NSMakePoint(NSMinX(imgRect), NSMaxY(imgRect)); 
[NSBezierPath strokeLineFromPoint:p1 toPoint:p2]; 

// draw second stroke with Core Graphics 
CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort]; 
CGContextBeginPath(ctx); 
CGContextMoveToPoint(ctx, 0.0, 0.0); 
CGContextAddLineToPoint(ctx, imgRect.size.width, imgRect.size.height); 
CGContextClosePath(ctx); 
CGContextStrokePath(ctx); 
[image unlockFocus]; 

गया दोस्तों यही कारण है कि।

graphicsPort वास्तव में void * है:

@property (readonly) void * graphicsPort 

और दस्तावेज

के रूप में निम्न स्तर के, प्लेटफ़ॉर्म-विशिष्ट ग्राफिक्स संदर्भ ग्राफिक बंदरगाह से का प्रतिनिधित्व किया।

जो काफी कुछ सब कुछ हो सकता है लेकिन अंतिम नोट कहते हैं

ओएस एक्स में, यह कोर ग्राफिक्स संदर्भ, एक CGContextRef वस्तु (अपारदर्शी प्रकार) है।

यह गुण नई संपत्ति

@property (readonly) CGContextRef CGContext 

जो 10.10 और बाद में ही उपलब्ध है के पक्ष में 10.10 में मान्य नहीं है। अगर आपको पुराने सिस्टम का समर्थन करना है, तो अभी भी graphicsPort का उपयोग करना ठीक है।