www.pudn.com > ImageSearch.rar > DIB24.cpp
// dib.cpp : implementation file
//
//
#include "stdafx.h"
#include "dib24.h"
#include "malloc.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CDIB
IMPLEMENT_SERIAL(CDIB24, CObject, 0 /* Schema number */ )
// Create a small DIB here so m_pBMI and m_pBits are always valid.
CDIB24::CDIB24()
{
m_pBMI = NULL;
m_pBits = NULL;
m_iAddWidth=0;
Create(16, 16);
}
CDIB24::~CDIB24()
{
// Free the memory.
if (m_pBMI != NULL) free(m_pBMI);
if (m_pBits != NULL) free(m_pBits);
}
/////////////////////////////////////////////////////////////////////////////
// CDIB serialization
// We don't support this yet.
void CDIB24::Serialize(CArchive& ar)
{
ASSERT(1);
}
/////////////////////////////////////////////////////////////////////////////
// CDIB commands
// Create a new empty 24bpp DIB
BOOL CDIB24::Create(int iWidth, int iHeight)
{
// Delete any existing stuff.
if (m_pBMI != NULL) free(m_pBMI);
if (m_pBits != NULL) free(m_pBits);
// Allocate memory for the header.
m_pBMI = (BITMAPINFO*) malloc(sizeof(BITMAPINFOHEADER));
if (!m_pBMI) {
TRACE("Out of memory for DIB header");
return FALSE;
}
// Allocate memory for the bits (DWORD aligned).
m_iAddWidth=((iWidth*3 + 3) & ~3)-iWidth*3;
int iBitsSize = ((iWidth*3 + 3) & ~3) * iHeight;
m_pBits = (BYTE*)malloc(iBitsSize);//RGB 各占一个字节(8位)
if (!m_pBits) {
TRACE("Out of memory for DIB bits");
free(m_pBMI);
m_pBMI = NULL;
return FALSE;
}
// Fill in the header info.
BITMAPINFOHEADER* pBI = (BITMAPINFOHEADER*) m_pBMI;
pBI->biSize = sizeof(BITMAPINFOHEADER);
pBI->biWidth = (iWidth + 3) & ~3 ;//(DWORD aligned)
pBI->biHeight = iHeight;
pBI->biPlanes = 1;
pBI->biBitCount = 24;
pBI->biCompression = BI_RGB;
pBI->biSizeImage = 0;
pBI->biXPelsPerMeter = 0;
pBI->biYPelsPerMeter = 0;
pBI->biClrUsed = 0;
pBI->biClrImportant = 0;
// Set all the bits to a known state (beautiful)
BYTE* pBits=m_pBits;
for (int i=0; iGetPosition();
// Read the file header to get the file size and to
// find out where the bits start in the file.
BITMAPFILEHEADER BmpFileHdr;
int iBytes;
iBytes = fp->Read(&BmpFileHdr, sizeof(BmpFileHdr));
if (iBytes != sizeof(BmpFileHdr)) {
TRACE("Failed to read file header");
goto $abort;
}
// Check that we have the magic 'BM' at the start.
if (BmpFileHdr.bfType != 0x4D42) {
TRACE("Not a bitmap file");
goto $abort;
}
// Make a wild guess that the file is in Windows DIB
// format and read the BITMAPINFOHEADER. If the file turns
// out to be a PM DIB file we'll convert it later.
BITMAPINFOHEADER BmpInfoHdr;
iBytes = fp->Read(&BmpInfoHdr, sizeof(BmpInfoHdr));
if (iBytes != sizeof(BmpInfoHdr)) {
TRACE("Failed to read BITMAPINFOHEADER");
goto $abort;
}
// Check that we got a real Windows DIB file.
if (BmpInfoHdr.biSize != sizeof(BITMAPINFOHEADER)) {
if (BmpInfoHdr.biSize != sizeof(BITMAPCOREHEADER)) {
TRACE(" File is not Windows or PM DIB format");
goto $abort;
}
}
// Work out how much memory we need for the BITMAPINFO
// structure and for the bits.
// Allocate the memory blocks.
// Copy the BmpInfoHdr we have so far,
int iBitsSize;
int iBISize;
iBISize = sizeof(BITMAPINFOHEADER);
iBitsSize = BmpFileHdr.bfSize -
BmpFileHdr.bfOffBits;
// Allocate the memory for the header.
pBmpInfo = (LPBITMAPINFO) malloc(iBISize);
if (!pBmpInfo) {
TRACE("Out of memory for DIB header");
goto $abort;
}
// Copy the header we already have.
memcpy(pBmpInfo, &BmpInfoHdr, sizeof(BITMAPINFOHEADER));
// Allocate the memory for the bits
// and read the bits from the file.
pBits = (BYTE*) malloc(iBitsSize);
if (!pBits) {
TRACE("Out of memory for DIB bits");
goto $abort;
}
// Seek to the bits in the file.
fp->Seek(dwFileStart + BmpFileHdr.bfOffBits, CFile::begin);
// Read the bits.
iBytes = fp->Read(pBits, iBitsSize);
if (iBytes != iBitsSize) {
TRACE("Failed to read bits");
goto $abort;
}
// Everything went OK.
if (m_pBMI != NULL) free(m_pBMI);
m_pBMI = pBmpInfo;
if (m_pBits != NULL) free(m_pBits);
m_pBits = pBits;
return TRUE;
$abort: // Something went wrong.
if (pBmpInfo) free(pBmpInfo);
if (pBits) free (pBits);
return FALSE;
}
// Draw the DIB to a given DC.
void CDIB24::Draw(CDC* pDC, int x, int y,int iScale)
{
::StretchDIBits(pDC->GetSafeHdc(), //hMemDC->GetSafeHdc()
x, // Destination x
y, // Destination y
DibWidth()*iScale, // Destination width
DibHeight()*iScale, // Destination height
0, // Source x
0, // Source y
DibWidth(), // Source width
DibHeight(), // Source height
GetBitsAddress(), // Pointer to bits
GetBitmapInfoAddress(), // BITMAPINFO
DIB_RGB_COLORS, // Options
SRCCOPY); // Raster operation code (ROP)
}
BOOL CDIB24::Save(CFile* fp) //Save into file;
{
BITMAPFILEHEADER bfHeader;
bfHeader.bfType=0x4d42;
bfHeader.bfSize=54+GetWidth()*GetHeight()*3;//3 for 24ppDIB
bfHeader.bfReserved1=0;
bfHeader.bfReserved2=0;
bfHeader.bfOffBits=54;
fp->Write(&bfHeader,sizeof(BITMAPFILEHEADER));
BITMAPINFO* pBMI=GetBitmapInfoAddress();
fp->Write(pBMI,sizeof(BITMAPINFOHEADER));
BYTE* pBits=GetBitsAddress();
int bs=GetHeight()*GetWidth()*3;
fp->Write(pBits,bs);
return TRUE;
}