C 保持居中的位图缩放

C 保持居中的位图缩放,c,image,algorithm,coordinates,C,Image,Algorithm,Coordinates,我正在开发一个支持多点触摸的嵌入式系统(stm32f4)上的图像查看器。要放入透视图,图像查看器应该具有类似于智能手机的功能。 我已经完成了图像缩放和缩放手势识别部分。但它仅从源图像原点坐标进行缩放。因此,如果我的原点(x,y[0,0])位于左上角,那么它将沿着该点缩放。如果我想在右下角找东西,我必须用捏手势,移动到我想要的位置,这是不受欢迎的 . 它应该沿着两个手指的中心 如何在遵循两个手指中心的同时实现缩放?我尝试这样做的结果是工作,但紧张,不稳定的版本基本上无法使用 我的缩放是通过始终打开

我正在开发一个支持多点触摸的嵌入式系统(stm32f4)上的图像查看器。要放入透视图,图像查看器应该具有类似于智能手机的功能。 我已经完成了图像缩放和缩放手势识别部分。但它仅从源图像原点坐标进行缩放。因此,如果我的原点(x,y[0,0])位于左上角,那么它将沿着该点缩放。如果我想在右下角找东西,我必须用捏手势,移动到我想要的位置,这是不受欢迎的 . 它应该沿着两个手指的中心

如何在遵循两个手指中心的同时实现缩放?我尝试这样做的结果是工作,但紧张,不稳定的版本基本上无法使用

我的缩放是通过始终打开源图像(在ram中)获取源图像[x,y]坐标和矩形来实现的。我想缩放[w,h]矩形以显示[w,h]并显示它。移动(平移手势)是通过移动源图像中的zoomRect[x,y]坐标来完成的。这意味着每次我移动手指时,我必须移动zoomedRect(增加[x,y])缩放zoomedRect并显示它。因此,由于ram有限,无法存储完全缩放的图像

Source image width,height[640, 480]:
+-------------------------------+
|   zoomedRect                  |
|   +--------------+            |
|   |              |            |
|   |              |            |
|   |              |            |
|   |              |            |
|   |              |            |
|   +--------------+            |
|                               |
|                               |
|                               |
+-------------------------------+

I take zoomedRect i.e. x,y[50, 50] width,height[160, 120]
and scale it to display size w,h[640x480]
Display:
+-------------------------------+
|                               |
|                               |
|                               |
|                               |
|                               |
|                               |
|                               |
|                               |
|                               |
+-------------------------------+
以下是我拥有/可以计算的:

  • 两个手指的中心

  • 将两个手指的中心平移到源图像(即使放大)

  • 分数比例(1.32,1.45…)和(源图像宽度|高度)/(缩放矩形宽度|高度)

  • 编辑:

    我试着计算两个手指接触时的中心点,然后用这个中心进行未来的计算,这就是为什么所有的跳跃和晃动都会发生的原因。但可能我这边有个错误,所以我会添加一些相关的代码。 正如我前面提到的,我更改zoomRect宽度、高度以缩放图像

    newWidth = tempWidth / scale;
    newHeight = tempHeight / scale;
    
    所以在缩放之后,我需要移动到靠近中心的位置,我通过计算比例的变化来实现 (lastWidth-newWidth)

    现在我们需要在两个手指之间的计算中心停止,并且不要越界[0,0]:

    #define LIMIT(value, min, max) (value < min ? min : (value > max ? max : value))
    newSourceX = LIMIT(newSourceX + ((int16_t)lastWidth - newWidth), 0, centerSourceX);
    newSourceY = LIMIT(newSourceY + ((int16_t)lastHeight - newHeight), 0, centerSourceY);
    

    结果:

    也许从第一个点锁定图像的中心点,您可以计算两个手指的中心,然后从此点开始缩放。而不是每次重新计算中心点。将其作为缩放点,然后从该点移动手指作为缩放因子,应停止您提到的抖动效果

    您有源图片,源坐标
    (x,y)
    在屏幕坐标中通过仿射变换进行变换。我假设缩放是一致的。开始时
    Scale=1;dx,dy=0

    ScrX = (x - dx) * Scale
    ScrY = (y - dy) * Scale
    
    所以我们看到了一张源图像,它是从dx,dy点切下来的,并按比例时间扩展的

    例如,dx=1,dy=1,Scale=2。左矩形是源,右矩形是屏幕

    让我们开始(
    b
    prefix)缩放手指的屏幕位置
    (bx0,by0)
    (bx1,by1)
    -相对的矩形角。末端(或中间)位置(
    e
    前缀)是
    (ex0,ey0)
    (ex1,ey1)

    让矩形的对角线对应于比例度:

    eScale = bScale * Sqrt(((ex1-ex0)^2 + (ey1-ey0)^2) / ((bx1-bx0)^2 + (by1-by0)^2)) 
    //use Math.Hypot or Vector.Length if available
    
    所以我们有了新的规模

    我们有起点和终点

     bcx = (bx0 + bx1) / 2
     bcy = (by0 + by1) / 2
     ecx = (ex0 + ex1) / 2
     ecy = (ey0 + ey1) / 2
    
    这两个屏幕点应对应于相同的源坐标

    bcx = (xx - bdx) * bScale
    ecx = (xx - edx) * eScale
    
    不包括我们得到的xx

    edx = bdx + bcx / bScale - ecx / eScale
    
    和edy的类似公式


    所以我们有了新的移位参数。

    您能更详细地解释一下这里的“bcx=(xx-bdx)*bScale ecx=(xx-edx)*eScale”和这里的“edx=bdx+bcx/bScale-ecx/eScale”发生了什么吗?我没有完全理解其中的意思。bcx对应于某个xx值。ecx对应于相同的值(我们对值x本身不感兴趣)。所以我们把第一个方程解成xx,把xx的表达式代入第二个方程。我以为我理解了你的答案,但在熟睡之后,用新鲜的眼睛看了看,我显然不明白
    ScrX=(x-dx)*缩放
    dx
    是缩放图像将被剪切的位置,但什么是
    x
    ?是源图像宽度吗?我从ScrX中得到了什么?另外,当您计算
    eScale
    时,
    bScale
    是如何计算的?您在源图片上有一个带有
    x
    坐标的点。该公式用于确定该点在屏幕上的位置。b缩放是指在用手指重新缩放之前的缩放。我添加了图片
    bcx = (xx - bdx) * bScale
    ecx = (xx - edx) * eScale
    
    edx = bdx + bcx / bScale - ecx / eScale