📄 dibsectionce.cpp
字号:
#include "stdafx.h"
#include "DIBSectionCE.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#ifndef _WIN32_WCE
#undef TRY
#undef CATCH
#undef END_CATCH
#define TRY try
#define CATCH(ex_class, ex_object) catch(ex_class* ex_object)
#define END_CATCH
#endif // _WIN32_WCE
// Standard colours
RGBQUAD CDIBSectionCE::ms_StdColours[] = {
{ 0x00, 0x00, 0x00, 0 }, // First 2 will be palette for monochrome bitmaps
{ 0xFF, 0xFF, 0xFF, 0 },
{ 0x00, 0x00, 0xFF, 0 }, // First 16 will be palette for 16 colour bitmaps
{ 0x00, 0xFF, 0x00, 0 },
{ 0x00, 0xFF, 0xFF, 0 },
{ 0xFF, 0x00, 0x00, 0 },
{ 0xFF, 0x00, 0xFF, 0 },
{ 0xFF, 0xFF, 0x00, 0 },
{ 0x00, 0x00, 0x80, 0 },
{ 0x00, 0x80, 0x00, 0 },
{ 0x00, 0x80, 0x80, 0 },
{ 0x80, 0x00, 0x00, 0 },
{ 0x80, 0x00, 0x80, 0 },
{ 0x80, 0x80, 0x00, 0 },
{ 0x80, 0x80, 0x80, 0 },
{ 0xC0, 0xC0, 0xC0, 0 },
};
/////////////////////////////////////////////////////////////////////////////
// CE DIBSection global functions
UINT CEGetDIBColorTable(HDC hdc, UINT uStartIndex, UINT cEntries, RGBQUAD *pColors);
/*static*/ int CDIBSectionCE::NumColorEntries(int nBitsPerPixel)
{
int nColors = 0;
switch (nBitsPerPixel)
{
case 1: nColors = 2; break;
#ifdef _WIN32_WCE
case 2: nColors = 4; break; // winCE only
#endif
case 4: nColors = 16; break;
case 8: nColors = 256; break;
case 16:
case 24:
case 32: nColors = 0; break; // 16,24 or 32 bpp have no color table
default:
ASSERT(FALSE);
}
return nColors;
}
/*static*/ int CDIBSectionCE::BytesPerLine(int nWidth, int nBitsPerPixel)
{
int nBytesPerLine = nWidth * nBitsPerPixel;
nBytesPerLine = ( (nBytesPerLine + 31) & (~31) ) / 8;
return nBytesPerLine;
}
#ifndef DIBSECTION_NO_PALETTE
//
// --- In?: palette - reference to a palette object which will be filled
// nNumColours - number of colour entries to fill
// --- Out :
// --- Returns : TRUE on success, false otherwise
// --- Effect : Creates a halftone color palette independant of screen color depth.
// palette will be filled with the colors, and nNumColours is the No.
// of colors to file. If nNumColoursis 0 or > 256, then 256 colors are used.
/*static*/ BOOL CDIBSectionCE::CreateHalftonePalette(CPalette& palette, int nNumColours)
{
palette.DeleteObject();
int nNumStandardColours = sizeof(ms_StdColours) / sizeof(ms_StdColours[0]);
int nIndex = 0;
int nNumEntries = nNumColours;
if (nNumEntries <= 0 || nNumEntries > 256)
nNumEntries = 256;
PALETTEINFO PalInfo;
PalInfo.palNumEntries = (WORD) nNumEntries;
// The standard colours (16)
for (int i = 0; i < nNumStandardColours; i++)
{
if (nIndex >= nNumEntries)
break;
PalInfo.palPalEntry[nIndex].peRed = ms_StdColours[i].rgbRed;
PalInfo.palPalEntry[nIndex].peGreen = ms_StdColours[i].rgbGreen;
PalInfo.palPalEntry[nIndex].peBlue = ms_StdColours[i].rgbBlue;
PalInfo.palPalEntry[nIndex].peFlags = 0;
nIndex++;
}
// A colour cube (6 divisions = 216)
for (int blue = 0; blue <= 5; blue++)
for (int green = 0; green <= 5; green++)
for (int red = 0; red <= 5; red++)
{
if (nIndex >= nNumEntries)
break;
PalInfo.palPalEntry[nIndex].peRed = (BYTE) ((red*255)/5);
PalInfo.palPalEntry[nIndex].peGreen = (BYTE) ((green*255)/5);
PalInfo.palPalEntry[nIndex].peBlue = (BYTE) ((blue*255)/5);
PalInfo.palPalEntry[nIndex].peFlags = 0;
nIndex++;
}
// A grey scale (24 divisions)
for (int grey = 0; grey <= 23; grey++)
{
if (nIndex >= nNumEntries)
break;
PalInfo.palPalEntry[nIndex].peRed = (BYTE) (grey*255/23);
PalInfo.palPalEntry[nIndex].peGreen = (BYTE) (grey*255/23);
PalInfo.palPalEntry[nIndex].peBlue = (BYTE) (grey*255/23);
PalInfo.palPalEntry[nIndex].peFlags = 0;
nIndex++;
}
return palette.CreatePalette((LPLOGPALETTE) PalInfo);
}
#endif // DIBSECTION_NO_PALETTE
/////////////////////////////////////////////////////////////////////////////
// CDIBSectionCE
CDIBSectionCE::CDIBSectionCE()
{
m_hBitmap = NULL;
m_hOldBitmap = NULL;
m_bReuseMemDC = FALSE;
DeleteObject(); // This will initialise to a known state - ie. empty
}
CDIBSectionCE::~CDIBSectionCE()
{
DeleteObject();
}
// --- In?:
// --- Out :
// --- Returns :
// --- Effect : Resets the object to an empty state, and frees all memory used.
void CDIBSectionCE::DeleteObject()
{
// Unselect the bitmap out of the memory DC before deleting bitmap
ReleaseMemoryDC(TRUE);
if (m_hBitmap)
::DeleteObject(m_hBitmap);
m_hBitmap = NULL;
m_ppvBits = NULL;
#ifndef DIBSECTION_NO_PALETTE
m_Palette.DeleteObject();
#endif
memset(&m_DIBinfo, 0, sizeof(m_DIBinfo));
m_iColorDataType = DIB_RGB_COLORS;
m_iColorTableSize = 0;
}
/////////////////////////////////////////////////////////////////////////////
// CDIBSectionCE diagnostics
/////////////////////////////////////////////////////////////////////////////
// CDIBSectionCE operations
// --- In?: pDC - Pointer to a device context
// ptDest - point at which the topleft corner of the image is drawn
// --- Out :
// --- Returns : TRUE on success
// --- Effect : Draws the image 1:1 on the device context
BOOL CDIBSectionCE::Draw(CDC* pDC, CPoint ptDest, BOOL bForceBackground /*=FALSE*/)
{
if (!m_hBitmap)
return FALSE;
CSize size = GetSize();
CPoint ptOrigin = CPoint(0,0);
/*
pDC->BitBlt(ptDest.x, ptDest.y, size.cx, size.cy,&m_MemDC,
ptOrigin.x, ptOrigin.y, SRCCOPY);
return TRUE;
*/
// Create a memory DC compatible with the destination DC
CDC* pMemDC = GetMemoryDC(pDC, FALSE);
if (!pMemDC)
return FALSE;
#ifndef DIBSECTION_NO_PALETTE
// Select and realize the palette
CPalette* pOldPalette = NULL;
if (m_Palette.m_hObject && UsesPalette(pDC))
{
pOldPalette = pDC->SelectPalette(&m_Palette, bForceBackground);
pDC->RealizePalette();
}
#endif // DIBSECTION_NO_PALETTE
BOOL bResult = pDC->BitBlt(ptDest.x, ptDest.y, size.cx, size.cy, pMemDC,
ptOrigin.x, ptOrigin.y, SRCCOPY);
#ifndef DIBSECTION_NO_PALETTE
if (pOldPalette)
pDC->SelectPalette(pOldPalette, FALSE);
#endif // DIBSECTION_NO_PALETTE
ReleaseMemoryDC();
return bResult;
}
// --- In?: pDC - Pointer to a device context
// ptDest - point at which the topleft corner of the image is drawn
// size - size to stretch the image
// --- Out :
// --- Returns : TRUE on success
// --- Effect : Stretch draws the image to the desired size on the device context
BOOL CDIBSectionCE::Stretch(CDC* pDC, CPoint ptDest, CSize size,
BOOL bForceBackground /*=FALSE*/)
{
if (!m_hBitmap)
return FALSE;
CPoint ptOrigin = CPoint(0,0);
CSize imagesize = GetSize();
/*
///=====================
pDC->StretchBlt(ptDest.x, ptDest.y, size.cx, size.cy,
&m_MemDC,
ptOrigin.x, ptOrigin.y, imagesize.cx, imagesize.cy,
SRCCOPY);
return TRUE;
*/
// Create a memory DC compatible with the destination DC
CDC* pMemDC = GetMemoryDC(pDC, FALSE);
if (!pMemDC)
return FALSE;
#ifndef DIBSECTION_NO_PALETTE
// Select and realize the palette
CPalette* pOldPalette = NULL;
if (m_Palette.m_hObject && UsesPalette(pDC))
{
pOldPalette = pDC->SelectPalette(&m_Palette, bForceBackground);
pDC->RealizePalette();
}
#endif // DIBSECTION_NO_PALETTE
#ifndef _WIN32_WCE
pDC->SetStretchBltMode(COLORONCOLOR);
#endif // _WIN32_WCE
BOOL bResult = pDC->StretchBlt(ptDest.x, ptDest.y, size.cx, size.cy,
pMemDC,
ptOrigin.x, ptOrigin.y, imagesize.cx, imagesize.cy,
SRCCOPY);
#ifndef DIBSECTION_NO_PALETTE
if (pOldPalette)
pDC->SelectPalette(pOldPalette, FALSE);
#endif // DIBSECTION_NO_PALETTE
ReleaseMemoryDC();
return bResult;
}
//////////////////////////////////////////////////////////////////////////////
// --- In?: lpBitmapInfo - pointer to a BITMAPINFO structure
// lpBits - pointer to image bits
// --- Out :
// --- Returns : Returns TRUE on success, FALSE otherwise
// --- Effect : Initialises the bitmap using the information in lpBitmapInfo to determine
// the dimensions and colours, and the then sets the bits from the bits in
// lpBits. If failure, then object is initialised back to an empty bitmap.
BOOL CDIBSectionCE::SetBitmap(LPBITMAPINFO lpBitmapInfo, LPVOID lpBits)
{
DeleteObject();
if (!lpBitmapInfo || !lpBits)
return FALSE;
HDC hDC = NULL;
TRY {
BITMAPINFOHEADER& bmih = lpBitmapInfo->bmiHeader;
// Compute the number of colours in the colour table
m_iColorTableSize = NumColorEntries(bmih.biBitCount);
DWORD dwBitmapInfoSize = sizeof(BITMAPINFO) + m_iColorTableSize*sizeof(RGBQUAD);
// Copy over BITMAPINFO contents
memcpy(&m_DIBinfo, lpBitmapInfo, dwBitmapInfoSize);
// Should now have all the info we need to create the sucker.
//TRACE(_T("Width %d, Height %d, Bits/pixel %d, Image Size %d\n"),
// bmih.biWidth, bmih.biHeight, bmih.biBitCount, bmih.biSizeImage);
// Create a DC which will be used to get DIB, then create DIBsection
hDC = ::GetDC(NULL);
if (!hDC)
{
TRACE0("Unable to get DC\n");
AfxThrowResourceException();
}
//m_iColorDataType = DIB_PAL_COLORS;
//m_DIBinfo.bmiHeader.biCompression = 0;
DWORD dwImageSize = m_DIBinfo.bmiHeader.biSizeImage;
if (dwImageSize == 0)
{
int nBytesPerLine = BytesPerLine(lpBitmapInfo->bmiHeader.biWidth,
lpBitmapInfo->bmiHeader.biBitCount);
dwImageSize = nBytesPerLine * lpBitmapInfo->bmiHeader.biHeight;
}
//解码数据流
int nWidth = m_DIBinfo.bmiHeader.biWidth;
int nHeight = m_DIBinfo.bmiHeader.biHeight;
if(m_DIBinfo.bmiHeader.biCompression != 0 )
{
int nRealWidth = m_DIBinfo.bmiHeader.biWidth;
if((nRealWidth % 4) != 0)
nRealWidth += 4 - (nRealWidth%4);
m_DIBinfo.bmiHeader.biWidth = nRealWidth;
int nRealHeight = m_DIBinfo.bmiHeader.biHeight;
//delete []lpBits;
BYTE *p = new BYTE[nRealHeight*nRealWidth];
memset(p,0,nRealHeight*nRealWidth);
m_DIBinfo.bmiHeader.biSizeImage = nRealHeight*nRealWidth;
//last dwImageSize is the compassed bytes
if(m_DIBinfo.bmiHeader.biCompression == 1)
BI_RLE8Processor(m_MemDC.GetSafeHdc(),(BYTE*)lpBits,dwImageSize,p,nRealWidth);
else
return FALSE;
// BI_RLE4Processor(m_MemDC.GetSafeHdc(),(BYTE*)lpBits,dwImageSize,p,505);
lpBits = p;
m_DIBinfo.bmiHeader.biCompression = 0;
};
m_hBitmap = CreateDIBSection(hDC, (const BITMAPINFO*) m_DIBinfo,
m_iColorDataType, &m_ppvBits, NULL, 0);
::ReleaseDC(NULL, hDC);
if (!m_hBitmap)
{
TRACE(L"CreateDIBSection failed %d\n", GetLastError());
AfxThrowResourceException();
}
dwImageSize = m_DIBinfo.bmiHeader.biSizeImage;
if (dwImageSize == 0)
{
int nBytesPerLine = BytesPerLine(lpBitmapInfo->bmiHeader.biWidth,
lpBitmapInfo->bmiHeader.biBitCount);
dwImageSize = nBytesPerLine * lpBitmapInfo->bmiHeader.biHeight;
}
#ifndef _WIN32_WCE
// Flush the GDI batch queue
GdiFlush();
#endif
memcpy(m_ppvBits, lpBits, dwImageSize);
#ifndef DIBSECTION_NO_PALETTE
if (!CreatePalette())
{
TRACE0("Unable to create palette\n");
AfxThrowResourceException();
}
#endif // DIBSECTION_NO_PALETTE
}
CATCH (CException, e)
{
e->Delete();
_ShowLastError();
if (hDC)
::ReleaseDC(NULL, hDC);
DeleteObject();
return FALSE;
}
END_CATCH
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -