ブラウザベースのビューア+画像エクスポートツール群。PWA としてインストール可能、オフラインで動作する。
A browser-based viewer + image export toolkit. Installable as a PWA and fully functional offline.
Created by id-fa, built with Claude Code.
pdf-viewer-with-screenshot/
├── pdf-viewer.html # PDF専用ビューア / PDF-only viewer
├── comic-viewer.html # 汎用ビューア / Universal viewer (PDF + CBZ/CBR/CB7/EPUB)
├── sw.js # Service Worker (precache + COOP/COEP)
├── manifest.webmanifest # PWA manifest
├── library.php # ライブラリ参照 API (任意) / Library API (optional, server install)
├── library.config.example.php # library.php の設定サンプル / Config sample
├── library.htaccess.example # Basic 認証のサンプル / Basic auth sample
├── tools/
│ ├── generate_coverimages.php # 表紙画像の一括生成 (CLI) / Cover generator (CLI)
│ └── generate_coverimages.py # 同上の Python 版 / same tool, Python version
├── vendor/ # Vendored libraries (no CDN required)
│ ├── pdfjs/ # PDF.js v4.9.155
│ ├── pica/ # Pica.js v10.0.2
│ ├── libarchive/ # libarchive.js v2.0.2
│ └── vips/ # wasm-vips v0.0.18 (optional, used with ?vips=1)
├── icons/ # PWA icons + generator
├── README.md # This file
└── CLAUDE.md # AI development guide
PDF専用の軽量ビューア。
A lightweight PDF-only viewer.
ローカルにダウンロードせず、GitHub Pages でホストされたページをそのまま利用できます。アクセス解析 (Google Analytics) はありますが、開いたファイルの内容は一切サーバーに送信されません。
You can use the viewer directly via GitHub Pages without downloading. Google Analytics is used for access analytics, but the contents of files you open are never sent to any server.
→ Open pdf-viewer → Open pdf-viewer (wasm-vips) ※wasm-vips 版 (初回アクセス時に vendor 一式 ~8MB をキャッシュ) / wasm-vips build (~8MB of vendored assets cached on first visit)
ローカルに置いて使う場合は、vendor/ の ES モジュールが file:// では CORS でブロックされるため HTTP サーバーが必要です (comic-viewer.html と同じ、下記「起動 / Getting Started」を参照)。
To use it locally, an HTTP server is required — the ES modules under vendor/ are blocked by CORS on file:// (same as comic-viewer.html; see "Getting Started" below).
http://localhost:8000/pdf-viewer.htmlをブラウザで開く / Openhttp://localhost:8000/pdf-viewer.htmlin your browser- 「Open PDF」ボタンまたはドラッグ&ドロップでPDFを読み込む / Load a PDF via "Open PDF" button or drag & drop
- ページを閲覧・画像として保存 / Browse pages and save as images
- PDF.js v4.9.155 (
vendor/に同梱 / vendored) - Pica.js v10.0.2 (
vendor/に同梱 / vendored) — 高品質画像縮小 (unsharp mask、Web Worker で実行) / High-quality image downscaling, runs in a Web Worker
PDF / CBZ / CBR / CB7 / EPUB に対応する汎用コミックビューア。
A universal comic viewer supporting PDF / CBZ / CBR / CB7 / EPUB.
| 形式 / Format | 拡張子 / Extension | ライブラリ / Library |
|---|---|---|
.pdf |
PDF.js v4.9.155 | |
| CBZ | .cbz, .zip |
libarchive.js v2.0.2 (WASM) |
| CBR | .cbr, .rar |
libarchive.js v2.0.2 (WASM) |
| CB7 | .cb7, .7z |
libarchive.js v2.0.2 (WASM) |
| EPUB | .epub |
libarchive.js v2.0.2 (WASM) ※固定レイアウト + リフロー本文表示 / Fixed-layout + reflowable text view |
アーカイブ内の画像ファイル (JPEG, PNG, WebP, GIF, BMP, AVIF, JXL, TIFF) を自動検出して表示します。
Image files within archives are automatically detected and displayed.
EPUB について / About EPUB: ページ画像としての表示は固定レイアウト(画像ベース)のみ。リフロー型は
Rキーの本文リーダで中身のテキストを読めます (縦書き・ページ分割は非対応)。本格的なリフロー表示には BiBI をお試しください。 / Only fixed-layout (image-based) EPUBs render as pages. Reflowable EPUBs can be read as text via theRkey reader (no vertical writing or pagination). For a full reflowable experience, try BiBI.
ローカルにサーバーを立てる代わりに、GitHub Pages でホストされたページをそのまま利用できます。アクセス解析 (Google Analytics) はありますが、開いたファイルの内容は一切サーバーに送信されません。
Instead of running a local server, you can use the viewer directly via GitHub Pages. Google Analytics is used for access analytics, but the contents of files you open are never sent to any server.
→ Open comic-viewer → Open comic-viewer (wasm-vips) ※wasm-vips 版 (初回アクセス時に vendor 一式 ~8MB をキャッシュ) / wasm-vips build (~8MB of vendored assets cached on first visit)
ローカルで起動する場合は、file:// では WASM Worker が動作しないため HTTP サーバーが必要です。
To run locally, a local HTTP server is required because WASM Workers do not work with file://.
# Python
python -m http.server 8000
# PHP
php -S localhost:8000
# Node.js (npx)
npx serve .ブラウザで http://localhost:8000/comic-viewer.html を開きます。
Open http://localhost:8000/comic-viewer.html in your browser.
以下の機能は両ビューアに共通です。 / The following features are shared by both viewers.
| 操作 / Control | 説明 / Description |
|---|---|
< / > ボタン |
ページ送り / Page navigation |
| ページ番号入力 | 任意ページにジャンプ / Jump to a specific page |
| Single / Spread / Scroll | 単ページ / 見開き / 連続スクロール切替 / Toggle single / spread / scroll |
| Right (R2L) / Left (L2R) | 綴じ方向 / Binding direction (R2L=日本漫画, L2R=洋書) |
| Cover | 表紙を単独ページとして扱う / Treat cover as standalone page |
| HQ | 高品質縮小モード (Pica.js) / High-quality downscale mode (Pica.js) |
| 0° / 90° / 180° / 270° | ページ回転 / Page rotation |
| 50% ~ 300% / Fit | 表示スケール / Display scale |
| Pan | ドラッグで画面パン / Drag to pan (scroll) |
| Map | ミニマップ表示 / Show minimap |
| Full | フルスクリーン / Fullscreen mode |
| Filter | 色調補正フィルター (プリセット3スロット保存可) / Color filters (3 preset slots) |
| Thumbs / Bookmarks / TOC | サイドバー切替 (TOC は EPUB 構造解析後のみ) / Sidebar tabs (TOC appears only after EPUB analysis) |
| 操作 / Input | R2L (右綴じ) | L2R (左綴じ) |
|---|---|---|
| ← / 画面左端タップ | 次ページ / Next | 前ページ / Prev |
| → / 画面右端タップ | 前ページ / Prev | 次ページ / Next |
| ↑ | 前ページ / Prev | 前ページ / Prev |
| ↓ | 次ページ / Next | 次ページ / Next |
| Home | 最初のページ / First page | 最初のページ / First page |
| End | 最後のページ / Last page | 最後のページ / Last page |
| 操作 / Input | 説明 / Description |
|---|---|
画面中央タップ / H キー |
UI表示/非表示トグル / Toggle UI visibility |
C キー |
Cover (表紙モード) トグル / Toggle cover mode |
B キー |
綴じ方向切替 (R2L ↔ L2R) / Toggle binding direction |
Z キー |
ズームトグル (300% + Pan + Map) / Toggle zoom (300% + Pan + Map) |
L キー |
Last Read ページにジャンプ / Jump to last read page |
M キー |
Max Read ページにジャンプ / Jump to max read page |
I キー |
PDF の文書情報プロパティを表示 / Show PDF document properties |
E キー |
EPUB 構造解析の再実行 (読み込み時に自動実行) / Re-analyze EPUB structure (runs automatically on open) |
T キー |
EPUB 目次の開閉 / Toggle EPUB table of contents |
R キー |
EPUB 本文テキストを表示 / Open the EPUB text reader |
O キー |
サーバーのライブラリを開く / Browse the server library |
Escape |
UI再表示 / Show UI |
| 左右スワイプ | ページ送り (スマホ対応) / Page navigation (touch) |
| ボタン / Button | 動作 / Action |
|---|---|
| Save Page | 現在のページを保存 (見開き時は2ページ結合) / Save current page (merged in spread) |
| Save 2P | 現在+次ページの見開きを保存 (スクロールモードでは縦連結) / Save current + next as spread (vertical in scroll mode) |
| Save All | 全ページを連番で保存 / Save all pages sequentially |
- 出力形式 / Format: PNG / JPEG 95% / WebP 95%
- 解像度 / Resolution: PDF は 2x スケール、アーカイブ画像はネイティブ解像度 / PDF at 2x scale, archive images at native resolution
- 回転 / Rotation: 回転設定が適用された状態でエクスポートされる (見開き結合保存を含む) / Rotation setting is applied to exports (including spread merge saves)
- 手動しおり: サムネイル上の
●マーカーをクリックして設定/解除 / Click●marker on thumbnail to set/unset - 自動しおり: 最後に開いたページ (last read) と到達最深ページ (max read) を自動記録 / Auto-records last read and max read page
- しおり一覧: Bookmarksタブにサムネイル付きで表示、クリックでジャンプ / Displayed with thumbnails in Bookmarks tab
- 管理: 現在の本のしおり消去、全消去、JSON export/import / Clear per book, clear all, JSON export/import
- データ共有: 両ビューアで同じ localStorage キーを使用 / Both viewers share the same localStorage keys
EPUB はファイル名順が読み順と一致しないことがあります。EPUB を開くと内部の構造 (container.xml → content.opf の spine) を自動的に解析し、正しいページ順に並べ替えます (E キーで手動再解析)。自動解析を止めたい場合は comic-viewer.html の定数 EPUB_AUTO_ANALYZE を false にすると、従来どおり E キーでの明示起動のみになります。
EPUB filenames often don't match reading order. Opening an EPUB now analyzes its structure automatically (container.xml → OPF spine) and reorders the pages; press E to re-run it manually. Set the EPUB_AUTO_ANALYZE constant in comic-viewer.html to false to go back to running it only on E.
- spine の XHTML を辿って
<img>を文書順に収集。spine から画像が取れない場合は manifest のimage/*の記述順にフォールバック / Walks the spine's XHTML for<img>in document order; falls back to manifestimage/*order - 解析後は並び順プルダウンに
Sort: EPUBが追加され、他の並び順にいつでも戻せる / Adds aSort: EPUBoption so you can switch back anytime - 目次が定義されていればサイドバーに
TOCタブが出現 (Tキーで開閉)。EPUB3 nav / EPUB2 NCX の両方に対応、階層表示・ページ番号付き・クリックでジャンプ / ATOCtab appears when a table of contents exists (Tto toggle); supports both EPUB3 nav and EPUB2 NCX
構造解析後 (読み込み時に自動実行)、TOC タブ下部の「本文を読む」または R キーで、EPUB 内の XHTML をそのまま読めるリーダが開きます。画像を 1 枚も持たないリフロー型 EPUB も開けます。
After the structure analysis (automatic on open), press R (or use "本文を読む" at the bottom of the TOC tab) to open a reader that shows the EPUB's own XHTML. Image-less reflowable EPUBs can be opened too.
- 文書間の移動 (‹ / › / ← / → / プルダウン)、文字サイズ変更 (A- / A+)、表示幅の切替 (幅: 標準 ⇄ 広い、次回以降も保持)、「原文CSS」の ON/OFF / Document navigation, font size, reader width (normal / wide, remembered), and an "original CSS" toggle
- 外部リソースは完全にブロック:
allow-scriptsなしの sandbox iframe +default-src 'none'の CSP + http(s) URL の除去の 3 重防御。画像・CSS はアーカイブ内から blob: URL として差し替え / No external resources: sandboxed iframe withoutallow-scripts, adefault-src 'none'CSP, and stripping of http(s) URLs. In-archive images/CSS are swapped to blob: URLs - 縦書き指定は横書きに矯正されます (本ビューアは縦書き要件を対象外としています) / Vertical writing is forced to horizontal
viewMode を Scroll に切り替えると、全ページを縦に並べて連続スクロール表示します (Webtoon形式)。
Switch viewMode to Scroll to display all pages in a continuous vertical scroll (Webtoon-style).
- Fit スケール時は幅フィット / Width-fit in Fit scale
- Home / End キーで先頭・末尾にジャンプ / Home/End to jump to first/last page
- Save 2P は縦連結 (上下) で保存 / Save 2P saves vertically concatenated
Filter ボタンでポップアップを開き、8種のスライダーで色調を調整できます。
Click Filter to open the popup and adjust colors with 8 sliders.
| スライダー / Slider | 範囲 / Range | 説明 / Description |
|---|---|---|
| Brightness | 50% – 150% | 明るさ (CSS filter) |
| Contrast | 50% – 150% | コントラスト (CSS filter) |
| Gamma | 0.20 – 3.00 | ガンマ補正。1.00 より大きいと中間調が明るくなる (SVG feComponentTransfer) / Gamma correction; >1.00 brightens midtones |
| Sepia | 0% – 100% | セピア (CSS filter) |
| Invert | 0% – 100% | 色反転 (CSS filter) |
| Sharpen | 0 – 500 | シャープネス強度 (Pica unsharp mask) |
| Sh.Radius | 0.5 – 2.0 | シャープネスぼかし半径 / Unsharp blur radius |
| Sh.Thresh | 0 – 255 | シャープネスしきい値 / Unsharp threshold |
- Sharpen 操作時: HQ 未チェックなら自動的に HQ を ON にする / Auto-enables HQ when Sharpen is adjusted
- プリセット保存: 3スロット (Save 1-3 / Load 1-3)。localStorage に保存され、両ビューアで共有。ガンマ・シャープネス設定も含む / 3 preset slots shared between both viewers via localStorage, including gamma and sharpness settings
- Reset: 全スライダーを初期値に戻す / Reset all sliders to default
?vips=1 を URL に付加すると、Pica.js の代わりに wasm-vips (libvips WASM) による高品質画像縮小が有効になります。
Append ?vips=1 to the URL to enable wasm-vips (libvips WASM) for high-quality image downscaling instead of Pica.js.
- 例 / Example:
comic-viewer.html?vips=1,pdf-viewer.html?vips=1 - HTTP サーバーが必要 (
file://では動作しない) / Requires HTTP server (does not work withfile://) - 設定は localStorage (
vipsEnabled) に保存され、Filter ポップアップ末尾のトグルでも切替可能。?vips=1は書き込み用のワンショット / The setting is stored in localStorage (vipsEnabled) and can also be toggled at the bottom of the Filter popup;?vips=1is just a one-shot way to write it - WASM モジュール (~4.8MB) + JS ローダー (~78KB) は、オフライン動作のため
?vips=1の有無にかかわらず Service Worker がプリキャッシュする。?vips=1が無効な間はロード・実行されないだけ / The WASM module (~4.8MB) + JS loader (~78KB) are precached by the Service Worker regardless of?vips=1so that offline mode works; without?vips=1they are simply never loaded or executed - vips ロード失敗時、および画像処理中のメモリ不足時は自動的に Pica にフォールバック / Falls back to Pica automatically on load failure, and per-call on out-of-memory during processing
PDFにアノテーションコメントがある場合、左下にフローティングボタン (💬) が表示されます。クリックでモーダル表示。
When a PDF contains annotation comments, a floating button (💬) appears. Click to view in a modal grouped by page.
I キーで PDF の文書情報 (タイトル・作成者・サブタイトル・キーワード・作成アプリ・PDF 変換・作成日・更新日・カスタム項目)、ファイル情報 (サイズ・ページ数・現在ページのサイズ・PDF バージョン・暗号化など)、XMP メタデータをモーダル表示します。もう一度 I または Escape で閉じます。
Press I to show the PDF's document information (title, author, subject, keywords, creator, producer, dates, custom entries), file details (size, page count, current page size, PDF version, encryption, …) and XMP metadata in a modal. Press I again or Escape to close.
サーバーに設置して使う場合、サーバー上の指定フォルダを一覧・検索して直接開けます。library.php を置いていないサーバーや GitHub Pages 版では、この UI は自動的に隠れます。
When self-hosted, you can browse and open files from a folder on the server. The UI hides itself automatically on servers without library.php (including the GitHub Pages build).
セットアップ / Setup
library.config.example.phpをlibrary.config.phpにコピーし、'root'に公開したいフォルダの絶対パスを書く- インターネットに公開するなら
'auth'に ID / パスワードを書く(サーバー設定は不要)
// library.config.php
return [
'root' => '/srv/library', // DOCUMENT_ROOT の外でよい / may live outside DOCUMENT_ROOT
'label' => 'My Library',
// Basic 認証 (null なら認証なし) / Basic auth (null = disabled)
'auth' => ['user' => 'yourname', 'pass' => 'yourpassword'],
];'pass' には password_hash() の出力も書けます($2y$ / $argon2 で始まる文字列はハッシュとみなして password_verify で照合)。
php -r "echo password_hash('yourpassword', PASSWORD_DEFAULT), PHP_EOL;"You can also put a password_hash() digest in 'pass' instead of a plaintext password.
使い方 / Usage
| 操作 / Input | 動作 / Action |
|---|---|
ヘッダーの Library ボタン / O キー |
ライブラリを開く / Open the library |
| パンくず・フォルダ行 | フォルダ移動 (設定フォルダより上には出られない) / Navigate folders (cannot escape the configured root) |
| 検索ボックス | インクリメンタルサーチ / Incremental search |
| 「サブフォルダも」 | ルート以下を横断検索 / Search across all subfolders |
| 並び順 + ▲▼ | 名前 (自然順) / 更新日時 / サイズ / Sort by name (natural), date, or size |
| ☰ リスト ⇄ ▦ サムネイル | 表示形式の切替 (次回も維持) / Toggle list and thumbnail view (persisted) |
| マウスオーバー / ロングタップ | 表紙画像を拡大プレビュー / Preview the cover image |
?lib=サブフォルダ/a.cbz |
起動時に指定ファイルを自動で開く / Open a file directly on startup |
表紙画像 / Cover Images
表紙は事前に用意された画像ファイルがあるものだけ表示します(自動生成はしません)。元のファイル名の後ろに .coverimage.<拡張子> を付けた画像を隣に置いてください。
Covers are shown only when a prepared image file exists — nothing is generated automatically. Place an image next to the book, named after the book plus .coverimage.<ext>.
Manga/SeriesA/vol01.cbz ← 本 / the book
Manga/SeriesA/vol01.cbz.coverimage.webp ← その表紙 / its cover
- 元のファイル名を丸ごと残すので、
vol01.cbzとvol01.pdfが同居しても衝突しません / Keeping the full original name avoids collisions between same-named files with different extensions - 対応形式は
webp/avif/png/jpg/jpeg/gif。命名規則はlibrary.config.phpのcoverSuffix/coverExtsで変更できます / The suffix and accepted extensions are configurable - サムネイル用の縮小画像を別途用意する必要はありません。サーバーに GD があれば表示サイズに合わせて自動的に縮小して配信し、ブラウザにキャッシュさせます / No separate thumbnails needed — the server downscales on the fly (when GD is available) and lets the browser cache the result
- リスト表示では表紙があるファイルのアイコンが 🖼 になります / In list view, files with a cover show a 🖼 icon
表紙の一括生成 / Generating Covers
tools/generate_coverimages.php で表紙をまとめて作れます(CLI 専用。Web から叩いても何もしません)。設定は library.config.php をそのまま使います。
tools/generate_coverimages.php generates the covers in bulk. It is CLI-only and reads the same library.config.php.
php tools/generate_coverimages.php --check # 使えるバックエンドを確認 / show available backends
php tools/generate_coverimages.php --dry-run -v # 何が作られるか確認 / preview
php tools/generate_coverimages.php # 生成 (既存はスキップ) / generate, skipping existing
php tools/generate_coverimages.php --mtime # 表紙の日時を元ファイルに合わせる / match source mtime
php tools/generate_coverimages.php --help| 対象 / Type | 表紙にするページ / Cover page |
|---|---|
| 1 ページ目 / first page | |
| EPUB | ビューアと同じ構造解析で求めた読み順の 1 枚目 / first image in reading order (same analysis as the viewer) |
| CBZ / CBR / CB7 / ZIP / RAR / 7z | ファイル名順の 1 ファイル目 (--sort=natural で自然順) / first file by name |
| オプション / Option | 説明 / Description |
|---|---|
--force / --stale |
既存を作り直す / 元ファイルより古いものだけ作り直す |
--mtime |
表紙の更新日時を抽出元ファイル自体 (PDF/EPUB/書庫) に合わせる / match the mtime of the source book, not of the image inside it |
--max-width=N --max-height=N |
最大解像度。超える画像だけ縮小 (既定 1200x1600) / downscale only when larger |
--format=webp|jpeg|png --quality=N |
出力形式と品質 (既定 webp / 82) |
--sort=lexical|natural |
書庫内のファイル名の並び順 (既定 lexical) |
--epub-cover=spine|metadata |
EPUB の表紙を読み順の 1 枚目にするか、OPF の cover-image 指定を優先するか |
--root --path --filter --ext --limit |
処理対象の絞り込み |
必要な外部依存は「あるものを自動で使う」方式です。CBZ/ZIP/EPUB は PHP 標準の ZipArchive だけで動きます。CBR/RAR/CB7/7z は 7z または unrar、PDF は Imagick / pdftoppm / mutool / magick / gs のいずれかが必要で、無い形式だけがスキップされます(--check で確認できます)。
Dependencies are picked up automatically: CBZ/ZIP/EPUB need nothing beyond PHP's ZipArchive; CBR/RAR/CB7/7z need 7z or unrar; PDF needs Imagick, pdftoppm, mutool, magick, or gs. Missing tools only skip the affected formats — run --check to see what is available.
Python 版 / Python Version
Windows の PHP は Imagick や Ghostscript を入れるのが面倒なので、同じ機能の Python 版も用意しています(tools/generate_coverimages.py)。pip だけで PDF のレンダリングまで揃うのが利点です。オプション名・表紙の決め方・出力は PHP 版と同じですが、library.config.php は読まず、設定は --root などのオプションか --config の JSON で渡します。
Installing Imagick/Ghostscript for PHP on Windows is a hassle, so the same tool is also provided in Python. Everything including PDF rendering installs via pip. Same options, same output; it does not read library.config.php — pass settings via options or --config JSON.
pip install pillow pypdfium2 # 必須 + PDF / required + PDF
pip install py7zr rarfile # 任意: 7z / RAR (無ければ外部の 7z / unrar を使う)
python tools/generate_coverimages.py --root=D:/Books --check
python tools/generate_coverimages.py --root=D:/Books --dry-run -v
python tools/generate_coverimages.py --root=D:/Books --mtime
python tools/generate_coverimages.py --config=cover.json{
"root": "D:/Books",
"format": "webp",
"quality": 82,
"maxWidth": 1200,
"maxHeight": 1600,
"sort": "lexical",
"epubCover": "spine",
"matchMtime": true
}- しおりを有効にしていると、一覧に既読ページのバッジ (
p.42) が出ます。しおりは「ファイル名 + サイズ」で識別するので、同じファイルをローカルから開いたときのしおりとそのまま共有されます / With bookmarks enabled, rows show a read-progress badge; bookmarks are keyed by name + size, so they are shared with the same file opened locally - 転送が途中で切れた場合は Range リクエストで受信済みの続きから再開します / Interrupted transfers resume from where they stopped via Range requests
制限事項 /

0 comments
log in to comment.