Objective c 对UIImage应用黑白过滤器
我需要在图像上应用黑白滤镜。我有一个视图,其中有一张由用户拍摄的照片,但我没有任何关于变换图像颜色的想法Objective c 对UIImage应用黑白过滤器,objective-c,uiimage,ciimage,Objective C,Uiimage,Ciimage,我需要在图像上应用黑白滤镜。我有一个视图,其中有一张由用户拍摄的照片,但我没有任何关于变换图像颜色的想法 - (void)viewDidLoad { [super viewDidLoad]; self.navigationItem.title = NSLocalizedString(@"#Paint!", nil); imageView.image = image; } 我该怎么做呢?目标C - (UIImage *)convertImageToGrayScale:(U
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = NSLocalizedString(@"#Paint!", nil);
imageView.image = image;
}
我该怎么做呢?目标C
- (UIImage *)convertImageToGrayScale:(UIImage *)image {
// Create image rectangle with current image width/height
CGRect imageRect = CGRectMake(0, 0, image.size.width, image.size.height);
// Grayscale color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
// Create bitmap content with current image size and grayscale colorspace
CGContextRef context = CGBitmapContextCreate(nil, image.size.width, image.size.height, 8, 0, colorSpace, kCGImageAlphaNone);
// Draw image into current context, with specified rectangle
// using previously defined context (with grayscale colorspace)
CGContextDrawImage(context, imageRect, [image CGImage]);
// Create bitmap image info from pixel data in current context
CGImageRef imageRef = CGBitmapContextCreateImage(context);
// Create a new UIImage object
UIImage *newImage = [UIImage imageWithCGImage:imageRef];
// Release colorspace, context and bitmap information
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
CFRelease(imageRef);
// Return the new grayscale image
return newImage;
}
Swift
func convertToGrayScale(image: UIImage) -> UIImage {
// Create image rectangle with current image width/height
let imageRect:CGRect = CGRect(x:0, y:0, width:image.size.width, height: image.size.height)
// Grayscale color space
let colorSpace = CGColorSpaceCreateDeviceGray()
let width = image.size.width
let height = image.size.height
// Create bitmap content with current image size and grayscale colorspace
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue)
// Draw image into current context, with specified rectangle
// using previously defined context (with grayscale colorspace)
let context = CGContext(data: nil, width: Int(width), height: Int(height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)
context?.draw(image.cgImage!, in: imageRect)
let imageRef = context!.makeImage()
// Create a new UIImage object
let newImage = UIImage(cgImage: imageRef!)
return newImage
}
当PiratM的解决方案起作用时,你失去了alpha通道。要保留alpha通道,您需要执行一些额外的步骤
+(UIImage *)convertImageToGrayScale:(UIImage *)image {
// Create image rectangle with current image width/height
CGRect imageRect = CGRectMake(0, 0, image.size.width, image.size.height);
// Grayscale color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
// Create bitmap content with current image size and grayscale colorspace
CGContextRef context = CGBitmapContextCreate(nil, image.size.width, image.size.height, 8, 0, colorSpace, kCGImageAlphaNone);
// Draw image into current context, with specified rectangle
// using previously defined context (with grayscale colorspace)
CGContextDrawImage(context, imageRect, [image CGImage]);
// Create bitmap image info from pixel data in current context
CGImageRef imageRef = CGBitmapContextCreateImage(context);
// Release colorspace, context and bitmap information
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
context = CGBitmapContextCreate(nil,image.size.width, image.size.height, 8, 0, nil, kCGImageAlphaOnly );
CGContextDrawImage(context, imageRect, [image CGImage]);
CGImageRef mask = CGBitmapContextCreateImage(context);
// Create a new UIImage object
UIImage *newImage = [UIImage imageWithCGImage:CGImageCreateWithMask(imageRef, mask)];
CGImageRelease(imageRef);
CGImageRelease(mask);
// Return the new grayscale image
return newImage;
}
这是swift 1.2版本
/// convert background image to gray scale
///
/// param: flag if true, image will be rendered in grays scale
func convertBackgroundColorToGrayScale(flag: Bool) {
if flag == true {
let imageRect = self.myImage.frame
let colorSpace = CGColorSpaceCreateDeviceGray()
let width = imageRect.width
let height = imageRect.height
let bitmapInfo = CGBitmapInfo(CGImageAlphaInfo.None.rawValue)
var context = CGBitmapContextCreate(nil, Int(width), Int(height), 8, 0, colorSpace, bitmapInfo)
let image = self.musicBackgroundColor.image!.CGImage
CGContextDrawImage(context, imageRect, image)
let imageRef = CGBitmapContextCreateImage(context)
let newImage = UIImage(CGImage: CGImageCreateCopy(imageRef))
self.myImage.image = newImage
} else {
// do something else
}
}
考虑到alpha通道,@rickster的版本看起来不错。但是没有.AspectFit或Fill contentMode的UIImageView无法显示它。因此,UIImage必须使用CGImage创建。此版本作为Swift UIImage extension实现,保持当前比例,并提供一些可选输入参数:
import CoreImage
extension UIImage
{
/// Applies grayscale with CIColorControls by settings saturation to 0.0.
/// - Parameter brightness: Default is 0.0.
/// - Parameter contrast: Default is 1.0.
/// - Returns: The grayscale image of self if available.
func grayscaleImage(brightness: Double = 0.0, contrast: Double = 1.0) -> UIImage?
{
if let ciImage = CoreImage.CIImage(image: self, options: nil)
{
let paramsColor: [String : AnyObject] = [ kCIInputBrightnessKey: NSNumber(double: brightness),
kCIInputContrastKey: NSNumber(double: contrast),
kCIInputSaturationKey: NSNumber(double: 0.0) ]
let grayscale = ciImage.imageByApplyingFilter("CIColorControls", withInputParameters: paramsColor)
let processedCGImage = CIContext().createCGImage(grayscale, fromRect: grayscale.extent)
return UIImage(CGImage: processedCGImage, scale: self.scale, orientation: self.imageOrientation)
}
return nil
}
}
更长但更快的方法是@ChrisStillwells答案的修改版本。考虑到Swift中的alpha通道和当前比例,作为UIImage扩展实现:
extension UIImage
{
/// Create a grayscale image with alpha channel. Is 5 times faster than grayscaleImage().
/// - Returns: The grayscale image of self if available.
func convertToGrayScale() -> UIImage?
{
// Create image rectangle with current image width/height * scale
let pixelSize = CGSize(width: self.size.width * self.scale, height: self.size.height * self.scale)
let imageRect = CGRect(origin: CGPointZero, size: pixelSize)
// Grayscale color space
if let colorSpace: CGColorSpaceRef = CGColorSpaceCreateDeviceGray()
{
// Create bitmap content with current image size and grayscale colorspace
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.None.rawValue)
if let context: CGContextRef = CGBitmapContextCreate(nil, Int(pixelSize.width), Int(pixelSize.height), 8, 0, colorSpace, bitmapInfo.rawValue)
{
// Draw image into current context, with specified rectangle
// using previously defined context (with grayscale colorspace)
CGContextDrawImage(context, imageRect, self.CGImage)
// Create bitmap image info from pixel data in current context
if let imageRef: CGImageRef = CGBitmapContextCreateImage(context)
{
let bitmapInfoAlphaOnly = CGBitmapInfo(rawValue: CGImageAlphaInfo.Only.rawValue)
if let contextAlpha = CGBitmapContextCreate(nil, Int(pixelSize.width), Int(pixelSize.height), 8, 0, nil, bitmapInfoAlphaOnly.rawValue)
{
CGContextDrawImage(contextAlpha, imageRect, self.CGImage)
if let mask: CGImageRef = CGBitmapContextCreateImage(contextAlpha)
{
// Create a new UIImage object
if let newCGImage = CGImageCreateWithMask(imageRef, mask)
{
// Return the new grayscale image
return UIImage(CGImage: newCGImage, scale: self.scale, orientation: self.imageOrientation)
}
}
}
}
}
}
// A required variable was unexpected nil
return nil
}
}
根据标签判断,也许OP认为(正确的)核心图像将提供一种快速简便的方法来实现这一点
以下是ObjC中的两个:
- (UIImage *)grayscaleImage:(UIImage *)image {
CIImage *ciImage = [[CIImage alloc] initWithImage:image];
CIImage *grayscale = [ciImage imageByApplyingFilter:@"CIColorControls"
withInputParameters: @{kCIInputSaturationKey : @0.0}];
return [UIImage imageWithCIImage:grayscale];
}
和斯威夫特:
func grayscaleImage(image: UIImage) -> UIImage {
let ciImage = CIImage(image: image)
let grayscale = ciImage.imageByApplyingFilter("CIColorControls",
withInputParameters: [ kCIInputSaturationKey: 0.0 ])
return UIImage(CIImage: grayscale)
}
只是可将图像转换为灰度的几个内置核心图像过滤器之一,和是不同的色调映射预设(每个都不带参数),您可以使用类似的过滤器进行自己的色调映射
与涉及创建和绘制到自己的CGBitmapContext
中的备选方案不同,这些方案无需额外工作即可保留原始图像的大小/比例和alpha。Swift 3.0版本:
extension UIImage {
func convertedToGrayImage() -> UIImage? {
let width = self.size.width
let height = self.size.height
let rect = CGRect(x: 0.0, y: 0.0, width: width, height: height)
let colorSpace = CGColorSpaceCreateDeviceGray()
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue)
guard let context = CGContext(data: nil, width: Int(width), height: Int(height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfo.rawValue) else {
return nil
}
guard let cgImage = cgImage else { return nil }
context.draw(cgImage, in: rect)
guard let imageRef = context.makeImage() else { return nil }
let newImage = UIImage(cgImage: imageRef.copy()!)
return newImage
}
}
在swift 3.0中
func convertImageToGrayScale(image: UIImage) -> UIImage {
// Create image rectangle with current image width/height
let imageRect = CGRect(x: 0, y: 0,width: image.size.width, height : image.size.height)
// Grayscale color space
let colorSpace = CGColorSpaceCreateDeviceGray()
// Create bitmap content with current image size and grayscale colorspace
let context = CGContext(data: nil, width: Int(image.size.width), height: Int(image.size.height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: CGImageAlphaInfo.none.rawValue)
// Draw image into current context, with specified rectangle
// using previously defined context (with grayscale colorspace)
context?.draw(image.cgImage!, in: imageRect)
// Create bitmap image info from pixel data in current context
let imageRef = context!.makeImage()
// Create a new UIImage object
let newImage = UIImage(cgImage: imageRef!)
// Release colorspace, context and bitmap information
//MARK: ToolBar Button Methods
// Return the new grayscale image
return newImage
}
Swift3+GPUImage
本规范(目标c)工作:
kCIInputContrast键:@10.0用于获得几乎黑白的图像。Swift 4解决方案
extension UIImage {
var withGrayscale: UIImage {
guard let ciImage = CIImage(image: self, options: nil) else { return self }
let paramsColor: [String: AnyObject] = [kCIInputBrightnessKey: NSNumber(value: 0.0), kCIInputContrastKey: NSNumber(value: 1.0), kCIInputSaturationKey: NSNumber(value: 0.0)]
let grayscale = ciImage.applyingFilter("CIColorControls", parameters: paramsColor)
guard let processedCGImage = CIContext().createCGImage(grayscale, from: grayscale.extent) else { return self }
return UIImage(cgImage: processedCGImage, scale: scale, orientation: imageOrientation)
}
}
在Swift 5中,使用CoreImage进行图像过滤 谢谢@rickster
extension UIImage{
var grayscaled: UIImage?{
let ciImage = CIImage(image: self)
let grayscale = ciImage?.applyingFilter("CIColorControls",
parameters: [ kCIInputSaturationKey: 0.0 ])
if let gray = grayscale{
return UIImage(ciImage: gray)
}
else{
return nil
}
}
}
将@FBente更新为Swift 5 使用CoreImage进行图像过滤
extension UIImage
{
/// Create a grayscale image with alpha channel. Is 5 times faster than grayscaleImage().
/// - Returns: The grayscale image of self if available.
var grayScaled: UIImage?
{
// Create image rectangle with current image width/height * scale
let pixelSize = CGSize(width: self.size.width * self.scale, height: self.size.height * self.scale)
let imageRect = CGRect(origin: CGPoint.zero, size: pixelSize)
// Grayscale color space
let colorSpace: CGColorSpace = CGColorSpaceCreateDeviceGray()
// Create bitmap content with current image size and grayscale colorspace
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue)
if let context: CGContext = CGContext(data: nil, width: Int(pixelSize.width), height: Int(pixelSize.height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)
{
// Draw image into current context, with specified rectangle
// using previously defined context (with grayscale colorspace)
guard let cg = self.cgImage else{
return nil
}
context.draw(cg, in: imageRect)
// Create bitmap image info from pixel data in current context
if let imageRef: CGImage = context.makeImage(){
let bitmapInfoAlphaOnly = CGBitmapInfo(rawValue: CGImageAlphaInfo.alphaOnly.rawValue)
guard let context = CGContext(data: nil, width: Int(pixelSize.width), height: Int(pixelSize.height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfoAlphaOnly.rawValue) else{
return nil
}
context.draw(cg, in: imageRect)
if let mask: CGImage = context.makeImage() {
// Create a new UIImage object
if let newCGImage = imageRef.masking(mask){
// Return the new grayscale image
return UIImage(cgImage: newCGImage, scale: self.scale, orientation: self.imageOrientation)
}
}
}
}
// A required variable was unexpected nil
return nil
}
}
关于如何保持透明度的完整性有什么想法吗?@Antzi将
kCGImageAlphaNone
更改为kcGimageAlphaPremultipledLast
(或任何您需要的内容)。这不是编译,它包含对未声明变量的引用,如MusicBackgroundColorThank,Chris-这对我来说非常有用!注意:第二个CGBitmapContextCreate看起来缺少相应的CGContextRelease。添加CGContextRelease(上下文);在return语句之前,应该清除此错误。无法在我的代码中使用此错误。转换后的图像始终显示为空白。此方法还保留了透明度,而接受的答案则没有。这不会同时保留原始的sizeGood解决方案,但如果让金字塔毁灭的话。试试守卫的说法?耶稣基督,末日金字塔D:这是逆时针旋转我的图像。你知道为什么吗?也许你的原始图像有一个方向。尝试复制方向。newImage.imageOrientation=self.imageOrientation相当高效,比“CIPhotoEffectNoir”过滤器快。谢谢
extension UIImage{
var grayscaled: UIImage?{
let ciImage = CIImage(image: self)
let grayscale = ciImage?.applyingFilter("CIColorControls",
parameters: [ kCIInputSaturationKey: 0.0 ])
if let gray = grayscale{
return UIImage(ciImage: gray)
}
else{
return nil
}
}
}
extension UIImage
{
/// Create a grayscale image with alpha channel. Is 5 times faster than grayscaleImage().
/// - Returns: The grayscale image of self if available.
var grayScaled: UIImage?
{
// Create image rectangle with current image width/height * scale
let pixelSize = CGSize(width: self.size.width * self.scale, height: self.size.height * self.scale)
let imageRect = CGRect(origin: CGPoint.zero, size: pixelSize)
// Grayscale color space
let colorSpace: CGColorSpace = CGColorSpaceCreateDeviceGray()
// Create bitmap content with current image size and grayscale colorspace
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue)
if let context: CGContext = CGContext(data: nil, width: Int(pixelSize.width), height: Int(pixelSize.height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)
{
// Draw image into current context, with specified rectangle
// using previously defined context (with grayscale colorspace)
guard let cg = self.cgImage else{
return nil
}
context.draw(cg, in: imageRect)
// Create bitmap image info from pixel data in current context
if let imageRef: CGImage = context.makeImage(){
let bitmapInfoAlphaOnly = CGBitmapInfo(rawValue: CGImageAlphaInfo.alphaOnly.rawValue)
guard let context = CGContext(data: nil, width: Int(pixelSize.width), height: Int(pixelSize.height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfoAlphaOnly.rawValue) else{
return nil
}
context.draw(cg, in: imageRect)
if let mask: CGImage = context.makeImage() {
// Create a new UIImage object
if let newCGImage = imageRef.masking(mask){
// Return the new grayscale image
return UIImage(cgImage: newCGImage, scale: self.scale, orientation: self.imageOrientation)
}
}
}
}
// A required variable was unexpected nil
return nil
}
}