Frage

Ich habe ein Graustufenbild, das ich für die Erstellung Cocoa Kontrollen verwenden möchten. Das Bild hat verschiedene Graustufen. Wo es am dunkelsten ist, möchte ich es einen bestimmten Farbton Farbe dunkelsten ziehen. Ich will es transparent sein, wo das Quellbild weiß ist.

Grundsätzlich mag ich das Verhalten von tintColor in UINavigationBar auf dem iPhone gesehen reproduzieren.

Bisher habe ich mehrere Möglichkeiten untersucht:

  • Zeichnen Sie die Tönungsfarbe über das Graustufenbild mit SourceOver Zusammensetzung -> Dies erfordert eine nicht-opake Tönung Farbe -> Das Ergebnis kommt viel dunkler als gewünscht

  • Verwenden Sie ein CIMultiplyCompositing CIFilter das Bild zu färben -> Ich kann nicht [CIImage drawAtPoint: fromRect: Betrieb: Fraktion:] nur einen Teil des Bildes zu zeichnen. Das gleiche funktioniert gut mit NSImage -> ich gelegentliche Abstürze, die ich nicht Sinn machen kann

  • Transformieren des Graustufenbildes in eine Maske. D. h Schwarz sollte undurchsichtig sein. Weiß sollte transparent sein. Grau sollte Zwischen Alpha-Werte haben. -> Dies scheint die beste Lösung zu sein -.> Versuchen Sie, wie ich könnte, ich dies nicht erreichen kann,

War es hilfreich?

Lösung 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];
}

Andere Tipps

Die obige Lösung nicht für mich arbeiten. Aber so viel einfachere Lösung funktioniert gut für mich

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

Eine zügige Durchführung von bluebamboo Antwort:

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
}

Swift-Version in Form des Zusatzes:

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

Der CIMultiplyCompositing Filter ist auf jeden Fall die Art und Weise, dies zu tun. Wenn es abstürzt, können Sie einen Stack-Trace schreiben? Ich benutze CIFilters stark und haben keine Probleme abstürzt.

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

Ich wollte ein Bild mit einer Tönung Farbe tönen, die die ursprünglichen Farben des Bildes zeigen, ohne zu sehen, durch alpha hatte. Hier ist, wie können Sie das tun:

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

Für ein feinkörnigen, können Sie ein Polynom Farb Ansatz verwenden, mit dem Ansatz, den ich im folgenden vorgeschlagen: Wie kann ich die Spinnen nSProgressIndicator in einer anderen Farbe angezeigt werden?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top