그레이 스케일 nsimage (또는 ciimage) 주석
-
06-07-2019 - |
문제
코코아 컨트롤을 그리는 데 사용하고 싶은 그레이 스케일 이미지가 있습니다. 이미지에는 다양한 수준의 회색이 있습니다. 가장 어두운 곳에서는 지정된 색조 색상을 가장 어두워지기를 원합니다. 소스 이미지가 흰색 인 경우 투명 해지기를 원합니다.
기본적으로 iPhone의 UinavigationBar에서 볼 수있는 TintColor의 동작을 재현하고 싶습니다.
지금까지 몇 가지 옵션을 탐색했습니다.
소스 오버 컴포지션을 사용하여 그레이 스케일 이미지 위에 색조 색상을 그리십시오 -> 이것은 비대형 색조 색상이 필요합니다 -> 결과는 원하는 것보다 훨씬 어둡게 나옵니다.
cimultiplycompositing cifilter를 사용하여 이미지를 착색하십시오 -> I Ca n't Cailage [ciimage drawAtpoint : fromEct : fraction :]는 이미지의 일부만 그려냅니다. nsimage와 동일하게 작동합니다 -> 가끔 충돌이 발생하여 이해할 수 없습니다.
그레이 스케일 이미지를 마스크로 변환하십시오. 즉, 검은 색은 불투명해야합니다. 흰색은 투명해야합니다. 회색에는 중간 알파 값이 있어야합니다. -> 이것은 최상의 솔루션 인 것 같습니다 -> 내가 할 수있는 것처럼 시도해 볼 수 없습니다.
해결책 3
- (NSImage *)imageTintedWithColor:(NSColor *)tint
{
if (tint != nil) {
NSSize size = [self size];
NSRect bounds = { NSZeroPoint, size };
NSImage *tintedImage = [[NSImage alloc] initWithSize:size];
[tintedImage lockFocus];
CIFilter *colorGenerator = [CIFilter filterWithName:@"CIConstantColorGenerator"];
CIColor *color = [[[CIColor alloc] initWithColor:tint] autorelease];
[colorGenerator setValue:color forKey:@"inputColor"];
CIFilter *monochromeFilter = [CIFilter filterWithName:@"CIColorMonochrome"];
CIImage *baseImage = [CIImage imageWithData:[self TIFFRepresentation]];
[monochromeFilter setValue:baseImage forKey:@"inputImage"];
[monochromeFilter setValue:[CIColor colorWithRed:0.75 green:0.75 blue:0.75] forKey:@"inputColor"];
[monochromeFilter setValue:[NSNumber numberWithFloat:1.0] forKey:@"inputIntensity"];
CIFilter *compositingFilter = [CIFilter filterWithName:@"CIMultiplyCompositing"];
[compositingFilter setValue:[colorGenerator valueForKey:@"outputImage"] forKey:@"inputImage"];
[compositingFilter setValue:[monochromeFilter valueForKey:@"outputImage"] forKey:@"inputBackgroundImage"];
CIImage *outputImage = [compositingFilter valueForKey:@"outputImage"];
[outputImage drawAtPoint:NSZeroPoint
fromRect:bounds
operation:NSCompositeCopy
fraction:1.0];
[tintedImage unlockFocus];
return [tintedImage autorelease];
}
else {
return [[self copy] autorelease];
}
}
- (NSImage*)imageCroppedToRect:(NSRect)rect
{
NSPoint point = { -rect.origin.x, -rect.origin.y };
NSImage *croppedImage = [[NSImage alloc] initWithSize:rect.size];
[croppedImage lockFocus];
{
[self compositeToPoint:point operation:NSCompositeCopy];
}
[croppedImage unlockFocus];
return [croppedImage autorelease];
}
다른 팁
위의 솔루션은 나에게 효과가 없었습니다. 그러나이 쉬운 솔루션은 저에게 훌륭하게 작동합니다
- (NSImage *)imageTintedWithColor:(NSColor *)tint
{
NSImage *image = [self copy];
if (tint) {
[image lockFocus];
[tint set];
NSRect imageRect = {NSZeroPoint, [image size]};
NSRectFillUsingOperation(imageRect, NSCompositeSourceAtop);
[image unlockFocus];
}
return image;
}
Bluebamboo의 답변의 신속한 구현 :
func tintedImage(_ image: NSImage, tint: NSColor) -> NSImage {
guard let tinted = image.copy() as? NSImage else { return image }
tinted.lockFocus()
tint.set()
let imageRect = NSRect(origin: NSZeroPoint, size: image.size)
NSRectFillUsingOperation(imageRect, .sourceAtop)
tinted.unlockFocus()
return tinted
}
확장 형태의 신속한 버전 :
extension NSImage {
func tintedImageWithColor(color:NSColor) -> NSImage {
let size = self.size
let imageBounds = NSMakeRect(0, 0, size.width, size.height)
let copiedImage = self.copy() as! NSImage
copiedImage.lockFocus()
color.set()
NSRectFillUsingOperation(imageBounds, .CompositeSourceAtop)
copiedImage.unlockFocus()
return copiedImage
}
}
cimultiplycompositing 필터는 분명히이를 수행하는 방법입니다. 충돌하는 경우 스택 추적을 게시 할 수 있습니까? 나는 cifilters를 많이 사용하고 충돌 문제가 없습니다.
//assume inputImage is the greyscale CIImage you want to tint
CIImage* outputImage = nil;
//create some green
CIFilter* greenGenerator = [CIFilter filterWithName:@"CIConstantColorGenerator"];
CIColor* green = [CIColor colorWithRed:0.30 green:0.596 blue:0.172];
[greenGenerator setValue:green forKey:@"inputColor"];
CIImage* greenImage = [greenGenerator valueForKey:@"outputImage"];
//apply a multiply filter
CIFilter* filter = [CIFilter filterWithName:@"CIMultiplyCompositing"];
[filter setValue:greenImage forKey:@"inputImage"];
[filter setValue:inputImage forKey:@"inputBackgroundImage"];
outputImage = [filter valueForKey:@"outputImage"];
[outputImage drawAtPoint:NSZeroPoint fromRect:NSRectFromCGRect([outputImage extent]) operation:NSCompositeCopy fraction:1.0];
나는 이미지 쇼의 원래 색상을 보지 않고 알파가있는 색조 색상의 이미지를 색조하고 싶었습니다. 다음은 다음과 같은 방법입니다.
extension NSImage {
func tinting(with tintColor: NSColor) -> NSImage {
guard let cgImage = self.cgImage(forProposedRect: nil, context: nil, hints: nil) else { return self }
return NSImage(size: size, flipped: false) { bounds in
guard let context = NSGraphicsContext.current()?.cgContext else { return false }
tintColor.set()
context.clip(to: bounds, mask: cgImage)
context.fill(bounds)
return true
}
}
}
보다 미세한 입자를 위해, 당신은 다음과 같은 접근법을 사용하여 다항식 색상 접근법을 사용할 수 있습니다. 회전하는 nsprogressindicator를 다른 색상으로 어떻게 표시 할 수 있습니까?