// ============================================================================= // Class Implementation : COXSplashWnd // ============================================================================= // // Version: 9.3 // This software along with its related components, documentation and files ("The Libraries") // is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is // governed by a software license agreement ("Agreement"). Copies of the Agreement are // available at The Code Project (www.codeproject.com), as part of the package you downloaded // to obtain this file, or directly from our office. For a copy of the license governing // this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900. // ////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "OXSplashWnd.h" #ifdef OX_SPLASHWND_JPEG #include "OXDIB.h" #endif #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // helper class COXSplashWndDIB // Data members ------------------------------------------------------------- // protected: // DDB members: // CBitmap* m_pBitmap; // --- The loaded DDB bitmap // CPalette* m_pPalette; // --- The palette to use with the bitmap // DIB members: // BITMAPINFOHEADER m_bmih; // --- The original bitmap header // CByteArray m_bits; // --- The original bitmap bits // DWORD m_nWidthBits; // --- Bits per scan line // The following members are used for quick access // int m_xMax; // --- Maximum x value in bitmap (zero-based) // int m_yMax; // --- Maximum y value in bitmap (zero-based) // int m_nBitCount; // --- Bitmap bitcount // int m_nRightShift; // --- 8 - m_nBitCount // BOOL m_bTopdown; // --- Whether the bits are organized top-down or not // BYTE* m_pBits0; // ---- Pointer to the actual bits // private: // Member functions --------------------------------------------------------- // public: COXSplashWndDIB::COXSplashWndDIB() : m_pBitmap(NULL), m_pPalette(NULL), m_nWidthBits(0), m_xMax(0), m_yMax(0), m_nBitCount(0), m_nRightShift(0), m_bTopdown(FALSE), m_pBits0(NULL) { ::ZeroMemory(&m_bmih, sizeof(m_bmih)); } COXSplashWndDIB::~COXSplashWndDIB() { delete m_pBitmap; delete m_pPalette; } CBitmap* COXSplashWndDIB::GetBitmap() { return m_pBitmap; } BOOL COXSplashWndDIB::GetBitmapInfo(BITMAP& bm) { if (m_pBitmap == NULL) return FALSE; m_pBitmap->GetBitmap(&bm); return TRUE; } BOOL COXSplashWndDIB::LoadResource(LPCTSTR lpszResourceName, BOOL bPrepareGetPixel) { BOOL bResult = FALSE; HINSTANCE hInstance = NULL; HRSRC hRsrc = NULL; HGLOBAL hGlobal = NULL; HBITMAP hBitmapFinal = NULL; HPALETTE hPal = NULL; LPBITMAPINFOHEADER lpbi = NULL; HDC hdc = NULL; int iNumColors = 0; if (m_pBitmap != NULL) { delete m_pBitmap; m_pBitmap = NULL; } if (m_pPalette != NULL) { delete m_pPalette; m_pPalette = NULL; } hInstance = AfxFindResourceHandle(lpszResourceName, RT_BITMAP); if (hInstance != NULL) hRsrc = ::FindResource(hInstance, lpszResourceName, RT_BITMAP); if (hRsrc != NULL) hGlobal = ::LoadResource(hInstance, hRsrc); if (hGlobal != NULL) { lpbi = (LPBITMAPINFOHEADER)::LockResource(hGlobal); if (lpbi != NULL) { hdc = ::GetDC(NULL); if (hdc != NULL) { hPal = CreateDIBPalette ((LPBITMAPINFO)lpbi, iNumColors); if ((hPal == NULL) && (::GetDeviceCaps(hdc, SIZEPALETTE) == 256)) { // .... Trying to show bitmap without palette on 256-color display // so let's use halftone palette (better than nothing) hPal = ::CreateHalftonePalette(hdc); } if (hPal != NULL) { ::SelectPalette(hdc, hPal, FALSE); ::RealizePalette(hdc); } hBitmapFinal = ::CreateDIBitmap(hdc, (LPBITMAPINFOHEADER)lpbi, (LONG)CBM_INIT, (LPSTR)lpbi + lpbi->biSize + iNumColors * sizeof(RGBQUAD), (LPBITMAPINFO)lpbi, DIB_RGB_COLORS); if (hBitmapFinal != NULL) { m_pBitmap = new CBitmap; m_pBitmap->Attach(hBitmapFinal); if (hPal != NULL) { m_pPalette = new CPalette; m_pPalette->Attach(hPal); } if (bPrepareGetPixel) PrepareGetPixel(*lpbi, iNumColors); bResult = TRUE; } else { if(hPal!=NULL) ::DeleteObject((HGDIOBJ)hPal); } ::ReleaseDC(NULL,hdc); } ::UnlockResource(hGlobal); } ::FreeResource(hGlobal); } return bResult; } #ifdef OX_SPLASHWND_JPEG BOOL COXSplashWndDIB::LoadJPEGFile(LPCTSTR lpszFileName, BOOL bPrepareGetPixel) { BOOL bResult = FALSE; HBITMAP hBitmapFinal = NULL; HPALETTE hPal = NULL; LPBITMAPINFOHEADER lpbi = NULL; HDC hdc = NULL; int iNumColors = 0; COXDIB dib; if(!dib.ReadJPEG(lpszFileName)) return FALSE; CMemFile memFile; if (!dib.Write(&memFile,FALSE)) { memFile.Close(); return FALSE; } if (m_pBitmap != NULL) { delete m_pBitmap; m_pBitmap = NULL; } if (m_pPalette != NULL) { delete m_pPalette; m_pPalette = NULL; } if(memFile.GetLength()>0) { BYTE* pBuffer=(BYTE*)memFile.Detach(); if(pBuffer!=NULL) { pBuffer=pBuffer+14; lpbi=(LPBITMAPINFOHEADER)pBuffer; hdc=::GetDC(NULL); if(hdc!=NULL) { hPal=CreateDIBPalette((LPBITMAPINFO)lpbi,iNumColors); if((hPal==NULL) && (::GetDeviceCaps(hdc,SIZEPALETTE)==256)) { // .... Trying to show bitmap without palette on 256-color display // so let's use halftone palette (better than nothing) hPal=::CreateHalftonePalette(hdc); } if(hPal!=NULL) { SelectPalette(hdc,hPal,FALSE); RealizePalette(hdc); } hBitmapFinal=::CreateDIBitmap(hdc,(LPBITMAPINFOHEADER)lpbi, (LONG)CBM_INIT,(LPSTR)lpbi+lpbi->biSize+ iNumColors * sizeof(RGBQUAD),(LPBITMAPINFO)lpbi,DIB_RGB_COLORS); if(hBitmapFinal!=NULL) { m_pBitmap=new CBitmap; m_pBitmap->Attach(hBitmapFinal); if(hPal!=NULL) { m_pPalette=new CPalette; m_pPalette->Attach(hPal); } if (bPrepareGetPixel) PrepareGetPixel(*lpbi, iNumColors); bResult=TRUE; } else { if(hPal!=NULL) ::DeleteObject((HGDIOBJ)hPal); } ::ReleaseDC(NULL,hdc); } ::free(pBuffer-14); } } return bResult; } #endif BOOL COXSplashWndDIB::LoadFile(LPCTSTR lpszFileName, BOOL bPrepareGetPixel) { BOOL bResult = FALSE; HBITMAP hBitmapFinal = NULL; HPALETTE hPal = NULL; LPBITMAPINFOHEADER lpbi = NULL; HDC hdc = NULL; int iNumColors = 0; CFile file; CMemFile memFile; CFileException fileException; if(!file.Open(lpszFileName,CFile::modeRead|CFile::shareDenyWrite,&fileException)) { TRACE(_T("COXSplashWndDIB::LoadFile : Could not open DIB file : %s\n"), lpszFileName); return FALSE; } if(!CopyFile(&memFile,&file)) { TRACE(_T("COXSplashWndDIB::LoadFile : Could not copy DIB file : %s\n"), lpszFileName); return FALSE; } file.Close(); if (m_pBitmap != NULL) { delete m_pBitmap; m_pBitmap = NULL; } if (m_pPalette != NULL) { delete m_pPalette; m_pPalette = NULL; } if(memFile.GetLength()>0) { BYTE* pBuffer=(BYTE*)memFile.Detach(); if(pBuffer!=NULL) { pBuffer=pBuffer+14; lpbi=(LPBITMAPINFOHEADER)pBuffer; hdc=::GetDC(NULL); if(hdc!=NULL) { hPal=CreateDIBPalette((LPBITMAPINFO)lpbi,iNumColors); if((hPal==NULL) && (::GetDeviceCaps(hdc,SIZEPALETTE)==256)) { // .... Trying to show bitmap without palette on 256-color display // so let's use halftone palette (better than nothing) hPal=::CreateHalftonePalette(hdc); } if(hPal!=NULL) { SelectPalette(hdc,hPal,FALSE); RealizePalette(hdc); } hBitmapFinal=::CreateDIBitmap(hdc,(LPBITMAPINFOHEADER)lpbi, (LONG)CBM_INIT,(LPSTR)lpbi+lpbi->biSize+ iNumColors * sizeof(RGBQUAD),(LPBITMAPINFO)lpbi,DIB_RGB_COLORS); if(hBitmapFinal!=NULL) { m_pBitmap=new CBitmap; m_pBitmap->Attach(hBitmapFinal); if(hPal!=NULL) { m_pPalette=new CPalette; m_pPalette->Attach(hPal); } if (bPrepareGetPixel) PrepareGetPixel(*lpbi, iNumColors); bResult=TRUE; } else { if(hPal!=NULL) ::DeleteObject((HGDIOBJ)hPal); } ::ReleaseDC(NULL,hdc); } ::free(pBuffer-14); } } return bResult; } HPALETTE COXSplashWndDIB::CreateDIBPalette (LPBITMAPINFO lpbmi, int& nNumColors) { LPBITMAPINFOHEADER lpbi = NULL; LPLOGPALETTE lpPal = NULL; HANDLE hLogPal = NULL; HPALETTE hPal = NULL; int i = 0; // ... Initialize return variable nNumColors = 0; lpbi = (LPBITMAPINFOHEADER)lpbmi; if (lpbi->biBitCount <= 8) nNumColors = (1 << lpbi->biBitCount); else nNumColors = 0; // No palette needed for 24 BPP DIB if (lpbi->biClrUsed > 0) nNumColors = lpbi->biClrUsed; // Use biClrUsed if (nNumColors != 0) { hLogPal = ::GlobalAlloc (GHND, sizeof (LOGPALETTE) + sizeof (PALETTEENTRY) * nNumColors); lpPal = (LPLOGPALETTE) ::GlobalLock (hLogPal); lpPal->palVersion = (WORD)0x300; lpPal->palNumEntries = (WORD)nNumColors; for (i = 0; i < nNumColors; i++) { lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed; lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen; lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue; lpPal->palPalEntry[i].peFlags = 0; } hPal = ::CreatePalette (lpPal); ::GlobalUnlock (hLogPal); ::GlobalFree (hLogPal); } return hPal; } BOOL COXSplashWndDIB::Draw(CDC* pDC) { if (m_pBitmap == NULL) return FALSE; CDC dcImage; if (!dcImage.CreateCompatibleDC(pDC)) return FALSE; if (m_pPalette != NULL) { dcImage.SelectPalette(m_pPalette, FALSE); dcImage.RealizePalette(); pDC->SelectPalette(m_pPalette, FALSE); pDC->RealizePalette(); } BITMAP bm; m_pBitmap->GetBitmap(&bm); CBitmap* pOldBitmap = dcImage.SelectObject(m_pBitmap); pDC->BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dcImage, 0, 0, SRCCOPY); dcImage.SelectObject(pOldBitmap); return TRUE; } COLORREF COXSplashWndDIB::GetPixel(POINT pt) { return GetPixel(pt.x, pt.y); } COLORREF COXSplashWndDIB::GetPixel(int x, int y) { UINT nBitStart = 0; BYTE* pPixel = NULL; if (x < 0 || m_xMax < x || y < 0 || m_yMax < y) return CLR_INVALID; // retrieve bit data nBitStart = m_nBitCount * x + m_nWidthBits * (m_bTopdown ? y : (m_yMax - y)); pPixel = m_pBits0 + (nBitStart >> 3); if (m_nBitCount == 24) return RGB(*(pPixel+2), *(pPixel+1), *pPixel); ASSERT(m_pPalette && (m_nBitCount == 1 || m_nBitCount == 4 || m_nBitCount == 8)); BYTE nIndex = 0; nIndex = *pPixel; if (m_nBitCount < 8) { nIndex <<= (nBitStart & 7); nIndex >>= m_nRightShift; } PALETTEENTRY pe; if (m_pPalette->GetPaletteEntries(nIndex, 1, &pe)) return RGB(pe.peRed, pe.peGreen, pe.peBlue); return CLR_INVALID; } // protected: void COXSplashWndDIB::PrepareGetPixel(BITMAPINFOHEADER& bmih, int iNumColors) // --- In : bmih: The DIB // nNumColors : Number of colors in palette // --- Out : // --- Returns : // --- Effect : Prepares some internal variables for future GetPixel() calls. { // ... others are not supported ASSERT(bmih.biCompression == BI_RGB); ::CopyMemory(&m_bmih, &bmih, bmih.biSize); // DWROD aligned DWORD nWidthDWORD = (bmih.biWidth * bmih.biBitCount + 31) >> 5; m_nWidthBits = nWidthDWORD << 5; DWORD nSizeImage = (nWidthDWORD << 2) * abs(bmih.biHeight); m_bits.SetSize(nSizeImage); ::CopyMemory(m_bits.GetData(), (BYTE*)&bmih + bmih.biSize + iNumColors * sizeof(RGBQUAD), nSizeImage); // fill up cache values for GetPixel() m_xMax = m_bmih.biWidth - 1; m_yMax = abs(m_bmih.biHeight) - 1; m_bTopdown = (m_bmih.biHeight < 0); m_pBits0 = m_bits.GetData(); m_nBitCount = m_bmih.biBitCount; m_nRightShift = 8 - m_bmih.biBitCount; } BOOL COXSplashWndDIB::CopyFile(CFile* pDestFile, CFile* pSourceFile) { ASSERT(pDestFile!=NULL); ASSERT(pSourceFile!=NULL); // use buffers const int nBufferLength = 1024; BYTE pBuffer[nBufferLength + 1]; int nLengthRead(0); BOOL bSuccess = TRUE; TRY { do { nLengthRead = pSourceFile->Read(pBuffer, nBufferLength); pDestFile->Write(pBuffer, nLengthRead); } while (nLengthRead == nBufferLength); // So while not EOF } CATCH(CFileException, pxFile) { TRACE(_T("COXSplashWndDIB::CopyFile : Catching FileException (%XH)\n"), pxFile->m_cause); bSuccess = FALSE; } END_CATCH return bSuccess; } /////////////////////////////////////////////////////////////////////////////