如何将TImage与TImageControl坐标转换为底层位图坐标?
FireMonkey中TImage/TImageControl的坐标转换与取像素实现
关于“本地点”的定义
- 控件本地点:指控件自身坐标系内的点,原点位于控件左上角,坐标值不受父控件的缩放、滚动或布局影响,仅相对于当前控件的边界。
- 位图坐标:指位图自身的像素坐标系,原点位于位图左上角,坐标范围是
[0, Bitmap.Width-1]和[0, Bitmap.Height-1]。
TImage与TImageControl的布局差异
- TImage默认将位图拉伸/适配到控件整个边界(可通过
WrapMode调整),无额外边距处理。 - TImageControl通过
MarginWrapMode属性实现位图的居中、留边等布局,转换坐标时FireMonkey会自动处理布局偏移,无需手动计算边距。
核心代码示例
TImage 鼠标移过取像素
在TImage的OnMouseMove事件中添加代码:
void __fastcall TForm1::Image1MouseMove(TObject *Sender, TShiftState Shift, float X, float Y) { TImage* targetImg = static_cast<TImage*>(Sender); if (!targetImg->Bitmap || targetImg->Bitmap->Width == 0 || targetImg->Bitmap->Height == 0) { Label1->Text = L"无有效位图"; return; } // 控件本地坐标 -> 位图像素坐标 TPointF bitmapPos = targetImg->ConvertLocalPointTo(targetImg->Bitmap, TPointF(X, Y)); // 校验坐标是否在位图范围内 if (bitmapPos.X >= 0 && bitmapPos.X < targetImg->Bitmap->Width && bitmapPos.Y >= 0 && bitmapPos.Y < targetImg->Bitmap->Height) { TColor pixelColor = targetImg->Bitmap->GetPixel(static_cast<int>(bitmapPos.X), static_cast<int>(bitmapPos.Y)); Label1->Text = String().sprintf(L"RGB: %d, %d, %d", GetRValue(pixelColor), GetGValue(pixelColor), GetBValue(pixelColor)); } else { Label1->Text = L"鼠标未在位图区域"; } }
TImageControl 鼠标移过取像素
在TImageControl的OnMouseMove事件中添加代码:
void __fastcall TForm1::ImageControl1MouseMove(TObject *Sender, TShiftState Shift, float X, float Y) { TImageControl* targetCtrl = static_cast<TImageControl*>(Sender); if (!targetCtrl->Bitmap || targetCtrl->Bitmap->Width == 0 || targetCtrl->Bitmap->Height == 0) { Label1->Text = L"无有效位图"; return; } // 控件本地坐标 -> 位图像素坐标(自动适配MarginWrapMode布局) TPointF bitmapPos = targetCtrl->ConvertLocalPointTo(targetCtrl->Bitmap, TPointF(X, Y)); if (bitmapPos.X >= 0 && bitmapPos.X < targetCtrl->Bitmap->Width && bitmapPos.Y >= 0 && bitmapPos.Y < targetCtrl->Bitmap->Height) { TColor pixelColor = targetCtrl->Bitmap->GetPixel(static_cast<int>(bitmapPos.X), static_cast<int>(bitmapPos.Y)); Label1->Text = String().sprintf(L"RGB: %d, %d, %d", GetRValue(pixelColor), GetGValue(pixelColor), GetBValue(pixelColor)); } else { Label1->Text = L"鼠标未在位图区域"; } }
ConvertLocalPointFrom 反向转换示例
如果需要将位图像素坐标转换为控件本地坐标(比如定位某个像素在控件上的位置),代码如下:
// 已知位图上的目标像素点 TPointF bitmapTarget(150, 150); // TImage:位图坐标 -> 控件本地坐标 TPointF imgLocalPos = Image1->ConvertLocalPointFrom(Image1->Bitmap, bitmapTarget); // TImageControl:位图坐标 -> 控件本地坐标(自动适配MarginWrapMode) TPointF ctrlLocalPos = ImageControl1->ConvertLocalPointFrom(ImageControl1->Bitmap, bitmapTarget); // 可用于定位控件(比如在该位置绘制标记) // Canvas->FillEllipse(RectF(ctrlLocalPos.X-5, ctrlLocalPos.Y-5, ctrlLocalPos.X+5, ctrlLocalPos.Y+5), 0);
关键说明
ConvertLocalPointTo(ATarget, APoint):将当前控件的本地坐标APoint转换为ATarget对象(此处为Bitmap)的坐标系坐标。ConvertLocalPointFrom(ASource, APoint):将ASource对象的坐标系坐标APoint转换为当前控件的本地坐标。- 两种转换函数都会自动处理控件的缩放、旋转、布局偏移(比如TImageControl的
MarginWrapMode),无需手动计算。
内容的提问来源于stack exchange,提问作者Drewski7280
相关产品推荐
相关产品推荐

