🖋 はじめに
Delphiで Photoshop の .psd ファイルを直接読み込み、
レイヤーツリーと画像プレビューを表示できる PSDビューワ のサンプルを公開しました。
内部の合成処理には自作クラス TPSDImage を使用しており、
PSDToolKit 互換構造を持つため、レイヤー単位の操作にも対応しています。
修正バージョンでは、非表示レイヤーを後読み(オンデマンド読込)方式 に変更し、
200MB級の大容量PSDでも高速にプレビューできるよう最適化しました。
📂 サンプルプロジェクトの構成
| ファイル | 内容 |
|---|---|
PSDImageForm.pas |
メインフォーム(UI部分、処理時間計測付き) |
PsdFileImageFrame.pas |
PSDプレビュー表示用フレーム(市松模様背景対応) |
PsdFileTreeFrame.pas |
レイヤーツリー表示用フレーム |
PSDImage.pas |
PSDファイル読込・合成クラス(後読込対応) |
💡 主な変更点(前回公開版との違い)
| 項目 | 説明 |
|---|---|
| 読込方式 | 全レイヤー一括 → 非表示レイヤーは後読込(Lazy Load) に変更 |
| メモリ効率 | 表示中のレイヤーのみ展開、他はオフセット情報のみ保持 |
| ファイルアクセス | 表示切替時に必要レイヤーのみ再オープンしてデコード |
| 安定性 | ファイルを開きっぱなしにせず、必要時のみアクセス |
| 表示 | 市松模様背景で透過プレビューを実現 |
| αブレンド | VCL制約内で擬似的に再現し、PNG保存時は透明保持 |
🧩 クラス構成
🟦 TPSDImage
PSDの全体情報を管理するクラス。
レイヤー構造・リソース・オフセット情報を保持し、
必要時のみピクセルデータを再読込します。
主な処理:
procedure LoadFromFile(const FileName : string);
procedure Render;
procedure UpdateVisibleLayers;
仕様:
- 初回読込ではレイヤーメタ情報(位置・サイズ・可視状態・オフセット)のみ解析
- 非表示レイヤーはファイルを開かずにスキップ
- 表示切替時に
UpdateVisibleLayersが必要分を読み込み - 透明を保持したまま
TBitmapとして利用可能
🟩 TFramePsdFileImage
PSDプレビューを行うフレーム。
背景には市松模様を描画し、透明部分の視認性を確保。
procedure TFramePsdFileImage.OnDrawFinish(Sender: TObject);
begin
DrawCheckerBoard(Canvas, r, 16);
RectToStreachRect(r, FPsdImage.Bitmap.Width, FPsdImage.Bitmap.Height);
ImagePsd.Canvas.StretchDraw(r, FPsdImage.Bitmap);
end;
- GDIでは透明合成不可のため、見た目上で擬似的に透過再現
-
TPngImage.Assign(Bitmap)で保存時は完全な透明を維持可能
🟨 TFramePsdFileTree
PSDのレイヤー階層(フォルダ構造)を TTreeView で表示。
クリックイベントで該当レイヤーの表示状態を切り替え、
必要であれば再読込が行われます。
procedure TFormPSDImage.OnTreeClick(Sender: TObject);
begin
FPSDImage.UpdateVisibleLayers;
FFrameImage.ShowImage;
end;
🖼 メインフォームの構成
procedure TFormPSDImage.Button1Click(Sender: TObject);
begin
OpenDialog1.Filter := 'PSD files (*.psd)|*.psd';
if not OpenDialog1.Execute then Exit;
StartTimer('Load');
FPSDImage.LoadFromFile(OpenDialog1.FileName);
StopTimer('Load');
StartTimer('Tree');
FFrameTree.ShowTree;
StopTimer('Tree');
StartTimer('View');
FFrameImage.ShowImage;
StopTimer('View');
Caption := Format('PSD表示テスト - %s', [ExtractFileName(OpenDialog1.FileName)]);
end;
※
StartTimer/StopTimerはグローバル関数として定義され、
デバッグ出力(OutputDebugString)に処理時間を自動表示します。
これによりロード・ツリー構築・描画それぞれのパフォーマンスを簡単に計測可能です。
🚀 後読込方式(Lazy Load)の効果
巨大なPSDを扱う際の処理効率が劇的に改善されます。
| 処理項目 | 旧方式(全読込) | 新方式(後読込) |
|---|---|---|
| 初回読込時間 | 数秒〜数十秒 | 数ms〜100ms前後 |
| メモリ使用量 | 数百MB | 数十MB以下 |
| 表示切替 | 即時反映 | 非表示→表示で必要分のみ再読込 |
| ファイルハンドル | 常時オープン | 必要時のみオープン/クローズ |
🧾 出力結果
- 透明部分も保持された状態でプレビュー表示
- PNG保存 (
TPngImage.Assign(FPSDImage.Bitmap)) により透明画像をそのまま出力可能 - デバッグ実行時には各処理時間がログに出力され、パフォーマンス検証が容易
⚙️ 動作環境
- Delphi 11 / 12
- Windows 10 / 11
- 依存ライブラリ:なし(VCLのみで動作)
📘 まとめ
- PSDのレイヤー構造を解析・プレビュー表示
- 非表示レイヤーはファイルを閉じたまま後読み対応
- 巨大PSDでも軽快な動作を実現
- デバッグログで処理時間の可視化が可能
- PNG出力では透明を保持
PSDファイルを扱うための 軽量・高速な最小構成サンプル として利用できます。
📄 ライセンス
MIT License
📦 GitHubリポジトリ
https://github.com/vramwiz/PsdImage