1

我知道可以使用像素缓冲区更改像素的颜色,如下面的代码所示,但我只想使用“CIFilter”模糊像素而不是更改颜色。我不想在整个图像上应用“CIFilter”。

//data pointer – stores an array of the pixel components. For example (r0, b0, g0, a0, r1, g1, b1, a1 .... rn, gn, bn, an)
let data : UnsafeMutablePointer<UInt8> = calloc(bytesPerRow, height)!.assumingMemoryBound(to: UInt8.self)

//get the index of the pixel (4 components times the x position plus the y position times the row width)
let pixelIndex = 4 * (location.x + (location.y * width))

//set the pixel components to the color components
data[pixelIndex] = red
data[pixelIndex+1] = green
data[pixelIndex+2] = blue
data[pixelIndex+3] = alpha

我们也可以使用下面的代码在像素上应用 CIFilter 吗?

if let pixelData = self.cgImage?.dataProvider?.data {
   let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)
   let pixelInfo: Int = ((Int(self.size.width) * Int(pos.y)) + Int(pos.x)) * 4
   let red = CGFloat(data[pixelInfo]) / CGFloat(255.0)
   let green = CGFloat(data[pixelInfo+1]) / CGFloat(255.0)
   let blue = CGFloat(data[pixelInfo+2]) / CGFloat(255.0)
   let alpha = CGFloat(data[pixelInfo+3]) / CGFloat(255.0)
 }
4

2 回答 2

0

我在没有测试代码的情况下很快就输入了这个 - 可能是一些错误。我最近做了一些非常相似的事情,所以不应该太离谱。我想知道得到了什么,如果这不起作用,我敢打赌它已经接近了。

/*
    Implementations
    Notes: 
    - I don't know what kind of `CIFilter` blur you'd like to apply, so I'm just using one from here
    - https://developer.apple.com/library/archive/documentation/GraphicsImaging/Reference/CoreImageFilterReference/#//apple_ref/doc/filter/ci/CIBoxBlur

*/

//Normal Image
let inputImage:UIImage = originalImage

//Blurred Image of only the BLURRED PIXELS -- we change the rest of the pixels to clear -- thus we can use this as the backgroundImage and the maskedImage
let unblurredImage = getBackgroundImage()
let filter = CIFilter(name: "CIBoxBlur")
filter?.setValue(unblurredImage, kCIInputImageKey)
let blurredImage = filter?.outputImage

//Now we can blend the 2 images
let blendFilter = CIFilter(name: "CIBlendWithAlphaMask")
blendFilter?.setValue(CIImage(image: inputImage), kCIInputImageKey)
blendFilter?.setValue(blurredImage, "inputBackgroundImage")
blendFilter?.setValue(blurredImage, "inputMaskImage")
let finalCIImage = blendFilter?.outputImage
let finalImage = UIImage(ciImage: finalCIImage)

/*
    Functions used in the process
*/

//Create an image of only the pixels we want to blur
func getBackgroundImage(ciimage: CIImage) -> UIImage {
    let inputCGImage = ciimage.convertCIImageToCGImage()!

    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("Couldn't create CGContext")
        return nil
    }

    context.draw(inputCGImage, in: CGRect(x: 0, y: 0, width: width, height: height))

        let pixelBuffer = buffer.bindMemory(to: RGBA32.self, capacity: width * height)

        for row in 0 ..< Int(height) {
            for column in 0 ..< Int(width) {
                let offset = row * width + column
                /*
                    You need to define aPixelIWantBlurred however you desire
                    Also, we don't edit the pixels we want to blur - we edit the other pixels to a transparent value. This allows us to use this as the background image and the masked image
                 */
                if pixelBuffer[offset] != aPixelIWantBlurred {
                    pixelBuffer[offset] = RGBA32.init(red: 0, green: 0, blue: 0, alpha: 0)
                }
            }
        }

     let outputCGImage = context.makeImage()!
     let outputImage = UIImage(cgImage: outputCGImage, scale: image.scale, orientation: image.imageOrientation)

     return outputImage
}

extension CIImage {
    func convertCIImageToCGImage() -> CGImage! {
        let context = CIContext(options: nil)
        return context.createCGImage(self, from: self.extent)
    }
}

struct RGBA32: Equatable {
    private var color: UInt32

    var redComponent: UInt8 {
        return UInt8((color >> 24) & 255)
    }

    var greenComponent: UInt8 {
        return UInt8((color >> 16) & 255)
    }

    var blueComponent: UInt8 {
        return UInt8((color >> 8) & 255)
    }

    var alphaComponent: UInt8 {
        return UInt8((color >> 0) & 255)
    }

    init(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) {
        let red   = UInt32(red)
        let green = UInt32(green)
        let blue  = UInt32(blue)
        let alpha = UInt32(alpha)
        color = (red << 24) | (green << 16) | (blue << 8) | (alpha << 0)
    }

    static let red     = RGBA32(red: 255, green: 0,   blue: 0,   alpha: 255)
    static let green   = RGBA32(red: 0,   green: 255, blue: 0,   alpha: 255)
    static let blue    = RGBA32(red: 0,   green: 0,   blue: 255, alpha: 255)
    static let white   = RGBA32(red: 255, green: 255, blue: 255, alpha: 255)
    static let black   = RGBA32(red: 0,   green: 0,   blue: 0,   alpha: 255)
    static let magenta = RGBA32(red: 255, green: 0,   blue: 255, alpha: 255)
    static let yellow  = RGBA32(red: 255, green: 255, blue: 0,   alpha: 255)
    static let cyan    = RGBA32(red: 0,   green: 255, blue: 255, alpha: 255)

    static let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Little.rawValue

    static func ==(lhs: RGBA32, rhs: RGBA32) -> Bool {
        return lhs.color == rhs.color
    }
}
于 2019-09-07T17:57:14.463 回答
0

查看CIBlendWithMask过滤器。它允许您创建任何形状(甚至是单个像素)的蒙版,并使用它将输入与另一个输入混合。如果您将inputBackgroundImage其设为原始图像,并使其inputImage成为应用了所需滤镜的原始图像,inputImageMask则该图像是全黑图像,只有您想要将单个像素更改为白色。

于 2019-09-07T00:56:52.520 回答