15,979
社区成员
发帖
与我相关
我的任务
分享
// DIB.cpp
//------------------------------------------------------------------------------//
#include "stdafx.h"
#include "DIB.h"
//------------------------------------------------------------------------------//
CDib::CDib()
{
// Set the Dib pointer to
// NULL so we know if it's
// been loaded.
this->m_pDib = NULL;
this->m_pBIH = NULL;
}
//------------------------------------------------------------------------------//
CDib::~CDib()
{
// If a Dib has been loaded,
// delete the memory.
this->ReleaseBuffer();
}
//------------------------------------------------------------------------------//
void CDib::ReleaseBuffer()
{
if( m_pDib != NULL )
{ delete [] m_pDib; }
m_pDib = NULL;
}
//------------------------------------------------------------------------------//
BOOL CDib::Load( const char *pszFilename )
{
CFile cf;
// Attempt to open the Dib file for reading.
if( !cf.Open( pszFilename, CFile::modeRead ) )
return( FALSE );
// Get the size of the file and store
// in a local variable. Subtract the
// size of the BITMAPFILEHEADER structure
// since we won't keep that in memory.
DWORD dwDibSize;
dwDibSize =
cf.GetLength() - sizeof( BITMAPFILEHEADER );
// Attempt to allocate the Dib memory.
unsigned char *pDib;
pDib = new unsigned char [dwDibSize];
if( pDib == NULL )
return( FALSE );
BITMAPFILEHEADER BFH;
// Read in the Dib header and data.
try{
// Did we read in the entire BITMAPFILEHEADER?
if( cf.Read( &BFH, sizeof( BITMAPFILEHEADER ) )
!= sizeof( BITMAPFILEHEADER ) ||
// Is the type 'MB'?
BFH.bfType != 'MB' ||
// Did we read in the remaining data?
cf.Read( pDib, dwDibSize ) != dwDibSize ){
// Delete the memory if we had any
// errors and return FALSE.
delete [] pDib;
cf.Close();
return( FALSE );
}
}
// If we catch an exception, delete the
// exception, the temporary Dib memory,
// and return FALSE.
catch( CFileException *e ){
e->Delete();
delete [] pDib;
cf.Close();
return( FALSE );
}
// If we got to this point, the Dib has been
// loaded. If a Dib was already loaded into
// this class, we must now delete it.
if( m_pDib != NULL )
delete m_pDib;
// Store the local Dib data pointer and
// Dib size variables in the class member
// variables.
m_pDib = pDib;
m_dwDibSize = dwDibSize;
// Pointer our BITMAPINFOHEADER and RGBQUAD
// variables to the correct place in the Dib data.
m_pBIH = (BITMAPINFOHEADER *) m_pDib;
m_pPalette =
(RGBQUAD *) &m_pDib[sizeof(BITMAPINFOHEADER)];
// Calculate the number of palette entries.
m_nPaletteEntries = 1 << m_pBIH->biBitCount;
if( m_pBIH->biBitCount > 8 )
m_nPaletteEntries = 0;
else if( m_pBIH->biClrUsed != 0 )
m_nPaletteEntries = m_pBIH->biClrUsed;
// Point m_pDibBits to the actual Dib bits data.
m_pDibBits =
&m_pDib[sizeof(BITMAPINFOHEADER)+
m_nPaletteEntries*sizeof(RGBQUAD)];
// If we have a valid palette, delete it.
if( m_Palette.GetSafeHandle() != NULL )
m_Palette.DeleteObject();
// If there are palette entries, we'll need
// to create a LOGPALETTE then create the
// CPalette palette.
if( m_nPaletteEntries != 0 ){
// Allocate the LOGPALETTE structure.
LOGPALETTE *pLogPal = (LOGPALETTE *) new char
[sizeof(LOGPALETTE)+
m_nPaletteEntries*sizeof(PALETTEENTRY)];
if( pLogPal != NULL ){
// Set the LOGPALETTE to version 0x300
// and store the number of palette
// entries.
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = m_nPaletteEntries;
// Store the RGB values into each
// PALETTEENTRY element.
for( int i=0; i<m_nPaletteEntries; i++ ){
pLogPal->palPalEntry[i].peRed =
m_pPalette[i].rgbRed;
pLogPal->palPalEntry[i].peGreen =
m_pPalette[i].rgbGreen;
pLogPal->palPalEntry[i].peBlue =
m_pPalette[i].rgbBlue;
}
// Create the CPalette object and
// delete the LOGPALETTE memory.
m_Palette.CreatePalette( pLogPal );
delete [] pLogPal;
}
}
cf.Close();
return( TRUE );
}
//------------------------------------------------------------------------------//
BOOL CDib::Save( const char *pszFilename )
{
// If we have no data, we can't save.
if( m_pDib == NULL )
return( FALSE );
CFile cf;
// Attempt to create the file.
if( !cf.Open( pszFilename,
CFile::modeCreate | CFile::modeWrite ) )
return( FALSE );
// Write the data.
try{
// First, create a BITMAPFILEHEADER
// with the correct data.
BITMAPFILEHEADER BFH;
memset( &BFH, 0, sizeof( BITMAPFILEHEADER ) );
BFH.bfType = 'MB';
BFH.bfSize = sizeof( BITMAPFILEHEADER ) + m_dwDibSize;
BFH.bfOffBits = sizeof( BITMAPFILEHEADER ) +
sizeof( BITMAPINFOHEADER ) +
m_nPaletteEntries * sizeof( RGBQUAD );
// Write the BITMAPFILEHEADER and the
// Dib data.
cf.Write( &BFH, sizeof( BITMAPFILEHEADER ) );
cf.Write( m_pDib, m_dwDibSize );
}
// If we get an exception, delete the exception and
// return FALSE.
catch( CFileException *e ){
e->Delete();
return( FALSE );
}
return( TRUE );
}
//------------------------------------------------------------------------------//
BOOL CDib::DrawPartion( HDC &pDC, int SrcnX, int SrcnY, int SrcnWidth, int SrcnHeight, int DestnX = 0, int DestnY = 0, int DestnWidth = -1, int DestnHeight = -1 ) // Draw BMP image
{
// If we have not data we can't draw.
if( m_pDib == NULL )
return( FALSE );
// Check for the default values of -1
// in the width and height arguments. If
// we find -1 in either, we'll set them
// to the value that's in the BITMAPINFOHEADER.
if( SrcnWidth == -1 ) { return FALSE; }
if( SrcnHeight == -1 ) { return FALSE; }
// Use StretchDIBits to draw the Dib.
StretchDIBits( pDC, DestnX, DestnY,
DestnWidth, DestnHeight,
SrcnX, SrcnY,
SrcnWidth, SrcnHeight,
m_pDibBits,
(BITMAPINFO *) m_pBIH,
BI_RGB, SRCCOPY );
return( TRUE );
}
//------------------------------------------------------------------------------//
BOOL CDib::Draw( HDC &pDC, int nX, int nY, int nWidth, int nHeight )
{
// If we have not data we can't draw.
if( m_pDib == NULL )
return( FALSE );
// Check for the default values of -1
// in the width and height arguments. If
// we find -1 in either, we'll set them
// to the value that's in the BITMAPINFOHEADER.
if( nWidth == -1 )
nWidth = m_pBIH->biWidth;
if( nHeight == -1 )
nHeight = m_pBIH->biHeight;
// Use StretchDIBits to draw the Dib.
StretchDIBits( pDC, nX, nY,
nWidth, nHeight,
0, 0,
m_pBIH->biWidth, m_pBIH->biHeight,
m_pDibBits,
(BITMAPINFO *) m_pBIH,
BI_RGB, SRCCOPY );
return( TRUE );
}
//------------------------------------------------------------------------------//
BOOL CDib::SetPalette( CDC *pDC )
{
// If we have not data we
// won't want to set the palette.
if( m_pDib == NULL )
return( FALSE );
// Check to see if we have a palette
// handle. For Dibs greater than 8 bits,
// this will be NULL.
if( m_Palette.GetSafeHandle() == NULL )
return( TRUE );
// Select the palette, realize the palette,
// then finally restore the old palette.
CPalette *pOldPalette;
pOldPalette = pDC->SelectPalette( &m_Palette, FALSE );
pDC->RealizePalette();
pDC->SelectPalette( pOldPalette, FALSE );
return( TRUE );
}
//------------------------------------------------------------------------------//
unsigned char * CDib::GetDIB()
{
return m_pDib;
}
//------------------------------------------------------------------------------//
unsigned char * CDib::GetDIBBits()// BMP Bits data
{
return m_pDibBits;
}
//------------------------------------------------------------------------------//
BITMAPINFO * CDib::GetDIBInfo() //眔BMP Infor
{
return (BITMAPINFO*)this->m_pBIH;
}
//------------------------------------------------------------------------------//
HBITMAP CDib::CreatBMP(int nWidth, int nHeight, int nColor, CClientDC *pDC, UINT c)
{
void * pdata=0;
BITMAPINFO bi;
ZeroMemory(&bi,sizeof(bi));
bi.bmiHeader.biSize=sizeof(bi.bmiHeader);
bi.bmiHeader.biHeight=nHeight;
bi.bmiHeader.biWidth=nWidth;
bi.bmiHeader.biPlanes=1;
bi.bmiHeader.biBitCount=nColor;
bi.bmiHeader.biCompression=BI_RGB;
bi.bmiHeader.biSizeImage=GetBMPImagePixelsPerLine(nWidth,nColor)*nHeight;
HBITMAP hBitmap=CreateDIBSection(pDC->m_hDC,&bi,DIB_RGB_COLORS,&pdata,NULL,0);
BYTE *p=(BYTE *)pdata;
for(int i=0;i<nHeight*GetBMPImagePixelsPerLine(nWidth,nColor);i++)
{
p[i]=c;//位图的颜色
}
return hBitmap;
}
int CDib::GetBMPImagePixelsPerLine(int ImageX,int weishu)
{
int bytes_per_line ;
bytes_per_line=(ImageX*weishu+31)/8;
bytes_per_line=bytes_per_line/4*4;//得到图像的一行的位数
return bytes_per_line;
}
BOOL CDib::SaveNewImage(HBITMAP hbitmap, LPSTR filename, int nColor)
{
BITMAP Bitmap;
HDC hDC;
DWORD dwPaletteSize=0,dwBmBitsSize,dwDIBSize, dwWritten;
BITMAPFILEHEADER bmfHdr;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
HANDLE fh, hDib, hPal,hOldPal=NULL;
if (nColor<= 8)
dwPaletteSize = (1<<nColor) *sizeof(RGBQUAD);
GetObject(hbitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = Bitmap.bmWidth;
bi.biHeight = Bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = nColor;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwBmBitsSize = ((Bitmap.bmWidth * nColor+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, 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,//not be shared
NULL, //cannot be inherited
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;
//write file header
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
//write bmp data
WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
DeleteObject(hbitmap);
return TRUE;
}
HBITMAP CDib::CopyScreenToBitmap(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;
}