XNA Game Studio 4.0の画像コーデック

歴史的背景

その昔、私達がXNA 1.0を設計していた時、テクスチャやモデルの読み込みをするのに単にD3DXのラッパーを作りよりも新しいものにしようと決めました。これは、後にコンテント・パイプラインと呼ばれるものでした。

しかし、1.0ベータをリリースした時にはコンテント・パイプラインは未完成でした。テクスチャ読み込み関数がなければ、せっかくのグラフィクスAPIを試すこともできません。このままではリリースできないので、急遽追加されたのがTexture2D.FromFileメソッドでした。

FromFileメソッドはWindows上でしか使えません。なぜなら、D3DXはXbox 360上ではサポートされていないからです。D3DXをXbox 360に移植することも考えましたが、既にコンテント・パイプラインで提供されているのと同じ機能を再実装するのは労力の無駄に思われました。また、FromFileメソッドを削除しようともしましたが、ベータ版との互換性を無くしてまで削除する必要はないと考えました。

XNA Game Studio 4.0ではプラットフォーム間での一貫性を保つことが目標です。Windows版のみの機能というのは、この目標に反します。また、Windows Phone対応によって、Webサービスやピクチャライブラリといった、実行時の画像の読み込みや、書き込みが必要になるシナリオへ対応することが重要になってきました。しかし、D3DXの画像処理用コードは、量が多く、不明瞭な機能も多いので、すべての対応プラットフォームへ移植するのには時間が掛かりすぎます。

そこで、私達はD3DXの画像読み込みコードの代わりに、シンプルな新しいAPIを使うことにしました。このAPIは

  • Windows、Xbox 360、そしてWindows Phoneで同じ動作をする
  • PNG、JPEG、そしてGIFフォーマットに対応
  • スケーリングや切抜き処理に対応
  • スクリーンショット、フォトアルバム、そしてWebサービスなどで扱うピクチャ向けに設計されている
  • ゲームテクスチャなどの大きな画像の読み込みには最適化されていない(コンテント・パイプラインを使うべき)
  • D3DXの画像読み込みより機能が少ない(ミップマップ、DXT圧縮や、カラーキーには対応していない)

画像読み込み用の二つのオーバーロードが追加されました。

 static Texture2D FromStream(GraphicsDevice GraphicsDevice, Stream stream);
static Texture2D FromStream(GraphicsDevice GraphicsDevice, Stream stream, int width, int height, bool crop);

これらのメソッドはファイルからではなくストリームから画像を読み込みます。ですから、他にもFileStream、MemoryStream、NetworkStream、TitleContainer.OpenStreamなど様々なストリームから画像を読み込むことができます。ファイルから画像を読み込む場合は、以下のようにします。

 using (Stream stream = File.OpenRead("cat.png"))
{
    texture = Texture2D.FromStream(graphicsDevice, stream);
}

以下は新しく追加された画像保存用のメソッドです。

 void SaveAsPng(Stream stream, int width, int height);
void SaveAsJpeg(Stream stream, int width, int height);

以下のようにしてファイルへ書き込みます。

 using (Stream stream = File.OpenWrite("cat.png"))
{
    texture.SaveAsPng(stream, texture.Width, texture.Height);
}

画像サイズを指定しないFromStreamオーバーロードを使った場合、GPUでサポートされている最大テクスチャサイズ(Reachは2048、HiDefは4096)を超えない限りは、元のサイズのままで読み込みます。たとえば以下の画像は私の飼っている犬のケスの画像で、サイズは192x288、SurfaceFormat.Colorのテクスチャとして読み込まれます。

source

読み込み元の画像サイズがGPUでサポートされるテクスチャサイズよりも大きい場合は、画像のアスペクト比を保ったままGPUでサポートされているサイズまで縮小します。

画像サイズを指定するオーバーロードを使うと、画像サイズを任意のサイズにすることができます。これはフォトアルバムやサムネイルを表示するときなどに便利です。cropパラメータにfalseを設定した場合、アスペクト比を保ったままで指定した画像サイズ内にスケーリングします。例えば上の画像をwidth=256、height=256、crop=falseを指定して読んだ場合は以下のようになります。

256x256-False

高さは256と指定されたサイズにスケーリングされましたが、幅はアスペクト比を保つ為に256ではなく170にスケーリングされています。もし、元画像のサイズが横長だった場合は幅が256になり、高さは256よりも小さい値になります。

同じ画像をwidth=256、height=256、crop=trueを指定した場合、

256x256-True

読み込まれた画像は指定したサイズと同じサイズにスケーリングされます。この時、新たに指定されたアスペクト比を保つ為に、元画像の上下部分が切り抜かれて、元画像に写っていた葉が消えています。

言い換えると:

  • Crop=false: 縦横の長さが長い方のサイズを指定したサイズにスケーリングし、短い方は指定したサイズより小さいサイズになる
  • Crop=true: 縦横の長さが短い方のサイズを指定したサイズにスケーリングし、長い方は指定したサイズで切り抜かれる

となります。

また、今まではTexture2D型を返すプロパティ等は代わりにStream型を返すようになっています。例えば、以前はTexture2Dを返していたPicture.GetTextureメソッドはStreamを返すPicture.GetImageメソッドに置き換わりました。同じようにアルバムアートや、ゲーマープロファイル内のゲーマーピクチャーもStream型を返すようになっています。

この変更はSilverlightと組み合わせて使うときに必要なものでした。XNAの型であるTexture2Dの代わりにStreamを返すことによって、メディアAPIが返すストリームをXNA用のゲームではFromStreamを使ってTexture2Dに変換することができ、Silverlight用アプリからはBitmapImageとして使うことができます。

原文:

http://blogs.msdn.com/b/shawnhar/archive/2010/05/10/image-codecs-in-xna-game-studio-4-0.aspx