请教一个简单的位图尺寸变换的方法。

dracoo 2004-10-25 05:45:07
从数据库中取出BMP图像的数据存为BYTE数组类型,然后希望进行尺寸变换后,依旧返回BYTE数组类型的值,写入数据库。只知道要先转换成CBitmap类型、CDC类型,进行StretchBlt变换,但具体的做法不清楚,时间紧迫,就请熟手帮一下忙了。
...全文
141 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
dracoo 2004-10-29
  • 打赏
  • 举报
回复
这是一个完整的单色位图缩放函数,lpIn和lpOut是指向BYTE[]类型的源位图数据和输出位图数据的指针,位图数据必须去掉头部信息。我用它做出的缩放位图效果还不错,但在缩小图像时,容易忽略细节,大家可以研究一下。

#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4) // for padding

void CLshotCtrl::ResizeMonoBmp( int inWidth, int inHeight, LPCVOID lpIn,
int outWidth, int outHeight, LPVOID lpOut)
{
BOOL hstretch, vstretch;
int nBytesRowSrc, nBytesSrc;
int nBytesRowDst, nBytesDst;
int xinc, xoff, xsrc, xdst;
int yinc, ysrc, ydst;
LPBYTE lpRowSrc, lpRowDst;

hstretch = (inWidth < outWidth);
vstretch = (inHeight < outHeight);
nBytesRowSrc = WIDTHBYTES(inWidth);
nBytesSrc = nBytesRowSrc * inHeight;
nBytesRowDst = WIDTHBYTES(outWidth);
nBytesDst = nBytesRowDst * outHeight;

if(inWidth != outWidth || inHeight != outHeight) {
memset(lpOut, 0, nBytesDst);

if(hstretch) {
xinc = (inWidth << 16) / outWidth;
xoff = ((inWidth << 16) - (xinc * outWidth)) / 2;
} else {
xinc = (outWidth << 16) / inWidth;
xoff = ((outWidth << 16) - (xinc * inWidth)) / 2;
}

if(vstretch) {
yinc = ((int)inHeight << 16) / outHeight;
ysrc = ((inHeight << 16) - (yinc * outHeight)) / 2;
for(ydst = 0; ydst < outHeight; ysrc += yinc, ydst++) {
lpRowSrc = (LPBYTE)lpIn + nBytesRowSrc * (ysrc >> 16);
lpRowDst = (LPBYTE)lpOut + nBytesRowDst * ydst;
if(hstretch) {
xsrc = xoff;
for(xdst = 0; xdst < outWidth; xsrc += xinc, xdst++)
lpRowDst[xdst >> 3] |=
((lpRowSrc[(xsrc >> 16) >> 3] >> (7 - ((xsrc >> 16) % 8))) & 0x01) << (7 - (xdst % 8));
} else {
xdst = xoff;
for(xsrc = 0; xsrc < inWidth; xsrc++, xdst += xinc)
lpRowDst[(xdst >> 16) >> 3] |=
((lpRowSrc[xsrc >> 3] >> (7 - (xsrc % 8))) & 0x01) << (7 - ((xdst >> 16) % 8));
}
}
} else {
yinc = ((int)outHeight << 16) / inHeight;
ydst = ((outHeight << 16) - (yinc * inHeight)) / 2;
for(ysrc = 0; ysrc < inHeight; ysrc++, ydst += yinc) {
lpRowSrc = (LPBYTE)lpIn + nBytesRowSrc * ysrc;
lpRowDst = (LPBYTE)lpOut + nBytesRowDst * (ydst >> 16);
if(hstretch) {
xsrc = xoff;
for(xdst = 0; xdst < outWidth; xsrc += xinc, xdst++)
lpRowDst[xdst >> 3] |=
((lpRowSrc[(xsrc >> 16) >> 3] >> (7 - ((xsrc >> 16) % 8))) & 0x01) << (7 - (xdst % 8));
} else {
xdst = xoff;
for(xsrc = 0; xsrc < inWidth; xsrc++, xdst += xinc)
lpRowDst[(xdst >> 16) >> 3] |=
((lpRowSrc[xsrc >> 3] >> (7 - (xsrc % 8))) & 0x01) << (7 - ((xdst >> 16) % 8));
}
}
}
} else
memcpy(lpOut, lpIn, nBytesDst);

return;
}
dracoo 2004-10-26
  • 打赏
  • 举报
回复
其中的WIDTHBYTES()函数做怎样计算?
dracoo 2004-10-26
  • 打赏
  • 举报
回复
问puhuofeie:你的这个函数只能处理256色和24位真彩吗,对于单色位图,也能处理吗?
agua06 2004-10-26
  • 打赏
  • 举报
回复
mark!
学习一下!
酒红绿叶 2004-10-26
  • 打赏
  • 举报
回复
void Geom_Zoom( BYTE *lpDIBBits,BYTE *lpNewDIBBits,long lWidth,long lHeight,
long lNewWidth,long lNewHeight ,int color)
{

//lpDIBBits 为输入源图.lpNewDIBBits为缩放后的图片,color为判断图片色彩
//的标志。为0是256灰度,为1是24位RGB。
double dZoom;

long i,j;
long lNewLineBytes; // 缩放后图像的宽度(lNewWidth',必须是4的倍数)

BYTE * lpSrc;// 指向源象素的指针
BYTE * lpDst;// 指向缩放图像对应象素的指针

long i0; // 象素在源DIB中的坐标
long j0;

long lLineBytes;// 图像每行的字节数

lLineBytes = WIDTHBYTES(8*lWidth);

dZoom = ((lNewWidth*1.0)/lWidth);

if( color == 0 )
{//256灰度缩放
lNewLineBytes = WIDTHBYTES(lNewWidth * 8);

// 针对图像每行进行操作
for(i = 0; i < lNewHeight; i++)
{
// 针对图像每列进行操作
for(j = 0; j < lNewWidth; j++)
{
lpDst = (BYTE *)lpNewDIBBits + lNewLineBytes * (lNewHeight - 1 - i) + j;

// 计算该象素在源DIB中的坐标
i0 = (long) (i / dZoom + 0.5);
j0 = (long) (j / dZoom + 0.5);

// 判断是否在源图范围内
if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight))
{

// 指向源DIB第i0行,第j0个象素的指针
lpSrc = (BYTE *)lpDIBBits + lLineBytes * (lHeight - 1 - i0) + j0;

// 复制象素
*lpDst = *lpSrc;

}
else
{
// 对于源图中没有的象素,直接赋值为255
* ((BYTE*)lpDst) = 255;
}
}
}
}
else if( color == 1 )
{//24位真彩色缩放

lNewLineBytes = WIDTHBYTES(lNewWidth*8);
long lNewLineByte2 = WIDTHBYTES(lNewWidth*24);

lLineBytes = WIDTHBYTES(8*lWidth);
long lLineBytes2 = WIDTHBYTES(lWidth*24);


// 针对图像每行进行操作
for(i = 0; i < lNewHeight; i++)
{
// 针对图像每列进行操作
for(j = 0; j < lNewWidth; j++)
{
lpDst = (BYTE *)lpNewDIBBits + lNewLineByte2 * (lNewHeight - 1 - i) + j*3;


// 计算该象素在源DIB中的坐标
i0 = (long) (i / dZoom + 0.5);
j0 = (long) (j / dZoom + 0.5);

// 判断是否在源图范围内
if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight))
{

// 指向源DIB第i0行,第j0个象素的指针
lpSrc = (BYTE *)lpDIBBits + (lLineBytes2 * (lHeight - 1 - i0) + 3*j0);
*(lpDst+0) = *(lpSrc+0);
*(lpDst+1) = *(lpSrc+1);
*(lpDst+2) = *(lpSrc+2);


}
else
{
*(lpDst+0) = 255;
*(lpDst+1) = 255;
*(lpDst+2) = 255;
// 对于源图中没有的象素,直接赋值为255

}
}
}

}


}


我自己写的。
酒红绿叶 2004-10-26
  • 打赏
  • 举报
回复
你通过数据进行变换,
不用DDB,而用DIB,完全使用数据,就可以了。
就是你读入图片是一个指针
lpDIBBIts
你可以把变化后的图片存入另一个指针。
lpNewDIBBits,
就可以了。

dracoo 2004-10-26
  • 打赏
  • 举报
回复
还有人有好的建议吗,我现在就是不知怎样读取StretchBlt变换后的位图数据,保存为BYTE数组。
其实并不要很复杂的处理,对图像质量的要求也不高。
DentistryDoctor 2004-10-25
  • 打赏
  • 举报
回复
CDC * pDC = CWnd::GetDesktopWindow()->GetDC();
ZeroMemory(pbminfo, sizeof BITMAPINFOHEADER);
pbminfo->biSize = sizeof BITMAPINFOHEADER;
pbminfo->biWidth =m_pFmt->biWidth;
pbminfo->biHeight = abs(m_pFmt->biHeight);
pbminfo->biPlanes = 1;
pbminfo->biBitCount = 24;
pbminfo->biCompression = BI_RGB;
pbminfo->biSizeImage = (3*pbminfo->biWidth+3)/4*4*abs(pbminfo->biHeight);
HBITMAP hBmp = CreateDIBSection(pDC->GetSafeHdc(), (BITMAPINFO*) pbminfo, DIB_RGB_COLORS, ppBits, NULL, 0);
if (hBmp)
{
if (pbminfo->biWidth == m_pFmt->biWidth && pbminfo->biHeight == abs(m_pFmt->biHeight))
{
SetDIBits(pDC->GetSafeHdc(), hBmp, 0, pbminfo->biHeight,bufDest.GetData(), (BITMAPINFO*) m_pFmt, DIB_RGB_COLORS);
}
else
{
//StretchDIBits变换尺寸
CDC dcMem;
dcMem.CreateCompatibleDC(pDC);
CBitmap * pSave = dcMem.SelectObject(CBitmap::FromHandle(hBmp));
StretchDIBits(dcMem.GetSafeHdc(), 0, 0, pbminfo->biWidth, pbminfo->biHeight,0, 0, m_pFmt->biWidth, abs(m_pFmt->biHeight),bufDest.GetData(), (BITMAPINFO*) m_pFmt, DIB_RGB_COLORS, SRCCOPY);
dcMem.SelectObject(pSave);
}
}
CWnd::GetDesktopWindow()->ReleaseDC(pDC);

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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