C#のwinformsで画像ファイルのPixelFormatからビット深度を確認する。

コンピュータ

BitmapオブジェクトのPixelFormatを見てビット深度(1ピクセルのビット数)確認します。

using System.Drawing;
using System.Drawing.Imaging;
class Program
{
    static void Main()
    {
        // 生成したビットマップオブジェクトのピクセルフォーマット
        using (var bmp = new Bitmap(10, 10))
        {
            Console.WriteLine("PixcelFormat:{0}", bmp.PixelFormat);
        }
        string dirpath = @".";
        // ストレージに保存してある画像ファイルのピクセルフォーマット
        IEnumerable<string> files = Directory.EnumerateFiles(
            dirpath, "*", SearchOption.AllDirectories);
        foreach(var file in files)
        {
            string ext = Path.GetExtension(file).ToUpper();
            if (ext != ".JPG" && ext != ".PNG") continue;
            string basename = Path.GetFileName(file);
            using (var bmp = new Bitmap(file))
            {
                BitmapData bd = bmp.LockBits(
                    new Rectangle(0, 0, bmp.Width, bmp.Height),
                    ImageLockMode.ReadWrite,
                    bmp.PixelFormat
                );
                Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\t{5}",
                        bmp.RawFormat, bmp.PixelFormat, bd.Stride, bd.Width, bd.Stride/bd.Width, basename);
                bmp.UnlockBits(bd);
            }
        }

    }
}

まず、Bitmap()をnewで新規作成した場合、デフォルトのピクセルフォーマットはFormat32bppArgbになりました。

次に256×256の画像ファイルを4つ用意します。

001.png…カラー(アルファチャンネル無し)
002.png…カラー(アルファチャンネルあり)
003.png…グレースケール
004.jpg…グレースケール

サンプルプログラムを実行した結果

Png  Format24bppRgb  768 256 3   001.png
Png Format32bppArgb 1024    256 4   002.png
Png Format32bppArgb 1024    256 4   003.png
Jpeg    Format8bppIndexed   256 256 1   004.jpg

003.pngがグレスケールで8ビットで済むところFormat32bppArgbと32ビットとなっています。
念のためStride(1列のバイト数)と幅を割り算してみても4バイトと同じ結果になりました。

ファイルのプロパティのビットの深度は8なのでBitmapオブジェクトに読み込まれる際RGBAに自動的に変換されていると思われます。

グレスケールのJpegファイルはFormat8bppIndexedとなっているあたりも不思議な感じがします。

Format8bppIndexedのMicrosoftのサイトの説明を見ると、

この形式が 1 ピクセルあたり 8 ビットであり、インデックス付きであることを指定します。 したがって、カラー テーブルには 256 色含まれています。

と記載されており、一見すると256インデックスカラーとも読み取れます。カラーテーブルにグレスケールの256諧調がセットされていると考えることもできますが、PixelFormatを見るだけではカラーかグレースケールを厳密に判定することは出来なさそうな感じがします。

なかなか、厄介な感じですが個人的にインデックスカラーの画像ファイルを取り扱うことは無さそうですので、Format8bppIndexed = グレースケールと判定することにすることは出来そうです。ただPNGファイルのグレスケールがFormat32bppArgbとなるのは厄介です。多分RGBに同じ値がセットされていると思われるのでそれで判定することも出来そうですが、全てのピクセルを検査するのコストが高そうです。以前JpegとPNGファイルのバイナリデータから幅と高さを取得するプログラムを書いたことがあり、同様な方法でビット深度を取得することが出来そうな気がしますが、面倒です。
C#でJpegとPNGファイルから幅と高さを取得
多数の画像ファイルから幅と高さを取得する必要があり、なるべく短い時間で取得できるように試作してみました。C#で画像の高さや幅を取得する方法として、画像ファイルからSystem.Drawing.Bitmapなどのオブジェクトを生成し、オブジェ...

とりあえず、PNGファイルはカラーであることが前提でプログラムを組み、必要があればグレスケールへ変換することにします。

コメント