使用Kingfisher在Swift中更改图像视图的tintColor。

huangapple go评论67阅读模式
英文:

Change tintcolor image view using kingfihser in swift

问题

我有一个水平的集合视图,所以当选择特定的单元格时会改变图像视图的颜色,问题是当选择图像时,图像的色调颜色成功改变,但某些图像的色调颜色不会按照正确的行为显示为背景颜色在图像上。

这是用于更改图像色调颜色的函数:

func imageWithColor(color1: UIColor) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
    color1.setFill()

    let context = UIGraphicsGetCurrentContext()! as CGContext
    context.translateBy(x: 0, y: self.size.height)
    context.scaleBy(x: 1.0, y: -1.0);
    context.setBlendMode(CGBlendMode.normal)

    let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
    context.clip(to: rect, mask: self.cgImage!)
    context.fill(rect)

    let newImage = UIGraphicsGetImageFromCurrentImageContext()! as UIImage
    UIGraphicsEndImageContext()

    return newImage
}

使用Kingfisher显示图像:

imageProduct.kf.setImage(with: URL(string: "imageurl"), placeholder: nil) { result in
    self.imageProduct.image = self.categoryImg.image?.imageWithColor(color1: UIColor.green)
}

必须成功更改从URL读取的任何图像的色调颜色(这是添加色调颜色时的问题图像的屏幕截图:https://freeimage.host/i/H4nx1s9)。

英文:

I have a horizontal collection view so when selecting the specific cell will change the color of the image view, the problem is when selecting an image tint color changes successfully on images, and some image's tint color does not work with the right behavior display as the background color on the image.

this is the function to change tint color of image

 func imageWithColor(color1: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        color1.setFill()

        let context = UIGraphicsGetCurrentContext()! as CGContext
        context.translateBy(x: 0, y: self.size.height)
        context.scaleBy(x: 1.0, y: -1.0);
        context.setBlendMode(CGBlendMode.normal)

        let rect = CGRectMake(0, 0, self.size.width, self.size.height) as CGRect
        context.clip(to: rect, mask: self.cgImage!)
        context.fill(rect)

        let newImage = UIGraphicsGetImageFromCurrentImageContext()! as UIImage
        UIGraphicsEndImageContext()

        return newImage
    }

display image using kingfihser
` imageProduct.kf.setImage(with: URL(string:"imageurl"), placeholder: nil) { result in

                self.imageProduct.image = self.categoryImg.image?.imageWithColor(color1: UIColor.green)

           }`

The tint color must be changed successfully on any image read from url (this is screenshot from issue image when add tint color https://freeimage.host/i/H4nx1s9).

答案1

得分: 1

这里的问题似乎与如何应用色彩渲染到包含 alpha 通道(透明度)的图像有关。如果图像具有 alpha 通道,那么当应用色彩渲染时,可能不会按预期应用,可能会在图像上显示背景颜色。

一种方法可以是检查图像是否具有 alpha 通道并以不同方式处理它。然而,在您的情况下,最快的解决方案可能是使用 UIImagerenderingMode 属性,该属性控制图像的绘制方式。您可以将其设置为.alwaysTemplate,这将使图像被视为用于与 tintColor 结合使用以创建最终彩色图像的模板。

以下是如何更改您的代码:

func imageWithColor(color1: UIColor) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
    color1.setFill()
    
    let context = UIGraphicsGetCurrentContext()! as CGContext
    context.translateBy(x: 0, y: self.size.height)
    context.scaleBy(x: 1.0, y: -1.0);
    context.setBlendMode(CGBlendMode.normal)
    
    let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
    context.clip(to: rect, mask: self.cgImage!)
    context.fill(rect)
    
    let newImage = UIGraphicsGetImageFromCurrentImageContext()! as UIImage
    UIGraphicsEndImageContext()
    
    return newImage.withRenderingMode(.alwaysTemplate) // 添加这一行
}

imageProduct.kf.setImage(with: URL(string: "imageurl"), placeholder: nil) { result in
    switch result {
    case .success(let value):
        let image = value.image.imageWithColor(color1: .green)
        DispatchQueue.main.async {
            self.imageProduct.image = image
            self.imageProduct.tintColor = .green
        }
    case .failure(let error):
        print("Error: \(error)") // 处理错误
    }
}

在上面的代码中,我们在返回图像之前将图像的 renderingMode 设置为 .alwaysTemplate。在成功使用 Kingfisher 获取图像后,我们将 imageWithColor 函数应用于它,然后将该图像设置为 imageProduct imageView,并最终将 imageViewtintColor 设置为所需的颜色。请注意,UI 更新应在主线程上执行,因此使用了 DispatchQueue.main.async

英文:

The issue here seems to be related to how tint color is applied to the images that contain an alpha channel (transparency). If an image has an alpha channel, then when the tint color is applied, it might not be applied as expected and could be showing the background color on the image.

One approach could be to check if the image has an alpha channel and handle it differently. However, in your case, the quickest solution could be to use the renderingMode property of UIImage which controls how the image is drawn. You can set it to .alwaysTemplate which treats the image as a template for a mask that will be used in conjunction with the tintColor to create the final colored image.

Here is how you can change your code:

func imageWithColor(color1: UIColor) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
    color1.setFill()

    let context = UIGraphicsGetCurrentContext()! as CGContext
    context.translateBy(x: 0, y: self.size.height)
    context.scaleBy(x: 1.0, y: -1.0);
    context.setBlendMode(CGBlendMode.normal)

    let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
    context.clip(to: rect, mask: self.cgImage!)
    context.fill(rect)

    let newImage = UIGraphicsGetImageFromCurrentImageContext()! as UIImage
    UIGraphicsEndImageContext()

    return newImage.withRenderingMode(.alwaysTemplate) // Add this line
}

imageProduct.kf.setImage(with: URL(string:"imageurl"), placeholder: nil) { result in
    switch result {
    case .success(let value):
        let image = value.image.imageWithColor(color1: .green)
        DispatchQueue.main.async {
            self.imageProduct.image = image
            self.imageProduct.tintColor = .green
        }
    case .failure(let error):
        print("Error: \(error)") // handle error
    }
}

In the code above, we set the renderingMode of the image to .alwaysTemplate before returning it. After the image is fetched successfully using Kingfisher, we apply the imageWithColor function to it, then set this image to the imageProduct imageView, and finally set the tintColor of the imageView to the desired color. Please note that UI updates should be done on the main thread, hence the DispatchQueue.main.async.

答案2

得分: 0

问题可能与图像的 alpha 通道或上下文中使用的混合模式有关。为了确保所有图像的行为一致,您可以修改您的 imageWithColor 函数如下所示:

func imageWithColor(color: UIColor) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
    
    let context = UIGraphicsGetCurrentContext()!
    let rect = CGRect(origin: .zero, size: self.size)
    
    // 绘制图像
    self.draw(in: rect)
    
    // 应用色彩
    context.setFillColor(color.cgColor)
    context.setBlendMode(.sourceAtop)
    context.fill(rect)
    
    // 使用色彩创建新图像
    let tintedImage = UIGraphicsGetImageFromCurrentImageContext()!
    
    UIGraphicsEndImageContext()
    
    return tintedImage
}

然后,您可以在 Kingfisher 的完成块中使用这个更新后的函数来设置图像的色彩:

imageProduct.kf.setImage(with: URL(string: "imageurl"), placeholder: nil) { result in
    if case .success(let value) = result {
        self.imageProduct.image = value.image.imageWithColor(color: UIColor.green)
    }
}

希望这有所帮助。

英文:

The issue might be related to the alpha channel of the image or the blend mode used in the context. To ensure consistent behaviour across all images, you can modify your imageWithColor like this

func imageWithColor(color: UIColor) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
    
    let context = UIGraphicsGetCurrentContext()!
    let rect = CGRect(origin: .zero, size: self.size)
    
    // Draw the image
    self.draw(in: rect)
    
    // Apply tint color
    context.setFillColor(color.cgColor)
    context.setBlendMode(.sourceAtop)
    context.fill(rect)
    
    // Create a new image with the tint color
    let tintedImage = UIGraphicsGetImageFromCurrentImageContext()!
    
    UIGraphicsEndImageContext()
    
    return tintedImage
}

You can then use this updated function to set the tint color of the image in your Kingfisher completion block,

imageProduct.kf.setImage(with: URL(string: "imageurl"), placeholder: nil) { result in
    if case .success(let value) = result {
        self.imageProduct.image = value.image.imageWithColor(color: UIColor.green)
    }
}

huangapple
  • 本文由 发表于 2023年6月5日 16:47:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76404789.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定