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

이 코드는 작동하지만 얻은 이미지는 그렇게 좋지 않습니다. 반환 된 이미지의 경계 픽셀이 간헐적이며 첫 번째 이미지처럼 매끄럽지 않습니다. 이 문제를 어떻게 해결할 수 있습니까?


답변:


264

iOS 7부터 이것은 가장 간단한 방법입니다.

목표 -C :

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 : 색상 정보를 무시하고 항상 이미지를 템플릿 이미지로 그립니다." 좋은!
Tieme

3
2.0 스위프트에서theImageView.image? = (theImageView.image?.imageWithRenderingMode(.AlwaysTemplate))! theImageView.tintColor = UIColor.magentaColor()
ColossalChris

@AnkishJain이 접근 방식에 대한 성능 문제가 있습니까?
Ríomhaire

3
이것은 이미지의 색상을 변경하는 것이 아니라 다른 색조 (색상)로 렌더링하도록 뷰에 지시합니다.
Steve Kuo

@Womble 정말 아닙니다. 실제로 모든 UIImage에 이것을 사용할 수 있습니다. img = [img imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; [button setTintColor:[UIColor redColor]]; [button setImage:img forState:UIControlStateNormal];@Ankish 감사합니다!
Motasim

31

이것은 위의 대답과 거의 같지만 약간 짧아졌습니다. 이것은 이미지를 마스크로만 취하고 실제로 이미지를 "곱하거나"색칠하지 않습니다.

목표 C :

    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);버전은 비 레티 나 그래픽 만 생성하므로 사용해야 합니다.
Nikola Lajic

user1270061은 제 경험상 그렇게하는 방법입니다. "burning"에 대한 다른 답변은 분명히 특정 색상의 소스 이미지가 필요합니다. 이것은 소스 픽셀의 알파 값을 사용하고 원하는 색상과 결합하여 완벽합니다.
Jason

완벽합니다. 저에게 잘 맞는 유일한 답변입니다. (5 월 16 일 ')
trdavidson

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

Swift 버전

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

내가 찾고 있던 정확한 솔루션! 감사!
비르 우리

가상 벽화 앱을 만들고 싶다면 어떻게하나요? 이것은 효과가 있습니다. 이미지의 벽에 색을 입히고 싶다면 어떨까요? 이 링크하시기 바랍니다 살펴보십시오 : - stackoverflow.com/questions/27482508/...
Shailesh

이것은 다른 솔루션보다 훨씬 잘 작동합니다.
Matt Hudson

3
이것은 물체 자체가 아닌 물체 배경에만 착색되었습니다.
user3562927

7

Swift 3.0에서

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

Swift 2.0에서

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

Swift 개척자를 즐기십시오


5
코드는 괜찮지 만 게시물은 UIImage에 관한 것입니다. 우리는 항상 UIImageViews를 다루지는 않습니다.
HenryRootTwo

6

Swift 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를 사용하여 할 수 있습니다.

이미지 자산 폴더의 이미지로 이동하면 오른쪽에있는 검사기를 열고 다음 옵션이있는 "Render As"드롭 다운이 있습니다.

  1. 기본
  2. 실물
  3. 주형

템플릿을 선택한 후에는 Xcode 스토리 보드 UI를 사용하든 프로그래밍 방식 으로든 원하는대로 이미지의 tintColor를 변경할 수 있습니다.

여기에 이미지 설명 입력

이 이미지를보십시오 :

여기에 이미지 설명 입력


XCODE 8을 사용하고 있습니까?
doxsi

2

@Anna의 대답에 대한 내 적응이 있습니다. 여기에 두 가지 핵심 사항이 있습니다.

  • 사용하다 destinationIn혼합 모드
  • UIGraphicsBeginImageContextWithOptions(backgroundSize, false, UIScreen.main.scale)부드러운 이미지를 얻으려면 전화

Swift 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를 확장 할 때 이미지를 전달하는 이유는 무엇입니까? 당신은 당신의 방법을 static 키워드를 제거하고 바로 사용해야합니다 self당신의 방법 내부 및 불필요한 이미지 매개 변수를 제거
레오 버스들이시길

1

@Anna의 답변을 바탕으로 신속한 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

Anna의 코드는 kCGBlendModeMultiply가 아닌 kCGBlendModeNormal을 사용하여 색상이 지정된 .image 배경 위에 UIImage.image를 복사하는 데 적합합니다. 예를 들어, self.mainImage.image = [self NormalImageByConstantColor: self.mainImage.image withColor: yourColor];yourColor의 불투명도를 유지하면서 mainImage.image의 내용을 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

Anna의 놀라운 코드의 Swift 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!
    }
}

0

iOS 13 이상 :

let redImage = image.withTintColor(.red, renderingMode: .alwaysTemplate)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.