总结让人进步,写出来给人看,更是受益匪浅。
2017年11月12日夜十点,程序调试断点过后,鼠标已经走位,缩放的观察观察失去了意义,虽然尝试有一些进展,但都是零星的,保存关机,打算明日再来。坐到床上,找到笔和稿纸,打算再推演一下,不知道,当时起笔,为什么会首先写下这几个字:A是参考点,A*S是放大后的图像...至今不明白这神来之笔,而后的逻辑推演草草十来行,问题便解决了。
后来又有两次总结进步,但仍不能明白为什么会有这样的发端。今天,又是一次总结。这似乎有点像和尚悟道,不明,师傅棒喝!突然悟道!这也很像乌云密布造势之后而来的最后一道刺眼的闪电,雨下而来!找不到发端,就不找了,该来的会来,功到自然成。
人家都说,第一次做,一定做到最好,我很信服这话,因为里边的神来之笔,后来不再有。
进入正题:一,A是参考点,A*S是放大后的图像,A*(S-1)移动出窗口之外,保持A点在窗口不动。比如图像1024*768,放大2倍,有1024*768出窗口,还有1024*768在窗口内,假定A在(200,200),放大后为(400,400),要保持不变,即要出窗口(200,200),这样A点会在窗口不动,在窗口的图像是(200,200,200+1024,200+768),其余截去。
二,然后鼠标移动到窗口一点e(x,y),它对应原图像B点,即B*S-A*(S-1),然后放大到S',那么B点如何保持不动呢?首先移动出窗口B*(S'-1),其次,再移动出窗口B*S-A*(S-1)-B,它相当于以B为参考点,那么在S时,deltaAB要移动出窗口,整理一下(B-A)(S-1)=deltaAB,所以以B为参考点,总共移动出窗口B*(S'-1)+B*S-A*(S-1)-B,令它等于★。这样保持B在放大S'时保持不动。
三,然后鼠标移动到窗口一点e1(x,y),它对应原图像C点,放大S时,C点在C*S-A*(S-1)【以A为参考,减去移动出窗口量A*(S-1)】;放大S'时,C点在C*S'-★【以B为参考,减去移动出窗口量★】;然后放大到S‘’,那么C点如何保持不动呢?首先移动出窗口C*(S''-1),其次,以C为参考点,那么在S'时,deltaBC要移动出窗口C*S'-★-C=deltaBC,总共移动出窗口C*(S''-1)+C*S'-★-C。
这样保持C在放大S‘’时保持不动。图像变成1024*768*S‘’,窗口内仍然1024*768,有1024*768*(S‘’-1)在窗口外。
四,鼠标再移动,令它C*(S''-1)+C*S'-★-C=★★,依次类推......缩小亦是此道理。
下面是C#代码:图像在pictureBox1中,分辨率1024*768
一, Point Xpt = new Point();
Point pt0 = new System.Drawing.Point();
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
pictureBox1.Focus();
if (Xpt.X != e.X && Xpt.Y != e.Y)
{
Xpt.X = e.X;
Xpt.Y = e.Y;
if (glob_ScaleX > 1)
{
Xpt.X = (Xpt.X + pt0.X) / (int)glob_ScaleX;
Xpt.Y = (Xpt.Y + pt0.Y) / (int)glob_ScaleX;
}
}
}
二,private void pictureBox1_MouseWheel(object sender, MouseEventArgs e)
{
if (e.Delta > 0)
{
glob_ScaleX += (float)(e.Delta / 120.0);
if (0 == glob_ScaleX) glob_ScaleX = 1;
}
else
{
glob_ScaleX -= (float)((-e.Delta) / 120.0);
if (0 == glob_ScaleX) glob_ScaleX = 1;
}
Point tempPt = new System.Drawing.Point(Xpt.X - e.X, Xpt.Y - e.Y);
pictureBox1.Image = ZoomImg(new Size(glob_curBitmap.Width, glob_curBitmap.Height), (int)glob_ScaleX,
new Point(Xpt.X, Xpt.Y), tempPt);
m_btempImage3 = true;
pt0.Y = ((int)glob_ScaleX - 1) * (Xpt.Y) + Xpt.Y - e.Y;
pt0.X = ((int)glob_ScaleX - 1) * (Xpt.X) + Xpt.X - e.X;
}
三, public Bitmap ZoomImg(Size srcbitmap, int multiple, Point pt, Point deltaPt)
{//继续改进版20171027//问题多多,但关键点已经突破。201710280716
//问题已经使用数学的方法解决。201711130731
if (multiple <= 0) { multiple = 0; pt0 = new System.Drawing.Point(); return glob_curBitmap; }
int tempW = (int)(srcbitmap.Width * multiple);
int tempH = (int)(srcbitmap.Height * multiple);
int orgW = srcbitmap.Width;
Bitmap bitmap = new Bitmap(1024, 768);
BitmapData bitmapdata = bitmap.LockBits(new Rectangle(new Point(0, 0), bitmap.Size),
ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
unsafe
{
byte* sourcebyte = (byte*)(bitmapdata.Scan0.ToPointer());
int h0 = (multiple - 1) * pt.Y + deltaPt.Y;
int w0 = (multiple - 1) * pt.X + deltaPt.X;
if (h0 <= 0 || w0 <= 0) { h0 = 0; w0 = 0; }
for (int y = h0; y < h0 + 768; y++)//只取pt.y处768
{
for (int x = w0; x < w0 + 1024; x++)//只取pt.x处1024
{
long index = (x / multiple) + (y / multiple) * orgW;//行扫描宽度
tempImage3[(y - h0) * _RoiW + (x - w0)] = sourcebyte[0] = glob_buffer8[index];
sourcebyte[1] = glob_buffer8[index];
sourcebyte[2] = glob_buffer8[index];
sourcebyte += 3;
}
}
}
bitmap.UnlockBits(bitmapdata);
return bitmap;
}
其实,第一次实现后,坐在那里,感到自己像图像中那个点一样,随着放大和缩小,自己在时光中穿越,你会发现时光倒流是非常难的,但有一种可能,就是永远在一个点放大缩小(你不仅可以到达未来,还可以回到过去,从前面的推演也可以论证,但是只要你移动了,想要回原来的点,可能性微乎其微!)。
待续(慢慢来!...........)每天一点小改变☺
我的邮箱liuganggang_1978@163.com;734523623@qq.com