图形学的几个非常有用的转换

简介:

1:将指定区域保存为位图信息,此区域如果从控件得到的dc而来,可以对指定控件抓图
HBITMAP CopyScreenToBitmap(LPRECT lpRect)
//lpRect 代表选定区域
{
HDC hScrDC, hMemDC;
// 屏幕和内存设备描述表
HBITMAP hBitmap, hOldBitmap; 
// 位图句柄
int nX, nY, nX2, nY2; 
// 选定区域坐标
int nWidth, nHeight;
// 位图宽度和高度
int xScrn, yScrn; 
// 屏幕分辨率
// 确保选定区域不为空矩形
if (IsRectEmpty(lpRect))
return NULL;
//为屏幕创建设备描述表
hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
//为屏幕设备描述表创建兼容的内存设备描述表
hMemDC = CreateCompatibleDC(hScrDC);
// 获得选定区域坐标
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;
// 获得屏幕分辨率
xScrn = GetDeviceCaps(hScrDC, HORZRES);
yScrn = GetDeviceCaps(hScrDC, VERTRES);
//确保选定区域是可见的
if (nX <0)
nX = 0;
if (nY<0)
nY = 0;
if (nX2 > xScrn)
nX2 = xScrn;
if (nY2 > yScrn)
nY2 = yScrn;
nWidth = nX2 - nX;
nHeight = nY2 - nY;
// 创建一个与屏幕设备描述表兼容的位图
hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);
// 把新位图选到内存设备描述表中
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
// 把屏幕设备描述表拷贝到内存设备描述表中
BitBlt(hMemDC, 0, 0, nWidth, nHeight,hScrDC, nX, nY, SRCCOPY);
//得到屏幕位图的句柄
hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
//清除 
DeleteDC(hScrDC);
DeleteDC(hMemDC);
// 返回位图句柄
return hBitmap;
}
2:对上面的延伸,将一个位图结构保存为文件

BOOL SaveBmp(HBITMAP hBitmap, CString FileName)
{
HDC hDC;
int iBits;
WORD wBitCount;
DWORD dwPaletteSize=0, dwBmBitsSize=0, dwDIBSize=0, dwWritten=0; 
BITMAP Bitmap; 
BITMAPFILEHEADER bmfHdr; 
BITMAPINFOHEADER bi; 
LPBITMAPINFOHEADER lpbi; 
HANDLE fh, hDib, hPal,hOldPal=NULL; 

hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); 
DeleteDC(hDC); 
if (iBits <= 1) wBitCount = 1; 
else if (iBits <= 4) wBitCount = 4; 
else if (iBits <= 8) wBitCount = 8; 
else wBitCount = 24; 

GetObject(hBitmap, sizeof(Bitmap), (LPSTR)&Bitmap);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = Bitmap.bmWidth;
bi.biHeight = Bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrImportant = 0;
bi.biClrUsed = 0;

dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;

hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER)); 
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); 
*lpbi = bi; 

hPal = GetStockObject(DEFAULT_PALETTE); 
if (hPal) 

hDC = ::GetDC(NULL); 
hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE); 
RealizePalette(hDC); 
}

GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER) 
+dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS); 

if (hOldPal) 

::SelectPalette(hDC, (HPALETTE)hOldPal, TRUE); 
RealizePalette(hDC); 
::ReleaseDC(NULL, hDC); 


fh = CreateFile(FileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS, 
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); 

if (fh == INVALID_HANDLE_VALUE) return FALSE; 

bmfHdr.bfType = 0x4D42; // "BM" 
dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize; 
bmfHdr.bfSize = dwDIBSize; 
bmfHdr.bfReserved1 = 0; 
bmfHdr.bfReserved2 = 0; 
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize; 

WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); 
WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL); 

GlobalUnlock(hDib); 
GlobalFree(hDib); 
CloseHandle(fh); 

return TRUE;
}

3:也是对1的延伸,将位图结构转为ipl,作为Opencv处理的接口

int stride = (width * sizeof( RGBTRIPLE ) + 3) & -4;
cvInitImageHeader( &ds_frame, cvSize(width, height), 8, 3,IPL_ORIGIN_BL, 4 );
ds_frame.widthStep = stride; 
cvSetData( &ds_frame, myBuffer, stride ); 

4:和上面的相反,将IPL转换为bitmap

IplImage* VideoResizeframe = NULL; 
CDC *pDC;
CRect rect;
BITMAPINFO bmi;
pDC = ((CPCSDlg*)AfxGetMainWnd())->m_VideoPreview.GetDC(); 
((CPCSDlg*)AfxGetMainWnd())->m_VideoPreview.GetWindowRect(rect);
VideoResizeframe = cvCreateImage(cvSize(rect.Width(), rect.Height()), IPL_DEPTH_8U,3);
cvResize(pFrame, VideoResizeframe, CV_INTER_LINEAR ); 
MYFillBitmapInfo(&bmi,VideoResizeframe->width,VideoResizeframe->height,(VideoResizeframe->depth)*(VideoResizeframe->nChannels));
::StretchDIBits(pDC->GetSafeHdc(),-4,-4,VideoResizeframe->width,VideoResizeframe->height,0,0,VideoResizeframe->width,VideoResizeframe->height,VideoResizeframe->imageData,&bmi,DIB_RGB_COLORS,SRCCOPY);
delete &bmi;
((CPCSDlg*)AfxGetMainWnd())->m_VideoPreview.ReleaseDC( pDC );
cvReleaseImage(&VideoResizeframe);

引用到的函数如下:
void MYFillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp )
{
ASSERT( bmi && width > 0 && height > 0 &&
(bpp == 8 || bpp == 24 || bpp == 32) );

BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);

memset( bmih, 0, sizeof(*bmih));
bmih->biSize = sizeof(BITMAPINFOHEADER);
bmih->biWidth = width;
bmih->biHeight = -abs(height);
bmih->biPlanes = 1;
bmih->biBitCount = bpp;
bmih->biCompression = BI_RGB;

if( bpp == 8 )
{
RGBQUAD* palette = bmi->bmiColors;
int i;
for( i = 0; i < 256; i++ )
{
palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
palette[i].rgbReserved = 0;
}
}
}

5:利用ipicture用接口实现vc任意控件上加载图象
HRESULT CDTS32Dlg::ShowPic(char *lpstrFile, HWND hWnd, int nScrWidth, int nScrHeight)
{
HDC hDC_Temp=(FromHandle(hWnd)->GetDC())->GetSafeHdc(); 

IPicture *pPic; 
IStream *pStm; 

BOOL bResult; 

HANDLE hFile=NULL; 
DWORD dwFileSize,dwByteRead; 

//打开硬盘中的图形文件 
hFile=CreateFile(lpstrFile,GENERIC_READ, 
FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); 

if (hFile!=INVALID_HANDLE_VALUE) 

dwFileSize=GetFileSize(hFile,NULL);//获取文件字节数 
if (dwFileSize==0xFFFFFFFF) 
return E_FAIL; 

else 

return E_FAIL; 



//分配全局存储空间 
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize); 
LPVOID pvData = NULL; 

if (hGlobal == NULL) 
return E_FAIL; 

if ((pvData = GlobalLock(hGlobal)) == NULL)//锁定分配内存块 
return E_FAIL; 

ReadFile(hFile,pvData,dwFileSize,&dwByteRead,NULL);//把文件读入内存缓冲区 

GlobalUnlock(hGlobal); 

CreateStreamOnHGlobal(hGlobal, TRUE, &pStm); 

//装入图形文件 
bResult=OleLoadPicture(pStm,dwFileSize,TRUE,IID_IPicture,(LPVOID*)&pPic); 

if(FAILED(bResult)) 
return E_FAIL; 

OLE_XSIZE_HIMETRIC hmWidth;//图片的真实宽度 
OLE_YSIZE_HIMETRIC hmHeight;//图片的真实高度 
pPic->get_Width(&hmWidth); 
pPic->get_Height(&hmHeight); 


//将图形输出到屏幕上(有点像BitBlt) 
bResult=pPic->Render(hDC_Temp,0,0,nScrWidth,nScrHeight, 
0,hmHeight,hmWidth,-hmHeight,NULL); 

pPic->Release(); 

CloseHandle(hFile);//关闭打开的文件 

if (SUCCEEDED(bResult)) 

return S_OK; 

else 

return E_FAIL; 



}

用法:
ShowPic(lpstrFile, GetDlgItem(IDC_STATIC_LOGO)->GetSafeHwnd( ), 90, 105);

 
6: 对1的延伸,将位图信息保存在剪切板 
HBITMAP dest = CopyScreenToBitmap(&Rc);
if (OpenClipboard()) 

EmptyClipboard(); 
SetClipboardData(CF_BITMAP, dest); 
CloseClipboard(); 
}


IplImage* hBitmap2Ipl(HBITMAP hBmp)
{
BITMAP bmp;

::GetObject(hBmp,sizeof(BITMAP),&bmp);

int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel/8 ;
int depth = bmp.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U;

IplImage* img = cvCreateImageHeader( cvSize(bmp.bmWidth, bmp.bmHeight)
, depth, nChannels );

img->imageData =
(char*)malloc(bmp.bmHeight*bmp.bmWidth*nChannels*sizeof(char));
memcpy(img->imageData,(char*)(bmp.bmBits),bmp.bmHeight*bmp.bmWidth*nChannels);

return img;
}


void createDIB(IplImage* &pict){
IplImage * Red=cvCreateImage( cvSize(IMAGE_WIDTH,IMAGE_HEIGHT),
IPL_DEPTH_8U, 1 );
IplImage * Green=cvCreateImage( cvSize(IMAGE_WIDTH,IMAGE_HEIGHT),
IPL_DEPTH_8U, 1 );
IplImage * Blue=cvCreateImage( cvSize(IMAGE_WIDTH,IMAGE_HEIGHT),
IPL_DEPTH_8U, 1 );
cvSetImageCOI( pict, 3);
cvCopy(pict,Red);
cvSetImageCOI( pict, 2);
cvCopy(pict,Green);
cvSetImageCOI(pict, 1);
cvCopy(pict,Blue);
//Initialize the BMP display buffer
bmi = (BITMAPINFO*)buffer;
bmih = &(bmi->bmiHeader);
memset( bmih, 0, sizeof(*bmih));
bmih->biSize = sizeof(BITMAPINFOHEADER);
bmih->biWidth = IMAGE_WIDTH;
bmih->biHeight = IMAGE_HEIGHT; // -IMAGE_HEIGHT;
bmih->biPlanes = 1;
bmih->biCompression = BI_RGB;
bmih->biBitCount = 24;
palette = bmi->bmiColors;
for( int i = 0; i < 256; i++ ){
palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed =
(BYTE)i;
palette[i].rgbReserved = 0;
}
cvReleaseImage(&Red);
cvReleaseImage(&Green);
cvReleaseImage(&Blue);
}


IplImage* hBitmap2Ipl(HBITMAP hBmp)
{
BITMAP bmp; 
::GetObject(hBmp,sizeof(BITMAP),&bmp);

int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel/8 ;
int depth = bmp.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U;


CString t;
t.Format("%d %d %d %d",bmp.bmWidth,bmp.bmHeight,depth,nChannels);
AfxMessageBox(t);


IplImage* img = cvCreateImage(cvSize(bmp.bmWidth,bmp.bmHeight),depth,nChannels); //cvCreateImageHeader
//img->origin = 1;
//img->widthStep = (bmp.bmWidth * sizeof( RGBTRIPLE ) + 3) & -4;


BYTE *pBuffer = new BYTE[bmp.bmHeight*bmp.bmWidth*nChannels]; 
GetBitmapBits(hBmp,bmp.bmHeight*bmp.bmWidth*nChannels,pBuffer); 
//cvSetData(img,(BYTE*)(bmp.bmBits),img->widthStep);
//cvSetData(img,pBuffer,bmp.bmHeight*bmp.bmWidth*nChannels);
memcpy(img->imageData,pBuffer,bmp.bmHeight*bmp.bmWidth*nChannels);
/* IplImage* img = cvCreateImageHeader(cvSize(bmp.bmWidth,bmp.bmHeight),depth,nChannels);
img->imageData = (char*)malloc(bmp.bmHeight*bmp.bmWidth*nChannels*sizeof(char)); 
memcpy(img->imageData,(char*)(bmp.bmBits),bmp.bmHeight*bmp.bmWidth*nChannels);
*/ 

return img;
}


IplImage* hBitmap2Ipl(HBITMAP hBmp)
{
BITMAP bmp; 
::GetObject(hBmp,sizeof(BITMAP),&bmp); 
int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel/8 ;
int depth = bmp.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U; 
IplImage* img = cvCreateImage(cvSize(bmp.bmWidth,bmp.bmHeight),depth,nChannels); //cvCreateImageHeader
BYTE *pBuffer = new BYTE[bmp.bmHeight*bmp.bmWidth*nChannels]; 
GetBitmapBits(hBmp,bmp.bmHeight*bmp.bmWidth*nChannels,pBuffer); 
memcpy(img->imageData,pBuffer,bmp.bmHeight*bmp.bmWidth*nChannels);
delete pBuffer; 
return img;
本文转自博客园知识天地的博客,原文链接: 图形学的几个非常有用的转换,如需转载请自行联系原博主。

相关文章
|
7月前
|
传感器 存储 编解码
即时通讯音视频开发(二十):一文读懂视频的颜色模型转换和色域转换
本文将以通俗易懂的文字,引导你理解视频是如何从采集开始,历经各种步骤,最终通过颜色模型转换和不同的色域转换,让你看到赏心悦目的视频结果的。
34 0
|
机器学习/深度学习
将现实问题转换为编程问题
考虑到一共五个人,直接模拟推理有些太难,计算机最擅长的遍历此时就会派上用场,将每个人从第1到第5来一遍,则一共会产生5^5种可能性,这个只需要一个5层循环即可搞定。但是这样会导致一些不期望出现的结果出现,因为并没有查重,所以会出现两个人抢名次的情况,也就是两个人或者更多的人名次相同的情况,例如两个第二,三个第三这样的,所以即使满足了条件,也要查看一下五个人的名次是否重复,这个交给一个函数来执行,只要五个人名次并列,那就返回0,否则返回1即可。有了这个思路,就能完成以下代码。
75 0
|
存储 机器学习/深度学习 算法
Python 实现LSB算法进行信息隐藏 包含空域与变换域 JPEG信息隐藏算法 对PDF文件进行信息隐藏 基于卷积神经网络的隐写分析 Matlab SRM、SCA隐写分析
Python 实现LSB算法进行信息隐藏 包含空域与变换域 JPEG信息隐藏算法 对PDF文件进行信息隐藏 基于卷积神经网络的隐写分析 Matlab SRM、SCA隐写分析
407 0
Python 实现LSB算法进行信息隐藏 包含空域与变换域 JPEG信息隐藏算法 对PDF文件进行信息隐藏 基于卷积神经网络的隐写分析 Matlab SRM、SCA隐写分析
|
存储 传感器 监控
浅谈移动 GIS (内附主要特征和用途)
浅谈移动 GIS (内附主要特征和用途)
351 0
浅谈移动 GIS (内附主要特征和用途)
|
存储 编译器 Go
基本数据转换细节讨论 | 学习笔记
简介:快速学习基本数据转换细节讨论
59 0
VB编程:利用数组随机抽取幸运观众-32
VB编程:利用数组随机抽取幸运观众-32
|
数据可视化 数据挖掘 图形学
|
vr&ar 图形学
【Unity3D 灵巧小知识点】☀️ | Unity 四元数、欧拉角 与 方向向量 之间转换
Unity 小科普 老规矩,先介绍一下 Unity 的科普小知识: Unity是 实时3D互动内容创作和运营平台 。 包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助 Unity 将创意变成现实。
文字处理技术:形状绕排的难点
文字处理技术:形状绕排的难点
89 0
VB编程:利用数组随机抽取幸运观众
VB编程:利用数组随机抽取幸运观众
239 0