使用 Stretch 在 TImage 中获取鼠标下方的像素。 Proportional 和 Center 都设置为 true
Getting the pixel under the mouse in TImage with Stretch. Proportional and Center all set to true
我有一个带有 TImage 的表格。 TImage 设置为 Align=alClient、Stretch=True、Proportional=True 和 Center=True。
在运行时,我将位图加载到该 TImage 中。它显示的比原来的尺寸小一点,但没有失真,正如我所料。
现在我想获取按下鼠标键时鼠标下方像素点的坐标。这是分配给 im_Input.OnMouseDown:
的代码
procedure Tf_ColorAdjustment.im_InputMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
im_Input.Picture.Bitmap.Canvas.Pixels[X - 1, Y - 1] := clYellow;
im_Input.Picture.Bitmap.Canvas.Pixels[X - 1, Y] := clYellow;
im_Input.Picture.Bitmap.Canvas.Pixels[X - 1, Y + 1] := clYellow;
im_Input.Picture.Bitmap.Canvas.Pixels[X, Y - 1] := clYellow;
im_Input.Picture.Bitmap.Canvas.Pixels[X, Y] := clYellow;
im_Input.Picture.Bitmap.Canvas.Pixels[X, Y + 1] := clYellow;
im_Input.Picture.Bitmap.Canvas.Pixels[X + 1, Y - 1] := clYellow;
im_Input.Picture.Bitmap.Canvas.Pixels[X + 1, Y] := clYellow;
im_Input.Picture.Bitmap.Canvas.Pixels[X + 1, Y + 1] := clYellow;
end;
(这只是测试代码以查看鼠标点击结束的位置。我知道使用像素 属性 非常慢,但这是使受影响的像素可见的最简单方法。)
如果所有这些标志都设置为 false,这会很好地工作,但是因为位图被缩小以匹配 window,像素看起来向左和向上移动。
我知道我需要调整坐标,但是我该怎么做呢? RTL/VCL 支持吗?类似于 TImage 的 CalcStretched 方法(我找不到它,但也许我只是忽略了它)。或者我真的必须自己编写计算程序吗?
(我不敢相信 Google 没有为此找到现成的解决方案。这一定是几十年来普遍遇到的问题。)
好吧,你只需要几个减法和除法:
function TForm1.ClientToBitmap(const P: TPoint): TPoint;
var
cW, cH: Integer; // width and height of control
bW, bH: Integer; // width and height of bitmap
Origin: TPointF; // top-left pixel of bitmap in the control
ZoomW, ZoomH: Double; // required zoom factor to make bitmap fit horisontally or vertically
Zoom: Double; // zoom factor
begin
cW := Image1.Width;
cH := Image1.Height;
bW := Image1.Picture.Bitmap.Width;
bH := Image1.Picture.Bitmap.Height;
ZoomW := cW/bW;
ZoomH := cH/bH;
Zoom := Min(ZoomW, ZoomH);
Origin.X := (cW - bW*Zoom) / 2;
Origin.Y := (cH - bH*Zoom) / 2;
Result.X := Round((P.X - Origin.X) / Zoom);
Result.Y := Round((P.Y - Origin.Y) / Zoom);
end;
现在:
procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
with ClientToBitmap(Point(X, Y)) do
begin
Image1.Picture.Bitmap.Canvas.Pixels[X - 1, Y - 1] := clBlack;
Image1.Picture.Bitmap.Canvas.Pixels[X - 1, Y] := clBlack;
Image1.Picture.Bitmap.Canvas.Pixels[X - 1, Y + 1] := clBlack;
Image1.Picture.Bitmap.Canvas.Pixels[X, Y - 1] := clBlack;
Image1.Picture.Bitmap.Canvas.Pixels[X, Y] := clBlack;
Image1.Picture.Bitmap.Canvas.Pixels[X, Y + 1] := clBlack;
Image1.Picture.Bitmap.Canvas.Pixels[X + 1, Y - 1] := clBlack;
Image1.Picture.Bitmap.Canvas.Pixels[X + 1, Y] := clBlack;
Image1.Picture.Bitmap.Canvas.Pixels[X + 1, Y + 1] := clBlack;
end;
end;
我有一个带有 TImage 的表格。 TImage 设置为 Align=alClient、Stretch=True、Proportional=True 和 Center=True。
在运行时,我将位图加载到该 TImage 中。它显示的比原来的尺寸小一点,但没有失真,正如我所料。
现在我想获取按下鼠标键时鼠标下方像素点的坐标。这是分配给 im_Input.OnMouseDown:
的代码procedure Tf_ColorAdjustment.im_InputMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
im_Input.Picture.Bitmap.Canvas.Pixels[X - 1, Y - 1] := clYellow;
im_Input.Picture.Bitmap.Canvas.Pixels[X - 1, Y] := clYellow;
im_Input.Picture.Bitmap.Canvas.Pixels[X - 1, Y + 1] := clYellow;
im_Input.Picture.Bitmap.Canvas.Pixels[X, Y - 1] := clYellow;
im_Input.Picture.Bitmap.Canvas.Pixels[X, Y] := clYellow;
im_Input.Picture.Bitmap.Canvas.Pixels[X, Y + 1] := clYellow;
im_Input.Picture.Bitmap.Canvas.Pixels[X + 1, Y - 1] := clYellow;
im_Input.Picture.Bitmap.Canvas.Pixels[X + 1, Y] := clYellow;
im_Input.Picture.Bitmap.Canvas.Pixels[X + 1, Y + 1] := clYellow;
end;
(这只是测试代码以查看鼠标点击结束的位置。我知道使用像素 属性 非常慢,但这是使受影响的像素可见的最简单方法。)
如果所有这些标志都设置为 false,这会很好地工作,但是因为位图被缩小以匹配 window,像素看起来向左和向上移动。
我知道我需要调整坐标,但是我该怎么做呢? RTL/VCL 支持吗?类似于 TImage 的 CalcStretched 方法(我找不到它,但也许我只是忽略了它)。或者我真的必须自己编写计算程序吗?
(我不敢相信 Google 没有为此找到现成的解决方案。这一定是几十年来普遍遇到的问题。)
好吧,你只需要几个减法和除法:
function TForm1.ClientToBitmap(const P: TPoint): TPoint;
var
cW, cH: Integer; // width and height of control
bW, bH: Integer; // width and height of bitmap
Origin: TPointF; // top-left pixel of bitmap in the control
ZoomW, ZoomH: Double; // required zoom factor to make bitmap fit horisontally or vertically
Zoom: Double; // zoom factor
begin
cW := Image1.Width;
cH := Image1.Height;
bW := Image1.Picture.Bitmap.Width;
bH := Image1.Picture.Bitmap.Height;
ZoomW := cW/bW;
ZoomH := cH/bH;
Zoom := Min(ZoomW, ZoomH);
Origin.X := (cW - bW*Zoom) / 2;
Origin.Y := (cH - bH*Zoom) / 2;
Result.X := Round((P.X - Origin.X) / Zoom);
Result.Y := Round((P.Y - Origin.Y) / Zoom);
end;
现在:
procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
with ClientToBitmap(Point(X, Y)) do
begin
Image1.Picture.Bitmap.Canvas.Pixels[X - 1, Y - 1] := clBlack;
Image1.Picture.Bitmap.Canvas.Pixels[X - 1, Y] := clBlack;
Image1.Picture.Bitmap.Canvas.Pixels[X - 1, Y + 1] := clBlack;
Image1.Picture.Bitmap.Canvas.Pixels[X, Y - 1] := clBlack;
Image1.Picture.Bitmap.Canvas.Pixels[X, Y] := clBlack;
Image1.Picture.Bitmap.Canvas.Pixels[X, Y + 1] := clBlack;
Image1.Picture.Bitmap.Canvas.Pixels[X + 1, Y - 1] := clBlack;
Image1.Picture.Bitmap.Canvas.Pixels[X + 1, Y] := clBlack;
Image1.Picture.Bitmap.Canvas.Pixels[X + 1, Y + 1] := clBlack;
end;
end;