📄 pic.cpp
字号:
delete[] prgb ;
}
}
//===================================================================
void FCDib::__ConvertToTrueColor (int iColor)
{
if ((this->GetHandle() == NULL) || (this->ColorBits () == iColor))
return ;
// 保存原始数据
FCDib OldPic (* (FCDib *) this) ;
if (this->Create (OldPic.Width(), OldPic.Height(), iColor))
{
// 获取调色板
RGBQUAD * prgb = NULL ;
if (OldPic.ColorBits() <= 8)
{
prgb = new RGBQUAD [1 << OldPic.ColorBits()] ;
OldPic.GetColorTable (0, 1 << OldPic.ColorBits(), prgb) ;
}
// 颜色转换
int nNewSpan = this->ColorBits() / 8, // 3 or 4
nOldSpan = OldPic.ColorBits() / 8, x, y ;
BYTE * pNew, * pOld ;
for (y = 0 ; y < (int)this->Height() ; y++)
{
pNew = this->GetBits (y) ;
pOld = OldPic.GetBits (y) ;
switch (OldPic.ColorBits())
{
case 1 :
case 4 : // 1,4 ==> 24,32
for (x = 0 ; x < (int)this->Width() ; x++)
this->SetPixelColor (x, y, prgb[(BYTE)OldPic.GetPixelData (x, y)]) ;
break ;
case 8 : // 8 ==> 24,32
for (x = 0 ; x < (int)this->Width() ; x++, pNew += nNewSpan)
CopyMemory (pNew, &prgb[pOld[x]], nNewSpan) ;
break ;
case 16 : // 16 ==> 24,32
for (x = 0 ; x < (int)this->Width() ; x++, pNew += nNewSpan, pOld +=2)
CopyMemory (pNew, &OldPic.ParsePixelData (*(WORD *)pOld), 3) ;
break ;
case 24 :
case 32 : // 24,32 ==> 32,24
for (x = 0 ; x < (int)this->Width() ; x++, pNew += nNewSpan, pOld += nOldSpan)
CopyMemory (pNew, pOld, 3) ;
break ;
}
}
if (prgb != NULL)
delete[] prgb ;
}
}
//===================================================================
void FCDib::fooRGBtoHLS (RGBTRIPLE rgb, double * H, double * L, double * S)
{
double delta ;
double r = (double) rgb.rgbtRed / 255 ;
double g = (double) rgb.rgbtGreen / 255 ;
double b = (double) rgb.rgbtBlue / 255 ;
double cmax = max (r, max (g, b)) ;
double cmin = min (r, min (g, b)) ;
*L = (cmax+cmin) / 2.0 ;
if (cmax == cmin)
{
*S = 0 ;
*H = 0 ;
}
else
{
if (*L < 0.5)
*S = (cmax-cmin) / (cmax+cmin) ;
else
*S = (cmax-cmin) / (2.0-cmax-cmin) ;
delta = cmax - cmin ;
if (r == cmax)
*H = (g-b) / delta ;
else
if (g == cmax)
*H = 2.0 + (b-r) / delta ;
else
*H = 4.0 + (r-g) / delta ;
*H /= 6.0 ;
if (*H < 0.0)
*H += 1 ;
}
}
//===================================================================
double FCDib::__fooHuetoRGB (double m1, double m2, double h)
{
if (h < 0)
h += 1.0 ;
if (h > 1)
h -= 1.0 ;
if (6.0*h < 1)
return (m1+(m2-m1)*h*6.0) ;
if (2.0*h < 1)
return m2 ;
if (3.0*h < 2.0)
return (m1+(m2-m1)*((2.0/3.0)-h)*6.0) ;
return m1 ;
}
RGBTRIPLE FCDib::fooHLStoRGB (const double& H, const double& L, const double& S)
{
double r, g, b ;
double m1, m2 ;
if (S == 0)
r = g = b = L ;
else
{
if (L <= 0.5)
m2 = L * (1.0+S) ;
else
m2 = L + S - L*S ;
m1 = 2.0*L - m2 ;
r = FCDib::__fooHuetoRGB (m1, m2, H+1.0/3.0) ;
g = FCDib::__fooHuetoRGB (m1, m2, H) ;
b = FCDib::__fooHuetoRGB (m1, m2, H-1.0/3.0) ;
}
RGBTRIPLE retRGB ;
retRGB.rgbtRed = max (min ((int)(r*255), 0xFF), 0) ;
retRGB.rgbtGreen = max (min ((int)(g*255), 0xFF), 0) ;
retRGB.rgbtBlue = max (min ((int)(b*255), 0xFF), 0) ;
return retRGB ;
}
//===================================================================
BOOL FCDib::CopyToClipboard (const RECT * rect)
{
BOOL bRet = FALSE ;
if (this->GetHandle () != NULL)
if (rect == NULL)
{
if (::OpenClipboard (NULL))
{
HBITMAP ddb = this->GetDDB_Handle () ;
if (::EmptyClipboard () && (ddb != NULL))
bRet = (::SetClipboardData (CF_BITMAP, ddb) != NULL) ;
::CloseClipboard () ;
::DeleteObject (ddb) ;
}
}
else
{
FCDib block ;
if (this->GetSubBlock (&block, *rect))
return block.CopyToClipboard (NULL) ;
}
return bRet ;
}
BOOL FCDib::PasteFromClipboard (const RECT * rect)
{
BOOL bRet = FALSE ;
if (this->IsPasteAvailable ())
if (::OpenClipboard (NULL))
{
if (rect == NULL)
if (IsClipboardFormatAvailable (CF_BITMAP))
bRet = this->AttachDDB ((HBITMAP) ::GetClipboardData (CF_BITMAP), 32) ;
else
{
BITMAPINFOHEADER * bmif = (BITMAPINFOHEADER *)::GetClipboardData (CF_DIB) ;
bRet = this->Create (bmif->biWidth, bmif->biHeight, bmif->biBitCount) ;
CopyMemory (this->GetMemStart(), ++bmif, this->GetPitch()*this->Height()) ;
}
else
{
FCDib block ;
if (IsClipboardFormatAvailable (CF_BITMAP))
{
bRet = block.AttachDDB ((HBITMAP) ::GetClipboardData (CF_BITMAP), this->ColorBits ()) ;
bRet |= this->CoverBlock (block, rect->left, rect->top) ;
}
else
{
BITMAPINFOHEADER * bmif = (BITMAPINFOHEADER *)::GetClipboardData (CF_DIB) ;
bRet = block.Create (bmif->biWidth, bmif->biHeight, bmif->biBitCount) ;
CopyMemory (block.GetMemStart(), ++bmif, this->GetPitch()*this->Height()) ;
bRet |= this->CoverBlock (block, rect->left, rect->top) ;
}
}
::CloseClipboard() ;
}
return bRet ;
}
BOOL FCDib::IsPasteAvailable () {
return (IsClipboardFormatAvailable (CF_BITMAP) || IsClipboardFormatAvailable(CF_DIB)) ;
}
//===================================================================
void FCDib::GetRGBChannel (FCDib * red, FCDib * green, FCDib * blue, FCDib * alpha)
{
if (this->ColorBits() < 24)
return ;
if (red != NULL) red->Create (this->Width(), this->Height(), 8) ;
if (green != NULL) green->Create (this->Width(), this->Height(), 8) ;
if (blue != NULL) blue->Create (this->Width(), this->Height(), 8) ;
if ((alpha != NULL) && (this->ColorBits() == 32))
alpha->Create (this->Width(), this->Height(), 8) ;
int nSpan = this->ColorBits() / 8 ; // 3 or 4
for (DWORD y=0 ; y < this->Height () ; y++)
{
BYTE * pRed = (red == NULL) ? NULL : red->GetBits (y),
* pGreen = (green == NULL) ? NULL : green->GetBits (y),
* pBlue = (blue == NULL) ? NULL : blue->GetBits (y),
* pAlpha = NULL,
* pSource = this->GetBits (y) ;
if ((alpha != NULL) && (this->ColorBits() == 32))
pAlpha = alpha->GetBits (y) ;
for (DWORD x=0 ; x < this->Width () ; x++, pSource += nSpan)
{
if (blue != NULL)
pBlue[x] = pSource[0] ;
if (green != NULL)
pGreen[x] = pSource[1] ;
if (red != NULL)
pRed[x] = pSource[2] ;
if (pAlpha != NULL)
pAlpha[x] = pSource[3] ;
}
}
}
//===================================================================
void FCDib::CombineChannel (FCDib * red, FCDib * green, FCDib * blue, FCDib * alpha)
{
if ((red == NULL) && (green == NULL) && (blue == NULL) && (alpha == NULL))
return ;
int nWidth, nHeight ;
if (red != NULL) { nWidth = red->Width() ; nHeight = red->Height() ; }
if (green != NULL) { nWidth = green->Width() ; nHeight = green->Height() ; }
if (blue != NULL) { nWidth = blue->Width() ; nHeight = blue->Height() ; }
if (alpha != NULL) { nWidth = alpha->Width() ; nHeight = alpha->Height() ; }
if (!this->Create (nWidth, nHeight, (alpha == NULL) ? 24 : 32))
return ;
int nSpan = this->ColorBits() / 8 ; // 3 or 4
for (DWORD y=0 ; y < this->Height () ; y++)
{
BYTE * pRed = (red == NULL) ? NULL : red->GetBits (y),
* pGreen = (green == NULL) ? NULL : green->GetBits (y),
* pBlue = (blue == NULL) ? NULL : blue->GetBits (y),
* pAlpha = (alpha == NULL) ? NULL : alpha->GetBits (y),
* pDest = this->GetBits (y) ;
for (DWORD x=0 ; x < this->Width () ; x++, pDest += nSpan)
{
if (blue != NULL)
pDest[0] = pBlue[x] ;
if (green != NULL)
pDest[1] = pGreen[x] ;
if (red != NULL)
pDest[2] = pRed[x] ;
if (alpha != NULL)
pDest[3] = pAlpha[x] ;
}
}
}
//===================================================================
void FCDib::AppendAlphaChannel (const FCDib & alpha)
{
if ((this->ColorBits() == 32) && (alpha.ColorBits () == 8))
if ((this->Width() == alpha.Width()) && (this->Height() == alpha.Height()))
{
for (DWORD y=0 ; y < this->Height () ; y++)
{
BYTE * pAlpha = alpha.GetBits (y) ;
RGBQUAD * pDest = (RGBQUAD *) this->GetBits (y) ;
for (DWORD x=0 ; x < this->Width () ; x++)
pDest[x].rgbReserved = pAlpha[x] ;
}
}
}
//===================================================================
void FCDib::InvertAlphaChannel ()
{
if (this->ColorBits() == 32)
{
DWORD nNum = this->Width() * this->Height() ;
RGBQUAD * pPixel = (RGBQUAD *)this->GetMemStart () ;
for (DWORD i=0 ; i < nNum ; i++, pPixel++)
pPixel->rgbReserved = ~pPixel->rgbReserved ;
}
}
//===================================================================
bool FCDib::IsGrayPalette () const
{
bool bRet = false ;
if ((this->GetHandle () != NULL) && (this->ColorBits() <= 8))
{
int nNum = 1 << this->ColorBits () ;
RGBQUAD * pal = new RGBQUAD[nNum] ;
this->GetColorTable (0, nNum, pal) ;
bRet = true ;
for (int i=0 ; (i < nNum) && bRet ; i++)
if ((pal[i].rgbBlue == pal[i].rgbGreen) && (pal[i].rgbBlue == pal[i].rgbRed))
continue ;
else
bRet = false ;
delete[] pal ;
}
return bRet ;
}
//===================================================================
BOOL FCDib::GetSubBlock (FCDib * SubDib, const RECT & rcBlock) const
{
RECT now = {0, 0, this->Width(), this->Height()},
rcDest ;
if ((::IntersectRect (&rcDest, &now, &rcBlock) == 0) || (SubDib == NULL) || (SubDib == this)
|| (this->ColorBits () < 8))
return FALSE ; // 没有相交区域
int iRectW = rcDest.right - rcDest.left,
iRectH = rcDest.bottom - rcDest.top ;
if (!SubDib->Create (iRectW, iRectH, this->ColorBits()))
return FALSE ;
// 区域象素由上至下Copy
DWORD dwLength = iRectW * this->ColorBits() / 8 ;
DWORD dwPitch = this->GetPitch () ;
BYTE * pSrc = this->GetBits (rcDest.left, rcDest.top) ;
for (int i = 0 ; i < iRectH ; i++, pSrc -= dwPitch)
CopyMemory (SubDib->GetBits (i), pSrc, dwLength) ;
// 复制调色板
if (this->ColorBits() <= 8)
{
int nNum = 1 << this->ColorBits() ;
RGBQUAD * pal = new RGBQUAD[nNum] ;
this->GetColorTable (0, nNum, pal) ;
SubDib->SetColorTable (0, nNum, pal) ;
delete[] pal ;
}
return TRUE ;
}
//===================================================================
BOOL FCDib::CoverBlock (const FCDib & Dib, int x, int y)
{
RECT now = {0, 0, Width(), Height()} ,
sub = {x, y, x+Dib.Width(), y+Dib.Height()} ,
rcDest ;
if ((::IntersectRect (&rcDest, &now, &sub) == 0) || (this->ColorBits() != Dib.ColorBits())
|| (this->ColorBits() < 8))
return FALSE ; // 没有相交区域
int iRectW = rcDest.right - rcDest.left,
iRectH = rcDest.bottom - rcDest.top ;
DWORD dwSubPitch = iRectW * Dib.ColorBits() / 8 ;
DWORD dwPitch = this->GetPitch() ;
BYTE * pDest = this->GetBits (x, y) ;
for (int i = 0 ; i < iRectH ; i++, pDest -= dwPitch) // 由上至下Copy
CopyMemory (pDest, Dib.GetBits (i), dwSubPitch) ;
return TRUE ;
}
//===================================================================
void FCDib::RegionFill (RGBQUAD rgb, RECT * rect)
{
if (this->ColorBits() >= 16)
if (rect == NULL)
{
if (this->ColorBits () == 16)
* (WORD *) &rgb = FCDib::fooCombine16Bit_555 (&rgb) ;
int nSpan = this->ColorBits() / 8 ; // 2 or 3 or 4
for (int y=0 ; y < (int)this->Height() ; y++)
{
BYTE * pPixel = this->GetBits (y) ;
for (int x=0 ; x < (int)this->Width() ; x++, pPixel += nSpan)
CopyMemory (pPixel, &rgb, nSpan) ;
}
}
else
{
FCDib block ;
this->GetSubBlock (&block, *rect) ;
block.RegionFill (rgb, NULL) ;
this->CoverBlock (block, rect->left, rect->top) ;
}
}
//===================================================================
void FCDib::LogicalOperate (const FCDib & Dib, DWORD dwRop, int x, int y)
{
RECT dib1 = {0, 0, Width(), Height()},
dib2 = {x, y, x + Dib.Width(), y + Dib.Height()},
rcDest ;
if ((::IntersectRect (&rcDest, &dib1, &dib2) != 0) && (Dib.ColorBits() >= 24) && (this->ColorBits() >= 24))
{
int nNewSpan = this->ColorBits() / 8,
nOldSpan = Dib.ColorBits() / 8 ; // 3 or 4
for (int y=rcDest.top ; y < rcDest.bottom ; y++)
{
BYTE * pDest = this->GetBits (rcDest.left, y) ;
BYTE * pSrc = Dib.GetBits (y - rcDest.top) ;
for (int x=rcDest.left ; x < rcDest.right ; x++, pDest += nNewSpan, pSrc += nOldSpan)
{
switch (dwRop)
{
case LOG_OPERATION_AND :
pDest[0] &= pSrc[0] ; pDest[1] &= pSrc[1] ; pDest[2] &= pSrc[2] ; break ;
case LOG_OPERATION_OR :
pDest[0] |= pSrc[0] ; pDest[1] |= pSrc[1] ; pDest[2] |= pSrc[2] ; break ;
case LOG_OPERATION_XOR :
pDest[0] ^= pSrc[0] ; pDest[1] ^= pSrc[1] ; pDest[2] ^= pSrc[2] ; break ;
case LOG_OPERATION_ADD :
pDest[0] = max (0, min (0xFF, pSrc[0] + pDest[0])) ;
pDest[1] = max (0, min (0xFF, pSrc[1] + pDest[1])) ;
pDest[2] = max (0, min (0xFF, pSrc[2] + pDest[2])) ; break ;
case LOG_OPERATION_SUB :
pDest[0] = max (0, min (0xFF, pSrc[0] - pDest[0])) ;
pDest[1] = max (0, min (0xFF, pSrc[1] - pDest[1])) ;
pDest[2] = max (0, min (0xFF, pSrc[2] - pDest[2])) ; break ;
case LOG_OPERATION_MUL :
pDest[0] = max (0, min (0xFF, pSrc[0] * pDest[0])) ;
pDest[1] = max (0, min (0xFF, pSrc[1] * pDest[1])) ;
pDest[2] = max (0, min (0xFF, pSrc[2] * pDest[2])) ; break ;
}
}
}
}
}
//===================================================================
void FCDib::AlphaBlend (const FCDib & Dib, int alpha, int x, int y)
{
RECT dib1 = {0, 0, Width(), Height()},
dib2 = {x, y, x + Dib.Width(), y + Dib.Height()},
rcDest ;
if ((::IntersectRect (&rcDest, &dib1, &dib2) != 0) && (Dib.ColorBits() >= 24) && (this->ColorBits() >= 24))
{
int nNewSpan = this->ColorBits() / 8,
nOldSpan = Dib.ColorBits() / 8 ; // 3 or 4
for (int y=rcDest.top ; y < rcDest.bottom ; y++)
{
BYTE * pDest = this->GetBits (rcDest.left, y) ;
BYTE * pSrc = Dib.GetBits (y - rcDest.top) ;
for (int x=rcDest.left ; x < rcDest.right ; x++, pDest += nNewSpan, pSrc += nOldSpan)
{
pDest[0] = max (0, min (0xFF, (pSrc[0] - pDest[0]) * alpha / 0xFF + pDest[0])) ;
pDest[1] = max (0, min (0xFF, (pSrc[1] - pDest[1]) * alpha / 0xFF + pDest[1])) ;
pDest[2] = max (0, min (0xFF, (pSrc[2] - pDest[2]) * alpha / 0xFF + pDest[2])) ;
}
}
}
}
//===================================================================
void FCDib::AlphaBlend (const FCDib & Dib32, int x, int y)
{
RECT dib1 = {0, 0, Width(), Height()},
dib2 = {x, y, x + Dib32.Width(), y + Dib32.Height()},
rcDest ;
if ((::IntersectRect (&rcDest, &dib1, &dib2) != 0) && (Dib32.ColorBits() == 32) && (this->ColorBits() >= 24))
{
int nSpan = this->ColorBits() / 8 ; // 3 or 4
for (int y=rcDest.top ; y < rcDest.bottom ; y++)
{
BYTE * pDest = this->GetBits (rcDest.left, y) ;
RGBQUAD * pSrc = (RGBQUAD *) Dib32.GetBits (y - rcDest.top) ;
for (int x=rcDest.left ; x < rcDest.right ; x++, pDest += nSpan, pSrc++)
{
pDest[0] = max (0, min (0xFF, (pSrc->rgbBlue - pDest[0]) * pSrc->rgbReserved / 0xFF + pDest[0])) ;
pDest[1] = max (0, min (0xFF, (pSrc->rgbGreen - pDest[1]) * pSrc->rgbReserved / 0xFF + pDest[1])) ;
pDest[2] = max (0, min (0xFF, (pSrc->rgbRed - pDest[2]) * pSrc->rgbReserved / 0xFF + pDest[2])) ;
}
}
}
}
//===================================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -