BMP画像をグレイスケール化するには?

解決


Delphi挑戦者  2004-10-28 04:04:21  No: 11556

初めまして、Delphi挑戦者と申します。
現在Delphi7にて、BMP画像のグレイスケール化に挑戦しています。
過去ログなどを読んだのですが、あまり理解できず…新しくたずねさせていただきます。

現在、私がプログラムしたものは下記の通りです。

//ユーザー関数(ウランバイト)←下で使います。
Function TForm1.RoundByte(data:Double):Byte;
begin
  if Data >= 255 then //バイトの範囲(0〜255)に値を丸め込む
      Data := 255;
      if Data <= 0 then
          Data := 0;
  RoundByte := Round(Data);
end;

procedure TForm1.Gray;
var
 x,y : Smallint; //ビットマップのx軸、y軸
 GrayBMP : TBitmap; //グレイ補正ビットマップ
 px1RGB : Longint; //ピクセル値(RGB型)
 R,G,B : Byte; //R値、G値、B値

begin
 CanselFlag := False;

 GrayBMP := TBitmap.Create;
 GrayBMP.Height := Form2.Image1.Height;
 GrayBMP.Width := Form2.Image1.Width;

 //プログレスバーの設定
 ProgressBar1.Max := GrayBMP.Width; //最大値をビットマップの横幅に設定
 ProgressBar1.Min := 0;              //最小値を0に設定
 ProgressBar1.Position := 0;         //ポジションを0に設定

 //Gray処理
 for x:=0 to GrayBMP.Width do
 begin
 for y:=0 to GrayBMP.Height do
 begin

 //元画像からの値の抽出
 px1RGB := ColorToRGB(Form2.Image1.Canvas.Pixels[x,y]);

 //3原色の分解
 R := GetRValue(px1RGB);
 G := GetRValue(px1RGB);
 B := GetRValue(px1RGB);

 //グレースケール化
 //Y = ( 0.298912 * R + 0.586611 * G + 0.114478 * B )
 R := RoundByte(R*0.298912);
 G := RoundByte(G*0.586611);
 B := RoundByte(B*0.114478);

 //ビットマップ描写
 GrayBMP.Canvas.Pixels[x,y] := RGB(R,G,B);

 end;

 //プログレスバー
  ProgressBar1.Position := x;
  end;
  ProgressBar1.Position := 0;
  //キャンセルフラグ
  if CanselFlag = False then
      Form2.ImageView(GrayBMP);
      GrayBMP.Free;
    end;

画像ファイルは
BitMap.LoadFromFile(OpenDialog1.FileName);    //ビットマップにファイルをロードする。
Form2.ImageView(BitMap);                     //「ImageView」手続きの呼び出し。
上記の方法で読み込んでいます。

現在グレースケール化としているところは動かしていません。
このプログラムのまま実行すると予測ですが、色の情報が失われて、ぱっと見はグレースケール化されたような形になっています。
グレースケール化の部分を動かすと、緑がかった画像になります。
NTSCでのグレースケールに挑戦したいのですが、どのような処理をすれば良いのかわかりません。
よろしくお願いしますm(__)m

わかりにくい文章で、すみません。


ウォレス  2004-10-28 05:06:11  No: 11557

単純に勘違いかと思います。

   R := RoundByte(R*0.298912 + G*0.586611 + B*0.11447);
   G := R; 
   B := R; 

でグレイスケールになりますよ♪

Y = ( 0.298912 * R + 0.586611 * G + 0.114478 * B )
と書いておられますよね。
Y  は一般に輝度(すなわちグレイスケール)をあらわすのに使う記号です。

余談ですが、Pixelsよりもscanlineを、
小数点演算より整数演算を使いましょう。


りりか  2004-10-28 05:32:05  No: 11558

インチキかな

uses
  Jpeg;

procedure ConvertToGrayScale(bmp:TBitmap);
var
  jpg:TJpegImage;
  ms:TMemoryStream;
begin
  jpg := TJpegImage.Create;
  ms  := TMemoryStream.Create;
  try
    jpg.Assign(bmp);
    jpg.SaveToStream(ms);
    ms.Position := 0;
    jpg.LoadFromStream(ms);
    jpg.Grayscale := true;
    bmp.Assign(jpg);
  finally
    jpg.Free;
    ms.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  bmp:TBitmap;
begin
  bmp := TBitmap.Create;
  try
    bmp.LoadFromFile('C:\TestPhoto.bmp');
    ConvertToGrayScale(bmp);
    Canvas.Draw(10,10,bmp);
  finally
    bmp.Free;
  end;
end;


Delphi挑戦者  2004-10-30 04:30:52  No: 11559

ウォレス様、りりか様、返信ありがとうございました。
無事にグレースケール化をすることができました。

ウォレス様のアドバイスにあるように、scanlineに変更しましたら、動きが速くなりました。
また、小数点についてもご指摘、ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加