11.4 C
London
Thursday, May 9, 2024

swift – Utilizing vImageFloodFill_ARGB8888 on iOS to create a Flood fill for a UIImage


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?

Latest news
Related news

LEAVE A REPLY

Please enter your comment!
Please enter your name here