📄 pic.cpp
字号:
#include "stdafx.h"
#include "..\..\Include\Pic\Pic.h"
//===================================================================
BOOL FCDib::Create (int iWidth, int iHeight, WORD wColorBit)
{
if ((iHeight < 0) || (iWidth < 0))
return FALSE ; // 不支持自上而下存储的DIB
if (pFooDib->hBitmap != NULL)
this->Unload () ;
// retrieve screen's setting
if ((iWidth == 0) || (iHeight == 0) || (wColorBit == 0))
{
HDC hSrcDC = ::CreateIC (TEXT("display"), NULL, NULL, NULL) ;
if (iWidth == 0) iWidth = (DWORD) GetDeviceCaps (hSrcDC, HORZRES) ;
if (iHeight == 0) iHeight = (DWORD) GetDeviceCaps (hSrcDC, VERTRES) ;
if (wColorBit == 0) wColorBit = (WORD) GetDeviceCaps (hSrcDC, BITSPIXEL) ;
::DeleteDC(hSrcDC) ;
}
// create DIB info header
BITMAPINFOHEADER *bmhf = (BITMAPINFOHEADER *) new BYTE[sizeof(BITMAPINFO) + ((wColorBit <= 8) ? (4 * (1 << wColorBit)) : 0)] ;
bmhf->biSize = sizeof (*bmhf) ;
bmhf->biWidth = iWidth ;
bmhf->biHeight = iHeight ;
bmhf->biPlanes = 1 ;
bmhf->biBitCount = wColorBit ;
bmhf->biCompression = BI_RGB ;
// create DIBSection
pFooDib->hBitmap = CreateDIBSection (NULL, (BITMAPINFO *)bmhf, DIB_RGB_COLORS, (VOID **)(&pFooDib->pByte), NULL, 0) ;
delete[] bmhf ;
if (pFooDib->hBitmap == NULL)
return FALSE ;
// get created DIB's information
DIBSECTION DibInfo ;
::GetObject (pFooDib->hBitmap, sizeof (DIBSECTION), &DibInfo) ;
CopyMemory (&pFooDib->DibInfo, &DibInfo.dsBmih, sizeof (BITMAPINFOHEADER)) ;
pFooDib->DibInfo.biCompression = BI_RGB ; // if color == 16 bit, this field meybe be modified
// create a line pointer, to accelerate pixel access
pFooDib->ppLine = (BYTE **) new BYTE [sizeof(BYTE *) * iHeight] ;
DWORD dwPitch = this->GetPitch () ;
pFooDib->ppLine[0] = pFooDib->pByte + (iHeight - 1) * dwPitch ;
for (int Y = 1 ; Y < iHeight ; Y++)
pFooDib->ppLine[Y] = pFooDib->ppLine[Y - 1] - dwPitch ;
// if the DIB's color bit <= 8, set a gray palette to it
if (this->ColorBits() <= 8)
this->SetGrayPalette () ;
return TRUE ;
}
//===================================================================
HBITMAP FCDib::GetDDB_Handle (HDC hdc)
{
BITMAPINFOHEADER * pbmfh ;
int nNum = 1 << this->ColorBits() ;
HBITMAP hBitmap ;
bool bCreate = false ;
if (this->GetHandle() == NULL)
return NULL ;
if (hdc == NULL)
{
hdc = ::CreateIC (TEXT("DISPLAY"), NULL, NULL, NULL) ;
bCreate = true ;
}
pbmfh = (BITMAPINFOHEADER *) new BYTE [sizeof(BITMAPINFO) + ((ColorBits() <= 8) ? (nNum * 4) : 0)] ;
CopyMemory (pbmfh, &pFooDib->DibInfo, sizeof(BITMAPINFOHEADER)) ;
// 8 位以下色设置调色板
if (this->ColorBits() <= 8)
this->GetColorTable (0, nNum, (RGBQUAD *)(pbmfh + 1)) ;
hBitmap = CreateDIBitmap (hdc, (BITMAPINFOHEADER *)pbmfh, CBM_INIT,
(VOID *)pFooDib->pByte, (BITMAPINFO *)pbmfh, DIB_RGB_COLORS) ;
delete[] pbmfh ;
if (bCreate)
::DeleteDC (hdc) ;
return hBitmap ;
}
//===================================================================
void FCDib::Unload ()
{
if (pFooDib->ppLine != NULL)
delete[] pFooDib->ppLine ;
if (pFooDib->hBitmap != NULL)
::DeleteObject (pFooDib->hBitmap) ;
pFooDib->ppLine = NULL ;
pFooDib->hBitmap = NULL ;
pFooDib->pByte = NULL ;
::ZeroMemory (&pFooDib->DibInfo, sizeof(pFooDib->DibInfo)) ;
}
//===================================================================
DWORD FCDib::GetPixelData (int x, int y) const
{
BYTE * pPixel = this->GetBits (x, y) ;
DWORD dwrgb ;
switch (this->ColorBits ())
{
case 1 : return 0x01 & (* pPixel >> (7 - (x & 7))) ;
case 4 : return 0x0F & (* pPixel >> (x & 1 ? 0 : 4)) ;
case 8 : return * (BYTE *) pPixel ;
case 16 : return * (WORD *) pPixel ;
case 24 : CopyMemory (&dwrgb, pPixel, 3) ; return dwrgb ;
case 32 : return * (DWORD *) pPixel ;
}
return 0 ;
}
//===================================================================
RGBQUAD FCDib::ParsePixelData (DWORD dwData) const
{
RGBQUAD rgb ;
// 取得调色板索引
if (this->ColorBits() <= 8)
this->GetColorTable ((int)dwData, &rgb) ;
switch (this->ColorBits())
{
case 24 : CopyMemory (&rgb, &dwData, 3) ; break ;
case 32 : CopyMemory (&rgb, &dwData, 4) ; break ;
case 16 : rgb = fooSplit16Bit_555 ((WORD)dwData) ; break ;
}
return rgb ;
}
//===================================================================
void FCDib::SetPixelData (int x, int y, DWORD dwPixel)
{
BYTE * pPixel = this->GetBits (x, y) ;
switch (this->ColorBits ())
{
case 1 : * pPixel &= ~(1 << (7 - (x & 7))) ;
* pPixel |= dwPixel << (7 - (x & 7)) ;
break ;
case 4 : * pPixel &= 0x0F << (x & 1 ? 4 : 0) ;
* pPixel |= dwPixel << (x & 1 ? 0 : 4) ;
break ;
case 8 : * pPixel = (BYTE) dwPixel ;
break ;
case 16 : * (WORD *) pPixel = (WORD) dwPixel ;
break ;
case 24 : CopyMemory (pPixel, &dwPixel, 3) ;
break ;
case 32 : * (DWORD *) pPixel = dwPixel ;
break ;
default :
return ;
}
}
//===================================================================
// 只对 16, 24, 32 位色有效
void FCDib::SetPixelColor (int x, int y, RGBQUAD rgb)
{
DWORD dwPixel ;
switch (this->ColorBits())
{
case 24 :
case 32 : dwPixel = * (DWORD *) &rgb ; break ;
case 16 : dwPixel = (DWORD) fooCombine16Bit_555 (&rgb) ; break ;
default :
return ; // 不支持的格式
}
this->SetPixelData (x, y, dwPixel) ;
}
//===================================================================
BOOL FCDib::GetColorTable (int iFirstIndex, int iNumber, RGBQUAD * pColors) const
{
if ((this->GetHandle() == NULL) || (this->ColorBits() > 8) || (pColors == NULL))
return FALSE ;
HDC hdcMem = CreateCompatibleDC (NULL) ;
HBITMAP hBitmap = (HBITMAP) SelectObject (hdcMem, pFooDib->hBitmap) ;
BOOL iReturn = (BOOL)::GetDIBColorTable (hdcMem, iFirstIndex, iNumber, pColors) ;
SelectObject (hdcMem, hBitmap) ;
DeleteDC (hdcMem) ;
return iReturn ;
}
//===================================================================
BOOL FCDib::SetColorTable (int iFirstIndex, int iNumber, RGBQUAD * pColors)
{
if ((this->GetHandle() == NULL) || (this->ColorBits() > 8) || (pColors == NULL))
return FALSE ;
HDC hdcMem = CreateCompatibleDC (NULL) ;
HBITMAP hBitmap = (HBITMAP) SelectObject (hdcMem, pFooDib->hBitmap) ;
BOOL iReturn = (BOOL)::SetDIBColorTable (hdcMem, iFirstIndex, iNumber, pColors) ;
SelectObject (hdcMem, hBitmap) ;
DeleteDC (hdcMem) ;
return iReturn ;
}
//===================================================================
BOOL FCDib::AttachDDB (HBITMAP hBitmap, int iColor)
{
if (hBitmap == NULL)
return FALSE ;
BITMAP bm ;
GetObject (hBitmap, sizeof(BITMAP), &bm) ;
if (!this->Create ((int)bm.bmWidth, (int)bm.bmHeight, (WORD)iColor))
return FALSE ;
// set the dib's header you want to get
BITMAPINFOHEADER * pBmif ;
int nNum = 1 << iColor ;
pBmif = (BITMAPINFOHEADER *) new BYTE [sizeof(BITMAPINFO) + ((iColor <= 8) ? (4 * nNum) : 0)] ;
::CopyMemory (pBmif, &pFooDib->DibInfo, sizeof(*pBmif)) ;
// <=8会收到调色板, 手动设置
HDC hdc = CreateIC (TEXT("DISPLAY"), NULL, NULL, NULL) ;
::GetDIBits (hdc, hBitmap, 0, bm.bmHeight, this->GetMemStart(), (BITMAPINFO *)pBmif, DIB_RGB_COLORS) ;
if (iColor <= 8)
this->SetColorTable (0, nNum, (RGBQUAD*)(pBmif + 1)) ;
DeleteDC (hdc) ;
delete[] pBmif ;
return TRUE ;
}
//===================================================================
BOOL FCDib::CaptureScreen (LPRECT lpRect)
{
HDC hSrcDC = NULL, hMemDC = NULL ;
BOOL bRet = FALSE ;
__try
{
hSrcDC = CreateDC (TEXT("DISPLAY"), NULL, NULL, NULL) ;
if (hSrcDC == NULL)
__leave ;
if (GetDeviceCaps (hSrcDC, BITSPIXEL) <= 8) // palette format
__leave ;
hMemDC = CreateCompatibleDC (hSrcDC) ;
if (hMemDC == NULL)
__leave ;
RECT rect, rcSrc ;
rcSrc.left = rcSrc.top = 0 ;
rcSrc.right = GetDeviceCaps (hSrcDC, HORZRES) ;
rcSrc.bottom = GetDeviceCaps (hSrcDC, VERTRES) ;
if (lpRect != NULL)
::IntersectRect (&rect, &rcSrc, lpRect) ;
else
::CopyRect (&rect, &rcSrc) ;
if (!this->Create (rect.right - rect.left, rect.bottom - rect.top, GetDeviceCaps (hSrcDC, BITSPIXEL)))
__leave ;
HBITMAP hTemp = (HBITMAP) SelectObject (hMemDC, pFooDib->hBitmap) ;
bRet = ::BitBlt (hMemDC, 0, 0, rect.right - rect.left,
rect.bottom - rect.top,
hSrcDC, rect.left, rect.top, SRCCOPY) ;
SelectObject (hMemDC, hTemp) ; // 置换 hBitmap
}
__finally
{
if (hMemDC != NULL) DeleteDC (hMemDC) ;
if (hSrcDC != NULL) DeleteDC (hSrcDC) ;
}
return bRet ;
}
//===================================================================
void FCDib::ConvertColorTo (int iColor)
{
if (this->ColorBits () == iColor)
return ;
HBITMAP hBitmap = this->GetDDB_Handle () ;
this->AttachDDB (hBitmap, iColor) ;
::DeleteObject (hBitmap) ;
}
//===================================================================
FCDib & FCDib::operator= (const FCDib & pic)
{
if ((&pic != this) && (pic.GetHandle () != NULL))
if (this->Create (pic.Width (), pic.Height (), pic.ColorBits ()))
{
// pixel copy
::CopyMemory (this->GetMemStart (), pic.GetMemStart (), pic.GetPitch () * this->Height ()) ;
// palette copy
if (pic.ColorBits() <= 8)
{
int iColor = 1 << pic.ColorBits() ;
RGBQUAD * Palette = new RGBQUAD [iColor] ;
pic.GetColorTable (0, iColor, Palette) ;
this->SetColorTable (0, iColor, Palette) ;
delete[] Palette ;
}
}
return *this ;
}
//===================================================================
int FCDib::ColorsUsed () const
{
int iCounter = 0,
iMaxColor = 1 << (min (ColorBits(), 24)) ;
BYTE * pMap = (PBYTE) ::VirtualAlloc (NULL, iMaxColor + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE) ;
if (pMap != NULL)
{
// VirtualAlloc分配的mem已初始化为0
for (DWORD y = 0 ; y < this->Height() ; y++)
for (DWORD x = 0 ; x < this->Width() ; x++)
{
if (pMap[this->GetPixelData (x, y) & 0x00FFFFFF] == 0)
{
pMap[this->GetPixelData (x, y) & 0x00FFFFFF] = 1 ;
iCounter++ ;
}
if (iCounter == iMaxColor)
goto CountOver ;
}
CountOver :
::VirtualFree (pMap, 0, MEM_RELEASE) ;
}
return iCounter ;
}
//===================================================================
BOOL FCDib::TakeKeyColor (RGBQUAD * rgb)
{
BOOL bResult = FALSE ;
BYTE * pMap = NULL ;
if (this->ColorBits() <= 8)
return FALSE ;
__try
{
int iCounter = 0,
iMaxColor = 1 << min(ColorBits(), 24) ;
pMap = (BYTE *) ::VirtualAlloc (NULL, iMaxColor + 1, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE) ;
if (pMap == NULL)
__leave ;
// VirtualAlloc分配的mem已初始化为0
for (DWORD y = 0 ; y < this->Height() ; y++)
for (DWORD x = 0 ; x < this->Width() ; x++)
if (pMap[this->GetPixelData (x, y) & 0x00FFFFFF] == 0)
{
pMap[this->GetPixelData (x, y) & 0x00FFFFFF] = 1 ;
iCounter++ ;
if (iCounter == iMaxColor)
__leave ;
}
// 查找颜色
DWORD idx = 0 ;
while (!bResult)
if (pMap[idx] == 0)
{
* rgb = this->ParsePixelData (idx) ;
bResult = TRUE ;
}
else
idx++ ;
}
__finally
{
if (pMap != NULL)
::VirtualFree (pMap, 0, MEM_RELEASE) ;
}
return bResult ;
}
//===================================================================
void FCDib::SetGrayPalette ()
{
if ((this->GetHandle() != NULL) && (this->ColorBits() <= 8))
{
// 设置调色板
int nNum = 1 << this->ColorBits() ;
int nSpan = 255 / (nNum - 1) ;
RGBQUAD * palette = new RGBQUAD[nNum] ;
for (int i=0 ; i < nNum ; i++)
{
palette[i].rgbRed = palette[i].rgbGreen = palette[i].rgbBlue = i * nSpan ;
}
this->SetColorTable (0, nNum, palette) ;
delete[] palette ;
}
}
//===================================================================
void FCDib::ConvertToGray ()
{
if ((this->GetHandle() == NULL) || this->IsGrayPalette ())
return ;
// <= 8 bit, 直接修改调色板和索引值
if (this->ColorBits() <= 8)
{
int nNum = 1 << this->ColorBits() ;
RGBQUAD * palette = new RGBQUAD[nNum] ;
this->GetColorTable (0, nNum, palette) ;
for (int i=0 ; i < nNum ; i++)
{
int gray = FCDib::fooGetGrayscale (palette[i]) ;
palette[i].rgbBlue = gray ;
palette[i].rgbGreen = gray ;
palette[i].rgbRed = gray ;
}
// 修改索引
for (int y=0 ; y < (int)this->Height() ; y++)
for (int x=0 ; x < (int)this->Width() ; x++)
this->SetPixelData (x, y, *(DWORD*)&palette[this->GetPixelData (x, y)]);
delete[] palette ;
this->SetGrayPalette () ;
return ;
}
// 保存原始数据
FCDib OldDib (* (FCDib *) this) ;
if (this->Create (OldDib.Width(), OldDib.Height(), 8))
{
// 设置8位灰度调色板
this->SetGrayPalette () ;
// 设置象素
for (int y=0 ; y < (int)this->Height() ; y++)
{
BYTE * pDest = this->GetBits (y) ;
for (int x=0 ; x < (int)this->Width() ; x++)
{
RGBQUAD rgb ;
OldDib.GetPixelColor (x, y, &rgb) ;
*pDest++ = FCDib::fooGetGrayscale (rgb) ;
}
}
}
}
//===================================================================
void FCDib::ConvertTo16Bit ()
{
if ((this->GetHandle() == NULL) || (this->ColorBits () == 16))
return ;
// 保存原始数据
FCDib OldPic (* (FCDib *) this) ;
if (this->Create (OldPic.Width(), OldPic.Height(), 16))
{
// 获取调色板
RGBQUAD * prgb = NULL ;
if (OldPic.ColorBits() <= 8)
{
int nNum = 1 << OldPic.ColorBits() ;
prgb = new RGBQUAD [nNum] ;
OldPic.GetColorTable (0, nNum, prgb) ;
for (int i=0 ; i < nNum ; i++) // ==> 16
* (DWORD *) &prgb[i] = (DWORD) FCDib::fooCombine16Bit_555 (&prgb[i]) ;
}
// 颜色转换
int nOldSpan = OldPic.ColorBits() / 8, x, y ; // 3 or 4
for (y = 0 ; y < (int)this->Height() ; y++)
{
BYTE * pNew = this->GetBits (y) ;
BYTE * pOld = OldPic.GetBits (y) ;
switch (OldPic.ColorBits())
{
case 1 :
case 4 : // 1,4 ==> 16
for (x = 0 ; x < (int)this->Width() ; x++)
this->SetPixelData (x, y, *(DWORD *)&prgb[(BYTE)OldPic.GetPixelData (x, y)]) ;
break ;
case 8 : // 8 ==> 16
for (x = 0 ; x < (int)this->Width() ; x++, pNew += 2)
CopyMemory (pNew, &prgb[pOld[x]], 2) ;
break ;
case 24 :
case 32 : // 24,32 ==> 16
for (x = 0 ; x < (int)this->Width() ; x++, pNew += 2, pOld += nOldSpan)
* (WORD *) pNew = FCDib::fooCombine16Bit_555 ((RGBQUAD *)pOld) ;
break ;
}
}
if (prgb != NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -