获取黑白UIImage(不是灰度)

我需要从另一个UIImage(而不是灰度)获得一个纯黑白的UIImage。 任何人都可以帮助我?

谢谢阅读。

编辑:

这是build议的解决scheme。 谢谢大家。 几乎我知道这不是更好的方式来做到这一点,它工作正常。

// Gets an pure black and white image from an original image. - (UIImage *)pureBlackAndWhiteImage:(UIImage *)image { unsigned char *dataBitmap = [self bitmapFromImage:image]; for (int i = 0; i < image.size.width * image.size.height * 4; i += 4) { if ((dataBitmap[i + 1] + dataBitmap[i + 2] + dataBitmap[i + 3]) < (255 * 3 / 2)) { dataBitmap[i + 1] = 0; dataBitmap[i + 2] = 0; dataBitmap[i + 3] = 0; } else { dataBitmap[i + 1] = 255; dataBitmap[i + 2] = 255; dataBitmap[i + 3] = 255; } } image = [self imageWithBits:dataBitmap withSize:image.size]; return image; } 

编辑1:

在回应评论时,下面是方法bitmapFromImageimageWithBits

 // Retrieves the bits from the context once the image has been drawn. - (unsigned char *)bitmapFromImage:(UIImage *)image { // Creates a bitmap from the given image. CGContextRef contex = CreateARGBBitmapContext(image.size); if (contex == NULL) { return NULL; } CGRect rect = CGRectMake(0.0f, 0.0f, image.size.width, image.size.height); CGContextDrawImage(contex, rect, image.CGImage); unsigned char *data = CGBitmapContextGetData(contex); CGContextRelease(contex); return data; } // Fills an image with bits. - (UIImage *)imageWithBits:(unsigned char *)bits withSize:(CGSize)size { // Creates a color space CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); if (colorSpace == NULL) { fprintf(stderr, "Error allocating color space\n"); free(bits); return nil; } CGContextRef context = CGBitmapContextCreate (bits, size.width, size.height, 8, size.width * 4, colorSpace, kCGImageAlphaPremultipliedFirst); if (context == NULL) { fprintf (stderr, "Error. Context not created\n"); free (bits); CGColorSpaceRelease(colorSpace ); return nil; } CGColorSpaceRelease(colorSpace ); CGImageRef ref = CGBitmapContextCreateImage(context); free(CGBitmapContextGetData(context)); CGContextRelease(context); UIImage *img = [UIImage imageWithCGImage:ref]; CFRelease(ref); return img; } 

如果你正在寻找的是图像的阈值 – 比某个值更亮的东西变成白色,一切变黑,然后你select的值 – 那么像GPU图像库将为你工作。

此代码可能有助于:

 for (int i = 0; i < image.size.width * image.size.height * 4; i += 4) { if (dataBitmap[i + 0] >= dataBitmap[i + 1] && dataBitmap[i + 0] >= dataBitmap[i + 2]){ dataBitmap[i + 1] = dataBitmap[i + 0]; dataBitmap[i + 2] = dataBitmap[i + 0]; } else if (dataBitmap[i + 1] >= dataBitmap[i + 0] && dataBitmap[i + 1] >= dataBitmap[i + 2]) { dataBitmap[i + 0] = dataBitmap[i + 1]; dataBitmap[i + 2] = dataBitmap[i + 1]; } else { dataBitmap[i + 0] = dataBitmap[i + 2]; dataBitmap[i + 1] = dataBitmap[i + 2]; } } 

虽然它可能是为了你的目的矫枉过正,我只是在我的示例应用程序在 iPhone摄像头的实时video。 该应用程序需要一个颜色和一个敏感度,并可以将所有像素在白色阈值以内,如果不是透明的。 我使用OpenGL ES 2.0可编程着色器来获得实时响应。 整个事情在这里描述这个post。

再一次,这可能是为了你想要的矫枉过正。 在你想要转换成黑白的简单UIImage的情况下,你可能会读取原始像素,遍历它们,并应用相同的阈值来输出最终的图像。 这不会像着色器那样快,但是编码会更简单。

代码为我工作,只需要一些调整…这里有一些改变,我做了正确的工作,通过分配dataBitmap[] array的第零个索引值…

  for (int i = 0; i < image.size.width * image.size.height * 4; i += 4) { //here an index for zeroth element is assigned if ((dataBitmap[i + 0]+dataBitmap[i + 1] + dataBitmap[i + 2] + dataBitmap[i + 3]) < (255 * 4 / 2)) { // multiply four,instead of three dataBitmap[i + 0] = 0; dataBitmap[i + 1] = 0; dataBitmap[i + 2] = 0; dataBitmap[i + 3] = 0; } else { dataBitmap[i + 0] = 255; dataBitmap[i + 1] = 255; dataBitmap[i + 2] = 255; dataBitmap[i + 3] = 255; } } 

希望它能工作。

这是一个迅速的3解决scheme:

 class func pureBlackAndWhiteImage(_ inputImage: UIImage) -> UIImage? { guard let inputCGImage = inputImage.cgImage, let context = getImageContext(for: inputCGImage), let data = context.data else { return nil } let white = RGBA32(red: 255, green: 255, blue: 255, alpha: 255) let black = RGBA32(red: 0, green: 0, blue: 0, alpha: 255) let width = Int(inputCGImage.width) let height = Int(inputCGImage.height) let pixelBuffer = data.bindMemory(to: RGBA32.self, capacity: width * height) for x in 0 ..< height { for y in 0 ..< width { let offset = x * width + y if pixelBuffer[offset].red > 0 || pixelBuffer[offset].green > 0 || pixelBuffer[offset].blue > 0 { pixelBuffer[offset] = black } else { pixelBuffer[offset] = white } } } let outputCGImage = context.makeImage() let outputImage = UIImage(cgImage: outputCGImage!, scale: inputImage.scale, orientation: inputImage.imageOrientation) return outputImage } class func getImageContext(for inputCGImage: CGImage) ->CGContext? { let colorSpace = CGColorSpaceCreateDeviceRGB() let width = inputCGImage.width let height = inputCGImage.height let bytesPerPixel = 4 let bitsPerComponent = 8 let bytesPerRow = bytesPerPixel * width let bitmapInfo = RGBA32.bitmapInfo guard let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo) else { print("unable to create context") return nil } context.setBlendMode(.copy) context.draw(inputCGImage, in: CGRect(x: 0, y: 0, width: CGFloat(width), height: CGFloat(height))) return context } struct RGBA32: Equatable { var color: UInt32 var red: UInt8 { return UInt8((color >> 24) & 255) } var green: UInt8 { return UInt8((color >> 16) & 255) } var blue: UInt8 { return UInt8((color >> 8) & 255) } var alpha: UInt8 { return UInt8((color >> 0) & 255) } init(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) { color = (UInt32(red) << 24) | (UInt32(green) << 16) | (UInt32(blue) << 8) | (UInt32(alpha) << 0) } static let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Little.rawValue } func ==(lhs: RGBA32, rhs: RGBA32) -> Bool { return lhs.color == rhs.color } 

使用Swift 3,我可以通过使用CIFilter来实现这种效果,首先应用CIPhotoEffectNoir (使其成为灰度),然后应用CIColorControlfilter,将kCIInputContrastKeyinput参数设置为较高值(即50)。 设置kCIInputBrightnessKey参数还将调整黑白对比度的显示强度,对较暗的图像为负值,对较亮的图像为正值。 例如:

 extension UIImage { func toBlackAndWhite() -> UIImage? { guard let ciImage = CIImage(image: self) else { return nil } guard let grayImage = CIFilter(name: "CIPhotoEffectNoir", withInputParameters: [kCIInputImageKey: ciImage])?.outputImage else { return nil } let bAndWParams: [String: Any] = [kCIInputImageKey: grayImage, kCIInputContrastKey: 50.0, kCIInputBrightnessKey: 10.0] guard let bAndWImage = CIFilter(name: "CIColorControls", withInputParameters: bAndWParams)?.outputImage else { return nil } guard let cgImage = CIContext(options: nil).createCGImage(bAndWImage, from: bAndWImage.extent) else { return nil } return UIImage(cgImage: cgImage) } }