둥근 NSImage를 그리는 방법
-
13-09-2019 - |
문제
나는 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];
}
}
...
이 방법에 대한 아이디어가 있습니까?
해결책
이미지를 그릴 때 클립 세트를 유지하고 대신 컨텍스트를 복원해야 합니다.또한 대상 불투명도를 고려하지 않고 이미지를 정상적으로 그리려면 "in" 합성을 사용하는 것이 아니라 "over"를 사용하고 싶다고 생각합니다.다음과 같이 시도해 보세요:
[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];
다른 팁
+ (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;
}
스위프트 버전 :
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)
당신이 잘못한 것에 대한 좀 더 많은 정보를 제공하기 위해 :
GSTATE를 저장하고 복원하는 목적은 GSTATE에 대한 변경 사항을 취소 할 수 있어야합니다. 귀하의 경우, 클립을 클리핑 한 후 GSAVE를 복원하면 클립을 실시하십시오. 그렇기 때문에 솔루션 (Rhult가 설명한)이 원하는 것을 그려야하는 것을 그려야합니다. ~ 전에 당신은 gstate를 복원합니다.
제휴하지 않습니다 StackOverflow