📄 dib.cpp
字号:
// DIB.cpp: implementation of the CDIB class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "DPO.h"
#include "DIB.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define WIDTHBYTES(bits) ((bits+31)/32*4)
#define RECTWIDTH(x) (x->right-x->left)
#define RECTHEIGHT(x) (x->bottom-x->top)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDIB::CDIB()
{
}
CDIB::~CDIB()
{
}
//每行像素所占用的字节数
WORD CDIB::BytePerLine(HANDLE hDIB)
{
WORD i;
LPBITMAPINFOHEADER lpbi; //文件信息头指针
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
i = WIDTHBYTES((lpbi->biWidth)*24); //得到字节数
GlobalUnlock(hDIB);
return i;
}
HANDLE CDIB::ReadDIBFile(HANDLE hFile)
{
BITMAPFILEHEADER bmfHeader;
DWORD dwBitsSize; //文件大小
HANDLE hDIB;
HANDLE hDIBtmp;
LPBITMAPINFOHEADER lpbi;
DWORD dwRead;
//得到文件大小
dwBitsSize = GetFileSize(hFile,NULL);
hDIB = GlobalAlloc(GMEM_MOVEABLE,(DWORD)(sizeof(BITMAPINFOHEADER)));
if(!hDIB)
return NULL;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
if(!lpbi)
{
GlobalFree(hDIB);
return NULL;
}
if(!ReadFile(hFile,(LPBYTE)&bmfHeader,sizeof(BITMAPFILEHEADER),&dwRead,NULL))
goto ErrExit;
if(sizeof(BITMAPFILEHEADER)!=dwRead)//读取文件出错
goto ErrExit;
if(bmfHeader.bfType != 0x4d42)//文件类型不匹配
goto ErrExit;
if(!ReadFile(hFile,(LPBYTE)lpbi,sizeof(BITMAPINFOHEADER),&dwRead,NULL))
goto ErrExit;
if(sizeof(BITMAPINFOHEADER)!= dwRead)//读取数据出错
goto ErrExit;
GlobalUnlock(hDIB);
if(lpbi->biSizeImage==0) //真彩色图像
lpbi->biSizeImage = (this->BytePerLine(hDIB))*lpbi->biHeight; //计算得到图像的数据大小
hDIBtmp = GlobalReAlloc(hDIB,lpbi->biSize+lpbi->biSizeImage,0);
if(!hDIBtmp)
goto ErrExitNoUnlock;
else
hDIB = hDIBtmp;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
//根据情况设定文件指针
if(bmfHeader.bfOffBits != 0L)
SetFilePointer(hFile,bmfHeader.bfOffBits,NULL,FILE_BEGIN);
//读取文件的象素颜色数据
if(ReadFile(hFile,(LPBYTE)lpbi+lpbi->biSize,lpbi->biSizeImage,&dwRead,NULL))
goto OKExit;
ErrExit:
GlobalUnlock(hDIB);
ErrExitNoUnlock:
GlobalFree(hDIB); //释放内存
return NULL;
OKExit:
GlobalUnlock(hDIB);
return hDIB;
}
HANDLE CDIB::LoadDIB(LPCTSTR lpFileName)
{
HANDLE hDIB;
HANDLE hFile;
//创建文件句柄
if((hFile = CreateFile(lpFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL))!= INVALID_HANDLE_VALUE)
{
//读取数据
hDIB = ReadDIBFile(hFile);
//关闭文件句柄
CloseHandle(hFile);
return hDIB;
}
return NULL;
}
BOOL CDIB::SaveDIB(HANDLE hDib, LPCTSTR lpFileName)
{
BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
LPBITMAPINFOHEADER lpBI; // Pointer to DIB info structure
HANDLE fh; // file handle for opened file
DWORD dwDIBSize;
DWORD dwWritten;
if (!hDib)
return FALSE;
fh = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (fh == INVALID_HANDLE_VALUE)
return FALSE;
// Get a pointer to the DIB memory, the first of which contains
// a BITMAPINFO structure
lpBI = (LPBITMAPINFOHEADER)GlobalLock(hDib);
if (!lpBI)
{
CloseHandle(fh);
return FALSE;
}
// Check to see if we're dealing with an OS/2 DIB. If so, don't
// save it because our functions aren't written to deal with these
// DIBs.
if (lpBI->biSize != sizeof(BITMAPINFOHEADER))
{
GlobalUnlock(hDib);
CloseHandle(fh);
return FALSE;
}
// Fill in the fields of the file header
// Fill in file type (first 2 bytes must be "BM" for a bitmap)
bmfHdr.bfType = 0x4d42; // "BM"
// Calculating the size of the DIB is a bit tricky (if we want to
// do it right). The easiest way to do this is to call GlobalSize()
// on our global handle, but since the size of our global memory may have
// been padded a few bytes, we may end up writing out a few too
// many bytes to the file (which may cause problems with some apps,
// like HC 3.0).
//
// So, instead let's calculate the size manually.
//
// To do this, find size of header plus size of color table. Since the
// first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains
// the size of the structure, let's use this.
// Partial Calculation
dwDIBSize = *(LPDWORD)lpBI;// + DIBNumColors((LPBYTE)lpBI) * sizeof(RGBQUAD);
// Now calculate the size of the image
// It's an RLE bitmap, we can't calculate size, so trust the biSizeImage
// field
if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
dwDIBSize += lpBI->biSizeImage;
else
{
DWORD dwBmBitsSize; // Size of Bitmap Bits only
// It's not RLE, so size is Width (DWORD aligned) * Height
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) *
lpBI->biHeight;
dwDIBSize += dwBmBitsSize;
// Now, since we have calculated the correct size, why don't we
// fill in the biSizeImage field (this will fix any .BMP files which
// have this field incorrect).
lpBI->biSizeImage = dwBmBitsSize;
}
// Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
// Now, calculate the offset the actual bitmap bits will be in
// the file -- It's the Bitmap file header plus the DIB header,
// plus the size of the color table.
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize;/* +
DIBNumColors((LPBYTE)lpBI) * sizeof(RGBQUAD); */
// Write the file header
WriteFile(fh, (LPBYTE)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
// Write the DIB header and the bits -- use local version of
// MyWrite, so we can write more than 32767 bytes of data
WriteFile(fh, (LPBYTE)lpBI, dwDIBSize, &dwWritten, NULL);
GlobalUnlock(hDib);
CloseHandle(fh);
if (dwWritten == 0)
return FALSE; // oops, something happened in the write
else
return TRUE; // Success code
}
BOOL CDIB::PaintDIBTrue(HDC hDC, LPRECT lpDCRect, HANDLE hDIB, LPRECT lpDIBRect, DWORD dwRop)
{
LPBYTE lpDIBHdr;
LPBYTE lpDIBBits;
BOOL bSuccess = FALSE;
if(!hDIB)
return FALSE;
lpDIBHdr = (LPBYTE)GlobalLock(hDIB);
lpDIBBits = lpDIBHdr + sizeof(BITMAPINFOHEADER); //指向图像数据
bSuccess = StretchDIBits(hDC,lpDCRect->left,
lpDCRect->top,
RECTWIDTH(lpDCRect),
RECTHEIGHT(lpDCRect),
lpDIBRect->left,
((LPBITMAPINFOHEADER)lpDIBHdr)->biHeight-lpDIBRect->top-RECTHEIGHT(lpDIBRect),
RECTWIDTH(lpDIBRect),
RECTHEIGHT(lpDIBRect),
lpDIBBits,
(LPBITMAPINFO)lpDIBHdr,
DIB_RGB_COLORS,
SRCCOPY);
GlobalUnlock(hDIB);
return bSuccess;
}
long CDIB::PixelOffset(int i, int j, WORD wBytesPerLine)
{
long Offset;
Offset=i*wBytesPerLine+j*3; //计算偏移
return Offset;
}
long CDIB::PixelOffsetEP(int i, int j, int height, WORD wBytesPerLine)
{
long Offset;
Offset=(height-j-1)*wBytesPerLine+i*3; //计算偏移
return Offset;
}
HDIB CDIB::ToGray(HANDLE hDIB)
{
HDIB hNewDIB=NULL;
LPBITMAPINFOHEADER lpSrc,lpDest;
LPBYTE lpS,lpD;
DWORD dwBytesPerLine;
DWORD dwImgSize;
WORD wBytesPerLine;
unsigned i,j,height,width;
if(!hDIB)
return NULL;
lpSrc=(LPBITMAPINFOHEADER)GlobalLock(hDIB);
dwBytesPerLine = WIDTHBYTES(24*(lpSrc->biWidth)); //每行图像占用的位数
dwImgSize=lpSrc->biHeight*dwBytesPerLine; //图像数据大小
hNewDIB=GlobalAlloc(GHND,sizeof(BITMAPINFOHEADER)+dwImgSize);
lpDest=(LPBITMAPINFOHEADER)GlobalLock(hNewDIB);
memcpy((void*)lpDest,(void*)lpSrc,sizeof(BITMAPINFOHEADER));
DWORD dwSBytesPerLine;
dwSBytesPerLine=(24*(lpSrc->biWidth)+31)/32*4; //每行图像占用的字节数
height=lpDest->biHeight;
width=lpDest->biWidth;
lpS=(LPBYTE)lpSrc;
wBytesPerLine=this->BytePerLine(hDIB);
lpD=(LPBYTE)lpDest;
lpS=lpS+sizeof(BITMAPINFOHEADER);
lpD=lpD+sizeof(BITMAPINFOHEADER);
unsigned r,g,b,gray;
for(i=0;i<height;i++)
{
for(j=0;j<(unsigned)lpDest->biWidth;j++)
{
r=*(lpS++);
g=*(lpS++);
b=*(lpS++);
gray=(g*50+r*39+b*11)/100;
*(lpD++)=gray;
*(lpD++)=gray;
*(lpD++)=gray;
}
//处理四字节对齐问题
unsigned k;
for(k=0;k<dwSBytesPerLine-lpSrc->biWidth*3;k++)
{
lpS++;
lpD++;
}
}
GlobalUnlock(hDIB);
GlobalUnlock(hNewDIB);
return hNewDIB;
}
HANDLE CDIB::WB(HANDLE hDIB, int Value)
{
HANDLE hDib;
hDib=(HANDLE)ToGray(hDIB);
LPBITMAPINFOHEADER lpbi;
LPBYTE lpS;
int width,height;
long lOffset;
WORD wBytesPerLine=BytePerLine(hDib);
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
width=lpbi->biWidth;
height=lpbi->biHeight;
lpS=(LPBYTE)lpbi;
lpS=lpS+sizeof(BITMAPINFOHEADER);
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
{
lOffset=this->PixelOffset(i,j,wBytesPerLine);
if(*(lpS+lOffset)<Value)
{
*(lpS+lOffset++)=0;
*(lpS+lOffset++)=0;
*(lpS+lOffset)=0;
}
else
{
*(lpS+lOffset++)=255;
*(lpS+lOffset++)=255;
*(lpS+lOffset)=255;
}
}
GlobalUnlock(hDib);
return hDib;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -