对UIImage应用黑白滤镜

时间:2023-02-08 21:18:31

I need to apply a black-and-white filter on a UIImage. I have a view in which there's a photo taken by the user, but I don't have any ideas on transforming the colors of the image.

我需要在UIImage上应用一个黑白滤镜。我有一个用户拍的照片的视图,但是我不知道如何改变图片的颜色。

- (void)viewDidLoad {
    [super viewDidLoad];
    self.navigationItem.title = NSLocalizedString(@"#Paint!", nil);
    imageView.image = image;
}

How can I do that?

我怎么做呢?

10 个解决方案

#1


21  

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

#2


21  

Judging by the tag, perhaps the OP was thinking (correctly) that Core Image would provide a quick and easy way to do this?

从ciimage标签来判断,也许OP认为(正确地)核心图像能够提供一种快速简便的方法来实现这个目标?

Here's that, both in ObjC:

这是ObjC中的两个

- (UIImage *)grayscaleImage:(UIImage *)image {
    CIImage *ciImage = [[CIImage alloc] initWithImage:image];
    CIImage *grayscale = [ciImage imageByApplyingFilter:@"CIColorControls"
        withInputParameters: @{kCIInputSaturationKey : @0.0}];
    return [UIImage imageWithCIImage:grayscale];
}

and Swift:

迅速:

func grayscaleImage(image: UIImage) -> UIImage {
    let ciImage = CIImage(image: image)
    let grayscale = ciImage.imageByApplyingFilter("CIColorControls",
        withInputParameters: [ kCIInputSaturationKey: 0.0 ])
    return UIImage(CIImage: grayscale)
}

CIColorControls is just one of several built-in Core Image filters that can convert an image to grayscale. CIPhotoEffectMono, CIPhotoEffectNoir, and CIPhotoEffectTonal are different tone-mapping presets (each takes no parameters), and you can do your own tone mapping with filters like CIColorMap.

CIColorControls是几个内置的核心图像过滤器之一,可以将图像转换为灰度。CIPhotoEffectMono、CIPhotoEffectNoir和CIPhotoEffectTonal是不同的色调映射预置(每个预置不带参数),您可以使用CIColorMap这样的过滤器来实现自己的色调映射。

Unlike alternatives that involve creating and drawing into one's own CGBitmapContext, these preserve the size/scale and alpha of the original image without extra work.

不像创建和绘制到自己的CGBitmapContext中那样,它们不需要额外的工作就可以保持原始图像的大小/比例和alpha值。

#3


19  

While PiratM's solution works you lose the alpha channel. To preserve the alpha channel you need to do a few extra steps.

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

#4


6  

The Version of @rickster looks good considering the alpha channel. But a UIImageView without .AspectFit or Fill contentMode can't display it. Therefore the UIImage has to be created with an CGImage. This Version implemented as Swift UIImage extension keeps the current scale and gives some optional input parameters:

考虑到alpha通道,@rickster版本看起来不错。但是没有. aspectfit或Fill contentMode的UIImageView不能显示它。因此,必须使用CGImage创建UIImage。这个版本实现为Swift UIImage扩展,保留当前的比例,并提供一些可选的输入参数:

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

The longer but faster way is the modificated version of @ChrisStillwells answer. Implemented as an UIImage extension considering the alpha channel and current scale in Swift:

更长的但是更快的方法是修改后的@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
    }
}

#5


1  

Swift 3.0 version:

斯威夫特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
    }
}

#6


1  

Swift3 + GPUImage

import GPUImage

extension UIImage {
    func blackWhite() -> UIImage? {
        guard let image: GPUImagePicture = GPUImagePicture(image: self) else {
            print("unable to create GPUImagePicture")
            return nil
        }
        let filter = GPUImageAverageLuminanceThresholdFilter()
        image.addTarget(filter)
        filter.useNextFrameForImageCapture()
        image.processImage()
        guard let processedImage: UIImage = filter.imageFromCurrentFramebuffer(with: UIImageOrientation.up) else {
            print("unable to obtain UIImage from filter")
            return nil
        }
        return processedImage
    }
}

#7


0  

Here is the swift 1.2 version

以下是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
    }
}

#8


0  

in swift 3.0

在斯威夫特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
}

#9


0  

This code (objective c) work:

本代码(objective c)工作:

CIImage * ciimage = ...;
CIFilter * filter = [CIFilter filterWithName:@"CIColorControls" withInputParameters:@{kCIInputSaturationKey : @0.0,kCIInputContrastKey : @10.0,kCIInputImageKey : ciimage}];
CIImage * grayscale  = [filtre outputImage];

The kCIInputContrastKey : @10.0 is to obtain an almost black and white image.

kCIInputContrastKey: @10.0是为了获得几乎黑白的图像。

#10


0  

Swift 4 Solution

斯威夫特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)
    }
}

#1


21  

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

#2


21  

Judging by the tag, perhaps the OP was thinking (correctly) that Core Image would provide a quick and easy way to do this?

从ciimage标签来判断,也许OP认为(正确地)核心图像能够提供一种快速简便的方法来实现这个目标?

Here's that, both in ObjC:

这是ObjC中的两个

- (UIImage *)grayscaleImage:(UIImage *)image {
    CIImage *ciImage = [[CIImage alloc] initWithImage:image];
    CIImage *grayscale = [ciImage imageByApplyingFilter:@"CIColorControls"
        withInputParameters: @{kCIInputSaturationKey : @0.0}];
    return [UIImage imageWithCIImage:grayscale];
}

and Swift:

迅速:

func grayscaleImage(image: UIImage) -> UIImage {
    let ciImage = CIImage(image: image)
    let grayscale = ciImage.imageByApplyingFilter("CIColorControls",
        withInputParameters: [ kCIInputSaturationKey: 0.0 ])
    return UIImage(CIImage: grayscale)
}

CIColorControls is just one of several built-in Core Image filters that can convert an image to grayscale. CIPhotoEffectMono, CIPhotoEffectNoir, and CIPhotoEffectTonal are different tone-mapping presets (each takes no parameters), and you can do your own tone mapping with filters like CIColorMap.

CIColorControls是几个内置的核心图像过滤器之一,可以将图像转换为灰度。CIPhotoEffectMono、CIPhotoEffectNoir和CIPhotoEffectTonal是不同的色调映射预置(每个预置不带参数),您可以使用CIColorMap这样的过滤器来实现自己的色调映射。

Unlike alternatives that involve creating and drawing into one's own CGBitmapContext, these preserve the size/scale and alpha of the original image without extra work.

不像创建和绘制到自己的CGBitmapContext中那样,它们不需要额外的工作就可以保持原始图像的大小/比例和alpha值。

#3


19  

While PiratM's solution works you lose the alpha channel. To preserve the alpha channel you need to do a few extra steps.

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

#4


6  

The Version of @rickster looks good considering the alpha channel. But a UIImageView without .AspectFit or Fill contentMode can't display it. Therefore the UIImage has to be created with an CGImage. This Version implemented as Swift UIImage extension keeps the current scale and gives some optional input parameters:

考虑到alpha通道,@rickster版本看起来不错。但是没有. aspectfit或Fill contentMode的UIImageView不能显示它。因此,必须使用CGImage创建UIImage。这个版本实现为Swift UIImage扩展,保留当前的比例,并提供一些可选的输入参数:

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

The longer but faster way is the modificated version of @ChrisStillwells answer. Implemented as an UIImage extension considering the alpha channel and current scale in Swift:

更长的但是更快的方法是修改后的@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
    }
}

#5


1  

Swift 3.0 version:

斯威夫特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
    }
}

#6


1  

Swift3 + GPUImage

import GPUImage

extension UIImage {
    func blackWhite() -> UIImage? {
        guard let image: GPUImagePicture = GPUImagePicture(image: self) else {
            print("unable to create GPUImagePicture")
            return nil
        }
        let filter = GPUImageAverageLuminanceThresholdFilter()
        image.addTarget(filter)
        filter.useNextFrameForImageCapture()
        image.processImage()
        guard let processedImage: UIImage = filter.imageFromCurrentFramebuffer(with: UIImageOrientation.up) else {
            print("unable to obtain UIImage from filter")
            return nil
        }
        return processedImage
    }
}

#7


0  

Here is the swift 1.2 version

以下是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
    }
}

#8


0  

in swift 3.0

在斯威夫特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
}

#9


0  

This code (objective c) work:

本代码(objective c)工作:

CIImage * ciimage = ...;
CIFilter * filter = [CIFilter filterWithName:@"CIColorControls" withInputParameters:@{kCIInputSaturationKey : @0.0,kCIInputContrastKey : @10.0,kCIInputImageKey : ciimage}];
CIImage * grayscale  = [filtre outputImage];

The kCIInputContrastKey : @10.0 is to obtain an almost black and white image.

kCIInputContrastKey: @10.0是为了获得几乎黑白的图像。

#10


0  

Swift 4 Solution

斯威夫特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)
    }
}