macOSの sips で落ちる画像を、別の方法で切り出す
2026.08.07 09:00
2026.08.30 00:36
紙の資料をiPhoneで撮り、その写真をAIへ渡して文字起こしすることがあります。ページ全体をそのまま読ませるより、数ブロックに切り、ルビや固有名詞だけ拡大したほうが認識は安定します。
そこでmacOS標準の sips を使おうとしたのですが、サンドボックス内では何度試しても書き出しに失敗しました。出力先を変えても駄目だったため、最終的にはSwiftからCoreGraphicsを直接使う小さな切り出しツールで代替しました。
sips -c 510 1670 --cropOffset 840 470 input.jpeg --out out.jpg
# Error 13: Cannot write to file
CoreGraphicsを直接使う
小さなSwiftバイナリで読み込み、切り出し、書き出しを行えます。
import Foundation
import CoreGraphics
import ImageIO
let a = CommandLine.arguments
guard let src = CGImageSourceCreateWithURL(URL(fileURLWithPath: a[1]) as CFURL, nil),
let img = CGImageSourceCreateImageAtIndex(src, 0, nil) else { exit(1) }
var x = Int(a[3]) ?? 0, y = Int(a[4]) ?? 0
var w = Int(a[5]) ?? 0, h = Int(a[6]) ?? 0
x = max(0, min(x, img.width - 1))
y = max(0, min(y, img.height - 1))
w = max(1, min(w, img.width - x))
h = max(1, min(h, img.height - y))
guard let sub = img.cropping(to: CGRect(x: x, y: y, width: w, height: h)) else {
exit(1)
}
拡大時は CGContext の補間品質を設定して描き直します。
ctx.interpolationQuality = .high
ctx.draw(sub, in: CGRect(x: 0, y: 0, width: nw, height: nh))
swiftcのキャッシュ先を変える
一時ディレクトリとモジュールキャッシュを、書き込める場所へ逃がします。警告が出ても生成物ができる環境があるため、終了コードだけでなく実行ファイルの存在も確認します。
export TMPDIR="${CACHE_DIR}/tmp"
mkdir -p "$TMPDIR" "${CACHE_DIR}/modcache"
swiftc -O -module-cache-path "${CACHE_DIR}/modcache" "$SRC" -o "$BIN" || true
[[ -x "$BIN" ]] || exit 1
実行時の無害な警告を除く場合、プロセス置換が使えない環境では標準エラーを一時ファイルへ保存してからフィルタします。
この小さなツールができてからは、ページを2〜4ブロックに切り、細かな文字だけ4〜5倍にして確認する流れが定着しました。sips をどうにか動かすことより、必要だった「切り出して書き出す」という処理を別の方法で満たすほうが早いケースでした。
標準コマンドが使えないと、環境そのものを直すことに意識が向きます。けれど、そのコマンドが実際にしていることを分解してみると、数十行の代替で先へ進めることがあります。今回いちばん大きかったのは、その切り替えでした。
今回は以上です。