You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 08:00:22