utilizing the speed up framework which I do not actually totally comprehend if I’m trustworthy, I’m attempting to create a flood fill for a UIImage. I’ve a UIImage extension I’ve create however the consequence I get is unpredictable if the picture is of something. If the UIImage is a single coloration picture the place each pixel is an identical then the result’s as expoected but when I take a picture from my digital camera roll and try and run the floodfill I get a large number. That is the code I am working with
import Speed up
import Speed up.vImage
import Basis
import CoreGraphics
extension UIImage {
func floodFill(seedPoint: CGPoint, replacementColor: UIColor) -> UIImage? {
guard var buffer = self.toVImage() else {
return nil
}
guard var maskBuffer = createMaskBuffer(width: Int(buffer.width), top: Int(buffer.top)) else {
return nil
}
let replacementRGBA = replacementColor.toRGBA()
// Create a contiguous reminiscence block for RGBA parts
var rgbaComponents: [UInt8] = [replacementRGBA.0, replacementRGBA.1, replacementRGBA.2, replacementRGBA.3]
let rgbaPointer = UnsafeMutablePointer<UInt8>.allocate(capability: 4)
rgbaPointer.initialize(from: &rgbaComponents, rely: 4)
// Go the pointer to the array
vImageFloodFill_ARGB8888(&buffer, &maskBuffer, vImagePixelCount(seedPoint.x), vImagePixelCount(seedPoint.y), rgbaPointer, 4, vImage_Flags(kvImageNoFlags))
rgbaPointer.deallocate()
guard let cgImage = vImageToCGImage(buffer: buffer) else {
return nil
}
return UIImage(cgImage: cgImage)
}
non-public func toVImage() -> vImage_Buffer? {
guard let cgImage = self.cgImage else {
return nil
}
var format = vImage_CGImageFormat(bitsPerComponent: 8,
bitsPerPixel: 32,
colorSpace: nil,
bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.first.rawValue),
model: 0,
decode: nil,
renderingIntent: .defaultIntent)
var buffer = vImage_Buffer()
let error = vImageBuffer_InitWithCGImage(&buffer, &format, nil, cgImage, vImage_Flags(kvImageNoFlags))
guard error == kvImageNoError else {
print("Error creating vImage buffer: (error)")
return nil
}
return buffer
}
non-public func vImageToCGImage(buffer: vImage_Buffer) -> CGImage? {
guard let context = CGContext(information: buffer.information,
width: Int(buffer.width),
top: Int(buffer.top),
bitsPerComponent: 8,
bytesPerRow: buffer.rowBytes,
house: CGColorSpaceCreateDeviceRGB(),
bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue).rawValue) else {
return nil
}
return context.makeImage()
}
non-public func createMaskBuffer(width: Int, top: Int) -> vImage_Buffer? {
let bytesPerPixel = 4
let bytesPerRow = width * bytesPerPixel
let byteCount = bytesPerRow * top
let maskData = UnsafeMutablePointer<UInt8>.allocate(capability: byteCount)
var maskBuffer = vImage_Buffer(information: maskData, top: vImagePixelCount(top), width: vImagePixelCount(width), rowBytes: bytesPerRow)
memset(maskBuffer.information, 0, byteCount)
return maskBuffer
}
}
extension UIColor {
func toRGBA() -> (UInt8, UInt8, UInt8, UInt8) {
var purple: CGFloat = 0, inexperienced: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0
getRed(&purple, inexperienced: &inexperienced, blue: &blue, alpha: &alpha)
return (UInt8(purple * 255), UInt8(inexperienced * 255), UInt8(blue * 255), UInt8(alpha * 255))
}
}
I’ve tried a number of approaches to passing the substitute coloration. Am I attempting to do one thing not possible right here is the vImageFloodFill_ARGB8888 flood fill operate not designed to be an precise flood fill however solely to fill empty photos?