📄 dib.cpp
字号:
//////////////////////////////////////////////////////////////////////////
//// Clipboard support
//---------------------------------------------------------------------
//
// Function: CopyToHandle
//
// Purpose: Makes a copy of the DIB to a global memory block. Returns
// a handle to the new memory block (NULL on error).
//
// Returns: Handle to new global memory block.
//
//---------------------------------------------------------------------
HGLOBAL CDIB::CopyToHandle()
{
CSharedFile file;
try
{
if (Save(file)==0)
return 0;
}
catch (CFileException* e)
{
e->Delete();
return 0;
}
return file.Detach();
}
//---------------------------------------------------------------------
//
// Function: ReadFromHandle
//
// Purpose: Initializes from the given global memory block.
//
// Returns: Number of read bytes.
//
//---------------------------------------------------------------------
DWORD CDIB::ReadFromHandle(HGLOBAL hGlobal)
{
CSharedFile file;
file.SetHandle(hGlobal, FALSE);
DWORD dwResult = Read(file);
file.Detach();
return dwResult;
}
//////////////////////////////////////////////////////////////////////////
//// Serialization support
void CDIB::Serialize(CArchive& ar)
{
CFile* pFile = ar.GetFile();
ASSERT(pFile != NULL);
if (ar.IsStoring())
{ // storing code
Save(*pFile);
}
else
{ // loading code
Read(*pFile);
}
}
//////////////////////////////////////////////////////////////////////////
//// Resource support
BOOL CDIB::ReadFromResource (UINT uResID)
{
HINSTANCE hInst = AfxGetInstanceHandle();
CString cstrResName;
//
// Find the bitmap resource
//
cstrResName.Format ("#%d",uResID);
HRSRC hResInfo = FindResource(hInst, cstrResName, "MY_BITMAP");
if (!hResInfo)
{
TRACE("CDIB: Failed to find resource %d.\n", uResID);
return FALSE;
}
//
// Load the bitmap resource
//
HANDLE hRes = LoadResource(hInst, hResInfo);
if (!hRes)
{
TRACE("CDIB: Failed to load resource %d.\n", uResID);
return FALSE;
}
//
// Lock the bitmap resource
//
PBYTE lpRes = (PBYTE)LockResource(hRes);
if (!lpRes)
{
TRACE("CDIB: Failed to lock resource.\n");
FreeResource(hRes);
return FALSE;
}
DWORD dwResSize = SizeofResource (hInst, hResInfo);
CMemFile memFile (lpRes, dwResSize);
DWORD dwBytesRead = Read (memFile);
FreeResource (hRes);
return (dwResSize == dwBytesRead);
}
//////////////////////////////////////////////////////////////////////////
//// Misc support
BOOL CDIB::CreateEmpty (UINT uXSize, UINT uYSize)
{
Free ();
m_pBMI = (LPBITMAPINFO)GlobalAllocPtr(GHND, sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD));
if (NULL == m_pBMI)
return FALSE;
// Clear palette to black
memset (m_pBMI->bmiColors, 120, 256 * sizeof(RGBQUAD));
DWORD dwBmBitsSize = WIDTHBYTES(uXSize*((DWORD)8)) * uYSize;
m_pBMI->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
m_pBMI->bmiHeader.biWidth = uXSize;
m_pBMI->bmiHeader.biHeight = uYSize;
m_pBMI->bmiHeader.biPlanes = 1;
m_pBMI->bmiHeader.biBitCount = 8;
m_pBMI->bmiHeader.biCompression = BI_RGB;
m_pBMI->bmiHeader.biSizeImage = dwBmBitsSize;
m_pBMI->bmiHeader.biXPelsPerMeter = 100;
m_pBMI->bmiHeader.biYPelsPerMeter = 100;
m_pBMI->bmiHeader.biClrUsed = 256;
m_pBMI->bmiHeader.biClrImportant = 256;
m_pBits = (LPBYTE)GlobalAllocPtr(GHND, dwBmBitsSize);
if (NULL == m_pBits)
{
GlobalFreePtr (m_pBMI);
return FALSE;
}
// Clear image to black
memset (m_pBits, 0, dwBmBitsSize);
return TRUE;
}
DWORD CDIB::CalcImageSize()
{
if ((m_pBMI->bmiHeader.biCompression == BI_RLE8) || (m_pBMI->bmiHeader.biCompression == BI_RLE4))
{
// It's an RLE bitmap, we can't calculate size, so trust the
// biSizeImage field
}
else
{
DWORD dwBmBitsSize; // Size of Bitmap Bits only
// It's not RLE, so size is Width (DWORD aligned) * Height
dwBmBitsSize = WIDTHBYTES((m_pBMI->bmiHeader.biWidth)*((DWORD)m_pBMI->bmiHeader.biBitCount)) *
m_pBMI->bmiHeader.biHeight;
// Now, since we have calculated the correct size, why don't we
// fill in the biSizeImage field (this will fix any .BMP files which
// have this field incorrect).
m_pBMI->bmiHeader.biSizeImage = dwBmBitsSize;
}
return m_pBMI->bmiHeader.biSizeImage;
}
void CDIB::FillSolidColor (BYTE R, BYTE G, BYTE B)
{
DWORD dwImageSize = CalcImageSize();
if (256<=NumColors())
{ // Palette based DIB
PIXEL ColorInd = PIXEL(m_pPalette->GetNearestPaletteIndex(RGB(R, G, B)));
memset (m_pBits, ColorInd, dwImageSize);
}
// We don't support non-palette DIBs for now
}
BOOL CDIB::CopyRectFrom (
CDIB *pSrcDIB,
int SrcX,
int SrcY,
UINT SrcWidth,
UINT SrcHeight,
int DstX, int DstY
)
{
if ((DstX >= int(Width())) || (DstY >= int(Height())))
return FALSE; // Completely out of region
if ((DstX + int(SrcWidth) < 0) || (DstY + int(SrcHeight)) < 0)
return FALSE; // Completely out of region
if (NumColors() != pSrcDIB->NumColors())
return FALSE; // Must have same color depth
if (NumColors() > 256)
return FALSE; // We currently don't support DIBs without palettes
if (DstX < 0)
{
SrcWidth += DstX;
SrcX -= DstX;
DstX = 0;
}
if (DstY < 0)
{
SrcHeight += DstY;
SrcY -= DstY;
DstY = 0;
}
DWORD dwSrcDIBWidth = pSrcDIB->Width();
DWORD dwSrcDIBHeight = pSrcDIB->Height();
DWORD dwMyWidth = Width();
ASSERT ((SrcX < int(dwSrcDIBWidth)) &&
(SrcY < int(dwSrcDIBHeight)));
ASSERT ((SrcX >= 0) && (SrcY >= 0));
SrcWidth = min (SrcWidth, UINT(dwMyWidth) - DstX);
SrcWidth = min (SrcWidth, UINT(dwSrcDIBWidth) - SrcX);
SrcHeight = min (SrcHeight, UINT(Height()) - DstY);
SrcHeight = min (SrcHeight, UINT(dwSrcDIBHeight) - SrcY);
PPIXEL pSrc = pSrcDIB->FindPixel(SrcX, SrcY);
PPIXEL pDst = FindPixel(DstX, DstY);
DWORD SrcInc = WIDTHBYTES(dwSrcDIBWidth << 3);
DWORD DstInc = WIDTHBYTES(dwMyWidth << 3);
for (UINT uCurHeight = 0; uCurHeight < SrcHeight; uCurHeight++)
{
memcpy (pDst, pSrc, SrcWidth);
pDst+= DstInc;
pSrc+= SrcInc;
}
return TRUE;
}
BOOL CDIB::CopyFrom (CDIB *pSrc)
{
DWORD dwWidth = Width(),
dwHeight= Height();
if (NULL == pSrc)
return FALSE; // Bad Src
if ((dwWidth != pSrc->Width()) ||
(dwHeight != pSrc->Height()) ||
(NumColors() != pSrc->NumColors())
)
return FALSE; // Bad size or color depth
memcpy (m_pBits, pSrc->m_pBits, m_pBMI->bmiHeader.biSizeImage);
return TRUE;
}
void CDIB::PasteCKRect (CDIB *Dib, int x, int y, PIXEL ColorKey)
{
// Clip Rect
int px,py,dx,dy,
mw = Width(), // My width
mh = Height(), // My height
ow = Dib->Width(), // Other's width
oh = Dib->Height(); // Other's height
if (x >= 0)
{
px = x;
dx = ((x + ow) < mw) ? ow : mw - x;
}
else
{
px = 0;
dx = x + (((x + ow) < mw) ? ow : mw - x);
}
if (y >= 0)
{
py = y;
dy = ((y + oh) < mh) ? oh : mh - y;
}
else
{
py = 0;
dy = y + (((y + oh) < mh) ? oh : mh - y);
}
// If Nothing to Paste return
if ( (dx <= 0) || (dy <= 0) )
return;
// Prepare Buffer Addresses
PPIXEL src = Dib->FindPixel (px-x, py-y);
PPIXEL dst = FindPixel (px, py);
DWORD SrcInc = WIDTHBYTES(ow << 3);
DWORD DstInc = WIDTHBYTES(mw << 3);
// Do Paste
while ( dy-- )
{
for ( int i=0; i<dx; i++ )
if (src[i] != ColorKey)
dst[i]=src[i];
src+=SrcInc;
dst+=DstInc;
}
}
void CDIB::FillRect (int x, int y, int w, int h, int R, int G, int B )
{
// Clip Rect
int iWidth = int(Width());
int iHeight = int(Height());
int px=(x>=0) ? x : 0;
int py=(y>=0) ? y : 0;
int dx=((x+w)<iWidth) ? w : iWidth-x;
int dy=((y+h)<iHeight) ? h : iHeight-y;
dx=(x>=0) ? dx : dx + x;
dy=(y>=0) ? dy : dy + y;
// If Nothing to Fill return
if ( (dx<=0) || (dy<=0) )
return;
// Prepare Buffer Address
PPIXEL dst = FindPixel (px, py);
PIXEL ColorInd = PIXEL(m_pPalette->GetNearestPaletteIndex(RGB(R, G, B)));
DWORD DstInc = WIDTHBYTES(iWidth << 3);
// Do Fill
while ( dy-- )
{
memset (dst, ColorInd, dx);
dst+=DstInc;
}
}
BOOL CDIB::CreateRotated (CDIB *pSrc, UINT uAngle /* 0, 90, 180 or 270 only */, BOOL bFlipHoriz, BOOL bFlipVert)
{
ASSERT (uAngle == 0 || uAngle == 90 || uAngle == 180 || uAngle == 270);
UINT uSrcWidth = pSrc->Width();
UINT uSrcHeight= pSrc->Height();
UINT uDstWidth;
UINT uDstHeight;
if (uAngle == 180)
return CreateRotated (pSrc, 0, !bFlipHoriz, !bFlipVert);
if (uAngle == 270)
return CreateRotated (pSrc, 90, !bFlipHoriz, !bFlipVert);
BOOL bSuccess;
if (uAngle == 0)
{
bSuccess = CreateEmpty (uSrcWidth, uSrcHeight);
uDstWidth = uSrcWidth;
uDstHeight = uSrcHeight;
}
else
{
bSuccess = CreateEmpty (uSrcHeight, uSrcWidth);
uDstWidth = uSrcHeight;
uDstHeight = uSrcWidth;
}
if (!bSuccess)
return FALSE; // Can't create
for (int x = 0; x < int(uDstWidth); x++)
for (int y = 0; y < int(uDstHeight); y++)
switch (uAngle)
{
case 0:
ColorAt (x, y) = pSrc->ColorAt ((bFlipHoriz ? uDstWidth-1-x : x), (bFlipVert ? uDstHeight-1-y : y));
break;
case 90:
ColorAt (x, y) =
pSrc->ColorAt ((bFlipVert ? uSrcWidth-1-y : y), (bFlipHoriz ? x : ( uSrcHeight-1-x )));
break;
default:
ASSERT (FALSE);
}
return TRUE;
}
BOOL CDIB::CopyPalette (CDIB *pSrc)
{
if ((NULL == pSrc) || (NULL == pSrc->m_pPalette))
return FALSE; // Bad source or source has no palette
BOOL bRes = CopyPalette (pSrc->m_pPalette);
if (bRes)
{
memcpy (m_pBMI->bmiColors, pSrc->m_pBMI->bmiColors, 256 * sizeof (RGBQUAD));
}
return bRes;
}
BOOL CDIB::CopyPalette (CPalette *pPal)
{
if (NULL == pPal)
return FALSE;
if (m_pPalette)
{
m_pPalette->DeleteObject();
delete m_pPalette;
m_pPalette = NULL;
}
UINT uNumColors = pPal->GetEntryCount();
// allocate memory block for logical palette
HANDLE hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*uNumColors);
// 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)uNumColors;
UINT uCount = pPal->GetPaletteEntries(0, uNumColors, lpPal->palPalEntry);
if (uCount != uNumColors)
{
::GlobalUnlock((HGLOBAL) hLogPal);
::GlobalFree((HGLOBAL) hLogPal);
return FALSE;
}
m_pPalette = new CPalette;
BOOL bResult = m_pPalette->CreatePalette(lpPal);
::GlobalUnlock((HGLOBAL) hLogPal);
::GlobalFree((HGLOBAL) hLogPal);
return bResult;
}
BOOL CDIB::GetPaletteFromResourceBitmap (UINT uResID)
{
CDIB tmpDIB;
if (!tmpDIB.ReadFromResource(uResID))
return FALSE;
return CopyPalette (&tmpDIB);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -