图片缩放应用(nearest / bilinear / three-order interpolate)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图片缩放应用(nearest / bilinear / three-order interpolate)相关的知识,希望对你有一定的参考价值。
typedef xPixel PIXELCOLORRGB;
double Sinxx(double value)
{
if (value < 0) value = -value;
if (value < 1.0) {
float temp = value * value;
return 0.5 * temp * value - temp + 2.0 / 3.0;
}
else if (value < 2.0) {
value = 2.0 - value;
value *= value * value;
return value / 6.0;
}
else {
return 0.0;
}
}
int BOUND(int value, int min, int max)
{
chASSERT(min <= max);
if (value <= min)
{
return min;
}
else if (value >= max)
{
return max;
}
else
{
return value;
}
}
enum ImageQaulityE
{
IMAGE_GEOMETRY_NEAREST_NEIGHBOR_INTERPOLATE = 0,
IMAGE_GEOMETRY_BILINEAR_INTERPOLATE,
IMAGE_GEOMETRY_THREE_ORDER_INTERPOLATE
};
ImageQaulityE Quality = ImageQaulityE::IMAGE_GEOMETRY_BILINEAR_INTERPOLATE;
PIXELCOLORRGB Interpolate(LPBYTE lpbySrcXY, int x, int y, float fu, float fv, int nScanWidth, int nScanHeight)
{
PIXELCOLORRGB rgb;
//行字节数, 可以将dwWidthBytes作为参数传递过来
DWORD dwWidthBytes = (DWORD)nScanWidth * 4;
switch (Quality)
{
case IMAGE_GEOMETRY_NEAREST_NEIGHBOR_INTERPOLATE:
{
BYTE* pbySrc = lpbySrcXY;
rgb.b = *pbySrc++;
rgb.g = *pbySrc++;
rgb.r = *pbySrc++;
rgb.a = *pbySrc;
break;
}
case IMAGE_GEOMETRY_BILINEAR_INTERPOLATE:
{
//相邻的四个像素最右下角点的x, y坐标偏移量
int nx = 1;
int ny = 1;
if ((x + 1) > (nScanWidth - 1)) nx = 0;
if ((y + 1) > (nScanHeight - 1)) ny = 0;
//相邻四个像素的像素值
BYTE abyRed[2][2], abyGreen[2][2], abyBlue[2][2], abyAlpha[2][2];
//像素点(x, y)的数据位置
BYTE* pbySrc = lpbySrcXY;
//获取像素数值.
//(x, y) = (x, y) + (0, 0)
abyBlue[0][0] = *pbySrc++;
abyGreen[0][0] = *pbySrc++;
abyRed[0][0] = *pbySrc++;
abyAlpha[0][0] = *pbySrc;
//(x + 1, y) = (x, y) + (1, 0)
pbySrc = (lpbySrcXY + nx * 4);
abyBlue[1][0] = *pbySrc++;
abyGreen[1][0] = *pbySrc++;
abyRed[1][0] = *pbySrc++;
abyAlpha[1][0] = *pbySrc;
//指向下一行数据
BYTE* pbySrcTemp = (lpbySrcXY + ny * dwWidthBytes);
//(x , y + 1) = (x, y) + (0, 1)
pbySrc = pbySrcTemp;
abyBlue[0][1] = *pbySrc++;
abyGreen[0][1] = *pbySrc++;
abyRed[0][1] = *pbySrc++;
abyAlpha[0][1] = *pbySrc;
//(x + 1, y + 1) = (x, y) + (1, 1)
pbySrc = pbySrcTemp + (4 * nx);
abyBlue[1][1] = *pbySrc++;
abyGreen[1][1] = *pbySrc++;
abyRed[1][1] = *pbySrc++;
abyAlpha[1][1] = *pbySrc;
rgb.r = (BYTE)(BOUND(((1 - fu) * (1 - fv) * ((float)abyRed[0][0]) +
(1 - fu) * fv * ((float)abyRed[0][1]) +
fu * (1 - fv) * ((float)abyRed[1][0]) +
fu * fv * ((float)abyRed[1][1])), 0, 255));
rgb.g = (BYTE)(BOUND(((1 - fu) * (1 - fv) * ((float)abyGreen[0][0]) +
(1 - fu) * fv * ((float)abyGreen[0][1]) +
fu * (1 - fv) * ((float)abyGreen[1][0]) +
fu * fv * ((float)abyGreen[1][1])), 0, 255));
rgb.b = (BYTE)(BOUND(((1 - fu) * (1 - fv) * ((float)abyBlue[0][0]) +
(1 - fu) * fv * ((float)abyBlue[0][1]) +
fu * (1 - fv) * ((float)abyBlue[1][0]) +
fu * fv * ((float)abyBlue[1][1])), 0, 255));
rgb.a = (BYTE)(BOUND(((1 - fu) * (1 - fv) * ((float)abyAlpha[0][0]) +
(1 - fu) * fv * ((float)abyAlpha[0][1]) +
fu * (1 - fv) * ((float)abyAlpha[1][0]) +
fu * fv * ((float)abyAlpha[1][1])), 0, 255));
break;
}
case IMAGE_GEOMETRY_THREE_ORDER_INTERPOLATE:
{
//像素坐标
int xx[4], yy[4];
//相邻四个像素的像素值
BYTE abyRed[4][4], abyGreen[4][4], abyBlue[4][4], abyAlpha[4][4];
xx[0] = -1; xx[1] = 0; xx[2] = 1; xx[3] = 2;
yy[0] = -1; yy[1] = 0; yy[2] = 1; yy[3] = 2;
//保证合法
if ((x - 1) < 0) xx[0] = 0;
if ((x + 1) > (nScanWidth - 1)) xx[2] = 0;
if ((x + 2) > (nScanWidth - 1)) xx[3] = ((xx[2] == 0) ? 0 : 1);
if ((y - 1) < 0) yy[0] = 0;
if ((y + 1) > (nScanHeight - 1)) yy[2] = 0;
if ((y + 2) > (nScanHeight - 1)) yy[3] = ((yy[2] == 0) ? 0 : 1);
//像素点(x, y)的数据位置
//获取数据
int i;
for (i = 0; i < 4; i++)
{
//像素点(x, y)的数据位置
BYTE* pbySrcBase = lpbySrcXY + yy[i] * dwWidthBytes;
for (int j = 0; j < 4; j++)
{
BYTE* pbySrc = pbySrcBase + 4 * xx[j];
abyBlue[i][j] = *pbySrc++;
abyGreen[i][j] = *pbySrc++;
abyRed[i][j] = *pbySrc++;
abyAlpha[i][j] = *pbySrc++;
}
}
//u, v向量
float afu[4], afv[4];
afu[0] = Sinxx(1.0f + fu);
afu[1] = Sinxx(fu);
afu[2] = Sinxx(1.0f - fu);
afu[3] = Sinxx(2.0f - fu);
afv[0] = Sinxx(1.0f + fv);
afv[1] = Sinxx(fv);
afv[2] = Sinxx(1.0f - fv);
afv[3] = Sinxx(2.0f - fv);
//矩阵乘向量的中间值
float afRed[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
float afGreen[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
float afBlue[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
float afAlpha[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
for (i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
afRed[i] += afv[j] * abyRed[j][i];
afGreen[i] += afv[j] * abyGreen[j][i];
afBlue[i] += afv[j] * abyBlue[j][i];
afAlpha[i] += afv[j] * abyAlpha[j][i];
}
}
rgb.r = (BYTE)(BOUND((afu[0] * afRed[0] + afu[1] * afRed[1] + afu[2] * afRed[2] +
afu[3] * afRed[3]), 0, 255));
rgb.g = (BYTE)(BOUND((afu[0] * afGreen[0] + afu[1] * afGreen[1] + afu[2] * afGreen[2] +
afu[3] * afGreen[3]), 0, 255));
rgb.b = (BYTE)(BOUND((afu[0] * afBlue[0] + afu[1] * afBlue[1] + afu[2] * afBlue[2] +
afu[3] * afBlue[3]), 0, 255));
rgb.a = (BYTE)(BOUND((afu[0] * afAlpha[0] + afu[1] * afAlpha[1] + afu[2] * afAlpha[2] +
afu[3] * afAlpha[3]), 0, 255));
break;
}
default: break;
}//end switch
return rgb;
}
bool xPixmap::load(const chConstStringA& filename)
{
QImage img;
if(img.load(toQString(filename)) || img.load(QString::fromLocal8Bit(filename.c_ptr(), filename.length())))
{
m_bHasAlphaChannel = img.hasAlphaChannel();
#if WINDOWS_SYSTEM
double nPDI = getCurrentStation().m_dPDI;
QSize sizeNew(_X(img.width()), _Y(img.height()));
//QSize sizeNew((img.width() * nPDI), (img.height() * nPDI));
if(filename.indexOf("-ext") != -1)
{
sizeNew = QSize(img.width(), img.height());
}
//img = img.scaled(sizeNew, Qt::IgnoreAspectRatio/*, Qt::SmoothTransformation*/);
#endif
int w = img.width() * nPDI;
int h = img.height() * nPDI;
setNull();
data().createGraphic(w, h);
if (-0.0001 < (nPDI - 1) && (nPDI - 1) < 0.0001)
{
memcpy((LPVOID)data().pixels(), img.constBits(), w * h * sizeof(xPixel));
}
else
{
xPixel* pImage = (xPixel*)img.constBits();
xPixel* pDst = (xPixel*)data().pixels();
for (int y = 0; y < h; ++y)
{
for (int x = 0; x < w; ++x)
{
float fX = x * 1.0 / nPDI;
float fY = y * 1.0 / nPDI;
xPixel* pSrc = pImage + (int)fY * img.width() + (int)fX;
*pDst = Interpolate((LPBYTE)pSrc, int(fX), int(fY), fX - int(fX), fY - int(fY), img.width(), img.height());
++pDst;
}
}
}
return true;
}
chASSERTx(FALSE, "Faile to load:%s", filename.c_str());
return false;
}
以上是关于图片缩放应用(nearest / bilinear / three-order interpolate)的主要内容,如果未能解决你的问题,请参考以下文章
OpenCV中的resize缩放使用最邻近插值INTER_NEAREST仍会产生新值
YOLOv3处理图片优化——cuda bilinear resize
适于Large Prime Characteristic Fields的高效算法及其在Bilinear Pairing和Supersingular Isogeny-Based协议中的应用