[Astro] #129 Camera RAW Viewer — libraw-wasm によるブラウザ完結型カメラRAWファイルデコード・プレビュー・書き出しツール
概要
libraw-wasm(LibRaw の WebAssembly ビルド)を使って、カメラ RAW ファイルをサーバーにアップロードすることなくブラウザ内で完結してデコード・プレビュー・書き出しできるツールを作りました。
Canon CR2/CR3、Nikon NEF、Sony ARW をはじめ、LibRaw がサポートする 500+ 機種のカメラ RAW フォーマットに対応しています。
GitHub - ybouane/LibRaw-Wasm
LibRaw WASM bindings to be able to use it in the browser. Web Worker によるメインスレッド非ブロック処理。
github.com
Camera RAW Viewer
ブラウザ完結型カメラRAWファイルデコード・プレビュー・書き出しツール。CR2/NEF/ARW等500+フォーマット対応。
lain-lab.comスクリーンショット
Sony DSLR-A350 ARW(14.5 MB)のデコード・プレビュー
Canon EOS 7D CR2(10.6 MB)— GPS・レンズ情報付き
バッチ処理 — 複数RAWファイルの一括読み込みとプレビュー切替
動画(GIF)
編集
バッチ処理
Sample data
サンプルデータは以下のSONYとraw.pixls.usのサイトからお借りしています。
SONY
SONY VAIO RAW データダウンロード
www.sony.jpraw.pixls.us
If you can provide a raw file from a camera we're currently missing, if the sample we have is not under co, or if you can provide a more useful photo from a camera model we already support (but NOT a photo of a color target!), please upload that file now.
raw.pixls.us動作確認済みフォーマット
| メーカー | フォーマット | テストカメラ | 結果 |
|---|---|---|---|
| Sony | ARW | DSLR-A350 | ✅ 正常デコード(4600×3068、約1.9秒) |
| Canon | CR2 | EOS 7D(sRAW2) | ✅ 正常デコード(GPS・レンズ情報取得) |
| Nikon | NEF | COOLSCAN 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 Balance | Camera WB / Auto WB / None | useCameraWb / 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() を使い、以下の形式で書き出します。
| 形式 | 品質調整 |
|---|---|
| JPEG | 10-100%(スライダー) |
| PNG | ロスレス |
| WebP | 10-100%(スライダー) |
機能一覧
| カテゴリ | 内容 |
|---|---|
| RAW デコード | 500+ カメラフォーマット対応(LibRaw / WASM) |
| メタデータ | EXIF・GPS・レンズ・メーカー固有情報の表示 |
| RAW Settings | Brightness・WB・Highlight・Quality・Denoise・Half Size の動的変更 |
| リアルタイムプレビュー | CSS Filter による Brightness 即時反映 |
| バッチ処理 | 複数ファイル一括読み込み・プレビュー切替・一括 Export |
| Export | JPEG / 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 書き出し(品質調整付き)