「DaVinci Resolve」の 3D LUT を使って iOS の UIImage にフィルタをかける

iOS

無料で使える高機能な動画編集ソフト「DaVinci Resolve」で書き出したカラーコレクションデータ(3D LUT)を使って、iOS の UIImage にフィルタをかける方法を解説します。

※高機能なツールで色味をじっくり調整できるので便利ですよ!

スポンサーリンク

DaVinci Resolve とは?

DaVinci Resolve」は Blackmagic Design 社がリリースしているプロ仕様の動画編集ソフトです。

DaVinci Resolve 17 | Blackmagic Design

サイトを見ると分かりますが、めちゃくちゃ高機能、しかも無償版があります。(太っ腹!)

有償版の「DaVinci Resolve Studio」は、4K〜16K解像度、120fps、HDR といったハイエンドな機能に対応しています。が、ハイエンドの機能を除けばほとんどの機能が無償版でも使えようになっています。(太っ腹!)

特にカラーコレクションの機能が充実しているので、これをiOSの画像フィルタ作成用に使えるのは嬉しいですね。

「DaVinci Resolve」の無償版はMacのAppStoreにもありますが、機能制限の内容が異なるようなので、上記の公式サイトからダウンロードしたものを使いましょう。

3D LUT(.cube)の作成

DaVinci Resolve」でのカラー調整については省きます。

カラータブ画面の左中央にあるプレビュー画像(矢印)を右クリックすると、3D LUT 書き出しメニューが表示されます。

  • Generate 3D LUT (33 Point Cube)
  • Generate 3D LUT (65 Point Cube)

どちらかを選びます。

Point数が33の場合、データ数は33*33*33になります。65の場合は65*65*65。Point数が多ければ解像度が上がりますが、その分データも大きくなるので、お好みで作成してください。

書き出したファイルの拡張子は *.cube です。

中身はこんな感じのテキストデータになっています。

TITLE "Generated by Resolve"
LUT_3D_SIZE 33

0.0285801 0.0230259 0.0308995
0.0283207 0.0238499 0.031342
0.0277562 0.0245823 0.0317998
0.0284428 0.0255436 0.0322118
0.0293278 0.0262913 0.0325628
0.0226749 0.0269169 0.0328069
0.0221256 0.0277104 0.0329747
0.0432441 0.0291447 0.0329137
...(以下省略)

UIImageにフィルタをかける

3D LUT(.cube)の読み込み

3D LUTデータをファイル名「sample.cube」で書き出して、Xcode にファイルを追加してある状態でのコード例(Swift)です。

var dimension = 0 // 3D LUTの1辺のサイズ
var dataArray = Array<Float>() // LUTデータ格納用Array

do {
    // *.cube を読み込んで行毎に分割
    let path = Bundle.main.path(forResource: "sample", ofType: "cube")!
    let content = try String(contentsOfFile: path)
    let lines = content.components(separatedBy: "\n")

    // 行毎に処理
    for line in lines {
        // Dimension (Davinch Resolve)
        if line.hasPrefix("LUT_3D_SIZE") {
            let values = line.split{$0 == " "}.map(String.init)
            dimension = Int(values[1])!
        }
        // RGBデータ(先頭1文字が数字ならデータ行と判定)
        if line.prefix(1).range(of: #"[0-9]+"#, options: .regularExpression ) != nil {
            let values = line.split{$0 == " "}.map(String.init)
            dataArray.append(Float(values[0])!) //R
            dataArray.append(Float(values[1])!) //G
            dataArray.append(Float(values[2])!) //B
            dataArray.append(1.0) //CIColorCubeではRGBAを使うのでalphaを追加
        }
    }
} catch  {
    // 読み込みエラー処理
}

// ArrayをNSDataに変換(CIColorCubeに入れるデータがNSDataなので変換)
let data = NSData(bytes: &dataArray, length: dataArray.count*MemoryLayout<Float>.size)

3D LUT のPoint数が dimension です。データは data に入ります。

DaVinci Resolve」に限らず、各種LUTフォーマットに合わせてパースのところを少し変えれば大体のLUTファイルは読み込めると思います。

CIFilter で 3D LUT を適用

読み込んだ 3D LUT(dimensionとdata)を使って、UIImageにフィルタをかけるコード(Swift)です。

// sourceImage が元画像となる UIImage
var outputImage = CIImage(cgImage: sourceImage.cgImage!)

// sRGB に変換
var filter = CIFilter(name: "CILinearToSRGBToneCurve")!
filter.setDefaults()
filter.setValue(outputImage, forKey: kCIInputImageKey)
outputImage = filter.outputImage!

// 3D LUT を適用
filter = CIFilter(name: "CIColorCube")!
filter.setDefaults()
filter.setValue(outputImage, forKey: kCIInputImageKey)
filter.setValue(dimension, forKey: "inputCubeDimension") // ここで dimension
filter.setValue(data, forKey: "inputCubeData") // ここで data
outputImage = filter.outputImage!

// リニアに変換
filter = CIFilter(name: "CISRGBToneCurveToLinear")!
filter.setDefaults()
filter.setValue(outputImage, forKey: kCIInputImageKey)
outputImage = filter.outputImage!

// UIImage にする
let context = CIContext(options: nil)
let cgImage = context.createCGImage(outputImage, from: outputImage.extent)!
let image = UIImage(cgImage: cgImage)

3D LUT の色空間が sRGB なので(iOSはリニア)、一旦 sRGB に変換してから LUT を適用して、リニアに戻しています。

以上で「DaVinci Resolve」の 3D LUT が適用された UIImage が出来上がります。

コメント

タイトルとURLをコピーしました