2025-11-27 16:46:48 +09:00

548 lines
13 KiB
C++

// =============================================================================
// 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 <afxtempl.h>
#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;
}
/////////////////////////////////////////////////////////////////////////////