[Astro] #129 Camera RAW Viewer — libraw-wasm によるブラウザ完結型カメラRAWファイルデコード・プレビュー・書き出しツール

[Astro] #129 Camera RAW Viewer — libraw-wasm によるブラウザ完結型カメラRAWファイルデコード・プレビュー・書き出しツール

概要

libraw-wasm(LibRaw の WebAssembly ビルド)を使って、カメラ RAW ファイルをサーバーにアップロードすることなくブラウザ内で完結してデコード・プレビュー・書き出しできるツールを作りました。

Canon CR2/CR3、Nikon NEF、Sony ARW をはじめ、LibRaw がサポートする 500+ 機種のカメラ RAW フォーマットに対応しています。

スクリーンショット

Sony DSLR-A350 ARW(14.5 MB)のデコード・プレビュー

Camera RAW Viewer — Sony ARW デコード結果

Canon EOS 7D CR2(10.6 MB)— GPS・レンズ情報付き

Camera RAW Viewer — Canon CR2 デコード結果

バッチ処理 — 複数RAWファイルの一括読み込みとプレビュー切替

Camera RAW Viewer — バッチ処理

動画(GIF)

編集

Camera RAW Viewer — 動画(編集)

バッチ処理

Camera RAW Viewer — 動画(バッチ処理)

Sample data

サンプルデータは以下のSONYとraw.pixls.usのサイトからお借りしています。

動作確認済みフォーマット

メーカーフォーマットテストカメラ結果
SonyARWDSLR-A350✅ 正常デコード(4600×3068、約1.9秒)
CanonCR2EOS 7D(sRAW2)✅ 正常デコード(GPS・レンズ情報取得)
NikonNEFCOOLSCAN IV ED⚠️ デコード可だが白飛び(フィルムスキャナー固有の問題)

LibRaw は内部で 600+ 機種のカメラをサポートしているため、上記以外のメーカー(Fuji RAF、Olympus ORF、Panasonic RW2、DNG 等)も原理的には対応しています。

技術構成

libraw-wasm

npm パッケージ libraw-wasm(v1.6.0)を使用。LibRaw を Emscripten で WebAssembly にコンパイルしたもので、WASM ファイルサイズは約 1.4MB。

処理は内蔵の Web Worker 内で実行されるため、メインスレッドをブロックしません。API は以下の4メソッド:

メソッド用途
open(bytes, settings)RAW ファイルを開いてデコード
metadata(full?)EXIF・GPS・レンズ・メーカー固有メタデータを取得
imageData()デモザイク済み RGB 画像データを取得
thumbnailData()埋め込みサムネイル(JPEG)を取得

Astro + Vite の設定

libraw-wasm は内部で new Worker(new URL('./worker.js', import.meta.url)) を使っているため、Vite の依存関係最適化から除外する必要があります。

// astro.config.mjs
export default defineConfig({
  vite: {
    optimizeDeps: {
      exclude: ['libraw-wasm'],
    },
  },
})

これを入れないと、Vite が worker.js を事前バンドルしようとして「ファイルが見つからない」エラーになります。libarchive.js 等の WASM + Web Worker 系パッケージでも同様のパターンが必要です。

実装内容

基本フロー

ファイル選択 / ドラッグ&ドロップ
  → ArrayBuffer 読み込み
  → LibRaw インスタンス生成
  → decoder.open(buffer, settings)  ← Web Worker 内で実行
  → decoder.metadata(true)          ← EXIF・GPS・レンズ情報取得
  → decoder.imageData()             ← デモザイク済み RGB 取得
  → Canvas に描画

RAW Settings による再現像

LibRaw のデコードパラメータを UI から動的に変更し、Re-process ボタンまたはスライダー操作で再デコードします。

パラメータ説明対応 LibRaw オプション
Brightness明るさ調整bright
White BalanceCamera WB / Auto WB / NoneuseCameraWb / useAutoWb
Highlightハイライト復元モード(0-3)highlight
Qualityデモザイク品質(Linear/VNG/PPG/AHD)userQual
Denoiseウェーブレットノイズ除去threshold
Half Size半解像度(高速プレビュー用)halfSize

Brightness スライダーはドラッグ中に CSS Filter(brightness())で即時プレビューし、ドラッグ離した時に WASM 再デコードを走らせることで、リアルタイム感のあるインタラクションを実現しています。

// ドラッグ中:CSS Filter で即時フィードバック(0ms)
brightInput.addEventListener('input', () => {
  previewCanvas.style.filter = `brightness(${val})`
})

// ドラッグ離した時:LibRaw で再デコード(約2秒)
brightInput.addEventListener('change', () => {
  previewCanvas.style.filter = 'none'
  processFile(currentFile)
})

16bit / 8bit 画像データの Canvas 描画

LibRaw は outputBps 設定に応じて 8bit(Uint8Array)または 16bit(Uint16Array)の RGB データを返します。Canvas の ImageData は 8bit RGBA なので、16bit データの場合は上位 8bit にシフトして変換します。

if (is16bit) {
  pixels[dstIdx]     = (data as Uint16Array)[srcIdx]     >> 8
  pixels[dstIdx + 1] = (data as Uint16Array)[srcIdx + 1] >> 8
  pixels[dstIdx + 2] = (data as Uint16Array)[srcIdx + 2] >> 8
} else {
  pixels[dstIdx]     = (data as Uint8Array)[srcIdx]
  pixels[dstIdx + 1] = (data as Uint8Array)[srcIdx + 1]
  pixels[dstIdx + 2] = (data as Uint8Array)[srcIdx + 2]
}
pixels[dstIdx + 3] = 255  // Alpha

メタデータ表示

LibRaw の metadata(true) は全メーカー固有メタデータを含む詳細情報を返します。

基本情報: カメラメーカー・モデル、解像度、ISO、シャッター速度、絞り、焦点距離、撮影日時

GPS: 緯度・経度(度分秒)、高度、ステータス

レンズ: レンズ名、メーカー、焦点距離レンジ、最大絞り、35mm 換算焦点距離

メーカー固有: Canon(ColorData、FlashMode 等)、Nikon(NEFBitDepth、Active_D_Lighting 等)、Sony(AFAreaMode、SonyRawFileType 等)、Fuji、Panasonic、Olympus、Pentax、Hasselblad、Ricoh、Kodak、PhaseOne、Samsung

バッチ処理

複数の RAW ファイルを一括で読み込み、ファイルリストに表示します。

  • ドラッグ&ドロップまたはファイル選択で複数ファイルを追加
  • リスト内のファイルをクリックで個別プレビュー切替
  • 「EXPORT ALL」ボタンで全ファイルを順次デコード → JPEG/PNG/WebP に変換してダウンロード

Export(書き出し)

Canvas の toBlob() を使い、以下の形式で書き出します。

形式品質調整
JPEG10-100%(スライダー)
PNGロスレス
WebP10-100%(スライダー)

機能一覧

カテゴリ内容
RAW デコード500+ カメラフォーマット対応(LibRaw / WASM)
メタデータEXIF・GPS・レンズ・メーカー固有情報の表示
RAW SettingsBrightness・WB・Highlight・Quality・Denoise・Half Size の動的変更
リアルタイムプレビューCSS Filter による Brightness 即時反映
バッチ処理複数ファイル一括読み込み・プレビュー切替・一括 Export
ExportJPEG / PNG / WebP への変換・品質調整・ダウンロード
Web Workerメインスレッド非ブロック処理
ブラウザ完結サーバーへのアップロード不要

技術スタック

  • libraw-wasm v1.6.0 — LibRaw の WebAssembly ビルド(Web Worker 内蔵)
  • Astro — ページビルド・スクリプトバンドル
  • Canvas API — RAW 画像の描画・Export

今後の展開

  • Photo Editor 連携 — RAW デコード → Photo Editor(WebGL シェーダー)の色調補正・シャープネスパイプライン。「ブラウザ版 Lightroom」に近いワークフローの実現
  • ヒストグラム表示 — RGB チャンネル別のヒストグラムをリアルタイム表示
  • WebGL シェーダーによる再現像 — デモザイク済み RGB を保持し、Fragment Shader で明るさ・コントラスト・カラーバランスを 60fps で調整

更新履歴

  • [v1.0] (2026-09-06): 初回公開。
    • libraw-wasm (v1.6.0) による RAW デコードパイプライン構築
    • Sony ARW / Canon CR2 / Nikon NEF 動作確認
    • EXIF・GPS・レンズ・メーカー固有メタデータ表示
    • RAW Settings(Brightness / WB / Highlight / Quality / Denoise / Half Size)
    • CSS Filter による Brightness リアルタイムプレビュー
    • バッチ処理(複数ファイル一括読み込み・EXPORT ALL)
    • JPEG / PNG / WebP 書き出し(品質調整付き)