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

  1. #include "stdafx.h"
  2. #include "resource.h"
  3. #include "imgutil.h"
  4. #include "cdithtbl.h"
  5. #include "dithers.h"
  6. #include "cdith8.h"
  7. #include "align.h"
  8. #include "cddsurf.h"
  9. //#include <icapexp.h>
  10. void CopyColorsFromPaletteEntries(RGBQUAD *prgb, const PALETTEENTRY *ppe, UINT uCount);
  11. CDitherTable* CDitherToRGB8::s_apTableCache[MAX_DITHERTABLE_CACHE_SIZE];
  12. ULONG CDitherToRGB8::s_nCacheSize;
  13. CRITICAL_SECTION CDitherToRGB8::s_csCache;
  14. void CDitherToRGB8::InitTableCache()
  15. {
  16. ULONG iTable;
  17. InitializeCriticalSection( &s_csCache );
  18. s_nCacheSize = 0;
  19. for( iTable = 0; iTable < MAX_DITHERTABLE_CACHE_SIZE; iTable++ )
  20. {
  21. s_apTableCache[iTable] = NULL;
  22. }
  23. }
  24. void CDitherToRGB8::CleanupTableCache()
  25. {
  26. ULONG iTable;
  27. EnterCriticalSection( &s_csCache );
  28. for( iTable = 0; iTable < s_nCacheSize; iTable++ )
  29. {
  30. _ASSERTE( s_apTableCache[iTable]->m_nRefCount == 0 );
  31. delete s_apTableCache[iTable];
  32. s_apTableCache[iTable] = NULL;
  33. }
  34. s_nCacheSize = 0;
  35. LeaveCriticalSection( &s_csCache );
  36. DeleteCriticalSection( &s_csCache );
  37. }
  38. CDitherToRGB8::CDitherToRGB8() :
  39. m_dwEvents( 0 ),
  40. m_iScanLine( 0 ),
  41. m_bProgressiveDither( FALSE ),
  42. m_pErrBuf( NULL ),
  43. m_pErrBuf1( NULL ),
  44. m_pErrBuf2( NULL ),
  45. m_pTable( NULL ),
  46. m_pbBits( NULL ),
  47. m_hbmDestDib( NULL )
  48. {
  49. }
  50. CDitherToRGB8::~CDitherToRGB8()
  51. {
  52. if (m_pTable)
  53. m_pTable->m_nRefCount--;
  54. if (m_hbmDestDib)
  55. DeleteObject(m_hbmDestDib);
  56. }
  57. STDMETHODIMP CDitherToRGB8::GetSurface( LONG nWidth, LONG nHeight,
  58. REFGUID bfid, ULONG nPasses, DWORD dwHints, IUnknown** ppSurface )
  59. {
  60. HRESULT hResult;
  61. CComPtr< IUnknown > pDestSurface;
  62. if (ppSurface != NULL)
  63. *ppSurface = NULL;
  64. if ((nWidth <= 0) || (nHeight <= 0))
  65. return E_INVALIDARG;
  66. if (ppSurface == NULL)
  67. return E_POINTER;
  68. if (IsEqualGUID(bfid, BFID_RGB_24))
  69. {
  70. m_eSrcFormat = RGB24;
  71. m_nBitsPerPixel = 24;
  72. }
  73. else if (IsEqualGUID(bfid, BFID_INDEXED_RGB_8))
  74. {
  75. m_eSrcFormat = RGB8;
  76. m_nBitsPerPixel = 8;
  77. }
  78. else
  79. return E_NOINTERFACE;
  80. m_nWidth = nWidth;
  81. m_nHeight = nHeight;
  82. if ((dwHints & IMGDECODE_HINT_TOPDOWN) &&
  83. (dwHints & IMGDECODE_HINT_FULLWIDTH) &&
  84. (m_dwEvents & IMGDECODE_EVENT_PROGRESS))
  85. m_bProgressiveDither = TRUE;
  86. else
  87. m_bProgressiveDither = FALSE;
  88. m_pErrBuf = new ERRBUF[(m_nWidth+2)*2];
  89. if (m_pErrBuf == NULL)
  90. return E_OUTOFMEMORY;
  91. m_pErrBuf1 = &m_pErrBuf[1];
  92. m_pErrBuf2 = &m_pErrBuf[m_nWidth+3];
  93. memset(m_pErrBuf, 0, sizeof( ERRBUF )*(m_nWidth+2)*2);
  94. hResult = m_pEventSink->GetSurface(m_nWidth, m_nHeight, BFID_INDEXED_RGB_8,
  95. nPasses, dwHints, &pDestSurface);
  96. if (FAILED(hResult))
  97. return( hResult );
  98. hResult = pDestSurface->QueryInterface(IID_IDirectDrawSurface,
  99. (void **)&m_pDestSurface);
  100. if (FAILED(hResult))
  101. return hResult;
  102. m_hbmDestDib = ImgCreateDib(m_nWidth, -LONG(m_nHeight), FALSE, m_nBitsPerPixel, 0, NULL,
  103. &m_pbBits, (int *)&m_nPitch);
  104. if (m_hbmDestDib == NULL)
  105. return E_OUTOFMEMORY;
  106. hResult = CreateDDrawSurfaceOnDIB(m_hbmDestDib, &m_pSurface);
  107. if (FAILED(hResult))
  108. return hResult;
  109. *ppSurface = (IUnknown *)m_pSurface;
  110. (*ppSurface)->AddRef();
  111. return S_OK;
  112. }
  113. STDMETHODIMP CDitherToRGB8::OnBeginDecode( DWORD* pdwEvents, ULONG* pnFormats,
  114. GUID** ppFormats )
  115. {
  116. HRESULT hResult;
  117. GUID* pFormats;
  118. ULONG nFormats;
  119. ULONG iFormat;
  120. BOOL bFound;
  121. if( pdwEvents != NULL )
  122. {
  123. *pdwEvents = 0;
  124. }
  125. if( pnFormats != NULL )
  126. {
  127. *pnFormats = 0;
  128. }
  129. if( ppFormats != NULL )
  130. {
  131. *pnFormats = NULL;
  132. }
  133. if( pdwEvents == NULL )
  134. {
  135. return( E_POINTER );
  136. }
  137. if( pnFormats == NULL )
  138. {
  139. return( E_POINTER );
  140. }
  141. if( ppFormats == NULL )
  142. {
  143. return( E_POINTER );
  144. }
  145. hResult = m_pEventSink->OnBeginDecode( &m_dwEvents, &nFormats, &pFormats );
  146. if( FAILED( hResult ) )
  147. {
  148. return( hResult );
  149. }
  150. bFound = FALSE;
  151. for( iFormat = 0; (iFormat < nFormats) && !bFound; iFormat++ )
  152. {
  153. if( IsEqualGUID( pFormats[iFormat], BFID_INDEXED_RGB_8 ) )
  154. {
  155. bFound = TRUE;
  156. }
  157. }
  158. CoTaskMemFree( pFormats );
  159. if( !bFound )
  160. {
  161. return( E_FAIL );
  162. }
  163. *ppFormats = (GUID*)CoTaskMemAlloc( 3*sizeof( GUID ) );
  164. if( *ppFormats == NULL )
  165. {
  166. return( E_OUTOFMEMORY );
  167. }
  168. *pnFormats = 3;
  169. (*ppFormats)[0] = BFID_GRAY_8;
  170. (*ppFormats)[1] = BFID_RGB_24;
  171. (*ppFormats)[2] = BFID_INDEXED_RGB_8;
  172. *pdwEvents = m_dwEvents|IMGDECODE_EVENT_BITSCOMPLETE|
  173. IMGDECODE_EVENT_PALETTE;
  174. return( S_OK );
  175. }
  176. STDMETHODIMP CDitherToRGB8::OnBitsComplete()
  177. {
  178. HRESULT hResult;
  179. hResult = DitherFull();
  180. if( FAILED( hResult ) )
  181. {
  182. return( hResult );
  183. }
  184. if( m_dwEvents & IMGDECODE_EVENT_BITSCOMPLETE )
  185. {
  186. hResult = m_pEventSink->OnBitsComplete();
  187. if( FAILED( hResult ) )
  188. {
  189. return( hResult );
  190. }
  191. }
  192. return( S_OK );
  193. }
  194. STDMETHODIMP CDitherToRGB8::OnDecodeComplete( HRESULT hrStatus )
  195. {
  196. HRESULT hResult;
  197. delete m_pErrBuf;
  198. m_pErrBuf = NULL;
  199. m_pErrBuf1 = NULL;
  200. m_pErrBuf2 = NULL;
  201. // Propagate the transparency information if necessary
  202. if (m_pSurface && m_pDestSurface)
  203. {
  204. DDCOLORKEY ddKey;
  205. if (SUCCEEDED(m_pSurface->GetColorKey(DDCKEY_SRCBLT, &ddKey)))
  206. m_pDestSurface->SetColorKey(DDCKEY_SRCBLT, &ddKey);
  207. }
  208. if( m_pSurface != NULL )
  209. {
  210. m_pSurface.Release();
  211. }
  212. if( m_pDestSurface != NULL )
  213. {
  214. m_pDestSurface.Release();
  215. }
  216. hResult = m_pEventSink->OnDecodeComplete( hrStatus );
  217. m_pEventSink.Release();
  218. if( FAILED( hResult ) )
  219. {
  220. return( hResult );
  221. }
  222. return( S_OK );
  223. }
  224. STDMETHODIMP CDitherToRGB8::OnPalette()
  225. {
  226. HRESULT hResult;
  227. CComPtr< IDirectDrawPalette > pPalette;
  228. PALETTEENTRY ape[256];
  229. if (m_eSrcFormat == RGB8)
  230. {
  231. hResult = m_pSurface->GetPalette(&pPalette);
  232. if (FAILED(hResult))
  233. return hResult;
  234. hResult = pPalette->GetEntries(0, 0, 256, ape);
  235. if (FAILED(hResult))
  236. return hResult;
  237. CopyColorsFromPaletteEntries(m_argbSrcColors, ape, 256);
  238. }
  239. if (m_dwEvents & IMGDECODE_EVENT_PALETTE)
  240. {
  241. hResult = m_pEventSink->OnPalette();
  242. if (FAILED(hResult))
  243. {
  244. return hResult;
  245. }
  246. }
  247. return S_OK;
  248. }
  249. STDMETHODIMP CDitherToRGB8::OnProgress( RECT* pBounds, BOOL bComplete )
  250. {
  251. HRESULT hResult;
  252. if( pBounds == NULL )
  253. {
  254. return( E_INVALIDARG );
  255. }
  256. if( m_bProgressiveDither && bComplete )
  257. {
  258. hResult = DitherBand( pBounds );
  259. if( FAILED( hResult ) )
  260. {
  261. return( hResult );
  262. }
  263. }
  264. else
  265. {
  266. hResult = ConvertBlock( pBounds );
  267. if( FAILED( hResult ) )
  268. {
  269. return( hResult );
  270. }
  271. }
  272. if( m_dwEvents & IMGDECODE_EVENT_PROGRESS )
  273. {
  274. hResult = m_pEventSink->OnProgress( pBounds, bComplete );
  275. if( FAILED( hResult ) )
  276. {
  277. return( hResult );
  278. }
  279. }
  280. return( S_OK );
  281. }
  282. STDMETHODIMP CDitherToRGB8::SetDestColorTable( ULONG nColors,
  283. const RGBQUAD* prgbColors )
  284. {
  285. ULONG iTable;
  286. HRESULT hResult;
  287. if( (nColors == 0) || (nColors > 256) )
  288. {
  289. return( E_INVALIDARG );
  290. }
  291. if( prgbColors == NULL )
  292. {
  293. return( E_INVALIDARG );
  294. }
  295. EnterCriticalSection( &s_csCache );
  296. if( m_pTable != NULL )
  297. {
  298. // Release whatever table we've got already
  299. m_pTable->m_nRefCount--;
  300. m_pTable = NULL;
  301. }
  302. // See if we can find the requested table in the cache
  303. for( iTable = 0; (iTable < s_nCacheSize) && (m_pTable == NULL); iTable++ )
  304. {
  305. if( s_apTableCache[iTable]->Match( nColors, prgbColors ) )
  306. {
  307. m_pTable = s_apTableCache[iTable];
  308. m_pTable->m_nRefCount++;
  309. }
  310. }
  311. if( m_pTable == NULL )
  312. {
  313. if( s_nCacheSize < MAX_DITHERTABLE_CACHE_SIZE )
  314. {
  315. m_pTable = new CDitherTable;
  316. if( m_pTable == NULL )
  317. {
  318. LeaveCriticalSection( &s_csCache );
  319. return( E_OUTOFMEMORY );
  320. }
  321. hResult = m_pTable->SetColors( nColors, prgbColors );
  322. if( FAILED( hResult ) )
  323. {
  324. LeaveCriticalSection( &s_csCache );
  325. m_pTable = NULL;
  326. return( hResult );
  327. }
  328. // Add a new cache entry
  329. m_pTable->m_nRefCount++;
  330. s_apTableCache[s_nCacheSize] = m_pTable;
  331. s_nCacheSize++;
  332. }
  333. else
  334. {
  335. // Find a cache entry to replace.
  336. for( iTable = 0; (iTable < s_nCacheSize) && (m_pTable == NULL);
  337. iTable++ )
  338. {
  339. if( s_apTableCache[iTable]->m_nRefCount == 0 )
  340. {
  341. m_pTable = s_apTableCache[iTable];
  342. hResult = m_pTable->SetColors( nColors, prgbColors );
  343. if( FAILED( hResult ) )
  344. {
  345. LeaveCriticalSection( &s_csCache );
  346. m_pTable = NULL;
  347. return( hResult );
  348. }
  349. m_pTable->m_nRefCount++;
  350. }
  351. }
  352. }
  353. }
  354. _ASSERTE( m_pTable != NULL );
  355. LeaveCriticalSection( &s_csCache );
  356. return( S_OK );
  357. }
  358. STDMETHODIMP CDitherToRGB8::SetEventSink( IImageDecodeEventSink* pEventSink )
  359. {
  360. if( pEventSink == NULL )
  361. {
  362. return( E_INVALIDARG );
  363. }
  364. m_pEventSink = pEventSink;
  365. return( S_OK );
  366. }
  367. HRESULT CDitherToRGB8::ConvertBlock( RECT* pBounds )
  368. {
  369. HRESULT hResult;
  370. void* pSrcBits;
  371. void* pDestBits;
  372. LONG nSrcPitch;
  373. LONG nDestPitch;
  374. DDSURFACEDESC ddsd;
  375. _ASSERTE( pBounds->left == 0 );
  376. _ASSERTE( pBounds->right == LONG( m_nWidth ) );
  377. ddsd.dwSize = sizeof(ddsd);
  378. hResult = m_pSurface->Lock(pBounds, &ddsd, 0, 0);
  379. if (FAILED(hResult))
  380. return hResult;
  381. pSrcBits = ddsd.lpSurface;
  382. nSrcPitch = ddsd.lPitch;
  383. hResult = m_pDestSurface->Lock(pBounds, &ddsd, 0, 0);
  384. if (FAILED(hResult))
  385. {
  386. m_pSurface->Unlock(pSrcBits);
  387. return hResult;
  388. }
  389. pDestBits = ddsd.lpSurface;
  390. nDestPitch = ddsd.lPitch;
  391. switch( m_eSrcFormat )
  392. {
  393. case RGB24:
  394. Convert24to8(LPBYTE(pDestBits), LPBYTE(pSrcBits), nDestPitch,
  395. nSrcPitch, m_pTable->m_abInverseMap, pBounds->left,
  396. pBounds->right-pBounds->left, pBounds->top,
  397. pBounds->bottom-pBounds->top );
  398. break;
  399. case RGB8:
  400. Convert8to8( LPBYTE( pDestBits ), LPBYTE( pSrcBits ), nDestPitch,
  401. nSrcPitch, m_argbSrcColors, m_pTable->m_abInverseMap, pBounds->left,
  402. pBounds->right-pBounds->left, pBounds->top,
  403. pBounds->bottom-pBounds->top );
  404. break;
  405. default:
  406. return E_FAIL;
  407. break;
  408. }
  409. m_pDestSurface->Unlock(pDestBits);
  410. m_pSurface->Unlock(pSrcBits);
  411. return S_OK;
  412. }
  413. HRESULT CDitherToRGB8::DitherBand( RECT* pBounds )
  414. {
  415. HRESULT hResult;
  416. void* pSrcBits;
  417. void* pDestBits;
  418. LONG nSrcPitch;
  419. LONG nDestPitch;
  420. LONG lDestTrans = -1;
  421. LONG lSrcTrans = -1;
  422. DDSURFACEDESC ddsd;
  423. DDCOLORKEY ddColorKey;
  424. _ASSERTE( pBounds->left == 0 );
  425. _ASSERTE( pBounds->right == LONG( m_nWidth ) );
  426. ddsd.dwSize = sizeof(ddsd);
  427. hResult = m_pSurface->Lock(pBounds, &ddsd, 0, 0);
  428. if (FAILED(hResult))
  429. return hResult;
  430. pSrcBits = ddsd.lpSurface;
  431. nSrcPitch = ddsd.lPitch;
  432. hResult = m_pDestSurface->Lock(pBounds, &ddsd, 0, 0);
  433. if (FAILED(hResult))
  434. {
  435. m_pSurface->Unlock(pSrcBits);
  436. return hResult;
  437. }
  438. pDestBits = ddsd.lpSurface;
  439. nDestPitch = ddsd.lPitch;
  440. switch (m_eSrcFormat)
  441. {
  442. case RGB24:
  443. Dith24to8(LPBYTE(pDestBits), LPBYTE(pSrcBits), nDestPitch,
  444. nSrcPitch, m_pTable->m_argbColors, m_pTable->m_abInverseMap,
  445. m_pErrBuf1, m_pErrBuf2, pBounds->left, pBounds->right-pBounds->left,
  446. pBounds->top, pBounds->bottom-pBounds->top);
  447. break;
  448. case RGB8:
  449. if (SUCCEEDED(m_pSurface->GetColorKey(DDCKEY_SRCBLT, &ddColorKey)))
  450. lSrcTrans = ddColorKey.dwColorSpaceLowValue;
  451. if (SUCCEEDED(m_pDestSurface->GetColorKey(DDCKEY_SRCBLT, &ddColorKey)))
  452. lDestTrans = ddColorKey.dwColorSpaceLowValue;
  453. // preserve the transparent index if necessary
  454. if (lSrcTrans >= 0 && lDestTrans == -1)
  455. {
  456. lDestTrans = lSrcTrans;
  457. }
  458. if (lSrcTrans == -1 || lDestTrans == -1)
  459. {
  460. Dith8to8(LPBYTE(pDestBits), LPBYTE(pSrcBits), nDestPitch, nSrcPitch,
  461. m_argbSrcColors, m_pTable->m_argbColors, m_pTable->m_abInverseMap,
  462. m_pErrBuf1, m_pErrBuf2, pBounds->left, pBounds->right-pBounds->left,
  463. pBounds->top, pBounds->bottom-pBounds->top);
  464. }
  465. else
  466. {
  467. Dith8to8t(LPBYTE(pDestBits), LPBYTE(pSrcBits), nDestPitch, nSrcPitch,
  468. m_argbSrcColors, m_pTable->m_argbColors, m_pTable->m_abInverseMap,
  469. m_pErrBuf1, m_pErrBuf2, pBounds->left, pBounds->right-pBounds->left,
  470. pBounds->top, pBounds->bottom-pBounds->top, (BYTE)lDestTrans, (BYTE)lSrcTrans);
  471. }
  472. break;
  473. default:
  474. return E_FAIL;
  475. }
  476. m_pDestSurface->Unlock(pDestBits);
  477. m_pSurface->Unlock(pSrcBits);
  478. return S_OK;
  479. }
  480. HRESULT CDitherToRGB8::DitherFull()
  481. {
  482. HRESULT hResult;
  483. RECT rect;
  484. rect.left = 0;
  485. rect.top = 0;
  486. rect.right = m_nWidth;
  487. rect.bottom = m_nHeight;
  488. hResult = DitherBand(&rect);
  489. if (FAILED(hResult))
  490. return hResult;
  491. return S_OK;
  492. }
  493. HRESULT DitherTo8( BYTE * pDestBits, LONG nDestPitch,
  494. BYTE * pSrcBits, LONG nSrcPitch, REFGUID bfidSrc,
  495. RGBQUAD * prgbDestColors, RGBQUAD * prgbSrcColors,
  496. BYTE * pbDestInvMap,
  497. LONG x, LONG y, LONG cx, LONG cy,
  498. LONG lDestTrans, LONG lSrcTrans)
  499. {
  500. ERRBUF* m_pErrBuf;
  501. ERRBUF* m_pErrBuf1;
  502. ERRBUF* m_pErrBuf2;
  503. // StartCAPAll();
  504. HRESULT hr = S_OK;
  505. m_pErrBuf = new ERRBUF[(cx+2)*2];
  506. if (m_pErrBuf == NULL)
  507. {
  508. return( E_OUTOFMEMORY );
  509. }
  510. m_pErrBuf1 = &m_pErrBuf[1];
  511. m_pErrBuf2 = &m_pErrBuf[cx+3];
  512. memset(m_pErrBuf, 0, sizeof( ERRBUF )*(cx+2)*2);
  513. if (bfidSrc == BFID_RGB_24)
  514. {
  515. Dith24to8( pDestBits, pSrcBits, nDestPitch, nSrcPitch,
  516. prgbDestColors, pbDestInvMap,
  517. m_pErrBuf1, m_pErrBuf2, x, cx, y, cy );
  518. }
  519. else if (bfidSrc == BFID_RGB_8)
  520. {
  521. if (lDestTrans == -1 || lSrcTrans == -1)
  522. {
  523. Dith8to8( pDestBits, pSrcBits, nDestPitch, nSrcPitch,
  524. prgbSrcColors, prgbDestColors, pbDestInvMap,
  525. m_pErrBuf1, m_pErrBuf2, x, cx, y, cy );
  526. }
  527. else
  528. {
  529. Dith8to8t( pDestBits, pSrcBits, nDestPitch, nSrcPitch,
  530. prgbSrcColors, prgbDestColors, pbDestInvMap,
  531. m_pErrBuf1, m_pErrBuf2, x, cx, y, cy, (BYTE)lDestTrans, (BYTE)lSrcTrans );
  532. }
  533. }
  534. else
  535. {
  536. hr = E_FAIL;
  537. }
  538. delete m_pErrBuf;
  539. // StopCAPAll();
  540. return hr;
  541. }