ビットマップの使用している色数を取得する

ビットマップで使用している色数を計算して取得します。ついでに「コールバックプロシージャ」と「ScanLine」の作り方・使い方も兼ねています。また、動的配列を使用しているのでDelphi4,0以降でないと実行できません。

※動的配列の部分で配列に格納するカラー値が何万色もある場合は計算するのにかなり時間がかかってしまいますのでご了承下さい。(1000色以下ぐらいならめちゃ高速で計算できます。)

■使用するコンポーネント

■使用するAPI関数

■ソースは下記のようになります。

■コールバックプロシージャ&関数の定義
type
TMyCallBack =procedure (const Min,Max,Pos : integer);


//-----------------------------------------------------------------------------
//■関数   GetColorCount
//■用途   ビットマップの使用色数を高速で取得する
//■引数   BMP     ...色数を取得するTBitmapオブジェクト
//      MyCallBack ...プログレスー表示用コールバックプロシージャ
//■戻り値
//      画像の色数
//-----------------------------------------------------------------------------

function GetColorCount(BMP : TBitmap; MyCallBack :TMyCallBack ):integer;
type
 PRGBColor = ^TRGBColor;
 TRGBColor = array[0..32768-1] of TRGBTriple;
var
 X,Y       : Integer;
 BMPLines    : PRGBColor;
 TempBMP     : TBitmap;
 i,j       : integer ;
 RGBCount    : array of DWORD;
 Not_Same_Color : Boolean;
begin

 //初期処理
 i :=0;
 Not_Same_Color :=False;
 TempBMP :=TBitmap.Create;
 TempBMP.Assign(BMP);
 TempBMP.PixelFormat :=pf24bit;

 for Y:=0 to TempBMP.Height-1 do
 begin
  //一ラインのカラーを取得(GetPixelを使用するより数100倍高速Y(^^)Y)
  BMPLines:=TempBMP.ScanLine[Y];

   for X:=0 to TempBMP.Width-1 do
   begin

      //配列の初期設定
      if (Y=0) and (X=0) then
      begin
       i:=1;
       SetLength(RGBCount,i);    
       RGBCount[0]:=RGB(BMPLines[X].rgbtRed,BMPLines[X].rgbtGreen,BMPLines[X].rgbtBlue) ;

      end
      else
      begin

        //配列の中に現在の色が存在するか検索
        for j:=0 to Length(RGBCount) -1 do
        begin
          if RGBCount[j]=RGB(BMPLines[X].rgbtRed,BMPLines[X].rgbtGreen,BMPLines[X].rgbtBlue) then
          begin
            Not_Same_Color :=False;
            Break;
          end;

          Not_Same_Color :=True;

        end;

        //同じ色でない場合は配列に追加する
       if Not_Same_Color then
       begin
          inc(i);
          SetLength(RGBCount,i);
          RGBCount[i-1] := RGB(BMPLines[X].rgbtRed,BMPLines[X].rgbtGreen,BMPLines[X].rgbtBlue) ;
          Not_Same_Color :=False;
       end;

     end;
  end;

  if Assigned(MyCallBack) then MyCallBack(0,100,Muldiv(Y,100,TempBMP.Height-1));

 end;{end for}

 Result :=Length(RGBCount);
 SetLength(RGBCount,0);
 TempBMP.Free ;
 if Assigned(MyCallBack) then MyCallBack(0,0,0);

end;

//進行状態をプログレスバーに表示するプロシージャ
procedure MyCallBack(Const Min,Max,Pos :integer);
begin
 
 Application.ProcessMessages;
 Form1.ProgressBar1.Min :=Min;
 Form1.ProgressBar1.Max :=Max;
 Form1.ProgressBar1.Position :=Pos;

 if Form1.ProgressBar1.Max=Form1.ProgressBar1.Position then Form1.ProgressBar1.Position :=0;
end;

■ボタンクリックで実行
procedure TForm1.Button1Click(Sender: TObject);
begin
  MessageBox(Form1.Handle,
        Pchar('この画像は'+inttostr(GetColorCount(Image1.Picture.Bitmap,@MyCallBack))+
           '色使用しています。'),'色数計算',MB_OK);
end;






Win32APIのページへ



ホーム PV ランキング