📄 dib.cpp
字号:
// DIB.cpp: implementation of the DIB class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "DIB.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
///////////////////////////////我的定义///////////////////////////////////
#define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
#define WIDTHBYTES(bits) ((((bits) + 31)>>5)<<2)
#define IS_WIN30_DIB(lpbi) ((*(LPDWORD)(lpbi)) == sizeof(BITMAPINFOHEADER))
struct DIBINFO : public BITMAPINFO
{
RGBQUAD arColors[255]; // Color table info - adds an extra 255 entries to palette
operator LPBITMAPINFO() { return (LPBITMAPINFO) this; }
operator LPBITMAPINFOHEADER() { return &bmiHeader; }
RGBQUAD* ColorTable() { return bmiColors; }
};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
DIB::DIB()
{
}
DIB::~DIB()
{
}
/**************************************************************************************
函数名:
SaveDIBToFile 保存DIB到文件
参数:
LPSTR hDib 指向DIB数据的指针,(BYTE)
LPCTSTR szFileName 文件全名,(包括路径)
返回值:
失败返回 FALSE 否则 返回 TRUE
**************************************************************************************/
BOOL DIB::SaveDIBToFile(LPSTR hDib)
{
// CFileDialog FileDlg(FALSE,_T("BMP"),_T("*.bmp"),OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,_T("*.bmp|*.bmp|*.*|*.*|"));
// if(FileDlg.DoModal()!=IDOK)
// return FALSE;
// LPCTSTR szFileName=(LPCTSTR)FileDlg.GetPathName();
HANDLE ghFile=NULL;
BOOL bResult=FALSE;
// Bitmap文件头
BITMAPFILEHEADER bmfHdr;
// 指向BITMAPINFOHEADER的指针
LPBITMAPINFOHEADER lpBI=NULL;
// DIB大小
DWORD dwDIBSize=0;
DWORD dwBytes=0;
if (hDib == NULL)
{
return FALSE;
}
// 读取BITMAPINFO结构,并锁定
lpBI=(LPBITMAPINFOHEADER)hDib;
if (lpBI == NULL)
{
return FALSE;
}
// 判断是否是WIN3.0 DIB
if (!IS_WIN30_DIB(lpBI))
{
// 返回FALSE
return FALSE;
}
// 文件类型"BM"
bmfHdr.bfType = DIB_HEADER_MARKER;
// 文件头大小+颜色表大小
// (BITMAPINFOHEADER和BITMAPCOREHEADER结构的第一个DWORD都是该结构的大小)
dwDIBSize = *(LPDWORD)lpBI + 0;//最后参数0表示是24位位图无调色板
// 计算图像大小
// 象素的大小
DWORD dwBmBitsSize;
// 大小为Width * Height
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;
// 计算出DIB真正的大小
dwDIBSize += dwBmBitsSize;
// 更新biSizeImage(很多BMP文件头中biSizeImage的值是错误的,对于24位位图来说,这里也可以为0)
lpBI->biSizeImage = dwBmBitsSize;
// 计算文件大小:DIB大小+BITMAPFILEHEADER结构大小
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
// 两个保留字
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
// 计算偏移量bfOffBits,它的大小为Bitmap文件头大小+DIB头大小+颜色表大小
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize
+ 0;//最后参数0表示是24位位图无调色板
//打开文件
ghFile=CreateFile(szFileName, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (ghFile==INVALID_HANDLE_VALUE)
{
//NKDbgPrintfW(_T("save dib to file fail. \r\n"));
return FALSE;
}
//写文件头
bResult=WriteFile(ghFile,(LPSTR)&bmfHdr,sizeof(BITMAPFILEHEADER),&dwBytes,NULL);
ASSERT(bResult!=FALSE);
// 写DIB头和象素
bResult=WriteFile(ghFile,(LPSTR)lpBI,dwDIBSize,&dwBytes,NULL);
ASSERT(bResult!=FALSE);
CloseHandle(ghFile);
// 返回TRUE
return TRUE;
}
/**************************************************************************************
函数名:
GettingBits 通过图像句柄得到DIB图像数据
参数:
HBITMAP hSourceBitmap 图像句柄
返回值:
LPSTR lpDIB DIB 指针
说明: 源句柄需要在函数外部删除。
**************************************************************************************/
LPSTR DIB::GettingBits(HBITMAP hSourceBitmap)
{
LPSTR lpDIB=NULL;
//1. Initialize source bitmap. For example load from resources.
//HBITMAP hSourceBitmap = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP1));
//2. Getting bimap size.
BITMAP bm;
GetObject(hSourceBitmap, sizeof(BITMAP), &bm);
lpDIB=(LPSTR)LocalAlloc(LPTR,bm.bmHeight*WIDTHBYTES(bm.bmWidth*24)+40);
if(lpDIB==NULL)
{
return NULL;
}
//3. Creating new bitmap and receive pointer to it's bits.
HBITMAP hTargetBitmap;
void *pBuffer;
//3.1 Initilize DIBINFO structure
DIBINFO dibInfo;
dibInfo.bmiHeader.biBitCount = 24;
dibInfo.bmiHeader.biClrImportant = 0;
dibInfo.bmiHeader.biClrUsed = 0;
dibInfo.bmiHeader.biCompression = 0;
dibInfo.bmiHeader.biHeight = bm.bmHeight;
dibInfo.bmiHeader.biPlanes = 1;
dibInfo.bmiHeader.biSize = 40;
dibInfo.bmiHeader.biSizeImage = WIDTHBYTES(bm.bmWidth*24)*bm.bmHeight;
dibInfo.bmiHeader.biWidth = bm.bmWidth;
dibInfo.bmiHeader.biXPelsPerMeter = 3780;
dibInfo.bmiHeader.biYPelsPerMeter = 3780;
dibInfo.bmiColors[0].rgbBlue = 0;
dibInfo.bmiColors[0].rgbGreen = 0;
dibInfo.bmiColors[0].rgbRed = 0;
dibInfo.bmiColors[0].rgbReserved = 0;
//3.2 Create bitmap and receive pointer to points into pBuffer
HDC hDC = ::GetDC(NULL);
ASSERT(hDC);
hTargetBitmap = CreateDIBSection(
hDC,
(const BITMAPINFO*)dibInfo,
DIB_RGB_COLORS,
(void**)&pBuffer,
NULL,
0);
::ReleaseDC(NULL, hDC);
//4. Copy source bitmap into the target bitmap.
//4.1 Create 2 device contexts
HDC memDc;
memDc=CreateCompatibleDC(NULL);
ASSERT(memDc!=NULL);
HDC targetDc;
targetDc=CreateCompatibleDC(NULL);
ASSERT(targetDc!=NULL);
//4.2 Select source bitmap into one DC, target into another
HBITMAP hOldBitmap1 = (HBITMAP)::SelectObject(memDc, hSourceBitmap);
HBITMAP hOldBitmap2 = (HBITMAP)::SelectObject(targetDc, hTargetBitmap);
//4.3 Copy source bitmap into the target one
BitBlt(targetDc,0, 0, bm.bmWidth, bm.bmHeight, memDc, 0, 0, SRCCOPY);
//4.4 Restore device contexts
::SelectObject(memDc, hOldBitmap1);
::SelectObject(targetDc, hOldBitmap2);
DeleteDC(memDc);
DeleteDC(targetDc);
//Here we can bitmap bits: pBuffer. Note:
// 1. pBuffer contains 3 bytes per point
// 2. Lines ane from the bottom to the top!
// 3. Points in the line are from the left to the right
// 4. Bytes in one point are BGR (blue, green, red) not RGB
// 5. Don't delete pBuffer, it will be automatically deleted
// when delete hTargetBitmap
LPSTR lptmp=lpDIB;
CopyMemory(lptmp,&dibInfo.bmiHeader,40);
lptmp+=40;
CopyMemory(lptmp,pBuffer,dibInfo.bmiHeader.biSizeImage);
// DeleteObject(hSourceBitmap);
DeleteObject(hTargetBitmap);
return lpDIB;
}
//CopyScreenToDIB,直接转换为DIB数据
HBITMAP DIB::CopyScreenToBitmap(HWND hPic, LPRECT lpRect)
{
int nWidth, nHeight;
HDC hScrDC;
HDC hMemDC;
// 屏幕和内存设备描述表
HBITMAP 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);
//这里如果使用DISPLAY设备DC的话
//也许会更有趣:)。
hScrDC = GetDC(hPic);
//为屏幕设备描述表创建兼容的内存设备描述表
hMemDC = CreateCompatibleDC(hScrDC);
// 获得选定区域坐标
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;
// 获得屏幕分辨率
RECT rc1;
GetWindowRect(hPic,&rc1);
// xScrn = GetDeviceCaps(hScrDC, HORZRES);
xScrn=rc1.right-rc1.left;
// yScrn = GetDeviceCaps(hScrDC, VERTRES);
yScrn=rc1.bottom-rc1.top;
//确保选定区域是可见的
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);
//清除
ReleaseDC(hPic,hScrDC);
DeleteDC(hMemDC);
// 返回位图句柄
return hBitmap;
}
///////////////////////////////////////////////////////////////////
HBITMAP DIB::DIBLoaditmap()
{
CString lpszFileName;
HBITMAP hBitmap;
TCHAR szFileter[] = _T("BMP Files(*.BMP)|*.BMP||*.* Files(*.*)|*.*||");
CFileDialog FileDlg(TRUE,NULL,NULL,OFN_HIDEREADONLY,szFileter);
if(FileDlg.DoModal()!=IDOK)
return NULL;
lpszFileName=FileDlg.GetPathName();
DeleteObject(hBitmap);
hBitmap=SHLoadDIBitmap(lpszFileName);
return hBitmap;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -