メモリを節約するには、どの画像形式がより効率的ですか?PNG、JPEG、またはGIF?
メモリを節約するには、どの画像形式がより効率的ですか?PNG、JPEG、またはGIF?
回答:
「メモリ」と「効率」は一般的に誤用されている用語なので、ゲームのパフォーマンスに影響を与える可能性のある4つの異なる要素の答えを紹介します。
短く簡潔にするためにあまりにも多くのことを単純化しすぎますが、以下のテキストには多くの不正確さがあります。ただし、主要な概念は理解できるものでなければなりません。
ストレージ
これは、イメージがソフトウェア配布で消費するサイズです。リソースが消費するスペースが大きいほど、ダウンロード(Webサイトから)が長くなります。CDやDVDなどの物理メディアで配布する場合は、おそらくこの点で深刻な最適化を行う必要があります。
一般に、JPEGは、境界線のない写真や画像に最適な圧縮を行います。ただし、JPEGは非可逆圧縮を使用するため、画像の品質が低下します(画像をJPEGとしてエクスポートする場合、圧縮レベル/劣化を微調整できます。詳細については、イメージングソフトウェアのマニュアルを参照してください)。
ただし、JPEGと同じくらい良いかもしれませんが、透明度はサポートしていません。これは、他の人を通して見える画像を持ちたい場合、または不規則な形状の画像が必要な場合に重要です。GIFは良い選択ですが、PNGにほぼ取って代わられました(PNGがサポートしていないのはGIFがサポートしていることはわずかですが、ゲームプログラミングにはほとんど関係ありません)。
PNGは透明度(および半透明度)をサポートし、品質を低下させることなくデータを圧縮し(ロスレス圧縮を使用)、かなりよく圧縮しますが、JPGほどではありません。
この問題は、適切な圧縮と透過性が必要な場合に発生します。わずかに劣化した画像を気にしない場合は、pngquantなどのPNG量子化プログラムを使用できます。これはTinyPNGでオンラインでテストできます。量子化自体によって実行される画像の劣化は、JPEG(量子化やその他の積極的な手法を含む)の劣化とは異なるため、さまざまな設定で両方を必ず試してください。
配布サイズを積極的に最小化する場合は、次のようにすべての画像を手動で処理できます。
if the image has transparency then
try pngquant on the image
if the results are not satisfactory then
revert to the non-quantized image
end
store as PNG
else
try storing it as JPG with different quality settings
if no single setting yields an image of an acceptable quality then
try pngquant on the image
if the results are not satisfactory then
revert to the non-quantized image
end
store as PNG
else
store as JPG
end
end
ヒント:一部の画像を1つの形式で保存し、他の画像を別の形式で保存してもかまいません。
DXT、ETC、PVRTCなど、他の特殊な形式があります。圧縮をサポートし、メモリに圧縮してロードすることもできますが、特定のGPUでのみサポートされ、これらのGPUのほとんどはそのうちの1つのみをサポートするため、ターゲットハードウェアの正確なハードウェア仕様を知らない限り(顕著なケースはPVRTCテクスチャをサポートするiPhone / iPad)、これらの形式は避けてください。
プログラムメモリ
これは「メモリ」で一般的に知られているものなので、ここに含めました。ただし、ゲームでグラフィックアクセラレーションを使用している場合(そして1998年以降にゲームを作成している場合はほとんどの場合)、メモリを消費するのはテクスチャ記述子(画像ごとに数バイト)だけです。サイズやフォーマットではなく、画像の量の影響を受けます(これにはいくつか注意点がありますが、ほとんどは無関係です)。
プラットフォームに専用のビデオメモリがなく、ハードウェアアクセラレーションなどの一般的でない場合、VRAMに関する次のセクションは完全にまたは部分的にRAMで行われますが、主な原則は同じです。
ビデオメモリ
これは、プログラムの実行後に画像が保存される場所です。一般に、画像をビデオメモリに読み込む前にすべての画像が圧縮解除されるため、保存した形式はここでは変わりません。
これで、画像が消費するVRAMは、VRAMにロードされたwidth * height * bitdepth
各画像のおおよそのサイズになります。ここで注意すべきことがいくつかあります。
画像がVRAMに保存される幅と高さは、元の画像のものと必ずしも一致しません。一部のGPUは2の累乗のサイズのテクスチャしか処理できないため、320x240の画像は実際にはVRAMの512x256のスペースに保存され、未使用のメモリは事実上無駄になります。2のべき乗ではないサイズのテクスチャをロードすることさえ許可されない場合があります(GLES 1.1など)。
したがって、VRAMの使用量を最小限に抑えたい場合は、画像のアトラス化と2の累乗でのサイズ変更を検討することをお勧めします。これは、レンダリング時のレンダリング状態の変更が少ないという利点もあります。これについては後で詳しく説明します。
ビット深度は非常に重要です。通常、テクスチャは32ビットARGBまたは32ビットXRGBでVRAMに読み込まれますが、ハードウェアが16ビット深度をサポートでき、ビット深度を低くしてもかまわない場合、各画像で消費されるVRAMの量を半分にできます。 、これは検討するのが面白いかもしれません。
しかし、何をするにしても、ゲームで使用するVRAMの量を考慮する際の最も重要な要素は、特定の時間にVRAMにある画像の量です。これは、パフォーマンスの高いゲームが必要な場合に、できるだけ低く抑えたい数値です。テクスチャをVRAMにロードおよびアンロードするには費用がかかるため、使用するたびに各イメージをロードすることはできません。使用する可能性が最も高いイメージをプリロードすることと、今後使用しないことが確実な場合にアンロードすることのバランスを取る必要があります。これを正しく行うのは簡単なことではなく、特定のゲームに対する独自の戦略を考える必要があります。
実行速度
「メモリ」ではありませんが、ゲームのパフォーマンスと非常に関連しています。画像の描画は高価であり、レンダリングを可能な限り高速に実行する必要があります。もちろん、ここでは、形式は重要ではありませんが、他のことは重要です。
画像サイズ(実際には「サンプリングサイズ」):描画しようとしている画像の領域が最大になるほど、描画に時間がかかります。画面の小さなセクションに巨大な画像をレンダリングすることはあまり効果的ではないため、mipmappingと呼ばれる手法があります。これは、画像を複数の解像度で数回保存し、できるだけ小さいものを使用して、レンダリング速度とVRAMを交換することで構成されますあなたがいつでも必要な品質。画像の読み込み時にミップマッピングを実行できます。これは、読み込み速度とVRAMの使用に影響を与えるか、前処理(同じ画像の異なるバージョンを手動で保存するか、DDSなどのミップマッピングをネイティブでサポートする形式を使用する)でストレージに影響しますおよびVRAMの使用量。ただし、読み込み速度にはほとんど影響しません。
レンダリング状態の変更。ほとんどの場合、画面上にいくつかの異なる画像を同時に描画します。ただし、GPUは常に1つのソースイメージのみを使用できます(これは事実ではありませんが、ここでご容赦ください)。現在レンダリングに使用されている画像は、多くのレンダリング状態の 1つであり、高価です。したがって、同じ画像を数回使用する場合(テクスチャアトラスについて言及したときに覚えていますか?)、レンダリング状態を変更し、異なる画像(これとは別のレンダリングステートがあり、レンダリングステートの変更を最小限に抑えるためのものを描画する順序を微調整することは、ゲームのパフォーマンスを向上させるときに非常に一般的なアクティビティです)
ただし、画像使用の最適化は非常に複雑なトピックであり、ここで書いたのは、ゲームを書くときに考慮する必要があるいくつかの要素の非常に広範かつ単純化した概要です。本当に必要な場合にのみ最適化します。ほとんどの場合、時期尚早な最適化は不要であり(場合によっては有害なこともあります)、簡単に実行してください。
setEnforcePotImages
ように、OpenGLES 1.0の2サイズのテクスチャの実行を無効にします。すべてのハードウェアが2のべき乗以外のテクスチャをサポートするわけではないため、これはお勧めできません。OpenGLES 2.0では、2のべき乗以外のテクスチャのサポートが必要です。したがって、2.0をターゲットにしている場合、任意のサイズのテクスチャを使用できます。詳細については、libgdxのドキュメントを参照してください。
画像がディスクからロードされ、レンダリング用にフォーマットされると、PNG、JPEG、またはGIFを使用して画像がディスクに保存されたかどうかに関係なく、同じ量のメモリが使用されます。
一般的な経験則:JPEGは非可逆形式であり、ディスク上の画像を小さくするために画像品質を低下させます。一方、PNGは可逆画像形式であるため、通常はディスク上のファイルサイズが大きくなります。GIFも技術的にはロスレス形式ですが、画像ごとに最大256色しかサポートしていないため、GIFとして保存した場合、ハイカラー画像の品質が大幅に低下します。
ただし、これはディスク上の表現のみです。メモリ内では、PNG、JPEG、またはGIFとしてディスクに保存したかどうかに関係なく、同じ量のメモリを使用して、両方が同じテクスチャ形式に展開されます。
場合によります。
Jpegは写真に最も効率的です。ロスレスではありませんが、このユースケースでは圧縮によって導入されたアーティファクトはほとんど見えません。
PNGはロスレスで、シャープな線とわずかな色のピクセルアートで最も効率的です。また、アルファ透明度もサポートしています。
GIFは、アニメーションを保存する機能を除いて、PNGでできることは何もできません。ただし、これはWebアプリケーションのコンテキストにのみ関係します。ゲーム開発では、通常、スプライトシートを使用してアニメーションを作成します。
Libgdxのようなグラフィックエンジンを使用する場合、画像を読み込んだ直後に圧縮を解除し、非圧縮RGBA値としてメモリに保持する可能性が高いことに注意してください。そのため、イメージ形式は読み込み速度にのみ関係し、ドライブスペース(またはネットワーク経由で送信する場合の帯域幅使用量)があります。
libgdxについてはあまり知りませんが、画像形式とグラフィックスについてはよく知ります。
JPEGは、実世界の写真の場合に非常に適しています。それらは非可逆ですが、書かれたテキストや漫画など、無地の色の付いたシャープなエッジの写真を撮らない限り、写真にアーティファクトは表示されません。大きな背景グラフィックに使用します。
GIFは廃止され、完全に透明にするための1つの専用色を使用したパレット色(ピクセルあたり最大8ビット)のみを保存できます。フレームに基づいた小さなアニメーションが可能です。かつてはパッキングアルゴリズムに関する特許があったため、どこでも合法的に使用することはできませんでした。その特許のため、PNGは開発されました。
PNGは多かれ少なかれ、RGB + alpha(最大32ビット)およびその他のピクセル形式を格納できるzip形式のビットマップです。これは、その画像の小さな部分の高速解凍に特化しており、非常に小さくて遅いデバイス(10年前の携帯電話など)には便利ですが、現在のライブラリはロード時にビットマップに展開するだけです。
PNGはGIFよりもサイズと速度と機能が優れていますが、ビットマップを効率的に保存する場合は、次のことをお勧めします。.PNM.BZ2([編集]異なる圧縮方法のため、.PNM.BZ2は常に効率的ではありません.PNG。[/ edit])よりも)
PNM / PBM / PGM / PAMは、プレーンテキストのKISSヘッダーを持つプレーンビットマップ形式です。これらにgzipを使用すると、ファイルサイズがPNGに似たものになるため、bzip2がより良いソリューションです。プログラムで内部的にビットマップを使用する場合は、.tarまたは.zipコンテナでbzip2圧縮ビットマップを使用することをお勧めします。bzip2がない場合、zipコンテナ(最大圧縮のzip)でPNMを使用することは、PNGを使用することに似ている場合があります。–したがって、PNGをZIPファイルに保存しても、利点はほとんどないか、まったくない可能性があります。ほとんどの場合、画像の読み込み時間が長くなります。
それに加えて、複数の小さなスプライト/画像を1つのビットマップに保存することは、特に同じ状況ですべて一緒に必要な場合に適しています。
ストレージ形式JPEGは、おそらく、情報の損失が検出できない可能性がある草や壁などの一部のテクスチャに最適な選択肢です。透明性が必要な場合、または2Dゲーム(プレーヤー、敵、宝箱)のスプライトなど、情報の損失で支払うことができない場合は、PNGが続きます。おそらく、その画像にPNGを使用する必要があります。
メモリコストについて言えば、ゲームグラフィックスをファイルシステムに保存するために使用される形式はまったく関係ありません。ピクセルバッファーをVRAMまたはRAM(ソフトウェアレンダラー)に保存する場合、ゲームは各ピクセルバッファーが使用するメモリよりもピクセルの高速読み取りを好むため、おそらく非圧縮で保存されます。
圧縮データをメモリに保存することは、ディスクの読み取りを保存するために何らかのキャッシュを維持すること以外は意味がありませんが、ゲーム内の特定の時間に使用中の画像については、そのキャッシュから非圧縮状態まで読み取る必要があります。
高速なハードウェアデコードが可能であれば、圧縮された画像データはもう少し意味があります。少なくとも法線マッピングについては、このhttp://en.wikipedia.org/wiki/3Dcを覚えています。これにより、VRAMを保存できます。ハードウェアデコードの他の例はまだ知りません。
再開:グラフィックを永続ストレージに保存するためにゲームで使用される形式が何であれ、必要に応じて高速レンダリングできるように、それをデコードし、ダイナミックメモリ、ビデオメモリ、またはその両方で非圧縮バージョンを維持する必要があります。
最後に:私はデスクトップの男です。「メモリ」と言うとき、私は常に動的メモリを指します。「ディスク」、「ファイルシステム」、または「永続ストレージ」と言うとき、デバイスで永続ストレージとして使用するものを常に参照します。通常はハードディスクで使用します。「メモリ効率」と言ったとき、「永続的なストレージ」ではなく「動的メモリ」と考えました。最近、私は多くの人が「メモリ」という言葉を使って「永続的なストレージ」(おそらくモバイルデバイスの用語?)を指すのを見ています。