RGB565图像的插值

asddg67 2008-12-18 01:47:38
我有转换完的RGB565的数据,大小是200*200, 我想转换成300*300, 我用了最简单的临近插值算法, 不知道为什么转换的过程会报错? 有经验的大侠指点一下



BOOL CXXX::Scale(LPBYTE lpbyBitsSrc32, int x, int y, int nWidth, int nHeight, int nScanWidth, int nScanHeight, LPBYTE lpbyBitsDst32, int nWidthImgDst, int nHeightImgDst)
{
//有效区域的宽度和高度
int w = min(nWidth, nScanWidth - x);
int h = min(nHeight, nScanHeight - y);

//宽度缩放比
float fScalex = (float)w / (float)nWidthImgDst;
float fScaley = (float)h / (float)nHeightImgDst;

//行字节数
DWORD dwWidthBytes = (DWORD)nScanWidth * 2;
//开始数据基索引
DWORD dwBaseIndex = y * dwWidthBytes + 2 * x;


//指向目标数据
BYTE* pbyDst = lpbyBitsDst32;

//完成变换
for(int i = 0; i < nHeightImgDst;i++)
{
//反向变换后获得的浮点y值
float fYInverse = i * fScaley;
//取整
int yy = (int)fYInverse;

//坐标差值
float fv = fYInverse - yy;

//对应于原图像的y坐标
yy += y;

BYTE* pbySrc = lpbyBitsSrc32 + yy * dwWidthBytes;

for(int j = 0;j < nWidthImgDst;j++)
{
//反向变换后获得的浮点x值
float fXInverse = j * fScalex;
//取整
int xx = (int)fXInverse;

//坐标差值
float fu = fXInverse - xx;

//对应于原图像的y坐标
xx += x;

//获取数据
BYTE* pbyCurrent = pbySrc + 2 * xx;
PIXELCOLORRGB rgb = Interpolate(pbyCurrent, xx, yy, fu, fv, nScanWidth, nScanHeight);

*pbyDst++ = rgb.blue;
*pbyDst++ = rgb.green;
*pbyDst++ = rgb.red;
//alpha数据由外部填充.
pbyDst++;
}
}
return TRUE;
}


PIXELCOLORRGB CXXX::Interpolate(LPBYTE lpbySrcXY, int x, int y, float fu, float fv, int nScanWidth, int nScanHeight)
{
PIXELCOLORRGB rgb;

//行字节数, 可以将dwWidthBytes作为参数传递过来
DWORD dwWidthBytes = (DWORD)nScanWidth * 2;

BYTE* pbySrc = lpbySrcXY;
rgb.blue = *pbySrc++;
rgb.green = *pbySrc++;
rgb.red = *pbySrc++;

return rgb;
}

...全文
315 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
evenklm 2009-02-01
  • 打赏
  • 举报
回复
大侠,我想请你帮帮忙,方便把你的转换好的rgb565的图片给我发一份,多谢了,或者给我发一份转换的算法,那个简单的去掉末尾几位的算法失真太大了,多谢了。
我的邮箱:evenklm@gmail.com

有空一定给我发一份阿,谢谢了。
evenklm 2009-02-01
  • 打赏
  • 举报
回复
大侠,我想请你帮帮忙,方便把你的转换好的rgb565的图片给我发一份,多谢了,或者给我发一份转换的算法,那个简单的去掉末尾几位的算法失真太大了,多谢了。
我的邮箱:evenklm@gmail.com

有空一定给我发一份阿,谢谢了。
ilovedrv 2008-12-19
  • 打赏
  • 举报
回复
看FreeImage源代码,FreeImage_Rescale函数的实现,支持8,16,24,32等格式,算法有几种,你可以测试下

DLL_API FIBITMAP * DLL_CALLCONV FreeImage_Rescale(FIBITMAP *dib, int dst_width, int dst_height, FREE_IMAGE_FILTER filter);


http://freeimage.sourceforge.net/

另外可以参考这篇论文

C code to zoom raster images up or down, with nice filtering.

http://www-2.cs.cmu.edu/afs/cs.cmu.edu/Web/People/ph/src/zoom/

freeimage 好像就是参考这个实现的

cnzdgs 2008-12-18
  • 打赏
  • 举报
回复
按你目前的插值方法,把
PIXELCOLORRGB rgb = Interpolate(pbyCurrent, xx, yy, fu, fv, nScanWidth, nScanHeight);

*pbyDst++ = rgb.blue;
*pbyDst++ = rgb.green;
*pbyDst++ = rgb.red;
//alpha数据由外部填充.
pbyDst++;
改成
*(PWORD)pbyDst = *(PWORD)pbyCurrent;
pbyDst += 2;
就可以了。
另外,DIB数据是从下到上储存的,要用高度减去y来计算数据位置,按目前的做法,获取的图象区域是不对的,不过对整个图象处理不会体现出问题。
asddg67 2008-12-18
  • 打赏
  • 举报
回复
StretchBlt/StretchDIBits效率不是很高...
如何是16为到16位,上面的程序该如何修改呢? 我是第一次搞这个,还请多多指教
cnzdgs 2008-12-18
  • 打赏
  • 举报
回复
16位到16位,如果只是复制颜色,直接按WORD赋值就可以了。
另外,如果只是为了放大显示,可以用StretchBlt/StretchDIBits来显示,效果也比较好。
asddg67 2008-12-18
  • 打赏
  • 举报
回复
还是16位到16为的转换
asddg67 2008-12-18
  • 打赏
  • 举报
回复
我是RGB565的原始数据,我将图像直接写到屏幕上是正确的,只不过图像有点小,所以想做个插值进行放大

RGB565的数据为uint8_t格式的
cnzdgs 2008-12-18
  • 打赏
  • 举报
回复
如果是16位到16位,或者32位到32位,直接赋值就可以。
如果是16位到32位
WORD w = *(PWORD)pbySrc;
rgb.red = (w & 0x1f);
rgb.green = ((w >> 5) & 0x3f);
rgb.blue = ((w >> 11) & 0x1f);
顺序我记不清了,可能red和blue要对调一下。32位到16位就是把上面的做法反过来。
cnzdgs 2008-12-18
  • 打赏
  • 举报
回复
主要问题就是我前面提的,你把16位色按照32位来处理了。另外,DIB数据是从下到上储存的,要用高度减去y来计算数据位置。
asddg67 2008-12-18
  • 打赏
  • 举报
回复
有人做过相关的吗?
ringphone 2008-12-18
  • 打赏
  • 举报
回复
越界了吧?都没看到你代码里有边界检查。
asddg67 2008-12-18
  • 打赏
  • 举报
回复
//lpbyBitsSrc32----传递源像素值,
//x, y, nWidth, nHeight, 定义区域的宽度
//nScanWidth, nScanHeight, 扫描宽度和扫描高度
//lpbyBitsDst32----存放最后缩放后的结果
//nWidthImgDst, nHeightImgDst缩放至多大

BOOL CImageGeometry::Scale(LPBYTE lpbyBitsSrc32, int x, int y, int nWidth, int nHeight, int nScanWidth, int nScanHeight, LPBYTE lpbyBitsDst32, int nWidthImgDst, int nHeightImgDst)


///lpbySrcXY----传递源像素(x, y)的地址,
//x, y, 经过反向变换后得到的对应于原图像的象点的坐标
//nScanWidth, int nScanHeight, 源扫描宽度和扫描高度
PIXELCOLORRGB CImageGeometry::Interpolate(LPBYTE lpbySrcXY, int x, int y, float fu, float fv, int nScanWidth, int nScanHeight)
cnzdgs 2008-12-18
  • 打赏
  • 举报
回复
函数的各个参数都是什么含义?
565是用16位(两个字节)来储存RGB颜色,分别占5、6、5位,而你的代码是按32位色来处理的。

16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧