今回はちょっとユーザー目線の機能を作ろうと考えます。
やりたい内容としては、表示している画像の拡大縮小です。
最終目標としては、【マウスポイントの位置を基準にスクロールで表示している画像の拡大縮小】を目指したいと思います。
やりたい内容を分けると下記2つになります。
■マウスポイントの位置の取得方法
■表示してい画像を拡大縮小方法
今回は『表示している画像の拡大/縮小の表示』をピックアップして説明します。
今回使用する関数
今回使用する関数は、今までに使っているものを使用する。
HOperatorSet.SetPart(HTuple, HTuple, HTuple, HTuple, HTuple)
SetPart()では、hWindowControlのディスプレイ(表示サイズ)の大きさの設定を行います。
【引数の紹介】
■HOperatorSet.SetPart(HTuple, HTuple, HTuple, HTuple, HTuple) 第1引数:hWindowControlのハンドル 第2引数:Y座標の始点 第3引数:X座標の始点 第4引数:Y座標の終点 第5引数:X座標の終点
サンプルを作ってみる
簡単なサンプルを作成して紹介していきたいと思う。
また、今回の拡大/縮小する時の【基準点は、画像中心】で算出する。
操作画面
簡単にコントロールの説明
■btnReadImg ⇒ 画像読込して、hWindowControl1に表示 ■lblReadImgSize ⇒ 読み込んだ画像のサイズを表示 ■hWindowControl1 ⇒ 画像を表示 ■lblCurrentImagePart ⇒ 現在のhWindowControl1のImagePartの数値を表示 (SetPartで設定した値) ■btnZoomOut ⇒ 表示している画像を縮小表示 ■btnZoomIn ⇒ 表示している画像を拡大表示
定義
今回は、読み込んだ時で表示した時のSetPart()で設定した数値と倍率の数値を保持したいため、フォーム内で使える構造体と変数を定義する。
//SetPartの表示の設定値 struct SetImagePart { internal double Top; internal double Left; internal double Bottom; internal double Right; } private SetImagePart ImgPart; private double ValueZoom = 1.0; //拡大縮小の倍率
処理
今回のテーマは、拡大縮小なので、その他の部分は省略します。※最後に補足として、記載。
■拡大
private void btnZoomIn_Click(object sender, EventArgs e)
{
if (DispOrgImg == null) return; //読み込んでいるかどうか
if (Math.Round(ValueZoom,2) <= 0) return; //0なので処理しない
//表示削除
HTuple hwndOrg = hWindowControl1.HalconWindow;
HOperatorSet.ClearWindow(hwndOrg);
ValueZoom -= 0.1;
//現在の中心位置を取得する。
double w = Math.Abs(ImgPart.Left) + Math.Abs(ImgPart.Right);
double h = Math.Abs(ImgPart.Top) + Math.Abs(ImgPart.Bottom);
double centerw = (int)((ImgPart.Left + ImgPart.Right) / 2);
double centerh = (int)((ImgPart.Top + ImgPart.Bottom) / 2);
SetImagePart tmp = new SetImagePart()
{
Left = centerw - Math.Round(w * ValueZoom / 2,2),
Top = centerh - Math.Round(h * ValueZoom / 2, 2),
Right = centerw + Math.Round(w * ValueZoom / 2, 2),
Bottom = centerh + Math.Round(h * ValueZoom / 2, 2),
};
lblCurrentImagePart.Text =
$"ImagePart 上: {tmp.Top} 左: {tmp.Left} 下: {tmp.Bottom} 右: {tmp.Right}";
HOperatorSet.SetPart(hwndOrg, tmp.Top, tmp.Left, tmp.Bottom, tmp.Right);
HOperatorSet.DispObj(DispOrgImg, hwndOrg);
}
■縮小
private void btnZoomOut_Click(object sender, EventArgs e)
{
if (DispOrgImg == null) return; //読み込んでいるかどうか
if (4.0 <= Math.Round(ValueZoom, 2)) return; //4倍まで
//表示削除
HTuple hwndOrg = hWindowControl1.HalconWindow;
HOperatorSet.ClearWindow(hwndOrg);
ValueZoom += 0.1;
//現在の中心位置を取得する。
double w = Math.Abs(ImgPart.Left) + Math.Abs(ImgPart.Right);
double h = Math.Abs(ImgPart.Top) + Math.Abs(ImgPart.Bottom);
double centerw = (int)((ImgPart.Left + ImgPart.Right) / 2);
double centerh = (int)((ImgPart.Top + ImgPart.Bottom) / 2);
SetImagePart tmp = new SetImagePart()
{
Left = centerw - Math.Round(w * ValueZoom / 2, 2),
Top = centerh - Math.Round(h * ValueZoom / 2, 2),
Right = centerw + Math.Round(w * ValueZoom / 2, 2),
Bottom = centerh + Math.Round(h * ValueZoom / 2, 2),
};
lblCurrentImagePart.Text =
$"ImagePart 上: {tmp.Top} 左: {tmp.Left} 下: {tmp.Bottom} 右: {tmp.Right}";
HOperatorSet.SetPart(hwndOrg, tmp.Top, tmp.Left, tmp.Bottom, tmp.Right);
HOperatorSet.DispObj(DispOrgImg, hwndOrg);
}
処理としては、変数[ValueZoom] に入れる数値が違うだけである。
ImagePart()の設定値を変更する為に、SetPart()のを使用する。
画像を縮小したい時は、
ImagePart()の値が現在より大きくすることで、表示される画像は小さくなる。
画像を拡大した時は、
ImagePart()の値が現在より小さくすることで、表示される画像は大きくなる。
計算の考え方
計算の考え方を少し紹介します。
赤点は、設定した内容の為、わかっています。
設定した内容から、【ImagePartの中心】【Width】【Height】を算出します。
この図から、求めると下記のようになる。
実行結果
画像の中心(hWindowControl中心)で拡大縮小できていそうです。
まとめ
拡大縮小の表示だけなら、SetPart()を使用する事で実現可能です。
今回の内容はSetPart()の使い方としての計算方法がメインになってしまいました。
ともあれ、拡大縮小表示が出来るようになりましたね。
次は、マウスのポインタの位置を中心に拡大縮小できるように作っていきたいと思います。
まずは第1段階として完成です。
補足(作った関数の紹介)
Zoom表示で表示する関数[DispZoom]
private void DispZoom(HTuple windowhandle, HObject img)
{
//Zoom方式で表示
HOperatorSet.GetImageSize(img, out HTuple w, out HTuple h);
double rateR = DEF_H / h, rateC = DEF_W / w;
double rate = (rateR < rateC) ? rateR : rateC;
double c1 = -((DEF_W / rate) - w) / 2;
double c2 = c1 + (DEF_W / rate);
double r1 = -((DEF_H / rate) - h) / 2;
double r2 = r1 + (DEF_H / rate);
HOperatorSet.SetPart(windowhandle, r1, c1, r2, c2);
HOperatorSet.DispObj(img, windowhandle);
}
画像を選択してもらう関数[SelectImageFile]
private DialogResult SelectImageFile(out string fp)
{
fp = "";
OpenFileDialog ofd = new OpenFileDialog();
ofd.FileName = "";
ofd.InitialDirectory = @"C:\";
ofd.Filter = "画像ファイル(*.png;*.jpg)|*.png;*.jpg";
ofd.Title = "開くファイルを選択してください";
DialogResult res = ofd.ShowDialog();
if (res == DialogResult.OK) fp = ofd.FileName;
return res;
}
【読込】ボタンの処理[btnReadImg_Click]
private void btnReadImg_Click(object sender, EventArgs e)
{
//初期化
DispOrgImg = null;
nudFixedPointX.Value = nudFixedPointX.Minimum;
nudFixedPointY.Value = nudFixedPointY.Minimum;
//表示削除
HTuple hwndOrg = hWindowControl1.HalconWindow;
HOperatorSet.ClearWindow(hwndOrg);
//画像を選択してもらう
if (SelectImageFile(out string fp) == DialogResult.OK)
{
//画像読込
HOperatorSet.ReadImage(out HObject img, fp);
DispOrgImg = img;
//最大値を設定
HOperatorSet.GetImageSize(DispOrgImg, out HTuple wb, out HTuple hb);
//XYのNumericUpDownの設定
nudFixedPointX.Maximum = wb.I;
nudFixedPointY.Maximum = hb.I;
//サイズ表示
lblReadImgSize.Text = "X:" + wb.D.ToString() + "pixel Y:" + hb.D.ToString() + "pixel";
//Zoom方式で表示
DispZoom(hwndOrg, img);
}
}
業務でプログラミング(C#/VB/Python)を作っている。
挫折を何回も繰り返し、幾度の壁を乗り越えてきた。
乗り越えてきた事を忘れないように記録に残す。
同じ思いをしている人への情報提供になれたらと思う。
基本は初心者に向けたプログラムの情報を提供する。
コメント