📄 ddb.cpp
字号:
// Ddb.cpp: implementation of the CDdb class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Ddb.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(CDdb,CObject)
CDdb::CDdb()
{
m_pDdbData=NULL;
m_hDdbData=0;
}
CDdb::~CDdb()
{
ClearMemory();
}
#ifdef _DEBUG
void CDdb::Dump(CDumpContext& dc)const
{
CObject::Dump(dc);
}
void CDdb::AssertValid()const
{
CObject::AssertValid();
ASSERT(m_pDdb!=NULL);
ASSERT(m_hDdbData!=0);
ASSERT(m_pDdbData!=NULL);
}
#endif
CDdb::CDdb(CBitmap *pBitmap)
{
m_pDdbData=NULL;
m_hDdbData=0;
SetDdb(pBitmap);
}
void CDdb::ClearMemory()
{
if(m_hDdbData!=NULL)
::GlobalFree(m_hDdbData);
m_pDdbData=NULL;
m_hDdbData=0;
}
void CDdb::SetDdb(CBitmap *pBitmap)
{
ASSERT(pBitmap);
BITMAP bitmap;
pBitmap->GetObject(sizeof(BITMAP),&bitmap);
m_nWidth=bitmap.bmWidth;
m_nHeight=bitmap.bmHeight;
m_pDdb=pBitmap;
HDC hdc=::GetDC(NULL);
m_nBitCount=24;
m_nBitCount=::GetDeviceCaps(hdc,BITSPIXEL);
if(m_nBitCount<8)
{
AfxMessageBox("please change your display mode.Thank you!");
return;
}
m_nDdbWidthBytes=CalcDdbWidthBytes(m_nWidth,m_nBitCount);
DWORD dwDdbBitsSize=m_nDdbWidthBytes*m_nHeight;
if(m_pDdbData!=NULL)
{
::GlobalFree(m_hDdbData);
m_pDdbData=NULL;
m_hDdbData=0;
}
m_hDdbData=(HGLOBAL)::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,dwDdbBitsSize);
if(m_hDdbData==0) return;
m_pDdbData=(BYTE*)::GlobalLock(m_hDdbData);
if(m_pDdbData==NULL)
{
::GlobalUnlock(m_hDdbData);
::GlobalFree(m_hDdbData);
m_hDdbData=0;
return;
}
m_pDdb->GetBitmapBits(dwDdbBitsSize,m_pDdbData);
::GlobalUnlock(m_hDdbData);
::ReleaseDC(NULL,hdc);
}
BYTE* CDdb::GetDdbData() const
{
return m_pDdbData;
}
BYTE CDdb::GetBitCount() const
{
return m_nBitCount;
}
LONG CDdb::GetWidth() const
{
return m_nWidth;
}
LONG CDdb::GetHeight() const
{
return m_nHeight;
}
LONG CDdb::GetDdbWidthBytes() const
{
return m_nDdbWidthBytes;
}
LONG CDdb::CalcDdbWidthBytes(LONG nWidth, BYTE byBitCount)
{
return (((nWidth*byBitCount+15)/16)*2);
}
LONG CDdb::CalcDibWidthBytes(LONG nWidth, BYTE byBitCount)
{
if(byBitCount==8)
return (((nWidth*8+31)/32)*4);
else
return (((nWidth*24+31)/32)*4);
}
void CDdb::GetRGB16(BYTE *pbyRGB, WORD *pwColor)
{
WORD* pwClr=pwColor;
pbyRGB[0]=(BYTE)(((*pwClr)&0x001F)<<3);
pbyRGB[1]=(BYTE)(((*pwClr)&0x07E0)>>3);
pbyRGB[2]=(BYTE)(((*pwClr)&0xF800)>>8);
}
DWORD CDdb::SetBitmapBits(DWORD dwCount, const void *lpbyBits)
{
ASSERT(lpbyBits);
return (m_pDdb->SetBitmapBits(dwCount,lpbyBits));
}
DWORD CDdb::SetBitmapBits(int x, int y, int nWidth, int nHeight, int nBitCount, LPBYTE lpbyBits)
{
ASSERT(lpbyBits);
if(nBitCount!=m_nBitCount) return 0;
if((x>m_nWidth-1) || (y>nHeight-1))
{
AfxMessageBox("Cross the border!");
return 0;
}
LONG w=(LONG)min(nWidth,m_nWidth-x);
LONG h=(LONG)min(nHeight,m_nHeight-y);
DWORD dwScanLength=CalcDdbWidthBytes(nWidth,nBitCount);
DWORD dwLength=w;
DWORD dwOffset=x;
if(nBitCount==16)
{
dwLength=w+w;
dwOffset=x+x;
}
else if(nBitCount==24)
{
dwLength=3*w;
dwOffset=3*x;
}
else if(nBitCount==32)
{
dwLength=4*w;
dwOffset=4*x;
}
BYTE* pbyDdbDst=m_pDdbData+y*m_nDdbWidthBytes+dwOffset;
BYTE* pbyDdbRsc=lpbyBits;
for(int i=0;i<h;i++)
{
::CopyMemory(pbyDdbDst,pbyDdbRsc,dwLength);
pbyDdbRsc+=dwScanLength;
pbyDdbDst+=m_nDdbWidthBytes;
}
m_pDdb->SetBitmapBits(m_nDdbWidthBytes*m_nHeight,m_pDdbData);
return (nWidth*nHeight*nBitCount);
}
void CDdb::GetDdbDataTo24(int x, int y, int nWidth, int nHeight, LPBYTE lpbyBits24)
{
ASSERT(lpbyBits24);
if((x>m_nWidth-1) || (y>nHeight-1))
{
AfxMessageBox("Cross the boader!");
return;
}
LONG w=(LONG)min(nWidth,m_nWidth-x);
LONG h=(LONG)min(nHeight,m_nHeight-y);
DWORD dwWidthBytes24=((w*24+15)/16)*2;
switch(m_nBitCount)
{
case 8:
{
RGBQUAD* pRGBQuad=new RGBQUAD[256];
if(pRGBQuad==NULL) return;
memset(pRGBQuad,0,256*sizeof(RGBQUAD));
GetSystemPaletteEntries(pRGBQuad);
DWORD dwBaseIndex=y*m_nDdbWidthBytes+x;
DWORD dwBase24=0;
for(LONG i=0;i<h;i++)
{
BYTE* pbyDdbRaw=m_pDdbData+dwBaseIndex;
BYTE* pbyBits24Raw=lpbyBits24+dwBase24;
for(LONG j=0;j<w;j++)
{
BYTE byPixel=*(pbyDdbRaw++);
*(pbyBits24Raw++)=pRGBQuad[byPixel].rgbBlue;
*(pbyBits24Raw++)=pRGBQuad[byPixel].rgbGreen;
*(pbyBits24Raw++)=pRGBQuad[byPixel].rgbRed;
}
dwBaseIndex+=m_nDdbWidthBytes;
dwBase24+=dwWidthBytes24;
}
delete[]pRGBQuad;
break;
}
case 24:
{
DWORD dwLength=w*3;
BYTE* pbyDdbRaw=m_pDdbData+y*m_nDdbWidthBytes+x+x+x;
BYTE* pbyBits24Raw=lpbyBits24;
for(LONG i=0;i<h;i++)
{
::CopyMemory(pbyBits24Raw,pbyDdbRaw,dwLength);
pbyDdbRaw+=m_nDdbWidthBytes;
pbyBits24Raw+=dwWidthBytes24;
}
break;
}
case 16:
case 32:
{
DWORD dwBaseIndex=y*m_nDdbWidthBytes+((m_nBitCount==16)?(x+x):(4*x));
DWORD dwBase24=0;
for(LONG i=0;i<h;i++)
{
BYTE* pbyDdbRaw=m_pDdbData+dwBaseIndex;
DWORD dwBitsIndex24=(DWORD)(i*dwWidthBytes24);
BYTE* pbyBits24Raw=lpbyBits24+dwBase24;
for(LONG j=0;j<w;j++)
{
if(m_nBitCount==16)
{
BYTE* pbyRGB=new BYTE[3];
WORD* pwDdbData_16=(WORD*)(pbyDdbRaw++);
GetRGB16(pbyRGB,pwDdbData_16);
pbyDdbRaw++;
*pbyBits24Raw++=pbyRGB[0];
*pbyBits24Raw++=pbyRGB[1];
*pbyBits24Raw++=pbyRGB[2];
}
if(m_nBitCount==32)
{
*pbyBits24Raw++=*pbyDdbRaw++;
*pbyBits24Raw++=*pbyDdbRaw++;
*pbyBits24Raw++=*pbyDdbRaw++;
pbyDdbRaw++;
}
}
dwBaseIndex+=m_nDdbWidthBytes;
dwBase24+=dwWidthBytes24;
}
break;
}
}
}
void CDdb::GetDdbDataTo32(int x, int y, int nWidth, int nHeight, LPBYTE lpbyBits32)
{
ASSERT(lpbyBits32);
if((x>m_nWidth-1) || (y>nHeight-1))
{
AfxMessageBox("Cross the border!");
return;
}
LONG w=(LONG)min(nWidth,m_nWidth-x);
LONG h=(LONG)min(nHeight,m_nHeight-y);
DWORD dwWidthBytes32= w*4;
switch(m_nBitCount)
{
case 8:
{
RGBQUAD* pRGBQuad=new RGBQUAD[256];
if(pRGBQuad==NULL) return;
memset(pRGBQuad,0,256*sizeof(RGBQUAD));
GetSystemPaletteEntries(pRGBQuad);
DWORD dwBaseIndex=y*m_nDdbWidthBytes+x;
DWORD dwBase32=0;
for(LONG i=0;i<h;i++)
{
BYTE* pbyDdbRaw=m_pDdbData+dwBaseIndex;
BYTE* pbyBits32Raw=lpbyBits32+dwBase32;
for(LONG j=0;j<w;j++)
{
BYTE byPixel=*(pbyDdbRaw++);
*(pbyBits32Raw++)=pRGBQuad[byPixel].rgbBlue;
*(pbyBits32Raw++)=pRGBQuad[byPixel].rgbGreen;
*(pbyBits32Raw++)=pRGBQuad[byPixel].rgbRed;
pbyBits32Raw++;
}
dwBaseIndex+=m_nDdbWidthBytes;
dwBase32+=dwWidthBytes32;
}
delete[] pRGBQuad;
break;
}
case 24:
{
DWORD dwBaseIndex=y*m_nDdbWidthBytes+x+x+x;
DWORD dwBase32=0;
for(LONG i=0;i<h;i++)
{
BYTE* pbyDdbRaw=m_pDdbData+dwBaseIndex;
BYTE* pbyBits32Raw=lpbyBits32+dwBase32;
for(LONG j=0;j<w;j++)
{
*(pbyBits32Raw++)=*(pbyDdbRaw++);
*(pbyBits32Raw++)=*(pbyDdbRaw++);
*(pbyBits32Raw++)=*(pbyDdbRaw++);
pbyBits32Raw++;
}
dwBaseIndex+=m_nDdbWidthBytes;
dwBase32+=dwWidthBytes32;
}
break;
}
case 16:
{
DWORD dwBaseIndex=y*m_nDdbWidthBytes+x+x;
DWORD dwBase32=0;
for(LONG i=0;i<h;i++)
{
BYTE* pbyDdbRaw=m_pDdbData+dwBaseIndex;
DWORD dwBitsIndex32=(DWORD)(i*dwWidthBytes32);
BYTE* pbyBits32Raw=lpbyBits32+dwBase32;
for(LONG j=0;j<w;j++)
{
BYTE* pbyRGB=new BYTE[3];
WORD* pwDdbData_16=(WORD*)(pbyDdbRaw++);
GetRGB16(pbyRGB,pwDdbData_16);
pbyDdbRaw++;
*pbyBits32Raw++=pbyRGB[0];
*pbyBits32Raw++=pbyRGB[1];
*pbyBits32Raw++=pbyRGB[2];
pbyBits32Raw++;
delete[]pbyRGB;
}
dwBaseIndex+=m_nDdbWidthBytes;
dwBase32+=dwWidthBytes32;
}
break;
}
case 32:
{
DWORD dwLength=w*4;
DWORD dwBaseIndex=y*m_nDdbWidthBytes+4*x;
BYTE* pbyDdbRaw=m_pDdbData+dwBaseIndex;
BYTE* pbyBits32Raw=lpbyBits32;
for(LONG i=0;i<h;i++)
{
::CopyMemory(pbyBits32Raw,pbyDdbRaw,dwLength);
pbyDdbRaw+=m_nDdbWidthBytes;
pbyBits32Raw+=dwWidthBytes32;
}
break;
}
}
}
void CDdb::GetSystemPaletteEntries(RGBQUAD *pRGBQuad)
{
ASSERT(pRGBQuad);
HDC hdc=::GetDC(NULL);
PALETTEENTRY* paletteEntry=new PALETTEENTRY[256];
::GetSystemPaletteEntries(hdc,0,256,paletteEntry);
for(int index=0;index<256;index++)
{
pRGBQuad[index].rgbRed=paletteEntry[index].peRed;
pRGBQuad[index].rgbGreen=paletteEntry[index].peGreen;
pRGBQuad[index].rgbBlue=paletteEntry[index].peBlue;
pRGBQuad[index].rgbReserved=0;
}
delete[] paletteEntry;
::ReleaseDC(NULL,hdc);
}
void CDdb::QuantizeColor(LPBYTE lpbyDdbBits24, int nScanWidth, int nScanHeight,
LPBYTE lpbyDdbBits8, CPalette *pPalette)
{
ASSERT(lpbyDdbBits24);
ASSERT(lpbyDdbBits8);
//第一步:对颜色分布进行统计:
//COLORQUANTIZATION结构记录位于小颜色立方体中的像素个数, 颜色分量之和.
typedef struct tagCOLORQUANTIZATION
{
DWORD dwRedSum; //红色总量
DWORD dwGreenSum; //绿色总量
DWORD dwBlueSum; //蓝色总量
DWORD dwPixelCount; //进入一个Box的颜色个数
BYTE byFlag; //是否抛弃, 等于0则抛弃, 非0则不抛弃
}COLORQUANTIZATION;
//分配内存, 必须初始化为0
BYTE* pbyColorBox = new BYTE[252 * sizeof(COLORQUANTIZATION)];
if (pbyColorBox == NULL) return ;
memset(pbyColorBox, 0, 252 * sizeof(COLORQUANTIZATION));
//指向COLORQUANTIZATION数据的指针
COLORQUANTIZATION* pCQBox = (COLORQUANTIZATION*)pbyColorBox;
//每行的大小(字节)
DWORD dwWidthBytes24 = ((nScanWidth * 24 + 15) / 16) * 2;
DWORD dwWidthBytes8 = ((nScanWidth * 8 + 15) / 16) * 2;
//现在进行统计
DWORD dwBaseIndex24 = 0;
DWORD dwBaseIndex8 = 0;
int i, j;
for(i = 0; i < nScanHeight; i++)
{
//指向Ddb内存数据的指针(行)
BYTE* pbyDdb24 = lpbyDdbBits24 + dwBaseIndex24;
BYTE* pbyDdb8 = lpbyDdbBits8 + dwBaseIndex8;
for(j = 0; j < nScanWidth; j++)
{
//获取当前点的颜色分量
BYTE byBlue = *(pbyDdb24++);
BYTE byGreen = *(pbyDdb24++);
BYTE byRed = *(pbyDdb24++);
//计算当前颜色在立方体中的位置:由颜色三分量的值决定, 因而这也是颜色量化映射关系.
BYTE byIndexR = (byRed >= 210) ? 5 : (byRed / 42);
BYTE byIndexG = (byGreen >= 216) ? 6 : (byGreen / 36);
BYTE byIndexB = (byBlue >= 210) ? 5 : (byBlue / 42);
BYTE byInBox = 42 * byIndexB + 6 * byIndexG + byIndexR;
(pCQBox + byInBox)->dwPixelCount++;
(pCQBox + byInBox)->dwRedSum += byRed;
(pCQBox + byInBox)->dwGreenSum += byGreen;
(pCQBox + byInBox)->dwBlueSum += byBlue;
*(pbyDdb8++) = byInBox;
}
dwBaseIndex24 += dwWidthBytes24;
dwBaseIndex8 += dwWidthBytes8;
}
//第二步选出发生频率最高的236种颜色
//临时数组, 用于存放分布频数
DWORD* pdwFrequency = new DWORD[252];
for(i = 0; i < 252; i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -