通过双线性插值做图片缩放(修改CDib库实现)

前言

做双线性插值用到的一个函数,CDib库的文件定义方式参考微软官方文档 Dib库。

双线性插值基础

理论基础

​ 这个文章觉得理论讲的还好,但算法讲的有点乱一篇文章为你讲透双线性插值 - 知乎 (zhihu.com)

算法

​ 这个参考知乎彻底搞懂双线性插值 - 知乎 (zhihu.com),算法部分讲的比上面那个清楚,有Python实现。

Cpp实现

void CDib::Zoom(double times,CDib* buffer)
{
	//空图片容错
	if (!this) return;
    
	//备份长宽 销毁原数据
	int Width = GetWidth()*times;
	int Height = GetHeight()*times;
	Destroy();
	
    //创建新的数据区
	int BPP = 8;
	Create(Width, Height, BPP, 0);
	m_nWidth = Width;
	m_nHeight = Height;
	
    //调色板赋值
	if (IsIndexed())
	{
		int nColors = 256;
		if (nColors > 0)
		{
			RGBQUAD *pal = new RGBQUAD[nColors];
			for (int i = 0; i < nColors; i++)
			{
				pal[i].rgbRed = i;
				pal[i].rgbBlue = i;
				pal[i].rgbGreen = i;
				pal[i].rgbReserved = BYTE(0);
			}
			SetColorTable(0, nColors, pal);
			delete[] pal;
		}
	}
	
    //获取数据区大小
	m_nWidthBytes = abs(GetPitch());
	m_nBitCount = GetBPP();
	m_pDibBits = (unsigned char*)GetBits() + (m_nHeight - 1)*GetPitch();
	
    //数据区赋值(逐像素计算)
	int srcWidth = buffer->GetWidth();
	int srcHeight = buffer->GetHeight();
	double srcX, srcY;
	int srcX_0, srcY_0, srcX_1, srcY_1;
	double value1, value2; // 存储对x轴线性插值后的值
	unsigned char* temp1,* temp2,* temp3,* temp4; //暂存对应像素点地址

	for (int dstY = 0; dstY < m_nHeight; dstY++)
	{
		for (int dstX= 0; dstX < m_nWidthBytes; dstX++)
		{
			//按比例对应
			/*srcX = (dstX)* (srcWidth * 1.0/ m_nWidth);
			srcY = (dstY) * (srcHeight * 1.0/ m_nHeight);*/
			

			// 按几何中心对应
			srcX = max((dstX + 0.5) * (srcWidth * 1.0 / m_nWidth) - 0.5 , 0);
			srcY = max((dstY + 0.5) * (srcHeight * 1.0/ m_nHeight) - 0.5 , 0);
			
			srcX_0 = min((int)floor(srcX), buffer->m_nWidth - 1);
			srcY_0 = min((int)floor(srcY), buffer->m_nHeight - 1);
			srcX_1 = min(srcX_0 + 1 , buffer->m_nWidth - 1);
			srcY_1 = min(srcY_0 + 1, buffer->m_nHeight - 1);

			//计算
			temp1 = buffer->m_pDibBits + srcY_0 * buffer->m_nWidthBytes + srcX_0;
			temp2 = buffer->m_pDibBits + srcY_0 * buffer->m_nWidthBytes + srcX_1;
			temp3 = buffer->m_pDibBits + srcY_1 * buffer->m_nWidthBytes + srcX_0;
			temp4 = buffer->m_pDibBits + srcY_1 * buffer->m_nWidthBytes + srcX_1;

			value1 = *temp1 * (srcX - srcX_0) + *temp2 * (srcX_1 - srcX);
			value2 = *temp3 * (srcX - srcX_0) + *temp4 * (srcX_1 - srcX);
			
			//赋值
			*(m_pDibBits + dstY * m_nWidthBytes + dstX) = \
				value1*(srcY - srcY_0) + value2 * (srcY_1 - srcY);
			int show = *(m_pDibBits + dstY * m_nWidthBytes + dstX);

		}
	}
觉得有用就点个赞,我比较喜欢臭美。
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值