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; 
}