前言
做双线性插值用到的一个函数,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);
}
}
觉得有用就点个赞,我比较喜欢臭美。