2009-12-04 158 views
4

我正在嘗試創建一個NSImageNSImageCell,圓角落在NSTableView的內部。我無法得到任何工作。這裏是最好的我到目前爲止我的自定義NSCell內:如何繪製圓角NSImage

- (void)drawInteriorWithFrame:(NSRect)frame inView:(NSView *)controlView { 
    if (thumbnailLink) { 
    NSURL *url = [NSURL URLWithString:thumbnailLink]; 
    if (url) { 
     NSRect imageFrame = [self _imageFrameForInteriorFrame:frame]; 
     NSImage *image = [[NSImage alloc] initWithContentsOfURL:url]; 
     [image setScalesWhenResized:YES]; 
     [image setSize:NSMakeSize(IMAGE_HEIGHT, IMAGE_WIDTH)]; 

     [NSGraphicsContext saveGraphicsState]; 
     imageFrame = NSInsetRect(imageFrame, 1, 1); 
     NSBezierPath *clipPath = [NSBezierPath bezierPathWithRoundedRect:imageFrame cornerRadius:5.0]; 
     [clipPath setWindingRule:NSEvenOddWindingRule]; 
     [clipPath addClip]; 
     [NSGraphicsContext restoreGraphicsState]; 
     [image drawInRect:imageFrame fromRect:NSMakeRect(0, 0, 0, 0) operation:NSCompositeSourceIn fraction:1.0]; 
     [image release]; 
    } 
} 
... 

上的任何想法如何呢?

回答

22

您需要在繪製圖像時保留剪輯集,然後恢復上下文。另外,我不認爲你想要使用「in」合成,而是如果你只是想正常繪製圖像而不考慮目標不透明度,則應該使用「合成」。嘗試是這樣的:

[NSGraphicsContext saveGraphicsState]; 

NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:imageFrame 
                xRadius:5 
                yRadius:5]; 
[path addClip]; 

[image drawInRect:imageFrame 
     fromRect:NSZeroRect 
     operation:NSCompositeSourceOver 
     fraction:1.0]; 

[NSGraphicsContext restoreGraphicsState]; 
+0

這個作品!非常感謝!! – nonamelive 2011-02-17 07:54:16

3

只需提供你做了什麼錯多一點信息:

保存和恢復gstate的目的是爲了能夠撤消更改gstate。在你的情況下,剪切後恢復gsave解開剪輯。這就是爲什麼解決方案(如由羅特所解釋的)是爲了在你恢復gstate之前繪製你想要的之前

9
+ (NSImage*)roundCorners:(NSImage *)image 
{ 

NSImage *existingImage = image; 
NSSize existingSize = [existingImage size]; 
NSSize newSize = NSMakeSize(existingSize.width, existingSize.height); 
NSImage *composedImage = [[[NSImage alloc] initWithSize:newSize] autorelease]; 

[composedImage lockFocus]; 
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh]; 

NSRect imageFrame = NSRectFromCGRect(CGRectMake(0, 0, 1024, 1024)); 
NSBezierPath *clipPath = [NSBezierPath bezierPathWithRoundedRect:imageFrame xRadius:200 yRadius:200]; 
[clipPath setWindingRule:NSEvenOddWindingRule]; 
[clipPath addClip]; 

[image drawAtPoint:NSZeroPoint fromRect:NSMakeRect(0, 0, newSize.width, newSize.height) operation:NSCompositeSourceOver fraction:1]; 

[composedImage unlockFocus]; 

return composedImage; 
} 
+0

良好的工作......不過,newSize的寬度和高度是向後的。 – 2013-05-18 03:28:13

+0

很好的答案。這篇文章實際上是剪輯圖像,而標記的答案只是掩蓋了圖像。這對我而言非常重要,因爲我必須在圓形圖像周圍繪製白色邊框。使用標記的答案方法,圖像中的像素流入邊界(使其看起來很糟糕)。這篇文章使邊框看起來很完美! – rocky 2016-10-10 23:40:00

4

斯威夫特版本:

func roundCorners(image: NSImage, width: CGFloat = 192, height: CGFloat = 192) -> NSImage { 
    let xRad = width/2 
    let yRad = height/2 
    let existing = image 
    let esize = existing.size 
    let newSize = NSMakeSize(esize.width, esize.height) 
    let composedImage = NSImage(size: newSize) 

    composedImage.lockFocus() 
    let ctx = NSGraphicsContext.currentContext() 
    ctx?.imageInterpolation = NSImageInterpolation.High 

    let imageFrame = NSRect(x: 0, y: 0, width: width, height: height) 
    let clipPath = NSBezierPath(roundedRect: imageFrame, xRadius: xRad, yRadius: yRad) 
    clipPath.windingRule = NSWindingRule.EvenOddWindingRule 
    clipPath.addClip() 

    let rect = NSRect(x: 0, y: 0, width: newSize.width, height: newSize.height) 
    image.drawAtPoint(NSZeroPoint, fromRect: rect, operation: NSCompositingOperation.CompositeSourceOver, fraction: 1) 
    composedImage.unlockFocus() 

    return composedImage 
} 

// then 
roundCorners(image) 
roundCorners(image, width: 512, height: 512) 
+0

謝謝,保羅;簡單而甜蜜:)(剛修復了一些硬編碼的值;等待同行評審。) – 2015-01-06 14:30:33

+0

不錯的工作,謝謝。對於那些從interwebs到達的人,一定要改變'width','height','xRadius'和'yRadius'以匹配你舍入的對象的尺寸。 – 2015-01-27 21:41:34

+0

NSMakeSize()的參數是相反的,無論如何你最好使用NSize初始化器:let newSize = NSSize(width:esize.width,height:esize.height) – 2016-01-16 17:56:12