// Dib.cpp : implementation file
//
#include "stdafx.h"
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <windowsx.h> // especially for GlobalAllocPtr
#include "Dib.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_SERIAL(CDib, CObject, 0)
////////////////////////////////////////////////////////////////////////////
CDib::CDib()
{
m_hDib = NULL;
m_hBitmap = NULL;
m_pPalette = NULL;
m_pBitmap = NULL;
}
CDib::~CDib()
{
Destroy();
if (m_pBitmap != NULL)
{
delete m_pBitmap;
m_pBitmap = NULL;
}
if (m_pPalette != NULL)
{
delete m_pPalette;
m_pPalette = NULL;
}
}
void CDib::Destroy()
{
if (m_hDib != NULL)
{
DestroyDIB(m_hDib);
m_hDib = NULL;
}
}
HDIB CDib::Detach()
{
if (m_hDib == NULL)
return NULL;
HDIB hDib = m_hDib;
m_hDib = NULL;
if (m_pBitmap != NULL)
{
delete m_pBitmap;
m_pBitmap = NULL;
}
if (m_pPalette != NULL)
{
delete m_pPalette;
m_pPalette = NULL;
}
return hDib;
}
BOOL CDib::Create(DWORD dwWidth, DWORD dwHeight)
{
HDIB hDib = CreateDefaultDIB(dwWidth, dwHeight);
if (! hDib)
return FALSE;
Destroy();
m_hDib = hDib;
return UpdateInternal();
}
BOOL CDib::Create(DWORD dwWidth, DWORD dwHeight, WORD wBitCount)
{
HDIB hDib = CreateDIB(dwWidth, dwHeight, wBitCount);
if (! hDib)
return FALSE;
Destroy();
m_hDib = hDib;
return UpdateInternal();
}
BOOL CDib::Create(LPBYTE lpDIB)
{
if (lpDIB == NULL)
return FALSE;
DWORD dwSize = DIBlockSize(lpDIB);
HDIB hDib = GlobalAlloc(GHND, dwSize);
// Check that DIB handle is valid
if (! hDib)
return FALSE;
LPBYTE lpbi = (LPBYTE)GlobalLock(hDib);
if (! lpbi)
return FALSE;
CopyMemory(lpbi, lpDIB, dwSize);
GlobalUnlock(hDib);
Destroy();
m_hDib = hDib;
return UpdateInternal();
}
BOOL CDib::Create(LPBYTE lpDIB,
WORD wBitCount) // bits/pixel
{
if (lpDIB == NULL)
return FALSE;
if (! Create(lpDIB))
return FALSE;
WORD wBits = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount;
if (wBitCount == wBits)
return TRUE;
HDIB hNewDib = ConvertDIBFormat(m_hDib, wBitCount, NULL);
if (! hNewDib)
return FALSE;
Destroy();
m_hDib = hNewDib;
return UpdateInternal();
}
BOOL CDib::Create(HBITMAP hBitmap) // DIB Section
{
if (! hBitmap)
return FALSE;
HDIB hDib = DIBSectionToDIB(hBitmap);
if (! hDib)
return FALSE;
Destroy();
m_hDib = hDib;
return UpdateInternal();
}
BOOL CDib::Create(HBITMAP hBitmap, // DIB Section
WORD wBitCount) // bits/pixel
{
HDIB hNewDib;
if (! hBitmap)
return FALSE;
HDIB hDib = DIBSectionToDIB(hBitmap);
if (! hDib)
return FALSE;
DIBSECTION ds;
GetObject(hBitmap, sizeof(DIBSECTION), &ds);
if (wBitCount == ds.dsBmih.biBitCount)
hNewDib = hDib;
else
{
hNewDib = ConvertDIBFormat(hDib, wBitCount, NULL);
// cleanup hDib
GlobalFree(hDib);
}
if (! hNewDib)
return FALSE;
Destroy();
m_hDib = hNewDib;
return UpdateInternal();
}
BOOL CDib::Create(HBITMAP hBitmap, // DDB bitmap
HPALETTE hPalette) // DDB palette
{
if (! hBitmap)
return FALSE;
HDIB hDib = BitmapToDIB(hBitmap, hPalette);
if (! hDib)
return FALSE;
Destroy();
m_hDib = hDib;
return UpdateInternal();
}
BOOL CDib::Create(HBITMAP hBitmap, // DDB bitmap
HPALETTE hPalette, // DDB palette
WORD wBitCount) // bits/pixel
{
if (! hBitmap)
return FALSE;
HDIB hDib = BitmapToDIB(hBitmap, hPalette, wBitCount);
if (! hDib)
return FALSE;
Destroy();
m_hDib = hDib;
return UpdateInternal();
}
BOOL CDib::Create(CRect rcScreen)
{
HDIB hDib = CopyScreenToDIB(rcScreen);
if (! hDib)
return FALSE;
Destroy();
m_hDib = hDib;
return UpdateInternal();
}
BOOL CDib::Create(HWND hWnd, WORD fPrintArea)
{
HDIB hDib = CopyWindowToDIB(hWnd, fPrintArea);
if (! hDib)
return FALSE;
Destroy();
m_hDib = hDib;
return UpdateInternal();
}
BOOL CDib::Create(HWND hWnd, CRect rcClientArea)
{
HDIB hDib = CopyClientRectToDIB(hWnd, rcClientArea);
if (! hDib)
return FALSE;
Destroy();
m_hDib = hDib;
return UpdateInternal();
}
BOOL CDib::Attach(HDIB hDib)
{
if (hDib == NULL)
return FALSE;
Destroy();
m_hDib = hDib;
return UpdateInternal();
}
void CDib::Serialize(CArchive& ar)
{
CObject::Serialize(ar);
ar.Flush();
if (ar.IsStoring())
{
Write(ar.GetFile());
}
else
{
Read(ar.GetFile());
}
}
BOOL CDib::Load(UINT uIDS, LPCTSTR lpszDibType)
{
LPCTSTR lpszDibRes = MAKEINTRESOURCE(uIDS);
return Load(lpszDibRes, lpszDibType);
}
BOOL CDib::Load(LPCTSTR lpszDibRes, LPCTSTR lpszDibType)
{
HINSTANCE hInst = AfxGetInstanceHandle();
HRSRC hRes = ::FindResource(hInst, lpszDibRes, lpszDibType);
HGLOBAL hData = ::LoadResource(hInst, hRes);
// if resource ok?
if (hRes == NULL || hData == NULL)
return FALSE;
// get resource buffer
LPBYTE lpBuf = (LPBYTE)::LockResource(hData);
// is DIB ?
if (((LPBITMAPFILEHEADER)lpBuf)->bfType != DIB_HEADER_MARKER/*"BM"*/)
return FALSE;
// use this buffer to create CDib
LPBYTE lpDIB = lpBuf + sizeof(BITMAPFILEHEADER);
return Create(lpDIB);
}
BOOL CDib::Load(LPCTSTR lpszDibFile)
{
TRY
{
CFile file(lpszDibFile, CFile::modeRead|CFile::shareDenyNone);
if (! Read(&file))
return FALSE;
}
CATCH (CException, e)
{
return FALSE;
}
END_CATCH
return TRUE;
}
BOOL CDib::Save(LPCTSTR lpszDibFile)
{
TRY
{
CFile file(lpszDibFile, CFile::modeCreate|CFile::modeWrite);
if (! Write(&file))
return FALSE;
}
CATCH (CException, e)
{
return FALSE;
}
END_CATCH
return TRUE;
}
BOOL CDib::Read(CFile *pFile)
{
WaitCursorBegin();
LPBITMAPINFOHEADER lpbi;
DWORD dwSize;
TRY
{
// read DIB file header
BITMAPFILEHEADER bmfHdr;
pFile->Read(&bmfHdr, sizeof(BITMAPFILEHEADER));
// is DIB file?
if (bmfHdr.bfType != DIB_HEADER_MARKER) // "BM"
{
WaitCursorEnd();
return FALSE;
}
DWORD dwLength = pFile->GetLength();
if (bmfHdr.bfSize != dwLength)
bmfHdr.bfSize = dwLength;
// read DIB buffer
dwSize = bmfHdr.bfSize - sizeof(BITMAPFILEHEADER);
lpbi = (LPBITMAPINFOHEADER)GlobalAllocPtr(GHND, dwSize);
DWORD dwCount = pFile->ReadHuge(lpbi, dwSize);
// read ok?
if (dwCount != dwSize)
{
GlobalFreePtr(lpbi);
WaitCursorEnd();
return FALSE;
}
// Check to see that it's a Windows DIB -- an OS/2 DIB would cause
// strange problems with the rest of the DIB API since the fields
// in the header are different and the color table entries are
// smaller.
//
// If it's not a Windows DIB (e.g. if biSize is wrong), return NULL.
if (lpbi->biSize != sizeof(BITMAPINFOHEADER))
{
GlobalFreePtr(lpbi);
WaitCursorEnd();
return FALSE;
}
// fill color num item
int nNumColors = (UINT)lpbi->biClrUsed;
if (nNumColors == 0)
{
// no color table for 24-bit, default size otherwise
if (lpbi->biBitCount > 8)//(lpbi->biBitCount != 24)
nNumColors = 1 << lpbi->biBitCount; // standard size table
}
// fill in some default values if they are zero
if (lpbi->biClrUsed == 0)
lpbi->biClrUsed = nNumColors;
if (lpbi->biSizeImage == 0)
lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3) * lpbi->biHeight;
}
CATCH (CException, e)
{
GlobalFreePtr(lpbi);
WaitCursorEnd();
return FAL