【问题标题】:How to use LUT png for CIColorCube filter?CIColorCube过滤器如何使用LUT png?
【发布时间】:2015-07-27 20:30:00
【问题描述】:

我想使用查找表 png (example) 作为 Swift 中 CIColorCube 过滤器的颜色立方体数据。到目前为止,我尝试(和发现)的所有示例都是带有计算颜色立方体的示例,如 this example

如何读取 png 作为查找数据?

【问题讨论】:

    标签: ios swift cifilter


    【解决方案1】:

    我现在使用 thisthis 项目来为 Swift 调整他们的 Objective-C 实现:

    func colorCubeFilterFromLUT(imageName : NSString) -> CIFilter? {
    
        let kDimension : UInt = 64
    
        let lutImage    = UIImage(named: imageName)!.CGImage
        let lutWidth    = CGImageGetWidth(lutImage!)
        let lutHeight   = CGImageGetHeight(lutImage!)
        let rowCount    = lutHeight / kDimension
        let columnCount = lutWidth / kDimension
    
        if ((lutWidth % kDimension != 0) || (lutHeight % kDimension != 0) || (rowCount * columnCount != kDimension)) {
    
            NSLog("Invalid colorLUT %@", imageName);
            return nil
        }
    
        let bitmap  = self.createRGBABitmapFromImage(lutImage)
        let size    = Int(kDimension) * Int(kDimension) * Int(kDimension) * sizeof(Float) * 4
        let data    = UnsafeMutablePointer<Float>(malloc(UInt(size)))
    
        var bitmapOffset : Int = 0
        var z : UInt = 0
    
    
        for (var row: UInt = 0; row < rowCount; row++)
        {
            for (var y: UInt = 0; y < kDimension; y++)
            {
                var tmp = z
                for (var col: UInt = 0; col < columnCount; col++)
                {
                    for (var x: UInt = 0; x < kDimension; x++) {
    
                        let alpha   = Float(bitmap[Int(bitmapOffset)]) / 255.0
                        let red     = Float(bitmap[Int(bitmapOffset+1)]) / 255.0
                        let green   = Float(bitmap[Int(bitmapOffset+2)]) / 255.0
                        let blue    = Float(bitmap[Int(bitmapOffset+3)]) / 255.0
    
                        var dataOffset = Int(z * kDimension * kDimension + y * kDimension + x) * 4
    
                        data[dataOffset] = red
                        data[dataOffset + 1] = green
                        data[dataOffset + 2] = blue
                        data[dataOffset + 3] = alpha
                        bitmapOffset += 4
                    }
                    z++
                }
                z = tmp
            }
            z += columnCount
        }
    
        let colorCubeData = NSData(bytesNoCopy: data, length: size, freeWhenDone: true)
    
        // create CIColorCube Filter
        var filter = CIFilter(name: "CIColorCube")
        filter.setValue(colorCubeData, forKey: "inputCubeData")
        filter.setValue(kDimension, forKey: "inputCubeDimension")
    
        return filter
    }
    
    
    func createRGBABitmapFromImage(inImage: CGImage) -> UnsafeMutablePointer<Float> {
    
        //Get image width, height
        let pixelsWide = CGImageGetWidth(inImage) 
        let pixelsHigh = CGImageGetHeight(inImage) 
    
        // Declare the number of bytes per row. Each pixel in the bitmap in this
        // example is represented by 4 bytes; 8 bits each of red, green, blue, and
        // alpha.
        let bitmapBytesPerRow = Int(pixelsWide) * 4 
        let bitmapByteCount = bitmapBytesPerRow * Int(pixelsHigh)
    
        // Use the generic RGB color space.
        let colorSpace = CGColorSpaceCreateDeviceRGB()
    
        // Allocate memory for image data. This is the destination in memory
        // where any drawing to the bitmap context will be rendered.
        let bitmapData = malloc(CUnsignedLong(bitmapByteCount)) // bitmap
        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedFirst.rawValue) 
    
        // Create the bitmap context. We want pre-multiplied RGBA, 8-bits
        // per component. Regardless of what the source image format is
        // (CMYK, Grayscale, and so on) it will be converted over to the format
        // specified here by CGBitmapContextCreate.
        let context = CGBitmapContextCreate(bitmapData, pixelsWide, pixelsHigh, 8, UInt(bitmapBytesPerRow), colorSpace, bitmapInfo)
    
    
        let rect = CGRect(x:0, y:0, width:Int(pixelsWide), height:Int(pixelsHigh))        
    
        // Draw the image to the bitmap context. Once we draw, the memory
        // allocated for the context for rendering will then contain the
        // raw image data in the specified color space.
        CGContextDrawImage(context, rect, inImage)
    
        // Now we can get a pointer to the image data associated with the bitmap
        // context.
        // var data = CGBitmapContextGetData(context)
        // var dataType = UnsafeMutablePointer<Float>(data)
        // return dataType
    
    
        var convertedBitmap = malloc(UInt(bitmapByteCount * sizeof(Float)))
        vDSP_vfltu8(UnsafePointer<UInt8>(bitmapData), 1, UnsafeMutablePointer<Float>(convertedBitmap), 1, vDSP_Length(bitmapByteCount))
    
        free(bitmapData)
        return UnsafeMutablePointer<Float>(convertedBitmap)
    }
    

    另请参阅this 答案。

    【讨论】:

      【解决方案2】:

      我以为我会为 Swift 3.0 更新这个也适用于 JPG 和 PNG 的 3D 颜色 LUT

      fileprivate func colorCubeFilterFromLUT(imageName : String) -> CIFilter? {
      
          let size = 64
      
          let lutImage    = UIImage(named: imageName)!.cgImage
          let lutWidth    = lutImage!.width
          let lutHeight   = lutImage!.height
          let rowCount    = lutHeight / size
          let columnCount = lutWidth / size
      
          if ((lutWidth % size != 0) || (lutHeight % size != 0) || (rowCount * columnCount != size)) {
              NSLog("Invalid colorLUT %@", imageName);
              return nil
          }
      
          let bitmap  = getBytesFromImage(image: UIImage(named: imageName))!
          let floatSize = MemoryLayout<Float>.size
      
          let cubeData = UnsafeMutablePointer<Float>.allocate(capacity: size * size * size * 4 * floatSize)
          var z = 0
          var bitmapOffset = 0
      
          for _ in 0 ..< rowCount {
              for y in 0 ..< size {
                  let tmp = z
                  for _ in 0 ..< columnCount {
                      for x in 0 ..< size {
      
                          let alpha   = Float(bitmap[bitmapOffset]) / 255.0
                          let red     = Float(bitmap[bitmapOffset+1]) / 255.0
                          let green   = Float(bitmap[bitmapOffset+2]) / 255.0
                          let blue    = Float(bitmap[bitmapOffset+3]) / 255.0
      
                          let dataOffset = (z * size * size + y * size + x) * 4
      
                          cubeData[dataOffset + 3] = alpha
                          cubeData[dataOffset + 2] = red
                          cubeData[dataOffset + 1] = green
                          cubeData[dataOffset + 0] = blue
                          bitmapOffset += 4
                      }
                      z += 1
                  }
                  z = tmp
              }
              z += columnCount
          }
      
          let colorCubeData = NSData(bytesNoCopy: cubeData, length: size * size * size * 4 * floatSize, freeWhenDone: true)
      
          // create CIColorCube Filter
          let filter = CIFilter(name: "CIColorCube")
          filter?.setValue(colorCubeData, forKey: "inputCubeData")
          filter?.setValue(size, forKey: "inputCubeDimension")
      
          return filter
      }
      
      
      fileprivate func getBytesFromImage(image:UIImage?) -> [UInt8]?
      {
          var pixelValues: [UInt8]?
          if let imageRef = image?.cgImage {
              let width = Int(imageRef.width)
              let height = Int(imageRef.height)
              let bitsPerComponent = 8
              let bytesPerRow = width * 4
              let totalBytes = height * bytesPerRow
      
              let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
              let colorSpace = CGColorSpaceCreateDeviceRGB()
              var intensities = [UInt8](repeating: 0, count: totalBytes)
      
              let contextRef = CGContext(data: &intensities, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo)
              contextRef?.draw(imageRef, in: CGRect(x: 0.0, y: 0.0, width: CGFloat(width), height: CGFloat(height)))
      
              pixelValues = intensities
          }
          return pixelValues!
      }
      

      【讨论】:

      • 这个有什么用?
      • 它用于 3 维颜色查找表,用于将输入颜色映射到输出颜色作为 CIImage 的 CIFilter。它是核心图像 iOS 框架的一部分。
      猜你喜欢
      • 2015-02-26
      • 2021-06-17
      • 1970-01-01
      • 2013-03-22
      • 1970-01-01
      • 2011-04-30
      • 2014-09-14
      • 2014-02-03
      • 2017-11-29
      相关资源
      最近更新 更多