イメージ コレクションおよび仮想イメージリスト コンポーネントを持つ高 DPI イメージのサポート
目次
概要
RAD Studio 10.3 Athens により、TImageCollection コンポーネントを TVirtualImageList コンポーネントと合わせて利用することで、スケーリング、高 DPI、マルチ解像度にイメージを、Windows VCL アプリケーションに含めることができます。
これらの対になったコンポーネントは、コントロールに使用される単一の特定のサイズのイメージ群のリストから、イメージのコレクション(各論理イメージが複数の解像度を持つことができる)の概念を分離します。 概して、イメージの複数の解像度を、イメージ コレクションに読み込みます。イメージ リストは、イメージ コレクションから取得したイメージのセットを保持し、それを、特定のサイズ(たとえば 16x16)で表示します。イメージはスムーズにサイズ変更および拡大縮小され、イメージ リストの実際の表示解像度は、DPI によって変わります。これは HIMAGELIST ハンドルを提供を含む、従来のイメージ リストと完全に互換性があり、簡単に置き換え可能で、また、VCL コントロールと Windows API イメージ リスト呼出しを使用したコードの両方に使用することができます。
イメージは、アルファ チャネルをサポートしており、PNG をイメージ コレクションに読み込むこともできます。また、旧式スタイルのカラー キー付き透明度ビットマップも読み込むことができます。
イメージ コレクション コンポーネントの利用
TImageCollection により、TWICImage クラスを利用して、ネイティブ形式のイメージを、格納、拡大縮小、描画することができます。
コレクションの各イメージは、それぞれ異なるサイズの数多くのバージョンがあります。 コンポーネントは、拡大縮小に最適なサイズを選択し、利用可能なサイズが要求されるサイズと等しかった場合、イメージを使用します。 また、アルファ チャネルでスケーリングされた 32 ビット TBitmap バージョンを作成することもできます。これは、TCustomImageList に直接追加できます。
TImageCollection は、TCustomImageCollection クラス(Vcl.BaseImageCollection ユニット)から継承しており、コレクションの基底メソッドを定義しています。
イメージ コレクション コンポーネント エディタ
イメージ コレクション エディタを開くには、TImageCollection をフォームまたはデータ モジュール上に配置し、フォームのコンポーネントをダブルクリックするか、それを右クリックして、[コレクション エディタを表示する...] オプションをコンテキスト メニューから選択します。また、TImageCollection.Images プロパティを オブジェクト インスペクタ でダブルクリックしても同様です。
イメージ コレクション エディタ ウィンドウでは、イメージをコンポーネントに追加し、それらをカテゴリに整理することができます。
追加をクリックすると、[開く]ダイアログ ボックスが開かれ、イメージを格納するフォルダを参照することができます。一度に 1 つのイメージを追加することも、フォルダから複数のイメージを選択して、それらを同時に追加することも可能です。イメージ コレクション エディタは、イメージをアルファベット順に表示します。
イメージを追加する際、同じ画像の複数のサイズを追加したい場合があります。たとえば、ピクセルを微調整した 16x16 バージョンの画像があり、それより大きな画像を他のサイズに合わせて拡大縮小して描画する必要があるとします。これを行うには、1 つの画像の複数のバージョンに、同じファイル名と区切り文字(ハイフンなど)を付けてから、サイズをピクセル単位で示す数値を付けます。たとえば、foo-16.png や foo-64.png などです。次に、[ファイル名のサイズを確認する]チェックボックスをオンにし、ドロップダウン オプションから画像サイズ区切り文字を、画像が共通名と画像サイズを区切るために使用する文字(前の例ではハイフン「-」)に変更します。これにより、自動的に、同じファイル名だが異なるピクセル サイズである、同イメージの複数の解像度を認識することができ、それらを、同じイメージの複数解像度として、コレクションに追加することができます。
[イメージ サイズ セパレータ]設定では、共通名とイメージ サイズを分けるための解析方法を制御し、また、共通のアイコンとイメージ サイズによるファイル名規則についてのオプションがあります。
ソースを特定のイメージに追加するには、コレクションからイメージを選択し、ウィンドウの下部にある[追加...]をクリックして[開く]ダイアログ ボックスを表示させ、そこでイメージ ファイルを探します。
カテゴリは現在のところ、整理のためにのみ使用されます。(VCL コントロールでは、イメージは今のところインデックスでのみ参照可能です。)
イメージをカテゴリで整理するには、イメージを選択して、[カテゴリを設定...]をクリックします。
上部セクションの[削除]ボタンを使用すると特定のイメージをコレクションから削除でき、[クリア]ボタンの場合には、コレクション内のすべてのイメージを削除することができます。
イメージをコレクションに追加したら、利用可能なイメージをいずれも選択でき、次のアクションを実行することができます:
- イメージの [名前]を編集します。
- イメージのカスタム[説明]を割り当てます。
- インデックス値を割り当てて、コレクション内のイメージ群の順番を変更します。
- 同じイメージに対して代わりのソースを追加する
- イメージのソースを削除する
- イメージの既存のソースを置換する
- index[name] を変更し、変更を適用する(VirtualImageList は、コレクションの name[index] を使用して、イメージを index[name] で更新します)。
- name[index] を変更し、変更を適用する(VirtualImageList は、コレクションの index[name] を使用して、イメージを name[index] で更新します)。
- イメージを別の名前で保存する([名前を付けて保存...]])
既存の TImageList を TImageCollection に読み込む。
旧スタイルのイメージ リストの新しいシステムへの変換を支援するために、イメージを、古い TImageList-s から TImageCollection へ読み込むことができます。 別の TImageList-s に、同じイメージの複数のサイズが存在する場合、両方とも一度に読み込むことができます。イメージはマージされ、イメージ コレクションは同じイメージの複数の解像度を保持することができます。
イメージを TImageList から TImageCollection へ読み込むには、同じフォームに両コンポーネントがなければなりません。
以下の手順に従い、フォーム上の既存の TImageList から TImageCollection へイメージを読み込みます:
- フォーム上の TImageCollection コンポーネントを右クリックし、[既存の TImageList からのロード...]オプションをコンテキスト メニューから選択します。
- 読み込みたい TImageList を選択し、イメージのカテゴリを割り当てます。TImageList は 1 つ以上選択することができます。これは特に、同じイメージの複数の解像度を読み込む際に便利で、これは以前は、複数のイメージ リストに格納されていました。
- [順番に読み込む]をクリックするとイメージ リストと同じ順でイメージを読み込みます。
- [マージを伴うロード]をクリックすると、異なるイメージ リストから、異なるイメージ ソースをマージします。マージしながら読み込む際には、イメージ リストはそれぞれイメージ サイズが異なるイメージ ファイルを同じ数持っていなければなりません。
- [コレクションを表示...]をクリックすると、イメージが TImageCollection にどのようにインポートされるか、ダイアログを閉じなくても確認することができます。
- [OK]をクリックして、設定を適用し、ダイアログ ボックスを閉じます。
- [適用]をクリックして、特定の変更のセットを適用し、さらに設定の構成を進めます。
- [キャンセル]をクリックして、ダイアログを閉じると、イメージ コレクションへの変更がすべて破棄されます。
仮想イメージリスト コンポーネントの利用
TVirtualImageList により、イメージをリストを生成し、すべてのイメージに同時に変更を適用することができます。
TVirtualImageList は TCustomImageCollection (TImageCollection) を使用して、内部イメージのリストを動的に生成します。
TVirtualImageList では、独自の幅および高さのプロパティを設定することができ、コンポーネントは自動的にすべてのイメージをスケーリングします。 DPI が代わると、高 DPI ディスプレイ上で、適切に表示されるよう、イメージのスケールを変更します。
VCL コントロールは、TCustomImageList を継承しているため、TVirtualImageList を変更せずに使用することができます。
仮想イメージリスト コンポーネント エディタ
仮想イメージ リスト コンポーネントとコンポーネント エディタを使用できるようにするには、ImageCollection プロパティをオブジェクト インスペクタでまず設定する必要があります。
[仮想画像リスト エディタ]を開くには、コンポーネントをフォーム内でダブルクリックするか、右クリックし、[画像リストエディタを表示...]オプションをコンテキスト メニューから選択します。
AutoFill プロパティを true に設定している場合、仮想イメージ リストは、コレクション内のすべてのイメージで、自動的に埋められていきます。 そうでなければ、コレクションからリストへイメージを手動で追加することも可能です。その際には、イメージ リスト エディタを使用します。
仮想イメージ リスト エディタ ウィンドウでは、イメージをコンポーネントに追加し、無効になったバージョンのイメージも含め、それらをカテゴリに整理することができます。
[追加]をクリックして、関連するイメージ コレクションを開き、仮想イメージ リストに含めたいイメージ群を選択します。特定のイメージ群をイメージ コレクションから選択するか、コレクションまたは既存のカテゴリからすべてのイメージを選択します。
さらに、仮想イメージ リスト エディタ ウィンドウには次のオプションがあります:
- [無効にする...]: 選択した画像の不透明度の低いバージョンまたはグレースケールのバージョンを作成して追加することができます。 無効にされたイメージの外観は、イメージ リストのプロパティ DisabledGrayscale および DisabledOpacity によって制御されます。
- [無効なコピーで追加...]: 関連付けられているイメージ コレクションからイメージを追加すると同時に、選択したイメージの無効なバージョンを作成して追加することができます。
- [置換]: 選択したイメージを置き換えることができます。
- [カテゴリの設定]: イメージをカテゴリに分類できます。カテゴリを作成するには、カテゴリに含めるイメージを選択して[カテゴリの設定...]をクリックし、カテゴリの名前を入力したら、[OK]をクリックして[カテゴリ]リストに表示させます。コンポーネント エディタが、そのカテゴリ名をイメージ名に追加します。
- [すべて無効にする]: 以前に追加したイメージを無効なイメージに変換します。
仮想 イメージ リスト コンポーネントにイメージを追加した後、次のアクションを実行できます。
- [再読み込み]: イメージの名前と説明を ImageCollection から再読み込みします。
- [削除]: 選択した1つまたは複数のイメージを、仮想イメージ リスト コンポーネントから削除します。
- [クリア]: コレクションのすべてのイメージを削除します。
- [名前]: イメージの名前を編集します。
- [説明]: イメージのカスタム説明を割り当てます。
複数解像度でのイメージ コンポーネントの利用
TVirtualImage コンポーネントは、TImage 系のコンポーネントに対して、複数の解像度をサポートしています。イメージのソースは ImageCollection からで、画面の DPI に合わせて複数の解像度を持つことができます。コンポーネントは、表示されるモニターによって適切なものが使用されます。
VirtualImage コンポーネントの構成の設定と主なプロパティには、次のものがあります: ImageCollection、ImageHeight、ImageIndex、ImageName、ImageWidth。
拡大縮小する際(例、StretchDraw)に、VCL TGraphic のスムーズな描画のために、ビットマップのスケーリング ロジックを使用する場合、さまざまな TGraphic クラスに対して即座に HQ スケーリング描画を利用できるようにするために、TScaledGraphicDrawer クラスがあり、次のような呼び出しがあります:
MyBitmap.EnableScaler(TD2DGraphicScaler);
Image1.Picture.Graphic.EnableScaler(TWICGraphicScaler);
さまざまなソリューションは、レンダリングの質やパフォーマンスの向上や劣化を伴います。さらにスケーリングのアルゴリズムを定義する独自の TScaledGraphicDrawer 派生クラスを記述することができます。
ベスト プラクティス
TVirtualImageList コンポーネントは、それらが配置されたフォームの DPI でスケーリングされます。 これにより、イメージ リストで描画されたフォームのコントロールは、常に正しくスケールの解像度で描画可能になります。 ただし、これには、2 つの意味があります:
- コントロールは常に、同一フォーム上のイメージ リストを参照しなければなりません。コントロールが、別のフォーム上のイメージ リストを参照しており、その 2 つのフォームの DPI が異なる場合(別の画面上にあるなど)、イメージは正しく描画されない可能性があります。
- TVirtualImageList は常に 1 つのフォームに(データ モジュールではなく)配置される必要があります。 フォームには関連づけられたモニタおよび DPI がありますが、データ モジュールにはありません。TImageCollection は、単なるソースであり、DPI の変更の影響を受けないため、どこにでの配置することができます。これらはソースであり、仮想イメージ リストは表現です。
このため、フォーム上のコントロールがイメージ リストを使用している場合、常に 1 つまたは複数の TVirtualImageLists をそのフォーム上に配置します。そして、コントロールをそれらローカルの同じフォームのイメージ リストのみ参照させます。 それらの TVirtualImageLists は、すべて同じ TImageCollection を参照できます。
仮想イメージ コレクションはとても便利なコントロールで、イメージのコレクション(TImageCollection)の概念を、特定の(DPI でスケーリングされているが)サイズのイメージのセット(TVirtualImageList)と区別します。 イメージ コレクションは、単なるコンテナであるため、DPI の変更の影響を受けません。 仮想イメージ リストは、別のフォームやデータ モジュール上のコレクションのイメージを参照することができます。 アプリケーションのメイン フォーム上の、または 1 つの共有データ モジュールに関連するイメージ群(たとえばすべてのツールバーやメニューのイメージ群など)に対して、1 つのイメージ コレクションを割り当てると、良い設計ができます。 他のフォームも、それぞれフォームに特化した仮想イメージ リストを持ち、それらのイメージ リストは集中管理するイメージ コレクションを使用します。
マルチサイズ
同じイメージに対して複数のサイズが必要な場合(SmallImages と LargeImages のプロパティを持つ TListView など)、2 つの TVirtualImageLists を、従来の TImageLists のように使用します。 両仮想 イメージ リストとも、同じイメージ コレクションを参照します。
アプリケーションにおける高 DPI のサポート:古い TImageLists の変換
TImageLists の利用から TVirtualImageLists へ VCL アプリケーションを変換することは一般的で、見た目の品質がアップグレードされるだけでなく、高 DPI のサポートも支援できるようになります。
TVirtualImageList は TCustomImageList の下位クラスであるため、コード レベルでの簡単な置換が可能であり、Windows API メソッドを直接呼び出すための、HIMAGELIST ハンドル プロパティも提供されています。
アプリケーションを新しい高 DPI イメージ リストを使用するように変換するには、2 つのアプローチがあります。
1つ目、同時にアイコンも、古いスタイルから最新のスタイルに、またはカラーキー透過から、アルファ チャンネルの 32 ビット イメージに、アップグレードする場合もあるでしょう。これを行う場合には、これらを新しいイメージ コレクションにシンプルに追加し、コンポーネントが新しいイメージ リストを参照するように変更することが一番簡単だとわかるでしょう。
2つ目、代わりに、古いイメージを徐々に置き換えるといったステップ by ステップの方法でアップグレードしたい、もしくは、まったく置き換えないという場合もあるでしょう(しかし、新しいシステムでは 32bpp アルファ チャンネルを利用することを推奨します)。 これを行うには、TImageCollection を配置して右クリックし、[既存の TImageList(s) からのロード...]を選択します。 イメージ リストを選択し、イメージを追加するのか、複数解像度で同じイメージを保有していた場合には、イメージをマージするのかを選択します。 詳細については、TImageList から TImageCollection、および上記の「既存の TImageList を TImageCollection に読み込む」を参照してください。
これにより、イメージ コレクションに古いイメージが格納されます。 古いイメージを使用すると、新しく設計されたイメージを使用した際に見られるような、画像品質や透過における向上はありませんが、イメージは各フォームの DPI に合わせてスケーリングされるようになります。 各フォーム上で新しい TVirtualImageList コンポーネントを作成し、 コレクションからイメージを追加します:これらは同じ関連順を維持するため、コレクションにすでにイメージがあるのでなければ、同じインデックスとなります。 その後、コンポーネントを変更して、新しい TVirtualImageLists を使用するようにします。
TCanvas 上での描画の際のスムーズなスケーリング
TCanvas.StretchDraw により、TGraphic を任意の四角形に描画できるようになります。TGraphic サブクラス実装はこれを実行する方法を決定しますが、実際には、VCL の描画(TBitmap など)では通常、GDI を介した最近隣リサンプリングを使用しており、しばしば、スケーリングまたは引き伸ばされたイメージは理想的な品質にはなりません。
TImageCollection を使用して、イメージを保持し(WIC として内部的に格納し、その形式で描画されます)、そしてそれを任意の四角形に描画します。これを行うには、高品質リサンプリングを使用します。