我正在尝试在NSImage
内创建一个带圆角的NSImageCell
或NSTableView
。我无法得到任何工作。这是我在自定义NSCell
内的最佳内容:
- (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];
}
}
...
关于如何做到这一点的任何想法?
答案 0 :(得分:23)
您需要在绘制图像时保持剪辑集,并在之后恢复上下文。另外我不认为你想要使用“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];
答案 1 :(得分:10)
+ (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;
}
答案 2 :(得分:6)
Swift版本:
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)
答案 3 :(得分:3)
只是提供一些关于你做错了什么的信息:
保存和恢复gstate的目的是能够撤消对gstate的更改。在您的情况下,剪辑后恢复gsave解除剪辑。这就是为什么解决方案(如Rhult所解释的)是在恢复gstate之前绘制你想要剪切的的内容。