codememo

UI이미지 색상 변경

tipmemo 2023. 7. 2. 20:45
반응형

UI이미지 색상 변경

UI 이미지의 색상을 변경하려고 합니다.내 코드:

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

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

iOS 7 이후로, 이것이 가장 간단한 방법입니다.

목표-C:

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

Swift 2.0:

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

Swift 4.0:

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

스토리보드:

먼저 이미지를 자산에서 템플릿(오른쪽 막대 - 렌더링 이름)으로 구성합니다.그러면 이미지의 색상이 적용된 틴트 색상이 될 것입니다.enter image description here

이것은 위의 답변과 거의 비슷하지만, 약간 단축되었습니다.이렇게 하면 이미지가 마스크로만 사용되고 실제로는 이미지에 "배색"하거나 색상을 지정하지 않습니다.

목표 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()

이미지에 색을 입히는 또 다른 방법은 단순히 이미지에 일정한 색을 곱하는 것입니다.때로는 검은색 영역의 색상 값을 "올리지" 않고 이미지의 상대적 강도를 동일하게 유지하기 때문에 더 좋습니다.색조로 오버레이를 사용하면 대비가 평평해지는 경향이 있습니다.

사용하는 코드는 다음과 같습니다.

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

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

}

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

프로그래밍 방식으로 할 필요가 없다면 Xcode UI를 사용하면 됩니다.

이미지 자산 폴더의 이미지로 이동하는 경우 오른쪽에서 검사자를 열면 다음 옵션이 포함된 "다른 이름으로 렌더링" 드롭다운이 표시됩니다.

  1. 체납
  2. 원래의
  3. 템플릿

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

enter image description here

다음 이미지 참조:

enter image description here

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

iOS 13 이상의 경우:

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

@Anna의 답변을 기반으로 swift 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
}

Anna의 코드는 kCGBLendModeMultiply가 아닌 kCGBLendModeNormal을 사용하여 색상이 지정된 .image 배경에 UIImage.image를 복사하는 데 적합합니다.예를 들어.self.mainImage.image = [self NormalImageByConstantColor: self.mainImage.image withColor: yourColor];색상의 불투명도를 유지하면서 색상 위에 mainImage.image의 내용을 배치합니다.이렇게 하면 카메라 롤에 저장할 이미지 뒤에 불투명한 배경색을 배치하는 문제가 해결되었습니다.

스위프트 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!
    }
}

안나의 놀라운 코드의 스위프트 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!
    }
}

언급URL : https://stackoverflow.com/questions/12872680/changing-uiimage-color

반응형