24ビットカラーの画像の中の色の数をかぞえるために、これまでに
ArrayList を使った関数をライブラリでつくってきた。ところで、
最近、申し訳ないがどこか探せないのだが Delphi で TBits クラスを
つかった実装を見かけた。論理的には、ArrayList で全色を保持して
ソートすることにより、色数をかぞえるよりスマートで、画像のサイズ
が大きくなるほど、速いと思われる。
C# で Delphi の TBits に相当するクラスは BitArray クラスである。
これは項目ごとに Boolean 値を保持できる。これをつかって、色を
かぞえるのは簡単かつソートがいらないので高速であるはずである。
さっそく試してみた。今回試した色をかぞえる画像はこれである。

ラ・フランドル、二ノ宮2、つくば市
結果は、以下に示すように、これまでの関数より2倍くらい速い。
ライブラリも変更することにしよう。

ArrayList を使った関数をライブラリでつくってきた。ところで、
最近、申し訳ないがどこか探せないのだが Delphi で TBits クラスを
つかった実装を見かけた。論理的には、ArrayList で全色を保持して
ソートすることにより、色数をかぞえるよりスマートで、画像のサイズ
が大きくなるほど、速いと思われる。
C# で Delphi の TBits に相当するクラスは BitArray クラスである。
これは項目ごとに Boolean 値を保持できる。これをつかって、色を
かぞえるのは簡単かつソートがいらないので高速であるはずである。
さっそく試してみた。今回試した色をかぞえる画像はこれである。

ラ・フランドル、二ノ宮2、つくば市
結果は、以下に示すように、これまでの関数より2倍くらい速い。
ライブラリも変更することにしよう。

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Drawing.Imaging; using System.Drawing.Drawing2D; using ImageUtils; using System.Collections; namespace CountColors { public partial class Form1 : Form { public Form1() { InitializeComponent(); } public static int CountColors(Bitmap bmp) { if (bmp.PixelFormat != PixelFormat.Format24bppRgb) return -1; int w = bmp.Width; int h = bmp.Height; BitArray ba = new BitArray(0x1000000, false); int count = 0; int indx; int ir; BmpProc24 src = new BmpProc24(bmp); for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) { ir = src.IndexR(x, y); indx = (int)((((src[ir] << 8) | src[ir - 1]) << 8) | src[ir - 2]); if (!ba[indx]) { ba[indx] = true; count++; } } src.Dispose(); return count; } private void button1_Click(object sender, EventArgs e) { Bitmap bmp = new Bitmap(@"c:\Home\ImgWork\LaFlandre.png"); StopWatch.Start(); int cn = CountColors(bmp); StopWatch.Stop(); label1.Text = cn.ToString() + " colors"; label2.Text = StopWatch.time.ToString() + " ms"; StopWatch.Start(); cn = ImgUtils.CountColors(bmp); StopWatch.Stop(); label3.Text = cn.ToString() + " colors"; label4.Text = StopWatch.time.ToString() + " ms"; bmp.Dispose(); } } }