⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dib256.cpp

📁 MiniWinOuterSM MiniWinOuterSM
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	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 + -