objective c - ग्रेस्केल NSImage(या CIImage) को छूना




objective-c cocoa (5)

मेरे पास एक ग्रेस्केल चित्र है जो मैं कोको नियंत्रणों को चित्रित करने के लिए उपयोग करना चाहता हूं। छवि में ग्रे के विभिन्न स्तर हैं। यह सबसे अंधेरा कहां है, मैं इसे एक विशिष्ट टिंट रंग अंधेरे को आकर्षित करना चाहता हूं। मुझे यह पारदर्शी होना चाहिए जहां स्रोत छवि सफेद है

असल में, मैं iPhone पर UINavigationBar में टिंटकोलर के व्यवहार को पुन: उत्पन्न करना चाहता हूं।

अब तक मैंने कई विकल्पों का पता लगाया है:

  • SourceOver संरचना का उपयोग करके ग्रेस्केल छवि पर टिंट रंग ड्रा -> इसमें गैर-अपारदर्शी टिन रंग की आवश्यकता होती है - परिणाम वांछित से ज्यादा गहरा होता है

  • छवि का टिंट करने के लिए CIMultiplyCompositing CIFilter का उपयोग करें -> मैं छवि के केवल एक हिस्से को आकर्षित करने के लिए [CIImage drawAtPoint: fromRect: ऑपरेशन: अंश:] नहीं कर सकता। NSImage के साथ ठीक एक ही काम करता है -> मुझे कभी-कभी दुर्घटनाएं मिलती हैं जो मैं समझ नहीं सका

  • एक मुखौटा में ग्रेस्केल छवि को रूपांतरित करें आईई ब्लैक अपारदर्शी होना चाहिए। सफेद पारदर्शी होना चाहिए। ग्रे में मध्यवर्ती अल्फा मान होना चाहिए। -> यह सबसे अच्छा समाधान प्रतीत होता है -> मैं कोशिश कर सकता हूं कि मैं इसे हासिल नहीं कर सकता।


CIMultiplyCompositing फ़िल्टर निश्चित रूप से ऐसा करने का तरीका है। यदि यह दुर्घटनाग्रस्त है, तो क्या आप एक स्टैक ट्रेस पोस्ट कर सकते हैं? मैं सीआईफ़िलर्स का भारी इस्तेमाल करता हूं और समस्याओं को दुर्घटनाग्रस्त नहीं करता हूं।

//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];

- (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];
}

एक्सटेंशन के रूप में स्विफ्ट संस्करण:

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
    }
}

ब्लूबैम्बो के जवाब का एक स्विफ्ट कार्यान्वयन:

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 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
        }
    }
}




core-image