BMP画像を使ってImage上に再び描画するには?

解決


ぷくぷく  2004-01-09 07:45:24  No: 6619

初心者な質問ですみません。
BMP画像をImageに取り込むことはできるのですが、その画像を使って
再びImage上に描画することはできるのでしょうか。
BMP画像は2階調化されたものを使うのですが、もしそのピクセルに数値が与えられていたり、関数があるのならそれを教えてもらいたいです。
座標に数値が与えられているのなら解決しそうな気はするのですが…
ぜひぜひお助け願います。


Mr.XRAY  URL  2004-01-09 09:30:25  No: 6620

>再びImage上に描画することはできるのでしょうか。

あまり意味がよく理解できていないので的はずれかもしれませんが,
つまり重ね描画ということですよね.
いくらでもできますよ.もじだって書けちゃいます.

Image1.Canvas.Draw(....

という感じです.Delphiでは画像などを表示,つまり描画するのに
Canvasという,文字どおりキャンパス(油絵などでも使う用語ですね)
に文字や画像を表示します.ヘルプでTCanvasを調べてみて下さい.
Canvasには座標(画面のドットと同じです)があります.

注意することはコントロール(コンポーネント)の中にはCanvasを
持たないものもあります.
そのようなものには任意の位置に文字とか画像は描画できません.
(特殊な方法を使用するとできますけどね...)


ぷくぷく  2004-01-09 10:23:46  No: 6621

質問の説明が不十分ですみません。
重ね描画と言いますか、読み込んだものとまったく同じ画像やそれを生かしたものをほかのImage上に作り出すこともできるんでしょうか。
というのは、もとの画像を使ってそれをグリッドで区切って、
そのマス目に色が入っているかいないかで判断をして、
さらに粗い画像をつくっていきたいのです。
だから色がついている座標に
数値(例えば黒なら255、白なら0というように)を与えたいのですが、
それってBMPにはついているんですよね?
(かなり不確かです)
それをどのようにDelphi上では読み取っていったらよいのでしょうか?

またまた説明不足でしたらすみません…


Halbow  URL  2004-01-09 10:41:00  No: 6622

Halbow です。

ビットマップはウィンドウズの標準の画像形式なので、ある点の色がどうなっているか
を具体的に知らなくても、複製や縮小・拡大などが簡単にできます。Delphi でも
Mr.XRAY さんがおっしゃっているように TCanvas のメソッドで簡単にできます。
でも、質問の本当の問題点は表題にあるような複製をつくることではなく、ビット
マップの特定の座標の点の色が黒か白かを知りたいのではないのですか?

そうであれば、これも簡単です。TImage や TBitmap には Canvas プロパティーが
ありますので、それの Pixels[x,y] プロパティーが使えます。速度を問題にしなければ
これをつかって、他の Canvas に複製することも簡単にできます。

速度が問題なときは、画像を TBitmap に読み込めば、Scanline[] というプロパティー
で高速にアクセスできます。この場合は、座標との対応がちょっと面倒ですが。

まずは、ヘルプで TCanvas クラスの Pixels[x,y] プロパティーを調べてください。


ぷくぷく  2004-01-10 02:57:29  No: 6623

TCanvas クラスの Pixels[x,y] プロパティを調べてみました。 
すると、このように使うのかのかなと思い組み立ててみたのですが、
これでは色を読み取ることができませんでした。
どうしたらそのPixelsの色を読み取って数値を与えることができるのでしょうか。
 (Image上には画像を取り込んでからです) 
for i:=0 to 400 do begin
    for j:=0 to 200 do begin
      if (Canvas.Pixels[i,j]=clBlack) then
        begin  Cell1[Data1[i].x,j]:=1;
        end
        else
        begin  Cell1[Data1[i].x,j]:=0;
        end;
    end;

    for j:=0 to 200 do begin
    if  (Cell1[Data1[i].x,j]=1) and
        (Cell1[Data1[i].x,j+1]=0)  then
        er[i]:=j;
    end;

  Data1[i].x:=i;
  Data1[i].y:=er[i];
  Memo1.Lines.Add(InttoStr(i)+' → '+InttoStr(er[i]));


Halbow  URL  2004-01-10 03:15:59  No: 6624

Halbow です。

> TCanvas クラスの Pixels[x,y] プロパティを調べてみました。 
> すると、このように使うのかのかなと思い組み立ててみたのですが、
> これでは色を読み取ることができませんでした。
> どうしたらそのPixelsの色を読み取って数値を与えることができるのでしょうか。
>  (Image上には画像を取り込んでからです) 
> for i:=0 to 400 do begin
>     for j:=0 to 200 do begin
>       if (Canvas.Pixels[i,j]=clBlack) then

えと、どのメソッドでこれを実行しているのか分かりませんが Canvas だけだと
なんの Canvas だか分かりません。Image1.Canvas とかしないと。あと黒が
必ず clBlack とは限りません。TColor は整数値ですから、IntToStr() で
表示できます。


Halbow  URL  2004-01-10 03:31:21  No: 6625

Halbow です。

Pixels[] を使って確かめてみる簡単な方法は、画像を読み込んだ Image1 などの
OnMouseMove イベントハンドラで、マウスの x,y 座標から Pixels[] の値を
求めて、Label1 に表示してみてください。


ぷくぷく  2004-01-10 04:50:51  No: 6626

何度もすみません。
OnMouseMove イベントハンドラの使い方もよくわからないのですが、
白黒の2階調化された画像でもclBlackは使えないのですね。
いきなりImageに読み込んだ2階調化された画像から、白か黒かを
判断する方法はないんでしょうか。

>TColor は整数値ですから、IntToStr() で表示できます。

とのことですが、画像自体が持っている整数値はどうやったら
知ることができるんでしょうか。

ほんとになにもわかっていない質問ばかりして申し訳ないのですが、
ぜひぜひよろしくお願いします。


Mr.XRAY  URL  2004-01-10 05:13:49  No: 6627

>とのことですが、画像自体が持っている整数値はどうやったら
>知ることができるんでしょうか。

単純な動作で確認していくのが,急がば回れだと思います.
[新規プロジェクト]でFormにボタンを一つ配置します.
ボタンのクリックイベントと,FormのOnMouseDownイベントに
以下のコードを書いて下さい.

実行したら,ボタンをクリックします.
次に,色のついた四角形をマウスでクリックしてみて下さい.

rocedure TForm1.Button1Click(Sender: TObject);
begin
     Form1.Canvas.Brush.Color:=clBlack;
     Form1.Canvas.Rectangle(50,150,150,250);
     Form1.Canvas.Brush.Color:=clWhite;
     Form1.Canvas.Rectangle(50,250,150,350);
     Form1.Canvas.Brush.Color:=clBlue;
     Form1.Canvas.Rectangle(50,350,150,450);
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
     V: Integer;
     R,G,B : Byte;
begin
     V:=Form1.Canvas.Pixels[X,Y];

     R:=GetRValue(V);
     G:=GetGValue(V);
     B:=GetBValue(V);
     ShowMessage('色数値= '+IntToStr(V)+
                 '  赤= '+IntToStr(R)+
                 '  緑= '+IntToStr(G)+
                 '  青= '+IntToStr(B));
end;


Mr.XRAY  URL  2004-01-10 05:18:05  No: 6628

OnMouseDownイベントのコードを次の様に変えてみると,
また何かがわかると思います.

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
     V: Integer;
     R,G,B : Byte;
begin
     V:=Form1.Canvas.Pixels[X,Y];

     R:=GetRValue(V);
     G:=GetGValue(V);
     B:=GetBValue(V);
     if V=clBlack then begin
       ShowMessage('黒だよ')
     end else begin
       ShowMessage('色数値= '+IntToStr(V)+
                   '  赤= '+IntToStr(R)+
                   '  緑= '+IntToStr(G)+
                   '  青= '+IntToStr(B));

     end;
end;


Mr.XRAY  URL  2004-01-10 05:27:30  No: 6629

さらに追い打ちですが,
>白黒の2階調化された画像でもclBlackは使えないのですね。

そうではなくて,DelphiのコントロールにはCanvas(カンバス)
がありますが,どのコントロールのCanvasか指定しないといけない
ということです.先の例のコードではForm1のCanvasを使用しています.

Canvasの指定は
  XXXXX.Canvas
の様にしますが,もし,XXXXXの部分を省略すると,Delphiは,一番
自分に近いCanvasを使用します.
例のコードでは

procedure TForm1.FormMouseDown(Sender: ..........

となっていますので,もし省略すると,このTForm1が一番ちかい,
Canvasをもったコントロール(コンポーネント)と解釈されるわけです.


Halbow  URL  2004-01-10 05:34:13  No: 6630

Halbow です。

> OnMouseMove イベントハンドラの使い方もよくわからないのですが、
> 白黒の2階調化された画像でもclBlackは使えないのですね。
> いきなりImageに読み込んだ2階調化された画像から、白か黒かを
> 判断する方法はないんでしょうか。

まずは試してみてください。Form1 に Image1 と Label1 を置いて

procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.AutoSize := true;
  Image1.Picture.LoadFromFile('c:\Test.bmp');// 画像を読み込む
end;

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  Label1.Caption := IntToHex(Image1.Canvas.Pixels[X,Y],8);
end;

とします。画像のファイル名はそちらのものに変えてください。

で、マウスを画像の黒いところに持っていったとき、00000000 なら 黒
白いところで 00FFFFFF なら白と言えます。二階調の白黒画像でも純粋
な白・黒であるとは限らないようです。でも、大部分は純粋な白黒です
けどね。その場合は、clBlack と clWhite と比較できます。

> 画像自体が持っている整数値はどうやったら
> 知ることができるんでしょうか。

Image1 などに表示して、Canvas.Pixels[] が最も簡単な方法です。
わたしだったら、ビットマップファイルを直接解析するんですが、
初心者には難しいです。


Mr.XRAY  URL  2004-01-10 05:48:41  No: 6631

>Label1.Caption := IntToHex(Image1.Canvas.Pixels[X,Y],8);

あっ,こちらのHex表示の方がいいですね.


ぷくぷく  2004-01-10 10:41:29  No: 6632

Halbowさん、 Mr.XRAYさん、ありがとうございます。
どちらのプログラムも作ってみることができ、Pixelsのことが少しは
わかってきた気がします。
しつこいようですが、下のようなプログラムは作ることができないんでしょうか。IntToHex関数がStringのためこれは実行できないのですが、このように
00000000か00FFFFFFかで1か0をCellに与えたいのですがどうしたらよいのでしょうか。
よろしくお願いします。  

  Sigma1:=0;
  for i:=0 to 400 do begin
    for j:=0 to 200 do begin
      if (IntToHex(Image1.Canvas.Pixels[i,j],8)=00000000) then
        begin  Cell1[i,j]:=1;
        end
        else
        begin  Cell1[i,j]:=0;
        end;
    end;

    for j:=0 to 200 do begin
    if  (Cell1[i,j]=1) and
        (Cell1[i,j+1]=0)  then
        er[i]:=j;
    end;

  Data1[i].x:=i;
  Data1[i].y:=er[i];
  Memo1.Lines.Add(InttoStr(i)+' → '+InttoStr(er[i]));

  Sigma1:=Sigma1+er[i];

  end;


Halbow  2004-01-10 11:03:25  No: 6633

Halbow です。

> 下のようなプログラムは作ることができないんでしょうか。IntToHex関数がStringのため
> これは実行できないのですが、このように 00000000 か 00FFFFFF かで1か0をCellに与え
> たいのですがどうしたらよいのでしょうか。
> よろしくお願いします。  

>   Sigma1:=0;
>   for i:=0 to 400 do begin
>     for j:=0 to 200 do begin
>       if (IntToHex(Image1.Canvas.Pixels[i,j],8)=00000000) then
>         begin  Cell1[i,j]:=1;
>         end
>         else
>         begin  Cell1[i,j]:=0;
>         end;
>     end;

> (IntToHex(Image1.Canvas.Pixels[i,j],8)=00000000)

ここの部分は

Image1.Canvas.Pixels[i,j] = clWhite 

でいいんじゃないですか? 実際に白が 00000000 であることを確認したのですよね。


Halbow  2004-01-10 11:09:38  No: 6634

Halbow です。

> ここの部分は

> Image1.Canvas.Pixels[i,j] = clWhite 

> でいいんじゃないですか? 実際に白が 00000000 であることを確認したのですよね。

すみません、白 と 黒 を間違えています。clWhite を clBlack か数値の 0 で
読み替えてください。


ぷくぷく  2004-01-10 11:43:33  No: 6635

Halbow さん
  無事画像に数値を与えて数えることができました。
ありがとうございます。

Mr.XRAY  さん
何度も親切にアドバイスありがとうございました。

ほんとに困り果てていたのでこうして解決できて本当に感謝しています。
ありがとうございます!!


ね〜え♪by あやや  2004-01-10 11:55:04  No: 6636

>ぷくぷくさん

ね〜え♪そのBMP画像って白か黒だけで、目で観た感じ灰色の部分が無いの?
だったら〜♪ 白い部分が$ffffffでなくて、また黒い部分が$000000でなくてもゼ〜ンゼン構わないと思うんだけど♪…違う?
例えば、だいたい中間の明るさの灰色の値を$777777として〜、
Image1.Canvas.Pixels[i,j] の値がそれより大きければ、Cellの値は 1
Image1.Canvas.Pixels[i,j] の値それより小さければ、Cellの値は 0
としていいんじゃない♪ど〜お?

あれっ?解決しちゃってたのネ♪


ぷくぷく  2004-01-10 20:34:21  No: 6637

>ね〜え♪by あやや  さん
  持っているBMP画像は基本的に白か黒かだけなので先の分でもできたのですが、言われているやり方でもやってみました!それだとさらにきっちり
判断できますね。
ありがとうございます!


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

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






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