📄 dib256.cpp
字号:
if( m_pPal )
pDC->SelectPalette( pOldPal, FALSE );
return nRet;
}
BITMAPINFO * CDIBitmap :: GetHeaderPtr() const {
ASSERT( m_pInfo );
ASSERT( m_pPixels );
return m_pInfo;
}
RGBQUAD * CDIBitmap :: GetColorTablePtr() const {
ASSERT( m_pInfo );
ASSERT( m_pPixels );
RGBQUAD* pColorTable = 0;
if( m_pInfo != 0 ) {
int cOffset = sizeof(BITMAPINFOHEADER);
pColorTable = (RGBQUAD*)(((BYTE*)(m_pInfo)) + cOffset);
}
return pColorTable;
}
BYTE * CDIBitmap :: GetPixelPtr() const {
// ASSERT( m_pInfo );
// ASSERT( m_pPixels );
return m_pPixels;
}
int CDIBitmap :: GetWidth() const {
ASSERT( m_pInfo );
return m_pInfo->bmiHeader.biWidth;
}
int CDIBitmap :: GetHeight() const {
ASSERT( m_pInfo );
return m_pInfo->bmiHeader.biHeight;
}
WORD CDIBitmap :: GetColorCount() const {
ASSERT( m_pInfo );
switch( m_pInfo->bmiHeader.biBitCount ) {
case 1: return 2;
case 4: return 16;
case 8: return 256;
default: return 0;
}
}
int CDIBitmap :: GetPalEntries() const {
ASSERT( m_pInfo );
return GetPalEntries( *(BITMAPINFOHEADER*)m_pInfo );
}
int CDIBitmap :: GetPalEntries( BITMAPINFOHEADER& infoHeader ) const {
int nReturn;
if( infoHeader.biClrUsed == 0 )
nReturn = ( 1 << infoHeader.biBitCount );
else
nReturn = infoHeader.biClrUsed;
return nReturn;
}
DWORD CDIBitmap :: GetBitsPerPixel() const {
ASSERT( m_pInfo );
return m_pInfo->bmiHeader.biBitCount;
}
DWORD CDIBitmap :: LastByte( DWORD dwBitsPerPixel, DWORD dwPixels ) const {
register DWORD dwBits = dwBitsPerPixel * dwPixels;
register DWORD numBytes = dwBits / 8;
register DWORD extraBits = dwBits - numBytes * 8;
return (extraBits % 8) ? numBytes+1 : numBytes;
}
DWORD CDIBitmap :: GetBytesPerLine() const {
return GetBytesPerLine(GetBitsPerPixel(), GetWidth());
}
DWORD CDIBitmap :: GetBytesPerLine( DWORD dwBitsPerPixel, DWORD dwWidth ) const {
DWORD dwBits = dwBitsPerPixel * dwWidth;
if( (dwBits % 32) == 0 )
return (dwBits/8); // already DWORD aligned, no padding needed
DWORD dwPadBits = 32 - (dwBits % 32);
return (dwBits/8 + dwPadBits/8 + (((dwPadBits % 8) > 0) ? 1 : 0));
}
BOOL CDIBitmap :: PadBits() {
if( m_bIsPadded )
return TRUE;
// dwAdjust used when bits per pixel spreads over more than 1 byte
DWORD dwAdjust = 1, dwOffset = 0, dwPadOffset=0;
BOOL bIsOdd = FALSE;
dwPadOffset = GetBytesPerLine(GetBitsPerPixel(), GetWidth());
dwOffset = LastByte(GetBitsPerPixel(), GetWidth());
if( dwPadOffset == dwOffset )
return TRUE;
BYTE * pTemp = new BYTE [GetWidth()*dwAdjust];
if( !pTemp ) {
TRACE1("CDIBitmap::PadBits(): could not allocate row of width %d.\n", GetWidth());
return FALSE;
}
// enough space has already been allocated for the bit array to
// include the padding, so we just need to shift rows around.
// This will pad each "row" on a DWORD alignment.
for( DWORD row = GetHeight()-1 ; row>0 ; --row ) {
CopyMemory((void *)pTemp, (const void *)(m_pPixels + (row*dwOffset)), dwOffset );
CopyMemory((void *)(m_pPixels + (row*dwPadOffset)), (const void *)pTemp, dwOffset);
}
delete [] pTemp;
return TRUE;
}
BOOL CDIBitmap::UnPadBits() {
if( ! m_bIsPadded )
return TRUE;
DWORD dwAdjust = 1;
BOOL bIsOdd = FALSE;
DWORD dwPadOffset = GetBytesPerLine(GetBitsPerPixel(), GetWidth());
DWORD dwOffset = LastByte(GetBitsPerPixel(), GetWidth());
BYTE * pTemp = new BYTE [dwOffset];
if( !pTemp ) {
TRACE1("CDIBitmap::UnPadBits() could not allocate row of width %d.\n", GetWidth());
return FALSE;
}
// enough space has already been allocated for the bit array to
// include the padding, so we just need to shift rows around.
for( DWORD row=1 ; row < DWORD(GetHeight()); ++row ) {
CopyMemory((void *)pTemp, (const void *)(m_pPixels + row*(dwPadOffset)), dwOffset);
CopyMemory((void *)(m_pPixels + (row*dwOffset)), (const void *)pTemp, dwOffset);
}
delete [] pTemp;
return TRUE;
}
BOOL CDIBitmap::Resize(DWORD dwWidth, DWORD dwHeight) {
ASSERT( m_pInfo );
ASSERT( m_pPixels );
try {
DWORD dwBitsPixel= GetBitsPerPixel();
int nBytePerPixel = dwBitsPixel / 8;
if (nBytePerPixel <= 0)
throw TEXT("Resizing not supported for other than 8 or 24 bit DIB's");
// Create a new pixel block
DWORD dwSizeImage = dwHeight * GetBytesPerLine(dwBitsPixel, dwHeight);
BYTE * pDIBDest = new BYTE[dwSizeImage];
if(!pDIBDest)
throw TEXT("Could not allocate memory for new DIB");
// Assign and precalculate some values, to use in the formula
// P = 2 * (D - S) with D is destination and S is Source
// When do we put a pixel extra or leave one out : (first version of formula)
// accumulator += P
// accumulator > S is the same as accumulator / S > 1
// We spotted some rounding errors --> second formula
// (accumulator + sign(accumulator)S) / 2 * S > 1 = divresult
// then accumulator -= 2 * S * divresult;
DWORD dwSourceWidth = GetWidth();
DWORD dwSourceHeight = GetHeight();
DWORD dwOffsetWidth = 2 * (dwWidth - dwSourceWidth);
DWORD dwOffsetHeight = 2 * (dwHeight - dwSourceHeight);
WORD * WidthCopyArray = new WORD[dwSourceWidth];
WORD * pWCpy = WidthCopyArray;
int nTempTotal=0;
int nAccumulator = 0;
int nDivResult = 0;
// Compute the transformation array for one scanline
int nSourceWidth = (int)dwSourceWidth;
int nDoubleSWidth = 2 * nSourceWidth;
for(register int Pixel = 0; Pixel < nSourceWidth; ++Pixel) {
// Per new pixel the acc must be incremented
nAccumulator += (int)dwOffsetWidth;
// Do we need to write a pixel
nDivResult = (nAccumulator + nSourceWidth * ((nAccumulator > 0) ? 1 : -1)) / nDoubleSWidth;
ASSERT(nDivResult >=-1);
if (nDivResult != 0)
// we needed to write or delete a pixel, so adjust the acc to account for that
nAccumulator -= nDoubleSWidth * nDivResult;
// write the number of pixels to write in the correct place in the array and
// move the array pointer one place further
*(pWCpy++) = (WORD)(nDivResult + 1);
#ifdef _DEBUG
nTempTotal += nDivResult + 1;
#endif
}
ASSERT(dwWidth == (DWORD)nTempTotal);
WORD * HeightCopyArray = new WORD[dwSourceHeight];
WORD * pHCpy = HeightCopyArray;
// Compute the transformation array for the different scanlines (= height DIB)
nTempTotal = 0;
nAccumulator = 0;
int nSourceHeight = (int)dwSourceHeight;
int nDoubleSHeight = 2 * nSourceHeight;
for(register int Scanline = 0; Scanline < nSourceHeight; ++Scanline) {
nAccumulator += (int)dwOffsetHeight;
nDivResult = (nAccumulator + nSourceHeight * ((nAccumulator > 0) ? 1 : -1)) / nDoubleSHeight;
ASSERT(nDivResult >=-1);
if (nDivResult != 0)
nAccumulator -= nDoubleSHeight * nDivResult;
*(pHCpy++) = (WORD)(nDivResult + 1);
#ifdef _DEBUG
nTempTotal += nDivResult + 1;
#endif
}
ASSERT(dwHeight == (DWORD)nTempTotal);
// Reset the transformation array pointers to their begin
pHCpy = HeightCopyArray;
pWCpy = WidthCopyArray;
// Get pointers to begin of each bitmap
BYTE * pSourceScanline = m_pPixels;
BYTE * pWithinSourceScanline = pSourceScanline;
BYTE * pDestScanline = pDIBDest;
BYTE * pWithinDestScanline = pDestScanline;
// Step through, resizing each pixel in each scan line
// to its required size
int OldScanline = 0;
ULONG ul;
while(OldScanline < nSourceHeight) {
// If equal to 0, this scanline disappears, so skip and proceed with next one
if(*pHCpy != 0) {
DWORD nDup = 0;
int OldPixel = 0;
pWCpy = WidthCopyArray;
// iterate the pixels on one scanline
while(OldPixel < nSourceWidth) {
nDup = *(pWCpy++);
// if the pixel we're dealing with has to be copied several times
while(nDup > 0) {
for(register int j = 0; j < nBytePerPixel; ++j)
*(pWithinDestScanline++) = *(pWithinSourceScanline + j);
--nDup;
}
pWithinSourceScanline += nBytePerPixel;
++OldPixel;
}
ASSERT((pWithinDestScanline - pDestScanline) == (LONG)dwWidth * nBytePerPixel);
ul = (ULONG)pWithinDestScanline;
ul += 3;
ul >>= 2;
ul <<= 2;
pWithinDestScanline = (LPBYTE)ul;
DWORD dwAlignedScanLineLength = pWithinDestScanline - pDestScanline;
nDup = 1;
while(nDup < *pHCpy) {
memcpy(pWithinDestScanline, pDestScanline, (size_t)dwAlignedScanLineLength);
pWithinDestScanline += dwAlignedScanLineLength;
nDup++;
}
// align the source and destination pointers on DWORD boundaries
ul = (ULONG)pWithinDestScanline;
ul +=3;
ul >>=2;
ul <<=2;
pWithinDestScanline = (LPBYTE)ul;
pDestScanline = pWithinDestScanline;
} else
pWithinSourceScanline += nSourceWidth * nBytePerPixel;
// align the source and destination pointers on DWORD boundaries
ul = (ULONG)pWithinSourceScanline;
ul += 3;
ul >>= 2;
ul <<= 2;
pWithinSourceScanline = (LPBYTE)ul;
OldScanline++;
pHCpy++;
}
delete [] WidthCopyArray;
delete [] HeightCopyArray;
// Release the old pixel buffer
delete [] m_pPixels;
m_pPixels = pDIBDest;
// adjust info header to new values
m_pInfo->bmiHeader.biWidth = dwWidth;
m_pInfo->bmiHeader.biHeight = dwHeight;
m_pInfo->bmiHeader.biSizeImage = dwSizeImage;
}
#ifdef _DEBUG
catch(LPCTSTR text)
#else
catch(LPCTSTR)
#endif
{
TRACE1("CDIBitmap::Resize(): %s\n", text);
return FALSE;
}
return TRUE;
}
BOOL CDIBitmap::MakeBitmap(CDC *pDC, CBitmap & Bitmap)
{
ASSERT_VALID(pDC);
// make sure the bitmap object is still empty
ASSERT(!Bitmap.m_hObject);
CBitmap* pBitmap2;
CDC newDC;
if(!newDC.CreateCompatibleDC(pDC))
return FALSE;
if(!Bitmap.CreateCompatibleBitmap(pDC, GetWidth(), GetHeight())) {
newDC.DeleteDC();
return FALSE;
}
pBitmap2 = newDC.SelectObject(&Bitmap);
::StretchDIBits(
newDC.GetSafeHdc(),
0,0,
GetWidth(), GetHeight(),
0,0,
GetWidth(), GetHeight(),
m_pPixels,
m_pInfo, DIB_RGB_COLORS,
SRCCOPY);
newDC.SelectObject(pBitmap2);
newDC.DeleteDC();
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -