UIImage रंग बदलना


100

मैं UIImage का रंग बदलने की कोशिश कर रहा हूं। मेरा कोड:

-(UIImage *)coloredImage:(UIImage *)firstImage withColor:(UIColor *)color {
    UIGraphicsBeginImageContext(firstImage.size);

    CGContextRef context = UIGraphicsGetCurrentContext();
    [color setFill];

    CGContextTranslateCTM(context, 0, firstImage.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    CGContextSetBlendMode(context, kCGBlendModeCopy);
    CGRect rect = CGRectMake(0, 0, firstImage.size.width, firstImage.size.height);
    CGContextDrawImage(context, rect, firstImage.CGImage);

    CGContextClipToMask(context, rect, firstImage.CGImage);
    CGContextAddRect(context, rect);
    CGContextDrawPath(context,kCGPathElementMoveToPoint);

    UIImage *coloredImg = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return coloredImg;
}

यह कोड काम करता है, लेकिन प्राप्त की गई छवि इतनी अच्छी नहीं है जितना ज़ोर से हो सकती है: लौटी हुई छवि के सीमा पिक्सेल रुक-रुक कर होते हैं और मेरी पहली छवि में उतने सहज नहीं होते हैं। मैं यह मुश्किल कैसे सुलझाऊँ?


जवाबों:


263

IOS 7 के बाद से, यह इसे करने का सबसे सरल तरीका है।

उद्देश्य सी:

theImageView.image = [theImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[theImageView setTintColor:[UIColor redColor]];

स्विफ्ट 2.0:

theImageView.image = theImageView.image?.imageWithRenderingMode(.AlwaysTemplate) 
theImageView.tintColor = UIColor.magentaColor()

स्विफ्ट 4.0:

theImageView.image = theImageView.image?.withRenderingMode(.alwaysTemplate) 
theImageView.tintColor = .magenta

स्टोरीबोर्ड:

पहले अपनी संपत्ति में छवि को टेम्पलेट के रूप में कॉन्फ़िगर करें (सही बार - रेंडर के रूप में)। तब छवि का रंग टिंट रंग लागू किया जाएगा। यहां छवि विवरण दर्ज करें


"UIImageRenderingModeAlwaysTemplate: हमेशा छवि को टेम्पलेट छवि के रूप में ड्रा करें, इसकी रंग जानकारी को अनदेखा करते हुए।" अच्छा!
तीये की

3
स्विफ्ट में 2.0+theImageView.image? = (theImageView.image?.imageWithRenderingMode(.AlwaysTemplate))! theImageView.tintColor = UIColor.magentaColor()
कोलोसालक्रिस

@AnkishJain इस दृष्टिकोण के आसपास कोई प्रदर्शन चिंताएं हैं?
रिओमेइरे

3
यह छवि का रंग नहीं बदलता है, बल्कि इसे अलग टिंट (रंग) के साथ देखने का निर्देश देता है।
स्टीव कू

@ वास्तव में नहीं। आप वास्तव में किसी भी UIImage के लिए इसका उपयोग कर सकते हैं। img = [img imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; [button setTintColor:[UIColor redColor]]; [button setImage:img forState:UIControlStateNormal];@ धन्यवाद धन्यवाद!
13

31

यह बहुत ऊपर जवाब है, लेकिन थोड़ा छोटा है। यह केवल छवि को एक मुखौटा के रूप में लेता है और वास्तव में छवि को "गुणा" या रंग नहीं करता है।

उद्देश्य सी:

    UIColor *color = <# UIColor #>;
    UIImage *image = <# UIImage #>;// Image to mask with
    UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [color setFill];
    CGContextTranslateCTM(context, 0, image.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextClipToMask(context, CGRectMake(0, 0, image.size.width, image.size.height), [image CGImage]);
    CGContextFillRect(context, CGRectMake(0, 0, image.size.width, image.size.height));

    UIImage *coloredImg = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

स्विफ्ट:

    let color: UIColor = <# UIColor #>
    let image: UIImage = <# UIImage #> // Image to mask with
    UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
    let context = UIGraphicsGetCurrentContext()
    color.setFill()
    context?.translateBy(x: 0, y: image.size.height)
    context?.scaleBy(x: 1.0, y: -1.0)
    context?.clip(to: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height), mask: image.cgImage!)
    context?.fill(CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
    let coloredImg = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

2
आपको उपयोग करना चाहिए UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);क्योंकि आपका संस्करण केवल गैर रेटिना ग्राफिक्स बनाएगा।
निकोला लाजिक

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

बिल्कुल सही - केवल जवाब है कि मेरे लिए अच्छा काम किया। (16 मई)
19

10

एक छवि को टिंट करने का दूसरा तरीका यह है कि इसे बस एक स्थिर रंग से गुणा करें। कभी-कभी, यह बेहतर होता है क्योंकि यह काले क्षेत्रों में रंग मूल्यों को "नहीं" उठाता है; यह छवि में सापेक्ष तीव्रता समान रखता है। टिंट के रूप में एक ओवरले का उपयोग करना इसके विपरीत को समतल करने के लिए जाता है।

यह मेरे द्वारा उपयोग किया जाने वाला कोड है:

UIImage *MultiplyImageByConstantColor( UIImage *image, UIColor *color ) {

    CGSize backgroundSize = image.size;
    UIGraphicsBeginImageContext(backgroundSize);

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    CGRect backgroundRect;
    backgroundRect.size = backgroundSize;
    backgroundRect.origin.x = 0;
    backgroundRect.origin.y = 0;

    CGFloat r,g,b,a;
    [color getRed:&r green:&g blue:&b alpha:&a];
    CGContextSetRGBFillColor(ctx, r, g, b, a);
    CGContextFillRect(ctx, backgroundRect);

    CGRect imageRect;
    imageRect.size = image.size;
    imageRect.origin.x = (backgroundSize.width - image.size.width)/2;
    imageRect.origin.y = (backgroundSize.height - image.size.height)/2;

    // Unflip the image
    CGContextTranslateCTM(ctx, 0, backgroundSize.height);
    CGContextScaleCTM(ctx, 1.0, -1.0);

    CGContextSetBlendMode(ctx, kCGBlendModeMultiply);
    CGContextDrawImage(ctx, imageRect, image.CGImage);

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return newImage;
}

स्विफ्ट संस्करण

extension UIImage{

    static func multiplyImageByConstantColor(image:UIImage,color:UIColor)->UIImage{
        let backgroundSize = image.size
        UIGraphicsBeginImageContext(backgroundSize)

        let ctx = UIGraphicsGetCurrentContext()

        var backgroundRect=CGRect()
        backgroundRect.size = backgroundSize
        backgroundRect.origin.x = 0
        backgroundRect.origin.y = 0

        var r:CGFloat
        var g:CGFloat
        var b:CGFloat
        var a:CGFloat
        color.getRed(&r, green: &g, blue: &b, alpha: &a)
        CGContextSetRGBFillColor(ctx, r, g, b, a)
        CGContextFillRect(ctx, backgroundRect)

        var imageRect=CGRect()
        imageRect.size = image.size
        imageRect.origin.x = (backgroundSize.width - image.size.width)/2
        imageRect.origin.y = (backgroundSize.height - image.size.height)/2

        // Unflip the image
        CGContextTranslateCTM(ctx, 0, backgroundSize.height)
        CGContextScaleCTM(ctx, 1.0, -1.0)

        CGContextSetBlendMode(ctx, .Multiply)
        CGContextDrawImage(ctx, imageRect, image.CGImage)

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage
    }
}

बिल्कुल समाधान मैं देख रहा था! धन्यवाद!
हमें 20

क्या होगा यदि मैं एक आभासी दीवार पेंटिंग ऐप बनाना चाहता हूं? यह काम करता है, क्या होगा अगर छवि में दीवारों को बस रंग देना है। कृपया इस लिंक पर एक नज़र डालें: - stackoverflow.com/questions/27482508/…
शैलेश

यह वहाँ से बाहर कुछ अन्य समाधानों की तुलना में बहुत बेहतर काम करता है।
मैट हडसन

3
इसने मेरे लिए केवल वस्तु पृष्ठभूमि को चित्रित किया, वस्तु को नहीं।
user3562927

7

स्विफ्ट 3.0 में

imageView.image? = (imageView.image?.withRenderingMode(.alwaysTemplate))!
imageView.tintColor = UIColor.magenta

स्विफ्ट 2.0 में

yourImage.image? = (yourImage.image?.imageWithRenderingMode(.AlwaysTemplate))!
yourImage.tintColor = UIColor.magentaColor()

आप का आनंद लें अग्रणी स्विफ्ट


5
कोड ठीक है, लेकिन पोस्ट UIImage के बारे में है। हम हमेशा UIImageViews के साथ काम नहीं कर रहे हैं।
हेनरीरूटोवो

5

स्विफ्ट 4.2 समाधान

extension UIImage {
    func withColor(_ color: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        guard let ctx = UIGraphicsGetCurrentContext(), let cgImage = cgImage else { return self }
        color.setFill()
        ctx.translateBy(x: 0, y: size.height)
        ctx.scaleBy(x: 1.0, y: -1.0)
        ctx.clip(to: CGRect(x: 0, y: 0, width: size.width, height: size.height), mask: cgImage)
        ctx.fill(CGRect(x: 0, y: 0, width: size.width, height: size.height))
        guard let colored = UIGraphicsGetImageFromCurrentImageContext() else { return self }
        UIGraphicsEndImageContext()
        return colored
    }
}

// Usage:
// let redImage = UIImage().withColor(.red)

5

IOS 10 से शुरू होकर आप उपयोग कर सकते हैं UIGraphicsImageRenderer:

extension UIImage {

    func colored(_ color: UIColor) -> UIImage {
        let renderer = UIGraphicsImageRenderer(size: size)
        return renderer.image { context in
            color.setFill()
            self.draw(at: .zero)
            context.fill(CGRect(x: 0, y: 0, width: size.width, height: size.height), blendMode: .sourceAtop)
        }
    }

}

3

यदि आपको इसे प्रोग्रामेटिक रूप से करने की आवश्यकता नहीं है, तो आप इसे केवल Xcode UI का उपयोग करके कर सकते हैं।

यदि आप अपनी छवि संपत्ति फ़ोल्डर में छवि पर जाते हैं, तो दाहिने हाथ पर निरीक्षक खोलें और निम्नलिखित विकल्पों के साथ "रेंडर अस" ड्रॉपडाउन है:

  1. चूक
  2. मूल
  3. खाका

एक बार जब आप टेम्प्लेट का चयन कर लेते हैं, तो आप जिस छवि को चाहते हैं, उसका रंग बदल सकते हैं - चाहे वह Xcode स्टोरीबोर्ड UI का उपयोग कर रहा हो या प्रोग्रामेटिक रूप से।

यहां छवि विवरण दर्ज करें

इस छवि को देखें:

यहां छवि विवरण दर्ज करें


क्या आप XCODE 8 का उपयोग कर रहे हैं?
doxsi

2

यहाँ मेरे अन्ना के उत्तर का अनुकूलन है। दो प्रमुख बिंदु यहां:

  • destinationInब्लेंडिंग मोड का उपयोग करें
  • UIGraphicsBeginImageContextWithOptions(backgroundSize, false, UIScreen.main.scale)सुचारू छवि प्राप्त करने के लिए कॉल करें

स्विफ्ट 3 में कोड :

extension UIImage {

    static func coloredImage(image: UIImage?, color: UIColor) -> UIImage? {

        guard let image = image else {
            return nil
        }

        let backgroundSize = image.size
        UIGraphicsBeginImageContextWithOptions(backgroundSize, false, UIScreen.main.scale)

        let ctx = UIGraphicsGetCurrentContext()!

        var backgroundRect=CGRect()
        backgroundRect.size = backgroundSize
        backgroundRect.origin.x = 0
        backgroundRect.origin.y = 0

        var r:CGFloat = 0
        var g:CGFloat = 0
        var b:CGFloat = 0
        var a:CGFloat = 0
        color.getRed(&r, green: &g, blue: &b, alpha: &a)
        ctx.setFillColor(red: r, green: g, blue: b, alpha: a)
        ctx.fill(backgroundRect)

        var imageRect = CGRect()
        imageRect.size = image.size
        imageRect.origin.x = (backgroundSize.width - image.size.width) / 2
        imageRect.origin.y = (backgroundSize.height - image.size.height) / 2

        // Unflip the image
        ctx.translateBy(x: 0, y: backgroundSize.height)
        ctx.scaleBy(x: 1.0, y: -1.0)

        ctx.setBlendMode(.destinationIn)
        ctx.draw(image.cgImage!, in: imageRect)

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage!
    }
}

2
UIImage का विस्तार करते समय आप छवि को क्यों पास करते हैं? आपको अपनी विधि के स्थैतिक कीवर्ड को हटा देना चाहिए और बस selfअपनी विधि के अंदर उपयोग करना चाहिए और अनावश्यक छवि पैरामीटर को हटा देना चाहिए
Leo Dabus

1

@ अन्ना के जवाब के आधार पर और मैं तेजी से 2.2 के लिए फिर से लिखना और अल्फा चैनल के साथ छवि को संभालता हूं:

static func multiplyImageByConstantColor(image:UIImage,color:UIColor)->UIImage{
    let backgroundSize = image.size
    UIGraphicsBeginImageContext(backgroundSize)

    let ctx = UIGraphicsGetCurrentContext()

    var backgroundRect=CGRect()
    backgroundRect.size = backgroundSize
    backgroundRect.origin.x = 0
    backgroundRect.origin.y = 0

    var r:CGFloat = 0
    var g:CGFloat = 0
    var b:CGFloat = 0
    var a:CGFloat = 0
    color.getRed(&r, green: &g, blue: &b, alpha: &a)
    CGContextSetRGBFillColor(ctx, r, g, b, a)

    // Unflip the image
    CGContextTranslateCTM(ctx, 0, backgroundSize.height)
    CGContextScaleCTM(ctx, 1.0, -1.0)
    CGContextClipToMask(ctx, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage);
    CGContextFillRect(ctx, backgroundRect)

    var imageRect=CGRect()
    imageRect.size = image.size
    imageRect.origin.x = (backgroundSize.width - image.size.width)/2
    imageRect.origin.y = (backgroundSize.height - image.size.height)/2


    CGContextSetBlendMode(ctx, .Multiply)
    CGContextDrawImage(ctx, imageRect, image.CGImage)

    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage
}

0

अन्ना का कोड UIImage.image को एक रंगीन .image पृष्ठभूमि पर कॉपी करने के लिए अच्छी तरह से kCGBlendModeMultiply के बजाय kCGBlendModeNormal का उपयोग करके काम करता है। उदाहरण के लिए, self.mainImage.image = [self NormalImageByConstantColor: self.mainImage.image withColor: yourColor];मुख्य रंग की सामग्री को अपने रंग के तिरंगे के ऊपर रखें। इसने कैमरा रोल को सहेजने के लिए एक छवि के पीछे अस्पष्टता के साथ एक पृष्ठभूमि रंग रखने की मेरी समस्या को हल किया।


0

स्विफ्ट 3:

extension UIImage{

    static func multiplyImageByConstantColor(image:UIImage,color:UIColor) -> UIImage{

        let backgroundSize = image.size
        UIGraphicsBeginImageContext(backgroundSize)

        guard let ctx = UIGraphicsGetCurrentContext() else {return image}

        var backgroundRect=CGRect()
        backgroundRect.size = backgroundSize
        backgroundRect.origin.x = 0
        backgroundRect.origin.y = 0

        var r:CGFloat = 0
        var g:CGFloat = 0
        var b:CGFloat = 0
        var a:CGFloat = 0
        color.getRed(&r, green: &g, blue: &b, alpha: &a)
        ctx.setFillColor(red: r, green: g, blue: b, alpha: a)

        // Unflip the image
        ctx.translateBy(x: 0, y: backgroundSize.height)
        ctx.scaleBy(x: 1.0, y: -1.0)
        ctx.clip(to: CGRect(0, 0, image.size.width, image.size.height), mask: image.cgImage!)
        ctx.fill(backgroundRect)


        var imageRect=CGRect()
        imageRect.size = image.size
        imageRect.origin.x = (backgroundSize.width - image.size.width)/2
        imageRect.origin.y = (backgroundSize.height - image.size.height)/2


        ctx.setBlendMode(.multiply)
        ctx.draw(image.cgImage!, in: imageRect)

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage!
    }
}

0

अन्ना के अद्भुत कोड का स्विफ्ट 3.0 संस्करण:

extension UIImage{

    static func multiplyImageByConstantColor(image:UIImage,color:UIColor)-> UIImage {
        let backgroundSize = image.size
        UIGraphicsBeginImageContext(backgroundSize)

        let ctx = UIGraphicsGetCurrentContext()!

        var backgroundRect=CGRect()
        backgroundRect.size = backgroundSize
        backgroundRect.origin.x = 0
        backgroundRect.origin.y = 0

        let myFloatForR = 0
        var r = CGFloat(myFloatForR)
        let myFloatForG = 0
        var g = CGFloat(myFloatForG)
        let myFloatForB = 0
        var b = CGFloat(myFloatForB)
        let myFloatForA = 0
        var a = CGFloat(myFloatForA)

        color.getRed(&r, green: &g, blue: &b, alpha: &a)
        ctx.setFillColor(red: r, green: g, blue: b, alpha: a)
        ctx.fill(backgroundRect)

        var imageRect=CGRect()
        imageRect.size = image.size
        imageRect.origin.x = (backgroundSize.width - image.size.width)/2
        imageRect.origin.y = (backgroundSize.height - image.size.height)/2

        // Unflip the image
        ctx.translateBy(x: 0, y: backgroundSize.height)
        ctx.scaleBy(x: 1.0, y: -1.0)

        ctx.setBlendMode(.multiply)
        ctx.draw(image.cgImage!, in: imageRect)

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage!
    }
}

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.