2009-12-04 115 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