gegle.exeでコマンドライン(PowerShell)で一括画像処理

コンピュータ

GEGL (GEneric Graphics Library) は GIMP が内部で使っている画像処理エンジンで、gegl.exe はその コマンドライン版。フィルターやリサイズなどのオペレーション(ノード)をパイプラインでつなぐ形で処理します。

高さを指定して縮小

# 高さを1600pxで縮小
$gegl = "${HOME}/scoop/apps/gimp/current/bin/gegl.exe" # 環境に合わせる

$inDir = "."
$outDir = "./output"
$targetH = 1600

New-Item -ItemType Directory -Path $outDir -Force | Out-Null # エラー無視

# PNGファイルの一覧を取得し、繰り返し処理
Get-ChildItem $inDir -Filter *.png | ForEach-Object {
    $in  = ($_.FullName -replace '\\','/') # 入力ファイル。\を/に置き換え
    $out = ((Join-Path $outDir ($_.BaseName + ".png")) -replace '\\','/')    # 出力ファイル

    # 画像の高さを取得しscaleを算出
    $img = [System.Drawing.Image]::FromFile($_.FullName)
    $scale = $targetH / $img.Height
    $img.Dispose()

    & $gegl -- `
        gegl:load path="$in" `
        gegl:scale-ratio x=$scale y=$scale sampler=nohalo `
        gegl:save path="$out"
}

gegl.exeの処理内容

読み込み→画像加工処理→描き込みの流れになり、画像加工処理部分を複数の複数つなげる、パイプライン処理になっています。

1.gegle:load … 画像ファイルを読み込み
2.gegl:scale-ratio … 縮小処理、補完方法をNoHaloを指定
3.gegl:save … 画像ファイルを保存

色・レベル補正

8ビットグレースケール限定

# 色→レベル補正(8bitグレスケール限定)

function ToLinear($v255) {
  $v = [double]$v255/255.0
  if ($v -le 0.04045) { $v/12.92 } else { [math]::Pow( ($v+0.055)/1.055, 2.4 ) }
}

$gegl = "${HOME}/scoop/apps/gimp/current/bin/gegl.exe" # 環境に合わせる

$inDir = "."
$outDir = "./output"

$inL=ToLinear 59
$inH=ToLinear 176
$outL=0.0
$outH=1.0

echo $inL
echo $inH

New-Item -ItemType Directory -Path $outDir -Force | Out-Null # エラー無視

# PNGファイルの一覧を取得し、繰り返し処理
Get-ChildItem $inDir -Filter *.png | ForEach-Object {
    $in  = ($_.FullName -replace '\\','/') # 入力ファイル。\を/に置き換え
    $out = ((Join-Path $outDir ($_.BaseName + ".png")) -replace '\\','/')    # 出力ファイル

    & $gegl -- `
        gegl:load path="$in" `
        gegl:levels in-low=$inL in-high=$inH out-low=$outL out-high=$outH `
        gegl:convert-format format="Y' u8" `
        gegl:png-save path="$out" bitdepth=8
}

最初gegl:levelsだけで実行しましたが、入力した画像が8ビットのグレースケール画像にたいし出力されるPNGファイルが64bitとなっていいて、gegl:convert-formatとgegl:png-save path="$out" bitdepth=8に変換しています。
また、ToLinearという関数を用意していますが、GIMPのレベルの値に近づけるための変換処理です。(何故か、GIMPで行ったLevelの数値をセットしても同じ結果にならない)
一応手元の環境で希望した通りの画像が出力されるようになりましたが、正しい処理とは思えないので様子見したいとお見ます。

色・レベル補正→高さを指定して縮小

# 色→レベル補正(8bitグレスケール限定)→縮小

function ToLinear($v255) {
  $v = [double]$v255/255.0
  if ($v -le 0.04045) { $v/12.92 } else { [math]::Pow( ($v+0.055)/1.055, 2.4 ) }
}

$gegl = "${HOME}/scoop/apps/gimp/current/bin/gegl.exe" # 環境に合わせる

$inDir = "."
$outDir = "./output"

$inL=ToLinear 59
$inH=ToLinear 176
$outL=0.0
$outH=1.0

$targetH = 1600

New-Item -ItemType Directory -Path $outDir -Force | Out-Null # エラー無視

# PNGファイルの一覧を取得し、繰り返し処理
Get-ChildItem $inDir -Filter *.png | ForEach-Object {
    $in  = ($_.FullName -replace '\\','/') # 入力ファイル。\を/に置き換え
    $out = ((Join-Path $outDir ($_.BaseName + ".png")) -replace '\\','/')    # 出力ファイル

    # 画像の高さを取得しscaleを算出
    $img = [System.Drawing.Image]::FromFile($_.FullName)
    $scale = $targetH / $img.Height
    $img.Dispose()

    & $gegl -- `
        gegl:load path="$in" `
        gegl:levels in-low=$inL in-high=$inH out-low=$outL out-high=$outH `
        gegl:scale-ratio x=$scale y=$scale sampler=nohalo `
        gegl:convert-format format="Y' u8" `
        gegl:png-save path="$out" bitdepth=8
}

コメント