常州金坛网站建设,8小8x人成免费观看网页,ui和平面设计的区别,千锋教育前端培训因工作需要使用软件方法缩放PNG图片#xff0c;询问chatgpt拿到了c双线性插值算法#xff0c;开始很顺利#xff0c;整理一下代码#xff0c;封装一下接口#xff0c;就可以使用了#xff0c;效果还不错#xff0c;马上编译发给测试组测试#xff0c;测试发现有一些图片… 因工作需要使用软件方法缩放PNG图片询问chatgpt拿到了c双线性插值算法开始很顺利整理一下代码封装一下接口就可以使用了效果还不错马上编译发给测试组测试测试发现有一些图片缩放后出现黑边还有一些图片缩放时程序崩溃了。有问题的代码如下。
BOOL hbmp_stretch_Bilinear(HBITMAP hbmp_dst, HBITMAP hbmp_src)
{BITMAP info_src, info_dst;GetObject(hbmp_src, sizeof(BITMAP), info_src);GetObject(hbmp_dst, sizeof(BITMAP), info_dst);int srcWidth info_src.bmWidth;int srcHeight info_src.bmHeight;int dstWidth info_dst.bmWidth; // 新的图像宽度int dstHeight info_dst.bmHeight; // 新的图像高度float rateX (float)(srcWidth - 1) / (float)(dstWidth - 1);float rateY (float)(srcHeight - 1) / (float)(dstHeight - 1);BYTE* bits (BYTE*)info_src.bmBits;float srcX, srcY;int x0, x1, y0, y1;int x, y;float fL, fR, fT, fB, fTL, fTR, fBL, fBR;for (y 0; y dstHeight; y) {for (x 0; x dstWidth; x) {srcX (float)x * rateX;srcY (float)y * rateY;x0 (int)srcX;y0 (int)srcY;x1 x0 1;y1 y0 1;BYTE* pTL bits[info_src.bmWidthBytes * y0 (x0 2)];BYTE* pTR bits[info_src.bmWidthBytes * y0 (x1 2)];BYTE* pBL bits[info_src.bmWidthBytes * y1 (x0 2)];BYTE* pBR bits[info_src.bmWidthBytes * y1 (x1 2)];BYTE* pTarget ((BYTE*)info_dst.bmBits)[info_dst.bmWidthBytes * y (x 2)];fR srcX - x0;fB srcY - y0;fL (1.0f - fR);fT (1.0f - fB);fTL fL * fT;fTR fR * fT;fBL fL * fB;fBR fR * fB;pTarget[0] (BYTE)(fTL * (float)pTL[0] fTR * (float)pTR[0] fBL * (float)pBL[0] fBR * (float)pBR[0]);pTarget[1] (BYTE)(fTL * (float)pTL[1] fTR * (float)pTR[1] fBL * (float)pBL[1] fBR * (float)pBR[1]);pTarget[2] (BYTE)(fTL * (float)pTL[2] fTR * (float)pTR[2] fBL * (float)pBL[2] fBR * (float)pBR[2]);pTarget[3] (BYTE)(fTL * (float)pTL[3] fTR * (float)pTR[3] fBL * (float)pBL[3] fBR * (float)pBR[3]);}}return true;
} 用有问题的图片单步跟踪执行很快锁定了有问题的代码行 float rateX (float)(srcWidth - 1) / (float)(dstWidth - 1);float rateY (float)(srcHeight - 1) / (float)(dstHeight - 1);。。。for (y 0; y dstHeight; y) {for (x 0; x dstWidth; x) {srcX (float)x * rateX;srcY (float)y * rateY;x0 (int)srcX;y0 (int)srcY; x0是源图像素点列坐标代入转换
x0(int)srcXx*rateXx*(srcWidth - 1)/(dstWidth - 1)
srcWidth:源图片的宽度 dstWidth目标图片的宽度 当到达像素行尾时xdstWidth-1根据上面的公式x0的理论值是srcWidth - 1正好覆盖源图片的一行。但是rateX转换浮点数时有可能会发生截断误差2个整数相除其结果有可能是有限不循环小数也有可能是无限循环小数第一种结果小数位数超过7位与第二种结果都会产生截断当发生向下截断时xdstWidth-1x0的值是srcWidth - 2x1x01的值不会越界其它情况x0的值是srcWidth - 1x1x01的值越界所以有些图片正常有些图片应用程序因为内存越界而崩溃。同理计算y0也存在同样的问题。找到了问题原因可以在计算rateX、rateY时额外加上或者减去一个微小值让rateX、rateY的截断发生在同一方向向上截断或者向下截断相应的得到两种解决方案。
解决方案一 在计算rateX、rateY时额外加上0.0001让rateX、rateY的截断全部是向上截断没有向下截断。 float rateX (float)(srcWidth -1 0.0001) / (float)(dstWidth - 1); float rateY (float)(srcHeight -1 0.0001) / (float)(dstHeight - 1);
此时遍历到行尾时x1会产生越界遍历到最后一行时y1会产生越界因此行尾与最后一行移出循环体做特别的处理。代码如下
BOOL hbmp_stretch_Bilinear_border(HBITMAP hbmp_dst, HBITMAP hbmp_src)
{BITMAP info_src, info_dst;GetObject(hbmp_src, sizeof(BITMAP), info_src);GetObject(hbmp_dst, sizeof(BITMAP), info_dst);int srcWidth info_src.bmWidth;int srcHeight info_src.bmHeight;int dstWidth info_dst.bmWidth; // 新的图像宽度int dstHeight info_dst.bmHeight; // 新的图像高度float rateX (float)(srcWidth -1 0.0001) / (float)(dstWidth - 1);float rateY (float)(srcHeight -1 0.0001) / (float)(dstHeight - 1);BYTE* bits (BYTE*)info_src.bmBits;float srcX, srcY;int x0, x1, y0, y1;int x, y;float fL, fR, fT, fB, fTL, fTR, fBL, fBR;for (y 0; y dstHeight-1; y) {for (x 0; x dstWidth-1; x) {srcX (float)x * rateX;srcY (float)y * rateY;x0 (int)srcX;y0 (int)srcY;x1 x0 1;y1 y0 1;BYTE* pTL bits[info_src.bmWidthBytes * y0 (x0 2)];BYTE* pTR bits[info_src.bmWidthBytes * y0 (x1 2)];BYTE* pBL bits[info_src.bmWidthBytes * y1 (x0 2)];BYTE* pBR bits[info_src.bmWidthBytes * y1 (x1 2)];BYTE* pTarget ((BYTE*)info_dst.bmBits)[info_dst.bmWidthBytes * y (x 2)];fR srcX - x0;fB srcY - y0;fL (1.0f - fR);fT (1.0f - fB);fTL fL * fT;fTR fR * fT;fBL fL * fB;fBR fR * fB;pTarget[0] (BYTE)(fTL * (float)pTL[0] fTR * (float)pTR[0] fBL * (float)pBL[0] fBR * (float)pBR[0]);pTarget[1] (BYTE)(fTL * (float)pTL[1] fTR * (float)pTR[1] fBL * (float)pBL[1] fBR * (float)pBR[1]);pTarget[2] (BYTE)(fTL * (float)pTL[2] fTR * (float)pTR[2] fBL * (float)pBL[2] fBR * (float)pBR[2]);pTarget[3] (BYTE)(fTL * (float)pTL[3] fTR * (float)pTR[3] fBL * (float)pBL[3] fBR * (float)pBR[3]);}int x_src srcWidth - 1;int y_src (int)y * rateY;BYTE* src bits[info_src.bmWidthBytes * y_src (x_src 2)];BYTE* target ((BYTE*)info_dst.bmBits)[info_dst.bmWidthBytes * y ((dstWidth - 1) 2)];target[0] src[0];target[1] src[1];target[2] src[2];target[3] src[3];}for (int x_dst 0; x_dst dstWidth; x_dst) {int x_src (int)x_dst * rateX;BYTE* src bits[info_src.bmWidthBytes * (srcHeight-1) (x_src 2)];BYTE* target ((BYTE*)info_dst.bmBits)[info_dst.bmWidthBytes * (dstHeight-1)(x_dst 2)];target[0] src[0];target[1] src[1];target[2] src[2];target[3] src[3];}return true;
} 解决方案二 在计算rateX、rateY时额外减去0.0001让rateX、rateY的截断全部是向下截断没有向上截断。 float rateX (float)(srcWidth -1 - 0.0001) / (float)(dstWidth - 1); float rateY (float)(srcHeight -1 - 0.0001) / (float)(dstHeight - 1); 这种方法巧妙利用在行尾与最后一行权重fBL、fBR约等于1.0从而避免特别处理行尾与最后一行。
BOOL hbmp_stretch_Bilinear(HBITMAP hbmp_dst, HBITMAP hbmp_src)
{BITMAP info_src, info_dst;GetObject(hbmp_src, sizeof(BITMAP), info_src);GetObject(hbmp_dst, sizeof(BITMAP), info_dst);int srcWidth info_src.bmWidth;int srcHeight info_src.bmHeight;int dstWidth info_dst.bmWidth; // 新的图像宽度int dstHeight info_dst.bmHeight; // 新的图像高度float rateX (float)(srcWidth - 1 - 0.0001) / (float)(dstWidth - 1);float rateY (float)(srcHeight - 1 - 0.0001) / (float)(dstHeight - 1);BYTE* bits (BYTE*)info_src.bmBits;float srcX, srcY;int x0, x1, y0, y1;int x, y;float fL, fR, fT, fB, fTL, fTR, fBL, fBR;for (y 0; y dstHeight; y) {for (x 0; x dstWidth; x) {srcX (float)x * rateX;srcY (float)y * rateY;x0 (int)srcX;y0 (int)srcY;x1 x0 1;y1 y0 1;BYTE* pTL bits[info_src.bmWidthBytes * y0 (x0 2)];BYTE* pTR bits[info_src.bmWidthBytes * y0 (x1 2)];BYTE* pBL bits[info_src.bmWidthBytes * y1 (x0 2)];BYTE* pBR bits[info_src.bmWidthBytes * y1 (x1 2)];BYTE* pTarget ((BYTE*)info_dst.bmBits)[info_dst.bmWidthBytes * y (x 2)];fR srcX - x0;fB srcY - y0;fL (1.0f - fR);fT (1.0f - fB);fTL fL * fT;fTR fR * fT;fBL fL * fB;fBR fR * fB;pTarget[0] (BYTE)(fTL * (float)pTL[0] fTR * (float)pTR[0] fBL * (float)pBL[0] fBR * (float)pBR[0]);pTarget[1] (BYTE)(fTL * (float)pTL[1] fTR * (float)pTR[1] fBL * (float)pBL[1] fBR * (float)pBR[1]);pTarget[2] (BYTE)(fTL * (float)pTL[2] fTR * (float)pTR[2] fBL * (float)pBL[2] fBR * (float)pBR[2]);pTarget[3] (BYTE)(fTL * (float)pTL[3] fTR * (float)pTR[3] fBL * (float)pBL[3] fBR * (float)pBR[3]);}}return true;
}