Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

652 lines
16 KiB

#include "stdafx.h"
#include "resource.h"
#include "imgutil.h"
#include "cdithtbl.h"
#include "dithers.h"
#include "cdith8.h"
#include "align.h"
#include "cddsurf.h"
//#include <icapexp.h>
void CopyColorsFromPaletteEntries(RGBQUAD *prgb, const PALETTEENTRY *ppe, UINT uCount);
CDitherTable* CDitherToRGB8::s_apTableCache[MAX_DITHERTABLE_CACHE_SIZE];
ULONG CDitherToRGB8::s_nCacheSize;
CRITICAL_SECTION CDitherToRGB8::s_csCache;
void CDitherToRGB8::InitTableCache()
{
ULONG iTable;
InitializeCriticalSection( &s_csCache );
s_nCacheSize = 0;
for( iTable = 0; iTable < MAX_DITHERTABLE_CACHE_SIZE; iTable++ )
{
s_apTableCache[iTable] = NULL;
}
}
void CDitherToRGB8::CleanupTableCache()
{
ULONG iTable;
EnterCriticalSection( &s_csCache );
for( iTable = 0; iTable < s_nCacheSize; iTable++ )
{
_ASSERTE( s_apTableCache[iTable]->m_nRefCount == 0 );
delete s_apTableCache[iTable];
s_apTableCache[iTable] = NULL;
}
s_nCacheSize = 0;
LeaveCriticalSection( &s_csCache );
DeleteCriticalSection( &s_csCache );
}
CDitherToRGB8::CDitherToRGB8() :
m_dwEvents( 0 ),
m_iScanLine( 0 ),
m_bProgressiveDither( FALSE ),
m_pErrBuf( NULL ),
m_pErrBuf1( NULL ),
m_pErrBuf2( NULL ),
m_pTable( NULL ),
m_pbBits( NULL ),
m_hbmDestDib( NULL )
{
}
CDitherToRGB8::~CDitherToRGB8()
{
if (m_pTable)
m_pTable->m_nRefCount--;
if (m_hbmDestDib)
DeleteObject(m_hbmDestDib);
}
STDMETHODIMP CDitherToRGB8::GetSurface( LONG nWidth, LONG nHeight,
REFGUID bfid, ULONG nPasses, DWORD dwHints, IUnknown** ppSurface )
{
HRESULT hResult;
CComPtr< IUnknown > pDestSurface;
if (ppSurface != NULL)
*ppSurface = NULL;
if ((nWidth <= 0) || (nHeight <= 0))
return E_INVALIDARG;
if (ppSurface == NULL)
return E_POINTER;
if (IsEqualGUID(bfid, BFID_RGB_24))
{
m_eSrcFormat = RGB24;
m_nBitsPerPixel = 24;
}
else if (IsEqualGUID(bfid, BFID_INDEXED_RGB_8))
{
m_eSrcFormat = RGB8;
m_nBitsPerPixel = 8;
}
else
return E_NOINTERFACE;
m_nWidth = nWidth;
m_nHeight = nHeight;
if ((dwHints & IMGDECODE_HINT_TOPDOWN) &&
(dwHints & IMGDECODE_HINT_FULLWIDTH) &&
(m_dwEvents & IMGDECODE_EVENT_PROGRESS))
m_bProgressiveDither = TRUE;
else
m_bProgressiveDither = FALSE;
m_pErrBuf = new ERRBUF[(m_nWidth+2)*2];
if (m_pErrBuf == NULL)
return E_OUTOFMEMORY;
m_pErrBuf1 = &m_pErrBuf[1];
m_pErrBuf2 = &m_pErrBuf[m_nWidth+3];
memset(m_pErrBuf, 0, sizeof( ERRBUF )*(m_nWidth+2)*2);
hResult = m_pEventSink->GetSurface(m_nWidth, m_nHeight, BFID_INDEXED_RGB_8,
nPasses, dwHints, &pDestSurface);
if (FAILED(hResult))
return( hResult );
hResult = pDestSurface->QueryInterface(IID_IDirectDrawSurface,
(void **)&m_pDestSurface);
if (FAILED(hResult))
return hResult;
m_hbmDestDib = ImgCreateDib(m_nWidth, -LONG(m_nHeight), FALSE, m_nBitsPerPixel, 0, NULL,
&m_pbBits, (int *)&m_nPitch);
if (m_hbmDestDib == NULL)
return E_OUTOFMEMORY;
hResult = CreateDDrawSurfaceOnDIB(m_hbmDestDib, &m_pSurface);
if (FAILED(hResult))
return hResult;
*ppSurface = (IUnknown *)m_pSurface;
(*ppSurface)->AddRef();
return S_OK;
}
STDMETHODIMP CDitherToRGB8::OnBeginDecode( DWORD* pdwEvents, ULONG* pnFormats,
GUID** ppFormats )
{
HRESULT hResult;
GUID* pFormats;
ULONG nFormats;
ULONG iFormat;
BOOL bFound;
if( pdwEvents != NULL )
{
*pdwEvents = 0;
}
if( pnFormats != NULL )
{
*pnFormats = 0;
}
if( ppFormats != NULL )
{
*pnFormats = NULL;
}
if( pdwEvents == NULL )
{
return( E_POINTER );
}
if( pnFormats == NULL )
{
return( E_POINTER );
}
if( ppFormats == NULL )
{
return( E_POINTER );
}
hResult = m_pEventSink->OnBeginDecode( &m_dwEvents, &nFormats, &pFormats );
if( FAILED( hResult ) )
{
return( hResult );
}
bFound = FALSE;
for( iFormat = 0; (iFormat < nFormats) && !bFound; iFormat++ )
{
if( IsEqualGUID( pFormats[iFormat], BFID_INDEXED_RGB_8 ) )
{
bFound = TRUE;
}
}
CoTaskMemFree( pFormats );
if( !bFound )
{
return( E_FAIL );
}
*ppFormats = (GUID*)CoTaskMemAlloc( 3*sizeof( GUID ) );
if( *ppFormats == NULL )
{
return( E_OUTOFMEMORY );
}
*pnFormats = 3;
(*ppFormats)[0] = BFID_GRAY_8;
(*ppFormats)[1] = BFID_RGB_24;
(*ppFormats)[2] = BFID_INDEXED_RGB_8;
*pdwEvents = m_dwEvents|IMGDECODE_EVENT_BITSCOMPLETE|
IMGDECODE_EVENT_PALETTE;
return( S_OK );
}
STDMETHODIMP CDitherToRGB8::OnBitsComplete()
{
HRESULT hResult;
hResult = DitherFull();
if( FAILED( hResult ) )
{
return( hResult );
}
if( m_dwEvents & IMGDECODE_EVENT_BITSCOMPLETE )
{
hResult = m_pEventSink->OnBitsComplete();
if( FAILED( hResult ) )
{
return( hResult );
}
}
return( S_OK );
}
STDMETHODIMP CDitherToRGB8::OnDecodeComplete( HRESULT hrStatus )
{
HRESULT hResult;
delete m_pErrBuf;
m_pErrBuf = NULL;
m_pErrBuf1 = NULL;
m_pErrBuf2 = NULL;
// Propagate the transparency information if necessary
if (m_pSurface && m_pDestSurface)
{
DDCOLORKEY ddKey;
if (SUCCEEDED(m_pSurface->GetColorKey(DDCKEY_SRCBLT, &ddKey)))
m_pDestSurface->SetColorKey(DDCKEY_SRCBLT, &ddKey);
}
if( m_pSurface != NULL )
{
m_pSurface.Release();
}
if( m_pDestSurface != NULL )
{
m_pDestSurface.Release();
}
hResult = m_pEventSink->OnDecodeComplete( hrStatus );
m_pEventSink.Release();
if( FAILED( hResult ) )
{
return( hResult );
}
return( S_OK );
}
STDMETHODIMP CDitherToRGB8::OnPalette()
{
HRESULT hResult;
CComPtr< IDirectDrawPalette > pPalette;
PALETTEENTRY ape[256];
if (m_eSrcFormat == RGB8)
{
hResult = m_pSurface->GetPalette(&pPalette);
if (FAILED(hResult))
return hResult;
hResult = pPalette->GetEntries(0, 0, 256, ape);
if (FAILED(hResult))
return hResult;
CopyColorsFromPaletteEntries(m_argbSrcColors, ape, 256);
}
if (m_dwEvents & IMGDECODE_EVENT_PALETTE)
{
hResult = m_pEventSink->OnPalette();
if (FAILED(hResult))
{
return hResult;
}
}
return S_OK;
}
STDMETHODIMP CDitherToRGB8::OnProgress( RECT* pBounds, BOOL bComplete )
{
HRESULT hResult;
if( pBounds == NULL )
{
return( E_INVALIDARG );
}
if( m_bProgressiveDither && bComplete )
{
hResult = DitherBand( pBounds );
if( FAILED( hResult ) )
{
return( hResult );
}
}
else
{
hResult = ConvertBlock( pBounds );
if( FAILED( hResult ) )
{
return( hResult );
}
}
if( m_dwEvents & IMGDECODE_EVENT_PROGRESS )
{
hResult = m_pEventSink->OnProgress( pBounds, bComplete );
if( FAILED( hResult ) )
{
return( hResult );
}
}
return( S_OK );
}
STDMETHODIMP CDitherToRGB8::SetDestColorTable( ULONG nColors,
const RGBQUAD* prgbColors )
{
ULONG iTable;
HRESULT hResult;
if( (nColors == 0) || (nColors > 256) )
{
return( E_INVALIDARG );
}
if( prgbColors == NULL )
{
return( E_INVALIDARG );
}
EnterCriticalSection( &s_csCache );
if( m_pTable != NULL )
{
// Release whatever table we've got already
m_pTable->m_nRefCount--;
m_pTable = NULL;
}
// See if we can find the requested table in the cache
for( iTable = 0; (iTable < s_nCacheSize) && (m_pTable == NULL); iTable++ )
{
if( s_apTableCache[iTable]->Match( nColors, prgbColors ) )
{
m_pTable = s_apTableCache[iTable];
m_pTable->m_nRefCount++;
}
}
if( m_pTable == NULL )
{
if( s_nCacheSize < MAX_DITHERTABLE_CACHE_SIZE )
{
m_pTable = new CDitherTable;
if( m_pTable == NULL )
{
LeaveCriticalSection( &s_csCache );
return( E_OUTOFMEMORY );
}
hResult = m_pTable->SetColors( nColors, prgbColors );
if( FAILED( hResult ) )
{
LeaveCriticalSection( &s_csCache );
m_pTable = NULL;
return( hResult );
}
// Add a new cache entry
m_pTable->m_nRefCount++;
s_apTableCache[s_nCacheSize] = m_pTable;
s_nCacheSize++;
}
else
{
// Find a cache entry to replace.
for( iTable = 0; (iTable < s_nCacheSize) && (m_pTable == NULL);
iTable++ )
{
if( s_apTableCache[iTable]->m_nRefCount == 0 )
{
m_pTable = s_apTableCache[iTable];
hResult = m_pTable->SetColors( nColors, prgbColors );
if( FAILED( hResult ) )
{
LeaveCriticalSection( &s_csCache );
m_pTable = NULL;
return( hResult );
}
m_pTable->m_nRefCount++;
}
}
}
}
_ASSERTE( m_pTable != NULL );
LeaveCriticalSection( &s_csCache );
return( S_OK );
}
STDMETHODIMP CDitherToRGB8::SetEventSink( IImageDecodeEventSink* pEventSink )
{
if( pEventSink == NULL )
{
return( E_INVALIDARG );
}
m_pEventSink = pEventSink;
return( S_OK );
}
HRESULT CDitherToRGB8::ConvertBlock( RECT* pBounds )
{
HRESULT hResult;
void* pSrcBits;
void* pDestBits;
LONG nSrcPitch;
LONG nDestPitch;
DDSURFACEDESC ddsd;
_ASSERTE( pBounds->left == 0 );
_ASSERTE( pBounds->right == LONG( m_nWidth ) );
ddsd.dwSize = sizeof(ddsd);
hResult = m_pSurface->Lock(pBounds, &ddsd, 0, 0);
if (FAILED(hResult))
return hResult;
pSrcBits = ddsd.lpSurface;
nSrcPitch = ddsd.lPitch;
hResult = m_pDestSurface->Lock(pBounds, &ddsd, 0, 0);
if (FAILED(hResult))
{
m_pSurface->Unlock(pSrcBits);
return hResult;
}
pDestBits = ddsd.lpSurface;
nDestPitch = ddsd.lPitch;
switch( m_eSrcFormat )
{
case RGB24:
Convert24to8(LPBYTE(pDestBits), LPBYTE(pSrcBits), nDestPitch,
nSrcPitch, m_pTable->m_abInverseMap, pBounds->left,
pBounds->right-pBounds->left, pBounds->top,
pBounds->bottom-pBounds->top );
break;
case RGB8:
Convert8to8( LPBYTE( pDestBits ), LPBYTE( pSrcBits ), nDestPitch,
nSrcPitch, m_argbSrcColors, m_pTable->m_abInverseMap, pBounds->left,
pBounds->right-pBounds->left, pBounds->top,
pBounds->bottom-pBounds->top );
break;
default:
return E_FAIL;
break;
}
m_pDestSurface->Unlock(pDestBits);
m_pSurface->Unlock(pSrcBits);
return S_OK;
}
HRESULT CDitherToRGB8::DitherBand( RECT* pBounds )
{
HRESULT hResult;
void* pSrcBits;
void* pDestBits;
LONG nSrcPitch;
LONG nDestPitch;
LONG lDestTrans = -1;
LONG lSrcTrans = -1;
DDSURFACEDESC ddsd;
DDCOLORKEY ddColorKey;
_ASSERTE( pBounds->left == 0 );
_ASSERTE( pBounds->right == LONG( m_nWidth ) );
ddsd.dwSize = sizeof(ddsd);
hResult = m_pSurface->Lock(pBounds, &ddsd, 0, 0);
if (FAILED(hResult))
return hResult;
pSrcBits = ddsd.lpSurface;
nSrcPitch = ddsd.lPitch;
hResult = m_pDestSurface->Lock(pBounds, &ddsd, 0, 0);
if (FAILED(hResult))
{
m_pSurface->Unlock(pSrcBits);
return hResult;
}
pDestBits = ddsd.lpSurface;
nDestPitch = ddsd.lPitch;
switch (m_eSrcFormat)
{
case RGB24:
Dith24to8(LPBYTE(pDestBits), LPBYTE(pSrcBits), nDestPitch,
nSrcPitch, m_pTable->m_argbColors, m_pTable->m_abInverseMap,
m_pErrBuf1, m_pErrBuf2, pBounds->left, pBounds->right-pBounds->left,
pBounds->top, pBounds->bottom-pBounds->top);
break;
case RGB8:
if (SUCCEEDED(m_pSurface->GetColorKey(DDCKEY_SRCBLT, &ddColorKey)))
lSrcTrans = ddColorKey.dwColorSpaceLowValue;
if (SUCCEEDED(m_pDestSurface->GetColorKey(DDCKEY_SRCBLT, &ddColorKey)))
lDestTrans = ddColorKey.dwColorSpaceLowValue;
// preserve the transparent index if necessary
if (lSrcTrans >= 0 && lDestTrans == -1)
{
lDestTrans = lSrcTrans;
}
if (lSrcTrans == -1 || lDestTrans == -1)
{
Dith8to8(LPBYTE(pDestBits), LPBYTE(pSrcBits), nDestPitch, nSrcPitch,
m_argbSrcColors, m_pTable->m_argbColors, m_pTable->m_abInverseMap,
m_pErrBuf1, m_pErrBuf2, pBounds->left, pBounds->right-pBounds->left,
pBounds->top, pBounds->bottom-pBounds->top);
}
else
{
Dith8to8t(LPBYTE(pDestBits), LPBYTE(pSrcBits), nDestPitch, nSrcPitch,
m_argbSrcColors, m_pTable->m_argbColors, m_pTable->m_abInverseMap,
m_pErrBuf1, m_pErrBuf2, pBounds->left, pBounds->right-pBounds->left,
pBounds->top, pBounds->bottom-pBounds->top, (BYTE)lDestTrans, (BYTE)lSrcTrans);
}
break;
default:
return E_FAIL;
}
m_pDestSurface->Unlock(pDestBits);
m_pSurface->Unlock(pSrcBits);
return S_OK;
}
HRESULT CDitherToRGB8::DitherFull()
{
HRESULT hResult;
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = m_nWidth;
rect.bottom = m_nHeight;
hResult = DitherBand(&rect);
if (FAILED(hResult))
return hResult;
return S_OK;
}
HRESULT DitherTo8( BYTE * pDestBits, LONG nDestPitch,
BYTE * pSrcBits, LONG nSrcPitch, REFGUID bfidSrc,
RGBQUAD * prgbDestColors, RGBQUAD * prgbSrcColors,
BYTE * pbDestInvMap,
LONG x, LONG y, LONG cx, LONG cy,
LONG lDestTrans, LONG lSrcTrans)
{
ERRBUF* m_pErrBuf;
ERRBUF* m_pErrBuf1;
ERRBUF* m_pErrBuf2;
// StartCAPAll();
HRESULT hr = S_OK;
m_pErrBuf = new ERRBUF[(cx+2)*2];
if (m_pErrBuf == NULL)
{
return( E_OUTOFMEMORY );
}
m_pErrBuf1 = &m_pErrBuf[1];
m_pErrBuf2 = &m_pErrBuf[cx+3];
memset(m_pErrBuf, 0, sizeof( ERRBUF )*(cx+2)*2);
if (bfidSrc == BFID_RGB_24)
{
Dith24to8( pDestBits, pSrcBits, nDestPitch, nSrcPitch,
prgbDestColors, pbDestInvMap,
m_pErrBuf1, m_pErrBuf2, x, cx, y, cy );
}
else if (bfidSrc == BFID_RGB_8)
{
if (lDestTrans == -1 || lSrcTrans == -1)
{
Dith8to8( pDestBits, pSrcBits, nDestPitch, nSrcPitch,
prgbSrcColors, prgbDestColors, pbDestInvMap,
m_pErrBuf1, m_pErrBuf2, x, cx, y, cy );
}
else
{
Dith8to8t( pDestBits, pSrcBits, nDestPitch, nSrcPitch,
prgbSrcColors, prgbDestColors, pbDestInvMap,
m_pErrBuf1, m_pErrBuf2, x, cx, y, cy, (BYTE)lDestTrans, (BYTE)lSrcTrans );
}
}
else
{
hr = E_FAIL;
}
delete m_pErrBuf;
// StopCAPAll();
return hr;
}