优化双线性插值图像放缩

void  MyDIBBitmap::VeryFastSmoothScaleFrom(_StretchScaleParam& pp, RECT rcTemp)
{
	//最快的方式实现双线性插值放缩图片
	//rcTemp是填充到this位图的区域,横向扫描可利用cpu cache机制提速
	if (_WIDTH(rcTemp) < 1 || _HEIGHT(rcTemp) < 1)
		return;

	//为了精度,使用16位定点数进行扫描
	//源坐标表示范围  [Src.start,   Src.end-1  ]=Src.start+ [0,Src.Len-1 ](Len=End-Start)
	//目标坐标表示范围[Dest.start,  Dest.end-1 ]=Dest.start+[0,Dest.Len-1](Len=End-Start)
	//(1)计算一个取景间隔 (2.0  / 256) 的作用是不触碰边界(避免做边界检测,但边界带有微弱误差)
	int interval_W = (int)(65536 * (((double)(_WIDTH(pp.rcSrc) - 1)) - (2.0 / 256)) / (_WIDTH(rcTemp) - 1));
	int interval_H = (int)(65536 * (((double)(_HEIGHT(pp.rcSrc) - 1)) - (2.0 / 256)) / (_HEIGHT(rcTemp) - 1));
	unsigned int scrXStart65536 = pp.rcSrc256.left * 256 + 1;
	unsigned int srcYStart65536 = pp.rcSrc256.top * 256 + 1;
	unsigned int srcX65536;
	unsigned int srcY65536 = srcYStart65536;

	for (int y = rcTemp.top; y < rcTemp.bottom; ++y)
	{
		srcX65536 = scrXStart65536;

		for (int x = rcTemp.left; x < rcTemp.right; ++x)
		{
			//计算原位图取景点,利用定点数替代浮点数
			//(2)还原成8位定点数坐标系
			unsigned int srcX256 = srcX65536 >> 8;
			unsigned int srcY256 = srcY65536 >> 8;
			//临近整数坐标
			unsigned int srcX0_256 = srcX256 & 0xFFFFFF00;
			unsigned int srcY0_256 = srcY256 & 0xFFFFFF00;
			//对应原图的像素坐标,因为上面的2/256的原因,此时y1不会越界
			unsigned int x0 = srcX0_256 >> 8;
			unsigned int y0 = srcY0_256 >> 8;
			unsigned int x1 = x0 + 1;
			unsigned int y1 = y0 + 1;
			//到临近整数的距离
			unsigned int dist_x0_256 = srcX256 - srcX0_256;
			unsigned int dist_y0_256 = srcY256 - srcY0_256;
			unsigned int dist_x1_256 = 256 - dist_x0_256;
			unsigned int dist_y1_256 = 256 - dist_y0_256;
			//4个面积权重
			unsigned int mj_00_65536 = dist_x1_256 * dist_y1_256;
			unsigned int mj_01_65536 = dist_x1_256 * dist_y0_256;
			unsigned int mj_10_65536 = dist_x0_256 * dist_y1_256;
			unsigned int mj_11_65536 = dist_x0_256 * dist_y0_256;
			//(3)定位输入点和输出点
			PixelARGB& pix_Src_00 = *(pp.srcImg->__GetPixelAt(x0, y0));
			PixelARGB& pix_Src_01 = *(pp.srcImg->__GetPixelAt(x0, y1));
			PixelARGB& pix_Src_10 = *(pp.srcImg->__GetPixelAt(x1, y0));
			PixelARGB& pix_Src_11 = *(pp.srcImg->__GetPixelAt(x1, y1));
			PixelARGB& pixDest = *(this->__GetPixelAt(x, y));
			//(4)结果
			pixDest.b_Alpha = (BYTE)((pix_Src_00.b_Alpha * mj_00_65536 + pix_Src_01.b_Alpha * mj_01_65536 + pix_Src_10.b_Alpha * mj_10_65536 + pix_Src_11.b_Alpha * mj_11_65536) >> 16);
			pixDest.b_Red   = (BYTE)((pix_Src_00.b_Red   * mj_00_65536 + pix_Src_01.b_Red   * mj_01_65536 + pix_Src_10.b_Red   * mj_10_65536 + pix_Src_11.b_Red   * mj_11_65536) >> 16);
			pixDest.b_Green = (BYTE)((pix_Src_00.b_Green * mj_00_65536 + pix_Src_01.b_Green * mj_01_65536 + pix_Src_10.b_Green * mj_10_65536 + pix_Src_11.b_Green * mj_11_65536) >> 16);
			pixDest.b_Blue  = (BYTE)((pix_Src_00.b_Blue  * mj_00_65536 + pix_Src_01.b_Blue  * mj_01_65536 + pix_Src_10.b_Blue  * mj_10_65536 + pix_Src_11.b_Blue  * mj_11_65536) >> 16);
			//next
			srcX65536 += interval_W;
		}

		srcY65536 += interval_H;
	}
}

猜你喜欢

转载自blog.csdn.net/lif12345/article/details/80488019