C 保持居中的位图缩放
我正在开发一个支持多点触摸的嵌入式系统(stm32f4)上的图像查看器。要放入透视图,图像查看器应该具有类似于智能手机的功能。 我已经完成了图像缩放和缩放手势识别部分。但它仅从源图像原点坐标进行缩放。因此,如果我的原点(x,y[0,0])位于左上角,那么它将沿着该点缩放。如果我想在右下角找东西,我必须用捏手势,移动到我想要的位置,这是不受欢迎的 . 它应该沿着两个手指的中心 如何在遵循两个手指中心的同时实现缩放?我尝试这样做的结果是工作,但紧张,不稳定的版本基本上无法使用 我的缩放是通过始终打开源图像(在ram中)获取源图像[x,y]坐标和矩形来实现的。我想缩放[w,h]矩形以显示[w,h]并显示它。移动(平移手势)是通过移动源图像中的zoomRect[x,y]坐标来完成的。这意味着每次我移动手指时,我必须移动zoomedRect(增加[x,y])缩放zoomedRect并显示它。因此,由于ram有限,无法存储完全缩放的图像C 保持居中的位图缩放,c,image,algorithm,coordinates,C,Image,Algorithm,Coordinates,我正在开发一个支持多点触摸的嵌入式系统(stm32f4)上的图像查看器。要放入透视图,图像查看器应该具有类似于智能手机的功能。 我已经完成了图像缩放和缩放手势识别部分。但它仅从源图像原点坐标进行缩放。因此,如果我的原点(x,y[0,0])位于左上角,那么它将沿着该点缩放。如果我想在右下角找东西,我必须用捏手势,移动到我想要的位置,这是不受欢迎的 . 它应该沿着两个手指的中心 如何在遵循两个手指中心的同时实现缩放?我尝试这样做的结果是工作,但紧张,不稳定的版本基本上无法使用 我的缩放是通过始终打开
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:
+-------------------------------+
| |
| |
| |
| |
| |
| |
| |
| |
| |
+-------------------------------+
以下是我拥有/可以计算的:
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