سؤال

لدي صورة ذات تدرج رمادي وأريد استخدامها لرسم عناصر تحكم الكاكاو.تحتوي الصورة على مستويات مختلفة من اللون الرمادي.عندما يكون أحلك، أريد أن أرسم لون خفيف محدد أغمق.أريد أن تكون شفافة حيث تكون الصورة المصدر بيضاء.

في الأساس، أريد إعادة إنتاج سلوك tintColor الذي يظهر في UINavigationBar على iPhone.

لقد استكشفت حتى الآن عدة خيارات:

  • ارسم لون الصبغة على الصورة الرمادية باستخدام تكوين Soundover -> هذا يتطلب لونًا غير معتمدًا -> النتيجة تخرج أكثر من ذلك بكثير مما هو مطلوب

  • استخدم cimultiplycompositing cifilter لتلميخ الصورة -> لا يمكنني [ciimage drawatpoint: fromrect: العملية: الكسر:] لرسم جزء فقط من الصورة.نفس الشيء يعمل بشكل جيد مع 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 بلون مختلف؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top