// Dib.cpp: implementation of the CDib class.
//
//////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// dib.cpp
//
#include "stdafx.h"
#include "dib.h"
#include <windowsx.h>
#include <afxadv.h> //CSharefile
#include <io.h>
#include <errno.h>
/////////////////////////////////////////////////////////////////////////////
// CDib
IMPLEMENT_DYNAMIC(CDib, CObject)
CDib::CDib()
{
m_pBMI = NULL;
m_pBits = NULL;
m_pPalette = NULL;
}
CDib::~CDib()
{
Free();
}
void CDib::Free()
{
// Make sure all member data that might have been allocated is freed.
if (m_pBits)
{
GlobalFreePtr(m_pBits);
m_pBits = NULL;
}
if (m_pBMI)
{
GlobalFreePtr(m_pBMI);
m_pBMI = NULL;
}
if (m_pPalette)
{
m_pPalette->DeleteObject();
delete m_pPalette;
m_pPalette = NULL;
}
}
/*************************************************************************
*
* Paint()
*
* Parameters:
*
* HDC hDC - DC to do output to
*
* LPRECT lpDCRect - rectangle on DC to do output to
*
* LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect
*
* CPalette* pPal - pointer to CPalette containing DIB's palette
*
* Return Value:
*
* BOOL - TRUE if DIB was drawn, FALSE otherwise
*
* Description:
* Painting routine for a DIB. Calls StretchDIBits() or
* SetDIBitsToDevice() to paint the DIB. The DIB is
* output to the specified DC, at the coordinates given
* in lpDCRect. The area of the DIB to be output is
* given by lpDIBRect.
*
************************************************************************/
BOOL CDib::Paint(HDC hDC, LPRECT lpDCRect, LPRECT lpDIBRect) const
{
if (!m_pBMI)
return FALSE;
CRect r1,r2;
r1.top=0;
r1.left=0;
r1.bottom=Height()-1;
r1.right=Width()-1;
r2.top=0;
r2.left=0;
r2.bottom=Height()-1;
r2.right=Width()-1;
if(lpDCRect==NULL) lpDCRect=&r1;
if(lpDIBRect==NULL) lpDIBRect=&r2;
HPALETTE hPal = NULL; // Our DIB's palette
HPALETTE hOldPal = NULL; // Previous palette
// Get the DIB's palette, then select it into DC
if (m_pPalette != NULL)
{
hPal = (HPALETTE) m_pPalette->m_hObject;
// Select as background since we have
// already realized in forground if needed
hOldPal = ::SelectPalette(hDC, hPal, TRUE);
}
/* Make sure to use the stretching mode best for color pictures */
::SetStretchBltMode(hDC, COLORONCOLOR);
/* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */
BOOL bSuccess;
if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) &&
(RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
bSuccess = ::SetDIBitsToDevice(hDC, // hDC
lpDCRect->left, // DestX
lpDCRect->top, // DestY
RECTWIDTH(lpDCRect), // nDestWidth
RECTHEIGHT(lpDCRect), // nDestHeight
lpDIBRect->left, // SrcX
(int)Height() -
lpDIBRect->top -
RECTHEIGHT(lpDIBRect), // SrcY
0, // nStartScan
(WORD)Height(), // nNumScans
m_pBits, // lpBits
m_pBMI, // lpBitsInfo
DIB_RGB_COLORS); // wUsage
else
bSuccess = ::StretchDIBits(hDC, // hDC
lpDCRect->left, // DestX
lpDCRect->top, // DestY
RECTWIDTH(lpDCRect), // nDestWidth
RECTHEIGHT(lpDCRect), // nDestHeight
lpDIBRect->left, // SrcX
lpDIBRect->top, // SrcY
RECTWIDTH(lpDIBRect), // wSrcWidth
RECTHEIGHT(lpDIBRect), // wSrcHeight
m_pBits, // lpBits
m_pBMI, // lpBitsInfo
DIB_RGB_COLORS, // wUsage
SRCCOPY); // dwROP
/* Reselect old palette */
if (hOldPal != NULL)
{
::SelectPalette(hDC, hOldPal, TRUE);
}
return bSuccess;
}
/*************************************************************************
*
* CreatePalette()
*
* Return Value:
*
* TRUE if succesfull, FALSE otherwise
*
* Description:
*
* This function creates a palette from a DIB by allocating memory for the
* logical palette, reading and storing the colors from the DIB's color table
* into the logical palette, creating a palette from this logical palette,
* and then returning the palette's handle. This allows the DIB to be
* displayed using the best possible colors (important for DIBs with 256 or
* more colors).
*
************************************************************************/
BOOL CDib::CreatePalette()
{
if (!m_pBMI)
return FALSE;
//get the number of colors in the DIB
WORD wNumColors = NumColors();
if (wNumColors != 0)
{
// allocate memory block for logical palette
HANDLE hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*wNumColors);
// if not enough memory, clean up and return NULL
if (hLogPal == 0)
return FALSE;
LPLOGPALETTE lpPal = (LPLOGPALETTE)::GlobalLock((HGLOBAL)hLogPal);
// set version and number of palette entries
lpPal->palVersion = PALVERSION;
lpPal->palNumEntries = (WORD)wNumColors;
for (int i = 0; i < (int)wNumColors; i++)
{
lpPal->palPalEntry[i].peRed = m_pBMI->bmiColors[i].rgbRed;
lpPal->palPalEntry[i].peGreen = m_pBMI->bmiColors[i].rgbGreen;
lpPal->palPalEntry[i].peBlue = m_pBMI->bmiColors[i].rgbBlue;
lpPal->palPalEntry[i].peFlags = 0;
}
/* create the palette and get handle to it */
if (m_pPalette)
{
m_pPalette->DeleteObject();
delete m_pPalette;
}
m_pPalette = new CPalette;
BOOL bResult = m_pPalette->CreatePalette(lpPal);
::GlobalUnlock((HGLOBAL) hLogPal);
::GlobalFree((HGLOBAL) hLogPal);
return bResult;
}
return TRUE;
}
/*************************************************************************
*
* Width()
*
* Return Value:
*
* DWORD - width of the DIB
*
* Description:
*
* This function gets the width of the DIB from the BITMAPINFOHEADER
* width field
*
************************************************************************/
DWORD CDib::Width() const
{
if (!m_pBMI)
return 0;
/* return the DIB width */
return m_pBMI->bmiHeader.biWidth;
}
/*************************************************************************
*
* Height()
*
* Return Value:
*
* DWORD - height of the DIB
*
* Description:
*
* This function gets the height of the DIB from the BITMAPINFOHEADER
* height field
*
************************************************************************/
DWORD CDib::Height() const
{
if (!m_pBMI)
return 0;
/* return the DIB height */
return m_pBMI->bmiHeader.biHeight;
}
/*************************************************************************
*
* PaletteSize()
*
* Return Value:
*
* WORD - size of the color palette of the DIB
*
* Description:
*
* This function gets the size required to store the DIB's palette by
* multiplying the number of colors by the size of an RGBQUAD
*
************************************************************************/
WORD CDib::PaletteSize() const
{
if (!m_pBMI)
return 0;
return NumColors() * sizeof(RGBQUAD);
}
/*************************************************************************
*
* NumColors()
*
* Return Value:
*
* WORD - number of colors in the color table
*
* Description:
*
* This function calculate