0

我写了一个 rgbToHSV cikernel 来转换图像中的像素;但是,它无法正常工作。我已将其范围缩小到 RGB 值在此过程中被扭曲的事实。

为了简化我的代码,我将其更改为一个简单的通过过滤器。

我已经传递了 1280 x 720 图像的图像,这些图像都是一种颜色,然后在它通过 cikernel 之前和之后在 (100, 100) v 位置采样像素颜色。

结果如下:

红色之前:pixelColor :: rgba:1.0:0.0:0.0:1.0 之后:pixelColor :: rgba:1.0:0.07450980392156863:0.0:1.0

之前的绿色:pixelColor :: rgba:0.0:1.0:0.0:1.0 之后:pixelColor :: rgba:0.0:0.984313725490196:0.0:1.0

蓝色之前:pixelColor :: rgba:0.0:0.0:1.0:1.0 之后:pixelColor :: rgba:0.0:0.1803921568627451:1.0:1.0

如您所见,红色和绿色略有失真,但蓝色严重失真。

我已经保存了输出文件并检查了颜色,过滤器肯定会改变颜色。

非常感谢任何关于为什么简单的直通会改变颜色的见解。

简化的直通滤波器:

kernel vec4 rgbToHsv( __sample rgb) {
  return rgb;
}

这是使用 cikernel 的 CIFilter:

class RgbToHsvFilter: CIFilter {
  @objc dynamic var inputImage: CIImage?

  
  private lazy var kernel: CIColorKernel? = {
    guard let path = Bundle.main.path(forResource: "RgbToHsv", ofType: "cikernel"),
      let code = try? String(contentsOfFile: path) else { fatalError("Failed to load RgbToHsv.cikernel from bundle") }
    let kernel = CIColorKernel(source: code)
    return kernel
  }()

  override public var outputImage: CIImage! {
    get {
      if let inputImage = self.inputImage {
        
        let args = [inputImage as AnyObject]
        return self.kernel?.apply(extent: inputImage.extent, arguments: args)
      } else {
        return nil
      }
    }
  }
}

调用过滤器

    let rgbToHsvFilter = RgbToHsvFilter()
    let currentCI = CIImage(cgImage: colorImage!.cgImage!)
    rgbToHsvFilter.setValue(currentCI, forKey: kCIInputImageKey)
    
    if let hsvImage = rgbToHsvFilter.outputImage {
      if let image = cgImage(from: hsvImage) {
        let newImage = UIImage(cgImage: image as! CGImage)
        
        
        let _ = newImage.getPixelColor(pos: pixelPoint)
     
        //UIImageWriteToSavedPhotosAlbum(newImage, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
      }
    }
  }

CGPoint 设置为 (100, 100) 的 getPixelColor 方法。我认为这个问题可能在这里发生,因为打印出来的颜色可能存在误传,但我检查了实际的输出图像,并且过滤器正在改变图像颜色:

  func getPixelColor(pos: CGPoint) -> UIColor {
    
    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 r = CGFloat(data[pixelInfo]) / CGFloat(255.0)
    let g = CGFloat(data[pixelInfo+1]) / CGFloat(255.0)
    let b = CGFloat(data[pixelInfo+2]) / CGFloat(255.0)
    let a = CGFloat(data[pixelInfo+3]) / CGFloat(255.0)
    
    print("pixelColor :: rgba : \(r) : \(g) : \(b) : \(a)")
    
    return UIColor(red: r, green: g, blue: b, alpha: a)
  }

和 cgImage(已编辑):


  func cgImage(from ciImage: CIImage) -> CGImage? {
      let context = CIContext(options: nil)
      return context.createCGImage(ciImage, from: ciImage.extent)
  }
4

1 回答 1

0

所以 CIContext 没有在方法 cgImage 中正确初始化。

这是更正的方法:

  func cgImage(from ciImage: CIImage) -> CGImage? {
    let context = CIContext(options: [CIContextOption.workingColorSpace: kCFNull!])
    return context.createCGImage(ciImage, from: ciImage.extent, format: .RGBA8, colorSpace: CGColorSpace.init(name: CGColorSpace.sRGB)!)
  }
于 2020-09-19T06:59:31.843 回答