色调正在反转 swift 中的颜色
Tint is inverting colors in swift
我正在尝试使用此代码为 UIImage 着色,但它似乎在反转颜色 - 为背景着色并将黑色描边变为白色。
我如何让它为图像的黑色笔划线着色并保留白色背景?这是一个游乐场示例,我在其中尝试了一种技术以及第一个答案建议的另一种技术。
游乐场代码
extension UIImage {
func tint(color: UIColor, blendMode: CGBlendMode = CGBlendMode.Normal) -> UIImage
{
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale);
let context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, self.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetBlendMode(context, blendMode);
let rect = CGRectMake(0, 0, self.size.width, self.size.height);
CGContextClipToMask(context, rect, self.CGImage);
color.setFill()
CGContextFillRect(context, rect);
let newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
func tint2(color: UIColor, blendMode: CGBlendMode) -> UIImage
{
let drawRect = CGRectMake(0.0, 0.0, size.width, size.height)
UIGraphicsBeginImageContextWithOptions(size, false, scale)
let context = UIGraphicsGetCurrentContext()
CGContextClipToMask(context, drawRect, CGImage)
color.setFill()
UIRectFill(drawRect)
drawInRect(drawRect, blendMode: blendMode, alpha: 1.0)
let tintedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return tintedImage
}
}
let stringUrl = "https://s3.amazonaws.com/neighbor-chat-assets/icons/avatar1000.png"
let url = NSURL(string: stringUrl)
let data = NSData(contentsOfURL: url!)
var originalimage = UIImage(data: data!)
var image = originalimage!.imageWithRenderingMode(.AlwaysTemplate).tint(UIColor.blueColor(), blendMode:.Normal)
var image2 = originalimage!.imageWithRenderingMode(.AlwaysTemplate).tint2(UIColor.blueColor(), blendMode:.Normal)
这应该可以,我刚刚用 png 和透明背景测试了它
func tint(color: UIColor, blendMode: CGBlendMode = CGBlendMode.Normal) -> UIImage
{
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale);
let context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, self.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetBlendMode(context, blendMode);
let rect = CGRectMake(0, 0, self.size.width, self.size.height);
CGContextClipToMask(context, rect, self.CGImage);
color.setFill()
CGContextFillRect(context, rect);
let newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
另请参阅 this post 了解更多信息。另一种方法是将图像包装在具有 UIImageRenderingMode.AlwaysTemplate 渲染模式的 UIImageView 中,然后设置 tintColor 属性.
编辑
所以如果图像中没有 alpha 通道,您可以使用这个函数来首先屏蔽掉某些颜色
func tint(color: UIColor, blendMode: CGBlendMode = CGBlendMode.Normal, colorToMask: UIColor = UIColor.blackColor()) -> UIImage
{
var fRed : CGFloat = 0
var fGreen : CGFloat = 0
var fBlue : CGFloat = 0
var fAlpha: CGFloat = 0
colorToMask.getRed(&fRed, green: &fGreen, blue: &fBlue, alpha: &fAlpha)
let rect = CGRectMake(0, 0, self.size.width, self.size.height);
var colorMasking : [CGFloat] = [fRed,fRed,fGreen,fGreen,fBlue,fBlue]
let newImageRef = CGImageCreateWithMaskingColors(self.CGImage!, &colorMasking)
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale);
let context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, self.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetBlendMode(context, blendMode);
CGContextClipToMask(context, rect, newImageRef!);
color.setFill()
CGContextFillRect(context, rect);
let newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
这个函数首先根据指定的颜色创建一个遮罩,并将上下文裁剪到这个遮罩上。
编辑 #2
正如评论中所述,我也没有设法屏蔽掉白色,我尝试了 UInt8 值(即 255)和浮点值(即 1.0),但仍然没有用。所以我能想到的唯一解决办法就是反转图像。这是函数:
func negativeImage() -> UIImage {
let coreImage = MYImage(CGImage: self.CGImage!)
let filter = CIFilter(name: "CIColorInvert", withInputParameters: ["inputImage" : coreImage])!
let result = filter.outputImage!
let context = CIContext(options:nil)
let cgimg : CGImageRef = context.createCGImage(result, fromRect: result.extent)
let bmpcontext = CGBitmapContextCreate(nil, Int(self.size.width), Int(self.size.height), 8, Int(self.size.width)*4, CGColorSpaceCreateDeviceRGB(),CGImageAlphaInfo.NoneSkipLast.rawValue)
CGContextDrawImage(bmpcontext, CGRectMake(0, 0, self.size.width, self.size.height), cgimg)
let newImgRef = CGBitmapContextCreateImage(bmpcontext)!
return UIImage(CGImage: newImgRef)
}
你可以这样使用它
var image : UIImage = ...
image = image.negativeImage()
image = image.tint(UIColor.redColor())
这里有一些一般注意事项
CGImageCreateWithMaskingColors
需要带有 NO alpha 通道的 CGImage,这就是为什么我在 negativeImage 函数中使用标志 CGImageAlphaInfo.NoneSkipLast
以删除 alpha 通道再次
- 这里绝对没有错误检查,您至少应该使用
CGImageGetAlphaInfo
检查 tint 函数中是否包含 alpha 通道
- 您可以使被遮盖的部分(在我们的示例中为白色)透明(通过在 tint 函数中的
UIGraphicsBeginImageContextWithOptions
命令中设置 false),或者通过设置 true 来设置特定颜色,即黑色默认(您需要在裁剪到蒙版之前进行绘画)。
我正在尝试使用此代码为 UIImage 着色,但它似乎在反转颜色 - 为背景着色并将黑色描边变为白色。
我如何让它为图像的黑色笔划线着色并保留白色背景?这是一个游乐场示例,我在其中尝试了一种技术以及第一个答案建议的另一种技术。
游乐场代码
extension UIImage {
func tint(color: UIColor, blendMode: CGBlendMode = CGBlendMode.Normal) -> UIImage
{
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale);
let context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, self.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetBlendMode(context, blendMode);
let rect = CGRectMake(0, 0, self.size.width, self.size.height);
CGContextClipToMask(context, rect, self.CGImage);
color.setFill()
CGContextFillRect(context, rect);
let newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
func tint2(color: UIColor, blendMode: CGBlendMode) -> UIImage
{
let drawRect = CGRectMake(0.0, 0.0, size.width, size.height)
UIGraphicsBeginImageContextWithOptions(size, false, scale)
let context = UIGraphicsGetCurrentContext()
CGContextClipToMask(context, drawRect, CGImage)
color.setFill()
UIRectFill(drawRect)
drawInRect(drawRect, blendMode: blendMode, alpha: 1.0)
let tintedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return tintedImage
}
}
let stringUrl = "https://s3.amazonaws.com/neighbor-chat-assets/icons/avatar1000.png"
let url = NSURL(string: stringUrl)
let data = NSData(contentsOfURL: url!)
var originalimage = UIImage(data: data!)
var image = originalimage!.imageWithRenderingMode(.AlwaysTemplate).tint(UIColor.blueColor(), blendMode:.Normal)
var image2 = originalimage!.imageWithRenderingMode(.AlwaysTemplate).tint2(UIColor.blueColor(), blendMode:.Normal)
这应该可以,我刚刚用 png 和透明背景测试了它
func tint(color: UIColor, blendMode: CGBlendMode = CGBlendMode.Normal) -> UIImage
{
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale);
let context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, self.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetBlendMode(context, blendMode);
let rect = CGRectMake(0, 0, self.size.width, self.size.height);
CGContextClipToMask(context, rect, self.CGImage);
color.setFill()
CGContextFillRect(context, rect);
let newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
另请参阅 this post 了解更多信息。另一种方法是将图像包装在具有 UIImageRenderingMode.AlwaysTemplate 渲染模式的 UIImageView 中,然后设置 tintColor 属性.
编辑
所以如果图像中没有 alpha 通道,您可以使用这个函数来首先屏蔽掉某些颜色
func tint(color: UIColor, blendMode: CGBlendMode = CGBlendMode.Normal, colorToMask: UIColor = UIColor.blackColor()) -> UIImage
{
var fRed : CGFloat = 0
var fGreen : CGFloat = 0
var fBlue : CGFloat = 0
var fAlpha: CGFloat = 0
colorToMask.getRed(&fRed, green: &fGreen, blue: &fBlue, alpha: &fAlpha)
let rect = CGRectMake(0, 0, self.size.width, self.size.height);
var colorMasking : [CGFloat] = [fRed,fRed,fGreen,fGreen,fBlue,fBlue]
let newImageRef = CGImageCreateWithMaskingColors(self.CGImage!, &colorMasking)
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale);
let context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, self.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetBlendMode(context, blendMode);
CGContextClipToMask(context, rect, newImageRef!);
color.setFill()
CGContextFillRect(context, rect);
let newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
这个函数首先根据指定的颜色创建一个遮罩,并将上下文裁剪到这个遮罩上。
编辑 #2
正如评论中所述,我也没有设法屏蔽掉白色,我尝试了 UInt8 值(即 255)和浮点值(即 1.0),但仍然没有用。所以我能想到的唯一解决办法就是反转图像。这是函数:
func negativeImage() -> UIImage {
let coreImage = MYImage(CGImage: self.CGImage!)
let filter = CIFilter(name: "CIColorInvert", withInputParameters: ["inputImage" : coreImage])!
let result = filter.outputImage!
let context = CIContext(options:nil)
let cgimg : CGImageRef = context.createCGImage(result, fromRect: result.extent)
let bmpcontext = CGBitmapContextCreate(nil, Int(self.size.width), Int(self.size.height), 8, Int(self.size.width)*4, CGColorSpaceCreateDeviceRGB(),CGImageAlphaInfo.NoneSkipLast.rawValue)
CGContextDrawImage(bmpcontext, CGRectMake(0, 0, self.size.width, self.size.height), cgimg)
let newImgRef = CGBitmapContextCreateImage(bmpcontext)!
return UIImage(CGImage: newImgRef)
}
你可以这样使用它
var image : UIImage = ...
image = image.negativeImage()
image = image.tint(UIColor.redColor())
这里有一些一般注意事项
CGImageCreateWithMaskingColors
需要带有 NO alpha 通道的 CGImage,这就是为什么我在 negativeImage 函数中使用标志CGImageAlphaInfo.NoneSkipLast
以删除 alpha 通道再次- 这里绝对没有错误检查,您至少应该使用
CGImageGetAlphaInfo
检查 tint 函数中是否包含 alpha 通道
- 您可以使被遮盖的部分(在我们的示例中为白色)透明(通过在 tint 函数中的
UIGraphicsBeginImageContextWithOptions
命令中设置 false),或者通过设置 true 来设置特定颜色,即黑色默认(您需要在裁剪到蒙版之前进行绘画)。