Использование vImageFloodFill_ARGB8888 в iOS для создания заливки Flood для UIImageIOS

Программируем под IOS
Ответить
Anonymous
 Использование vImageFloodFill_ARGB8888 в iOS для создания заливки Flood для UIImage

Сообщение Anonymous »


Изображение
Я отредактировал сообщение, добавив изображение результатов. Я также отредактировал блок кода. чтобы показать, что я использую, это основано непосредственно на документации Apple для этого.
Используя платформу Accelerate, которую я, если честно, не совсем понимаю, я пытаюсь создать заливку для UIImage. У меня есть расширение UIImage, но результат, который я получаю, непредсказуем, если изображение представляет собой что-либо. Если UIImage представляет собой одноцветное изображение, в котором каждый пиксель идентичен, результат будет таким, как ожидалось, но если я возьму изображение из фотопленки и попытаюсь запустить FloodFill, то получу путаницу.

Это код, с которым я работаю:

Код: Выделить всё

import Accelerate
import Accelerate.vImage
import Foundation
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), height: Int(buffer.height)) else {
return nil
}

let replacementRGBA = replacementColor.toRGBA()

var cgImageFormatPlanarF = vImage_CGImageFormat(
bitsPerComponent: 32,
bitsPerPixel: 32,
colorSpace: CGColorSpaceCreateDeviceGray(),
bitmapInfo: CGBitmapInfo(
rawValue: kCGBitmapByteOrder32Host.rawValue |
CGBitmapInfo.floatComponents.rawValue |
CGImageAlphaInfo.none.rawValue),
renderingIntent: .defaultIntent)!

let bufferPlanarF = try! vImage.PixelBuffer(
cgImage: self.cgImage!,
cgImageFormat: &cgImageFormatPlanarF)
bufferPlanarF.colorThreshold(
0.5,
destination: bufferPlanarF)
let bufferRGB8 = vImage.PixelBuffer(
planarBuffers: [bufferPlanarF, bufferPlanarF, bufferPlanarF, bufferPlanarF])

// Create a contiguous memory block for RGBA components
var rgbaComponents: [UInt8] = [replacementRGBA.0, replacementRGBA.1, replacementRGBA.2, replacementRGBA.3]

bufferRGB8.withUnsafePointerToVImageBuffer { src in
vImageFloodFill_ARGB8888(src, nil,
UInt(seedPoint.x), UInt(seedPoint.y),
&rgbaComponents, 8, 0)

}

let cgImageFormatRGB8 = vImage_CGImageFormat(
bitsPerComponent: 8,
bitsPerPixel: 8 * 4,
colorSpace: CGColorSpaceCreateDeviceRGB(),
bitmapInfo: CGBitmapInfo(
rawValue: CGImageAlphaInfo.noneSkipFirst.rawValue),
renderingIntent: .defaultIntent)!

guard let result = bufferRGB8.makeCGImage(cgImageFormat: cgImageFormatRGB8) else{
return nil
}
return UIImage(cgImage: result)
}

private func toVImage() -> vImage_Buffer? {
guard let cgImage = self.cgImage else {
return nil
}

guard let colorSpace = cgImage.colorSpace else {
return nil
}

var format = vImage_CGImageFormat(bitsPerComponent: 8,
bitsPerPixel: 8 * 4,
colorSpace: CGColorSpaceCreateDeviceRGB(),
bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.noneSkipLast.rawValue))!

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
}

private func vImageToCGImage(buffer: vImage_Buffer) -> CGImage? {

guard let context = CGContext(data: buffer.data,
width: Int(buffer.width),
height: Int(buffer.height),
bitsPerComponent: 8,
bytesPerRow: buffer.rowBytes,
space: CGColorSpaceCreateDeviceRGB(),
bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue).rawValue) else {
return nil
}

return context.makeImage()
}

private func createMaskBuffer(width: Int, height: Int) ->  vImage_Buffer? {

let bytesPerPixel = 4
let bytesPerRow = width * bytesPerPixel
let byteCount = bytesPerRow * height
let maskData = UnsafeMutablePointer.allocate(capacity: byteCount)

var maskBuffer = vImage_Buffer(data: maskData, height: vImagePixelCount(height), width: vImagePixelCount(width), rowBytes: bytesPerRow)

memset(maskBuffer.data, 0, byteCount)

return maskBuffer
}

}

extension UIColor {
func toRGBA() -> (UInt8, UInt8, UInt8, UInt8) {
var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0
getRed(&red, green: &green, blue: &blue, alpha: &alpha)

return (UInt8(red * 255), UInt8(green * 255), UInt8(blue * 255), UInt8(alpha * 255))
}
}

Я попробовал несколько подходов к передаче цвета замены. Я пытаюсь сделать что-то невозможное?
Функция заливки vImageFloodFill_ARGB8888 не предназначена для настоящей заливки, а предназначена только для заполнения пустых изображений.

Подробнее здесь: https://stackoverflow.com/questions/784 ... -a-uiimage
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»