PVRTC圧縮のアルゴリズムとは?

最近、花粉症が収まってきてちょっとずつ調子が上向きな R&D部 上田です。

1か月お休みを挟んで、第三回目になる今回はPVRTC形式のアルゴリズムについてのお話です。

PVRTCって何?

まず最初にPVRTCの基本情報をざっくり書いておきます。

正式名称 PowerVR Texture Compression
開発元 Imagination Technologies
圧縮モード 4bppモード、2bppモード
圧縮方式 非可逆圧縮(圧縮後の画像は劣化します)
特記事項 画像サイズの縦横がそれぞれ2の累乗の画像のみに対応

圧縮モードにある「bpp」という単位は「bits per pixel」の略で、1ピクセルの色を表現するのに必要とするビット数を表しています。4bppというのは1ピクセルにつき4ビットの色情報を使っているということになります。ちなみに24ビットRGBカラーは24bpp、32ビットARGBカラーは32bppとなります。

特記事項にある2の累乗というのは、2の掛け算だけで作れる数のことで、2・4・8・16・32・64・128・256・512・1024・2048……という数字になります。
そのためこの制限の例を挙げると、

○:2×2、32×32、256×512、1024×64・・・など
×:3×3、48×48、640×480、1024×768・・・など

ということになります。

PVRTCってどんなところで使われているの?

Imagination Technologies社の開発したGPUであるPowerVRシリーズがiPhone用のGPUとして採用されることでPVRTCが広く普及するようになりました。

その他にも、Androidなどの端末(TI OMAP)にも対応しているものがあるほか、ゲーム機のPlayStation®Vitaでも使われています。

PVRTCの圧縮品質はどんな感じ?

PVRTCを使って画像を圧縮してみましょう。

サンプルとして、24ビットRGBカラーで画像サイズが512×256の画像を用意しました。
それぞれの画像容量は、無圧縮で 393,216 バイト(=512×256×3)です。

flower_512-256_quater-NearestNeighbor cat_512-256_quater-NearestNeighbor renga_512-256_quater-NearestNeighbor
無圧縮の元画像(各 393,216 バイト)
(クリックで等倍表示)

これらの画像をPVRTCの4bppモードで圧縮します。

flower_pvrtc4bpp_512-256_quater-NearestNeighbor cat_pvrtc4bpp_512-256_quater-NearestNeighbor renga_pvrtc4bpp_512-256_quater-NearestNeighbor
PVRTC圧縮後の画像(4bppモード 各 65,536 バイト)
(クリックで等倍表示)

圧縮するとそれぞれの画像容量は 65,536 バイト となり、圧縮前の6分の1になります。

写真や自然画のような画像では、PVRTCによる圧縮でもDXTCと同様に劣化はほとんど分からないぐらいのレベルに抑えられています。

注)ブログ内の画像は、ブラウザでそのまま表示できるように全てPNG形式に変換しているため、上記画像容量とは異なります。以下の画像についても同様です。

また上記の画像は4bppモードで圧縮したものですが、2bppモードを使うことで画像容量をさらに半分(32,768バイト)にすることが可能です。こちらのモードでは、クッキリした境目のあたり(花の周囲など)に若干ブロックノイズが見られます。

flower_pvrtc2bpp_512-256_quater-NearestNeighbor cat_pvrtc2bpp_512-256_quater-NearestNeighbor renga_pvrtc2bpp_512-256_quater-NearestNeighbor
PVRTC圧縮後の画像(2bppモード 各 32,768 バイト)
(クリックで等倍表示)

PVRTCには苦手な画像がある?

PVRTCは上で示したように写真や自然画のような画像は比較的綺麗に圧縮できていました。

それでは、アニメ調の画像ではどうなるのでしょうか? DXTCの時と同様に魔法少女の画像をPVRTCで圧縮してみましょう。

figure_magicalgirl_original_fullfigure_magicalgirl_pvrtc4bpp_fullfigure_magicalgirl_pvrtc2bpp_fullfigure_magicalgirl_dxtc_full
PVRTCとDXTCによって圧縮した魔法少女画像の比較

画像の変化が分かりやすいように、少女の頭上の犬部分を拡大してみます。

figure_magicalgirl_dog_original_fullfigure_magicalgirl_dog_pvrtc4bpp_fullfigure_magicalgirl_dog_pvrtc2bpp_fullfigure_magicalgirl_dog_dxtc_full
犬の部分を拡大(4倍)して比較

拡大するとよくわかるのですが、PVRTC圧縮した画像は絵の輪郭付近でにじむように色が変化してしまって画像が劣化しています。4bppモードより2bppモードの方がより劣化が激しいのも見てとれます。

またDXTCの劣化具合と比較すると、PVRTCでは輪郭付近で色がにじんでいるのに対し、DXTCはブロック状に色のおかしい部分(ブロックノイズ)が出現していて、劣化具合にそれぞれ特徴があることがわかります。

PVRTCってどんなアルゴリズム?

それではPVRTC形式(4bppモード)のアルゴリズムを解説しましょう。

1.4×4ピクセルのブロックに分割する

まずPVRTCではDXTCと同じように、4×4ピクセルを1つのブロックとして扱います。

figure_16pixel_to_1block_half-bycubic

4×4ピクセルを1ブロックとして扱う

2.代表色2色を決定する

次にそれぞれのブロックごとに代表色となる2色を決定します。

figure_select_2color_half-bycubic

1ブロックごとに2色の代表色を決定する

ここでは単純に代表色2色を決定すると書きましたが、後述する手順の関係上、実際にはそんなに簡単に代表色を決めることはできません。ブロックに無い色を代表色に設定することもできます。

3.各ピクセルの代表色のブレンド方法を決める

代表色2色を4種類の割り合いでブレンドして、各ピクセルを最も近い色で置き換えます。そして、各ピクセルのブレンド方法をデータとして保存します。

figure_modulation_data_half-bycubic

各ピクセルの代表色のブレンド方法を決めて、Modulation Dataとして保存する

この保存したブレンド方法のデータをModulation Dataと呼びます。

ブレンド方法は4種類なので2ビットで表現でき、1ブロックは16ピクセルで構成されているので、Modulation Dataは32ビットになります。

ところで、ここまで説明してきた代表色の2色ですが、Color Aは16ビット、Color Bは15ビットのデータになっています。

そしてこれらとは別に「Mode Bit」と呼ばれる1ビットのデータがあり、このMode Bitの値によって代表色2色のブレンド方法が切り替わる仕組みになっています。
(Color BがColor Aに比べて1ビット少ないのは、このMode Bitに1ビット使っているからです)

figure_modulation_data_mode_half-bycubic

Modulation Data には二つのモードがある

なお今回の記事では、すべてMode Bitが1の場合の例で説明しています。

4.完成・・・?

ここまでで、代表色2色とModulation Dataを生成しました。

代表色のColor Aが16ビット、Color Bが15ビット、Modulation Dataが32ビットで、これに1ビットのMode bitを加えた合計64ビットがPVRTC圧縮(4bpp)の1ブロックのデータになります。

figure_block_structure_image_half-bycubic

PVRTC圧縮(4bpp)画像の1ブロック分のデータ

しかし、この64ビットのデータを単純に復元したのではDXTC(過去の記事参照)とあまり変わりません。

figure_not_blend_original_color_half-bycubic

PVRTCでの画像復元は代表色の単純なブレンドではない

実はPVRTC圧縮形式では復元方法に大きな特徴があります。

5.代表色を使ってブロック内の色を補間する

PVRTC圧縮形式では、代表色のColor A と Color Bをブレンドする前に一つ処理を挟みます。
それは、代表色を使ってブロック内の色を補間するという処理です。
まず、代表色であるColor A と Color Bがブロック内の中心より右下のピクセルに入っているとします。

figure_before_interpolation_half-bycubic

代表色をブロック内の1つのピクセルのみに入れる

そしてブロック内の他のピクセルの色は、自分自身の代表色と周りのブロックの代表色を使って補間することで色を入れていきます。

figure_interpolation_half-bycubic

代表色が入っているピクセル以外は補間して色を入れる

この補間処理は、バイリニア補間方式で行われています。

6.補間結果を利用して Color A と Color B をブレンドする

Color AとColor Bを補間した後、Modulation Dataに従って各ピクセルの色をブレンドします。

figure_blend_after_interpolation_half-bycubic

補間した後でModulation Dataに従って色を混ぜ合わせる

このように、PVRTC圧縮形式では単純に代表色を混ぜ合わせるのではなく補間を利用することで、補間しない場合に比べて、隣接ブロックとの境界の色変化が滑らかになり、DXTCのようなブロックノイズ(ブロック境界で色が急激に変化して画像にブロックが浮き出てしまう現象)が発生しにくくなります。

ただし、補間という処理が入るためにColor AとColor Bの指定やModulation Dataの作成は補間結果を想定して行わなければなりません。そのためこれらのデータの選び方によって画質が大きく変わってしまうことが、この圧縮方法のもっとも難しい点と言えるでしょう。

2bppモードはどうなる?

2bppモードでは、1ブロックを32ピクセル(横8ピクセル×縦4ピクセル)とします。そして圧縮後の1ブロック分のデータは64ビットになります。

4bppモードが16ピクセルを64ビットで表現するのに対して、2bppモードは32ピクセルを64ビットで表現しているため、圧縮後のデータ量は4bppモードの半分になります。

当然のことながら、2bppモードの方が圧縮率が高い分、画質は更に低下します。

PVRTCでアニメ調の絵が劣化する原因を考える

それではこんな風に絵が劣化してしまう原因を考えてみましょう。

1ブロックで使用できる色数が少ない!

一つ目の原因はDXTCと同じで、1ブロックで使用できる色が少ないことがあげられます。

つまり、基本的には1ブロックで代表色2色とその補間色しか使えませんので、

figure_pvrtc_unlike_figure_half-bycubic

PVRTCでもDXTCと同様にこのような色の変換は起こっている

実際に、上記の魔法少女の画像でも黒の輪郭線周辺で色がおかしくなっているのが確認できます。

またPVRTC特有の色のにじむような劣化については、復元処理での補間が関係しています。

figure_diff_pvrtc_dxtc_half-bycubic

PVRTCとDXTCの劣化の違いについて(画像はイメージです、実際の圧縮結果とは異なります)

DXTCではブロック毎に色が独立しているので、一つのブロックで劣化が発生してしまっても他のブロックには影響しません。

しかしPVRTCでは復元時の補間の影響で、一つのブロックの劣化が他のブロックに影響を及ぼしたり、隣り合うブロックの色がお互いに影響を与えてしまうため、色がにじんだように見えているのです。

色情報のビット数が少ない!

また、PVRTCは代表色に使っている色情報のビット数が少ないことも劣化理由の一つになっています。以下はPVRTCの代表色についてのビット構造です。

figure_pvrtc_color_info_half-bycubic

PVRTCの代表色のビット構造

32ビットARGBカラー画像では、ARGBそれぞれで8ビット使用することができます。これは階調にすると各色256階調ということになります。

対して、PVRTCの代表色では各色5ビット~3ビットしか使うことができません。色情報が5ビットだと32階調、4ビットだと16階調、3ビットだと8階調となってしまいますから、256階調と比べると大幅に使用できる色が減っていることになり、これが画像の劣化原因になっています。

アルファ付き画像がより苦手?

上の魔法少女の画像はアルファ無しの画像でした。実はPVRTC圧縮は輪郭のくっきりした画像でもアルファ付きの画像がより苦手です。

次のような、文字とその周りをアルファチャンネルを使って透明にした画像をPVRTC圧縮してみます。

figure_rare_text_original_half-bycubic

figure_rare_text_pvrtc_by-cubic

アルファ付きテクスチャをPVRTC圧縮すると劣化が大きく出てしまう  ※透過(アルファ)部を分かりやすくするため、背景色として水色を重ねてあります

上で説明したように、代表色のアルファチャンネルは3ビット、つまり8階調しか使えないので圧縮前の画像よりも階調が大きく落ちます。

さらに上の文字の例のように輪郭の外側をアルファを使って透明にしているような画像では、輪郭部分でアルファチャンネルが急激に変化しているのですが、PVRTCではアルファチャンネルにも補間を行うためにこの輪郭部分のアルファチャンネルがぼやけてしまいます。

この二つの理由によって、アニメ調の絵や書き文字のような、アルファ付きの画像でかつ輪郭部分の外側をアルファチャンネルで透明にしているような画像は特に劣化が大きくなってしまうことになります。

Clear PVRTC ってなんだ?

最後にちょっとだけ宣伝です。

ウェブテクノロジでは従来よりも高画質なPVRTC形式の画像を生成する新技術「Clear PVRTC」を開発いたしました。(プレスリリースはこちら)

この技術では、従来PVRTC形式との完全な互換性を保ったままでより高画質なPVRTC画像生成を実現しています。

上記の文字サンプル画像もこのとおり。

figure_rare_text_clear_pvrtc_half-bycubic

驚きの美しさに!!

「Clear PVRTC」は弊社製品 OPTPiX imesta for Mobile & Social の無償アップデートとして4/2から搭載中です。

無料トライアル版もご用意しておりますので、PVRTCの画像品質にお困りの方はぜひ一度お試しください。

タグ , , , | 2020/06/16 更新 |