挑战图像高手,如何实现BMP的缩放?
我说的位图缩放是指将一个位图文件first.bmp,按比例n缩放后存入第二个位图文件second.bmp,如n=0.5,second.bmp的大小是原来first.bmp的一半。不是使用StretchBlt实现缩放显示!
请高手指点!
问题点数:100、回复次数:10Top
1 楼HUNTON(追求完美)回复于 2003-09-04 08:52:21 得分 10
如果是要缩放算法的话,可以用图形的四点转正来做,然后再用双线性插值
http://expert.csdn.net/Expert/topic/2077/2077097.xml?temp=.140423
这里有讲。Top
2 楼hhoking(妙手仁心)回复于 2003-09-04 09:07:54 得分 30
这属于最基本的图像变换处理了,基本思路是遍历目标图的每一个像素点,根据比例因子去
计算该点在源图是哪一点,将那一点的像素值存入目标图就行了。
伪代码:
缩放比率:n
目标图:pDst,nDstW(=nSrcW*n),nDstH(=nSrcH*n)
原图:pSrc,nSrcW,nSrcH
for(int j; j<nDstH; j++)
for(int i; i<nDstW; i++)
{
pDst = f(pSrc);
pDst++;
}
至于目标图到源图的对应关系f,我想你应该可以自己推出来了吧。
Top
3 楼npucwj(眸眸)回复于 2003-09-04 09:22:21 得分 0
这样是不是太难了,那位大侠有现成的代码提供?谢谢!Top
4 楼bluebohe(薄荷)回复于 2003-09-04 09:26:23 得分 20
这里有一个处理图形的库啦,你可以研究一下,添加不超过十行代码,应该就能完成你的功能
http://www.vchelp.net/vchelp/file2002_4/flib.asp?type_id=18&class_id=1&cata_id=12&article_id=907Top
5 楼npucwj(眸眸)回复于 2003-09-04 17:26:56 得分 0
up一下。Top
6 楼nonocast(如果没有如果)回复于 2003-09-04 17:30:31 得分 0
CxImage
www.codeproject.com
--------------
May you succeed!
-------------------Top
7 楼dawndu(东南飞)回复于 2003-09-04 22:30:03 得分 10
上面都是高手在论道,都是自己写的算法,小弟是个新人,也发表一下愚见。
StretchBlt是可以实现缩放的,为什么不用它把一个BMP用StretchBlt到一个内存DC中呢,然后再DDBTODIB不就可以了。
不过这个不是算法了,博大家一笑而已Top
8 楼dawndu(东南飞)回复于 2003-09-04 22:38:18 得分 0
楼主要求太高了,如果要我缩放,我就只能这么做了,急切想知道算法啊!Top
9 楼hhoking(妙手仁心)回复于 2003-09-05 09:38:21 得分 0
如果你是想学习的话,就不应该嫌它难。况且我说过,这还只是图像处理的最基本简单的东西。
就是这个简单的缩放变换,也还有可扩展的地方,比如你想得到更好的画质,要用到二次线性插
值。得到非常完美的画质,要用到高阶插值。
当然,如果你要只想简单的得到这样一个效果,用StretchBlt完全可以达到同样的目的。只不过
你要StretchBlt到一个MemDC,然后Bitblt回源DC,这样就得到了新的被缩放过的位图。你保存
的话,一定是新的位图。Top
10 楼rabithao(兔巴哥)回复于 2003-09-05 13:40:51 得分 30
最基本的就是填充或者提取像素:
CShowDibDoc* pDoc = GetDocument();
int horizon;
int vertical;
CScale dlg;
//读取放大或者缩小的比例
if(dlg.DoModal()==IDOK)
{
horizon = dlg.m_horizon;
vertical = dlg.m_vertical;
}
else
{
return ;
}
LPBITMAPINFOHEADER lpbmi;
//BYTE* lpDIBBits;
lpbmi = (LPBITMAPINFOHEADER)GlobalLock((HGLOBAL)pDoc->m_Dib.m_hDIB);
LPSTR lpDIB;
lpDIB = (LPSTR)GlobalLock((HGLOBAL) pDoc->m_Dib.m_hDIB);
unsigned char* lpDIBBits = (unsigned char *)::FindDIBBits(lpDIB);
//lpDIBBits = (BYTE*)(lpbmi + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256);
HANDLE buffer;
LPSTR bufdata;
//分配一块内存,用来存放信息头和调色板
buffer = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, sizeof(BITMAPINFO) + 256*sizeof(RGBQUAD));
bufdata = (LPSTR) GlobalLock((HGLOBAL) buffer);
//将信息头和调色板暂时存放在刚分配的内存中
for(int k=0; k<sizeof(BITMAPINFO) + 256*sizeof(RGBQUAD); k++)
{
*(bufdata + k) = *(lpDIB + k);
}
HANDLE datahandle;
LPSTR data;
int height = lpbmi->biHeight;
int width = lpbmi->biWidth;
int lWidthBytes = WIDTHBYTES(width*8);
//取出图像中原来的数据
datahandle = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, height*lWidthBytes);
data = (LPSTR) GlobalLock((HGLOBAL) datahandle);
for(int i=0; i<height; i++)
{
for(int j=0; j<width; j++)
{
*(data + i*lWidthBytes + j) = *(lpDIBBits + i*lWidthBytes + j);
}
}
int Sheight = height*vertical/100; //缩小后的图像
int Swidth = width*horizon/100;
int lwidthbytes = WIDTHBYTES(Swidth*8);//缩小后的
//释放掉原来的内存快,重新分配内存。
GlobalUnlock((HGLOBAL) pDoc->m_Dib.m_hDIB);
GlobalFree((HGLOBAL) pDoc->m_Dib.m_hDIB);
pDoc->m_Dib.m_hDIB = (HDIB)GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, sizeof(BITMAPINFO) + 256*sizeof(RGBQUAD) + Sheight*lwidthbytes);
lpDIB = (LPSTR)GlobalLock((HGLOBAL) pDoc->m_Dib.m_hDIB);
//将暂存的信息头和调色板重新放到新的内存中。
for(int l=0; l<sizeof(BITMAPINFO) + 256*sizeof(RGBQUAD); l++)
{
*(lpDIB + l) = *(bufdata + l);
}
//调整信息头
lpbmi = (LPBITMAPINFOHEADER)GlobalLock((HGLOBAL)pDoc->m_Dib.m_hDIB);
lpbmi->biSizeImage = (lpbmi->biSizeImage*vertical*horizon)/10000;
//lpbmi->biSize = lpbmi->biSize - (3*height*width/4);
lpbmi->biHeight = Sheight;
lpbmi->biWidth = Swidth;
lpDIBBits = (unsigned char*)::FindDIBBits(lpDIB);
//调整图像, 进行缩放。
for( int a=0; a<Sheight; a++)
{
for(int b=0; b<Swidth; b++)
{
*(lpDIBBits + a*lwidthbytes + b) = *(data + (int)(a*100/vertical)*lWidthBytes + (int)(b*100/horizon));
}
}
pDoc->SetModifiedFlag(TRUE);
GlobalUnlock((HGLOBAL) buffer);
GlobalFree((HGLOBAL) buffer);
GlobalUnlock((HGLOBAL) datahandle);
GlobalFree((HGLOBAL) datahandle);
GlobalUnlock((HGLOBAL) pDoc->m_Dib.m_hDIB);
//OnDoRealize((WPARAM)m_hWnd,0);
OnInitialUpdate();
pDoc->UpdateAllViews(NULL);Top



