// ==========================================================================
// Class Implementation : COXDIB
// ==========================================================================
// Source file : oxdib.cpp
// Source : Periphere NV
// Creation Date : 2nd November 1995
// Last Modification : 17th March 1997
// //////////////////////////////////////////////////////////////////////////
#include "stdafx.h" // standard MFC include
#include "oxdib.h" // class specification
#include "limits.h" // For long -> int truncation
#ifndef NO_DITHER
#include "oxhlftne.h" // conversion tables and halftone palettefor 16 bit
#endif // NO_DITHER
#include <windowsx.h>
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
#define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
IMPLEMENT_SERIAL(COXDIB, CObject, 1)
#define new DEBUG_NEW
/////////////////////////////////////////////////////////////////////////////
// Definition of static members
// Data members -------------------------------------------------------------
// protected:
// LPBYTE m_pDIB;
// --- Handle(Global memory) to DIB (or NULL) when not connected to a DIB
// CPalette* m_pPalette;
// --- Pointer to the pallet belonging to the DIB (or NULL if none)
// private:
// Member functions ---------------------------------------------------------
// public:
COXDIB::COXDIB()
:
m_pDIB(NULL),
m_pPalette(NULL)
{
ASSERT_VALID(this);
}
COXDIB::COXDIB(LPBYTE pDIB)
:
m_pDIB(NULL),
m_pPalette(NULL)
{
// Copy the DIB memory and initialize the palette of the copy
m_pDIB = CopyData (pDIB);
if (m_pDIB != NULL)
{
LPSTR lpDIB = (LPSTR) m_pDIB;
InitPalette(lpDIB);
}
ASSERT_VALID(this);
}
BOOL COXDIB::ClearSystemPalette()
{
//*** A dummy palette setup
struct
{
WORD Version;
WORD NumberOfEntries;
PALETTEENTRY aEntries[256];
} Palette =
{
0x300,
256
};
HPALETTE ScreenPalette = 0;
HDC ScreenDC;
int Counter;
UINT nMapped = 0;
BOOL bOK = FALSE;
int nOK = 0;
// Reset everything in the system palette to black
for(Counter = 0; Counter < 256; Counter++)
{
Palette.aEntries[Counter].peRed = 0;
Palette.aEntries[Counter].peGreen = 0;
Palette.aEntries[Counter].peBlue = 0;
Palette.aEntries[Counter].peFlags = PC_NOCOLLAPSE;
}
// Create, select, realize, deselect, and delete the palette
ScreenDC = ::GetDC(NULL);
ScreenPalette = ::CreatePalette((LOGPALETTE*)&Palette);
if (ScreenPalette)
{
ScreenPalette = ::SelectPalette(ScreenDC, ScreenPalette, FALSE);
nMapped = ::RealizePalette(ScreenDC);
ScreenPalette = ::SelectPalette(ScreenDC, ScreenPalette, FALSE);
bOK = ::DeleteObject(ScreenPalette);
}
nOK = ::ReleaseDC(NULL, ScreenDC);
return bOK && (nOK == 1);
}
BOOL COXDIB::GetSystemPalette(CPalette* pPalette)
{
ASSERT(pPalette != NULL);
HDC hDC; // handle to a DC
LPLOGPALETTE lpLogPal; // pointer to a logical palette
// Find out how many palette entries we want.
hDC = GetDC(NULL);
if (hDC == NULL)
return FALSE;
// For non-palette devices, there's no palette available
if ((::GetDeviceCaps(hDC, RASTERCAPS) & RC_PALETTE) != RC_PALETTE)
{
TRACE0("COXDIB::GetSystemPalette : No palette device\n");
return FALSE;
}
// Find out the number of palette entries on this device.
int nColors = GetDeviceCaps(hDC, SIZEPALETTE);
// Sometimes we'll use the # of system reserved
// colors for our palette size.
if (nColors == 0)
nColors = GetDeviceCaps(hDC, NUMCOLORS);
ASSERT(nColors != 0);
// Allocate room for the palette and lock it.
lpLogPal = (LPLOGPALETTE)::GlobalAlloc(GPTR, sizeof(LOGPALETTE)
+ sizeof(PALETTEENTRY)
* nColors);
// if not enough memory, clean up and return NULL
if (lpLogPal == NULL)
{
TRACE0("COXDIB::GetSystemPalette : Not enough memory for logical palette\n");
ReleaseDC(NULL, hDC);
return FALSE;
}
// set version and number of palette entries
lpLogPal->palVersion = PALVERSION;
lpLogPal->palNumEntries = (WORD)nColors;
// Copy the current system palette into our logical palette
::GetSystemPaletteEntries(hDC, 0, nColors,
(LPPALETTEENTRY)(lpLogPal->palPalEntry));
// Go ahead and create the palette. Once it's created,
// we no longer need the LOGPALETTE, so free it.
// -- create the palette and get handle to it
BOOL bResult = pPalette->CreatePalette(lpLogPal);
::GlobalFree(lpLogPal);
ReleaseDC(NULL, hDC);
return bResult;
}
LPBYTE WINAPI COXDIB::MakeCopy()
{
return CopyData(m_pDIB);
}
CBitmap* COXDIB::MakeBitmap(CDC* pDC, CSize& bmSize)
{
BITMAP bm;
DWORD dwFore, dwBack;
LPSTR lpDIB; // pointer to packed-DIB
PDIB lpbmih; // pointer to a Win 3.0-style DIB
LPBITMAPINFO lpbmi; // pointer to the bitmap info
lpDIB = (LPSTR) m_pDIB;
// point to the header (whether Win 3.0 and old)
lpbmi = (LPBITMAPINFO)lpDIB;
lpbmih = (PDIB)lpDIB;
// checks to see whether DIB buffer is properly loaded
// ... Check for valid DIB handle
if (m_pDIB == NULL)
{
TRACE0("COXDIB::MakeBitmap : DIB not loaded, nothing to copy to bitmap\n");
bmSize.cx = bmSize.cy = 0;
return NULL;
}
// checks to see wether DIB header is valid
// ... Check for valid DIB header compression member (must be uncompressed = BI_RGB)
if (lpbmi->bmiHeader.biCompression != BI_RGB || lpbmih->biCompression != BI_RGB)
{
TRACE0("COXDIB::MakeBitmap : DIB compressed, unable to handle bitmap\n");
return NULL;
}
// this code conditions the bitmap for mono or color
int nPlanes = pDC->GetDeviceCaps(PLANES);
int nBitsPixel = pDC->GetDeviceCaps(BITSPIXEL);
CBitmap* pConfigBitmap = new CBitmap;
char bits[100];
if (GetNumBitsPerPixel(lpDIB) == 1)
{
pConfigBitmap->CreateBitmap(1, 1, 1, 1, bits);
}
else
{
pConfigBitmap->CreateBitmap(1, 1, nPlanes, nBitsPixel, bits);
}
CBitmap* pOriginalBitmap =
(CBitmap*) pDC->SelectObject(pConfigBitmap);
// CreateDIBitmap "switches bits" for mono bitmaps, depending on colors,
// so we'll fool it
if (GetMonoColors(dwFore, dwBack, lpDIB))
{
SetMonoColors(0L, 0xFFFFFFL, lpDIB);
}
// Get the DIB's palette, then select it into DC
HPALETTE hPal=NULL; // Our DIB's palette
HPALETTE hOldPal=NULL; // Previous palette
if (m_pPalette != NULL)
{
hPal = (HPALETTE) m_pPalette->m_hObject;
// ... Select as background since we have
// already realized in forground if needed
hOldPal = ::SelectPalette(pDC->m_hDC, hPal, TRUE);
pDC->RealizePalette();
}
#ifdef WIN32
HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(), lpbmih,
CBM_INIT, (CONST BYTE*) FindDIBBits(lpDIB), lpbmi, DIB_RGB_COLORS);
#else
HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(), lpbmih,
CBM_INIT, FindDIBBits(lpDIB), lpbmi, DIB_RGB_COLORS);
#endif
// ... Reselect old palette
if (hOldPal != NULL)
{
::SelectPalette(pDC->m_hDC, hOldPal, TRUE);
}
if (hBitmap == NULL)
{
TRACE0("null bitmap\n");
delete pDC->SelectObject(pOriginalBitmap); // delete config bitmap
return NULL; // untested error logic
}
SetMonoColors(dwFore, dwBack, lpDIB);
// Can't use CBitmap::FromHandle here because we need to
// delete the object later
CBitmap* pBitmap = new CBitmap;
pBitmap->Attach(hBitmap);
pBitmap->GetObject(sizeof(bm), &bm);
bmSize.cx = bm.bmWidth;
bmSize.cy = bm.bmHeight;
delete pDC