I'm trying to apply this mask to the original image
Notice there are some grey areas, I want to keep everything except PURE black.
I've found this code
func maskImage(image: UIImage, mask: UIImage) -> UIImage {
let imageReference = (image.cgImage)!
let maskReference = (mask.cgImage)!
let imageMask = CGImage(
maskWidth: maskReference.width
, height: maskReference.height
, bitsPerComponent: maskReference.bitsPerComponent
, bitsPerPixel: maskReference.bitsPerPixel
, bytesPerRow: maskReference.bytesPerRow
, provider: maskReference.dataProvider!
, decode: nil
, shouldInterpolate: true
)
return (UIImage(cgImage: (imageReference.masking(imageMask!))!))
}
But it does the opposite, it removes all white pixels instead.
Edit ---
For example if the above mask is implied to a pure color background
right now so far the solution submitted gives this image
Notice there are holes in the middle, grey areas. Everything should be solid blue. In order words, the mask should only take out PURE black areas.
Update the mask before applying it like:
let maskReference = (mask.turnedNotPureBlackIntoBlack()!.cgImage)!
Using this extension:
extension UIImage {
func turnedNotPureBlackIntoBlack() -> UIImage? {
guard let cgImage else { return nil }
let width = cgImage.width
let height = cgImage.height
let bytesPerPixel = 4
let bitsPerComponent = 8
let bytesPerRow = bytesPerPixel * width
let pixels = UnsafeMutablePointer<UInt32>.allocate(capacity: height * width)
guard let context = CGContext(
data: pixels,
width: width,
height: height,
bitsPerComponent: bitsPerComponent,
bytesPerRow: bytesPerRow,
space: CGColorSpaceCreateDeviceRGB(),
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Big.rawValue
) else {
return nil
}
context.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height))
for j in 0..<height {
for i in 0..<width {
let currentPixel = pixels + j * width + i
let color = currentPixel.pointee
let r = UInt32((color >> 00) & 0xFF)
let g = UInt32((color >> 08) & 0xFF)
let b = UInt32((color >> 16) & 0xFF)
let a = UInt32((color >> 24) & 0xFF)
let pureBlack = 0
switch (r, g, b) {
case (0, 0, 0): currentPixel.pointee = 0xFFFFFFFF
default: currentPixel.pointee = UInt32(pureBlack)
}
}
}
guard let newCGImage = context.makeImage() else { return nil }
let processedImage = UIImage(cgImage: newCGImage)
pixels.deallocate()
return processedImage
}
}
Original Mask | Converted Mask |
---|---|
Note that some pixels in the original image are NOT pure black but its not easy to see them with plain eyes
By the way, I suggest inverting the mask outside the code for better performance if possible