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.

726 lines
24 KiB

  1. /*----------------------------------------------------------------------+
  2. | msyuv.c - Microsoft YUV Codec |
  3. | |
  4. | Copyright (c) 1993 Microsoft Corporation. |
  5. | All Rights Reserved. |
  6. | |
  7. +----------------------------------------------------------------------*/
  8. #include <windows.h>
  9. #include <windowsx.h>
  10. #include <mmsystem.h>
  11. #ifndef _WIN32
  12. #include "stdarg.h"
  13. #endif
  14. #ifdef _WIN32
  15. #include <memory.h> /* for memcpy */
  16. #endif
  17. #include "msyuv.h"
  18. // ICINFO use WCHAR if _WIN32 is #defined; so force it to use WCHAR; where else are TCHAR
  19. WCHAR szDescription[] = L"Microsoft YUV";
  20. WCHAR szName[] = L"MS-YUV";
  21. WCHAR szAbout[] = L"About";
  22. #define VERSION 0x00010000 // 1.0
  23. // pull these in from amvideo.h
  24. #define WIDTHBYTES(bits) ((DWORD)(((bits)+31) & (~31)) / 8)
  25. #define DIBWIDTHBYTES(bi) (DWORD)WIDTHBYTES((DWORD)(bi)->biWidth * (DWORD)(bi)->biBitCount)
  26. #define _DIBSIZE(bi) (DIBWIDTHBYTES(bi) * (DWORD)(bi)->biHeight)
  27. #define DIBSIZE(bi) ((bi)->biHeight < 0 ? (-1)*(_DIBSIZE(bi)) : _DIBSIZE(bi))
  28. /*****************************************************************************
  29. ****************************************************************************/
  30. INSTINFO * NEAR PASCAL Open(ICOPEN FAR * icinfo)
  31. {
  32. INSTINFO * pinst;
  33. //
  34. // refuse to open if we are not being opened as a Video compressor
  35. //
  36. if (icinfo->fccType != ICTYPE_VIDEO)
  37. return NULL;
  38. // dwFlags contain wMode
  39. // Only support Decompress mode (or for Query purpose)
  40. if( icinfo->dwFlags != ICMODE_DECOMPRESS
  41. && icinfo->dwFlags != ICMODE_QUERY // Open for infomational purpose
  42. ) {
  43. dprintf1((TEXT("Open: unsupported wMode=%d\n"), icinfo->dwFlags));
  44. return NULL;
  45. }
  46. pinst = (INSTINFO *)LocalAlloc(LPTR, sizeof(INSTINFO));
  47. if (!pinst) {
  48. icinfo->dwError = (DWORD)ICERR_MEMORY;
  49. return NULL;
  50. }
  51. //
  52. // init structure
  53. //
  54. pinst->dwFlags = icinfo->dwFlags;
  55. pinst->pXlate = NULL;
  56. //
  57. // return success.
  58. //
  59. icinfo->dwError = ICERR_OK;
  60. return pinst;
  61. }
  62. /*****************************************************************************
  63. ****************************************************************************/
  64. DWORD NEAR PASCAL Close(INSTINFO * pinst)
  65. {
  66. if (pinst->pXlate) {
  67. DecompressEnd(pinst);
  68. }
  69. #ifdef ICM_DRAW_SUPPORTED
  70. if (pinst->vh) {
  71. dprintf1((TEXT(" pinst->vh = 0x%x\n"), pinst->vh));
  72. DrawEnd(pinst);
  73. }
  74. #endif
  75. LocalFree((HLOCAL)pinst);
  76. return 1;
  77. }
  78. /*****************************************************************************
  79. ****************************************************************************/
  80. BOOL NEAR PASCAL QueryAbout(INSTINFO * pinst)
  81. {
  82. return TRUE;
  83. }
  84. DWORD NEAR PASCAL About(INSTINFO * pinst, HWND hwnd)
  85. {
  86. MessageBoxW(hwnd,szDescription,szAbout,MB_OK|MB_ICONINFORMATION);
  87. return ICERR_OK;
  88. }
  89. /*****************************************************************************
  90. ****************************************************************************/
  91. BOOL NEAR PASCAL QueryConfigure(INSTINFO * pinst)
  92. {
  93. return FALSE;
  94. }
  95. DWORD NEAR PASCAL Configure(INSTINFO * pinst, HWND hwnd)
  96. {
  97. return (TRUE);
  98. }
  99. /*****************************************************************************
  100. ****************************************************************************/
  101. /*
  102. * lossless translation - hence no need for state adjustments
  103. */
  104. DWORD NEAR PASCAL GetState(INSTINFO * pinst, LPVOID pv, DWORD dwSize)
  105. {
  106. return 0;
  107. }
  108. /*****************************************************************************
  109. ****************************************************************************/
  110. DWORD NEAR PASCAL SetState(INSTINFO * pinst, LPVOID pv, DWORD dwSize)
  111. {
  112. return(0);
  113. }
  114. /*****************************************************************************
  115. ****************************************************************************/
  116. DWORD NEAR PASCAL GetInfo(INSTINFO * pinst, ICINFO FAR *icinfo, DWORD dwSize)
  117. {
  118. if (icinfo == NULL)
  119. return sizeof(ICINFO);
  120. if (dwSize < sizeof(ICINFO))
  121. return 0;
  122. icinfo->dwSize = sizeof(ICINFO);
  123. icinfo->fccType = ICTYPE_VIDEO;
  124. icinfo->fccHandler = FOURCC_UYVY; // default UYVY and also supports YUYV/YUY2;
  125. icinfo->dwFlags = 0;
  126. icinfo->dwVersion = VERSION;
  127. icinfo->dwVersionICM = ICVERSION;
  128. wcscpy(icinfo->szDescription, szDescription);
  129. wcscpy(icinfo->szName, szName);
  130. return sizeof(ICINFO);
  131. }
  132. /*****************************************************************************
  133. ****************************************************************************/
  134. DWORD FAR PASCAL CompressQuery(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  135. {
  136. return ((DWORD) ICERR_BADFORMAT);
  137. }
  138. /*****************************************************************************
  139. ****************************************************************************/
  140. DWORD FAR PASCAL CompressGetFormat(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  141. {
  142. return((DWORD) ICERR_BADFORMAT);
  143. }
  144. /*****************************************************************************
  145. ****************************************************************************/
  146. DWORD FAR PASCAL CompressBegin(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  147. {
  148. return((DWORD) ICERR_ERROR);
  149. }
  150. /*****************************************************************************
  151. ****************************************************************************/
  152. DWORD FAR PASCAL CompressGetSize(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  153. {
  154. return (0);
  155. }
  156. /*****************************************************************************
  157. ****************************************************************************/
  158. DWORD FAR PASCAL Compress(INSTINFO * pinst, ICCOMPRESS FAR *icinfo, DWORD dwSize)
  159. {
  160. return((DWORD) ICERR_ERROR);
  161. }
  162. /*****************************************************************************
  163. ****************************************************************************/
  164. DWORD FAR PASCAL CompressEnd(INSTINFO * pinst)
  165. {
  166. return (DWORD)ICERR_ERROR;
  167. }
  168. /*****************************************************************************
  169. ****************************************************************************/
  170. DWORD NEAR PASCAL DecompressQuery(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  171. {
  172. //
  173. // determine if the input DIB data is in a format we like.
  174. //
  175. if (lpbiIn == NULL ||
  176. lpbiIn->biBitCount != 16 ||
  177. (lpbiIn->biCompression != FOURCC_UYVY &&
  178. lpbiIn->biCompression != FOURCC_YUY2 &&
  179. lpbiIn->biCompression != FOURCC_YVYU )) {
  180. dprintf1((TEXT("Bad input format: lpbiIn=%x; In.biBitCount=%d; FourCC %x != UYVY or YUY2\n"),
  181. lpbiIn, lpbiIn->biBitCount, lpbiIn->biCompression));
  182. return (DWORD)ICERR_BADFORMAT;
  183. }
  184. //
  185. // are we being asked to query just the input format?
  186. //
  187. if (lpbiOut == NULL) {
  188. return ICERR_OK;
  189. }
  190. /* must be 1:1 (no stretching) */
  191. if ((lpbiOut->biWidth != lpbiIn->biWidth) ||
  192. (abs(lpbiOut->biHeight) != abs(lpbiIn->biHeight))) {
  193. dprintf1((TEXT("##### Can't stretch: %dx%d != %dx%d\n"),
  194. lpbiIn->biWidth, lpbiIn->biHeight,
  195. lpbiOut->biWidth, lpbiOut->biHeight));
  196. return((DWORD) ICERR_BADFORMAT);
  197. }
  198. /*
  199. * we translate to 32/24/16/8 bits RGB
  200. */
  201. if (lpbiOut->biBitCount != 16 && lpbiOut->biBitCount != 8 && lpbiOut->biBitCount != 32 && lpbiOut->biBitCount != 24) {
  202. return((DWORD) ICERR_BADFORMAT);
  203. }
  204. dprintf2((TEXT("DeCmQry: In4CC(%x,%s)<==>Out(%x,%s); RGB565(%s);\n"),
  205. lpbiIn->biCompression,
  206. (CHAR *) &lpbiOut->biCompression,
  207. lpbiOut->biCompression,
  208. lpbiOut->biCompression == BI_RGB ? "RGB" : (CHAR *) &lpbiOut->biCompression,
  209. pinst->bRGB565?"T":"F"));
  210. dprintf2((TEXT(" In:%dx%dx%d=%d; Out:%dx%dx%d=%d\n"),
  211. lpbiIn->biWidth, lpbiIn->biHeight, lpbiIn->biBitCount, lpbiIn->biSizeImage,
  212. lpbiOut->biWidth, lpbiOut->biHeight, lpbiOut->biBitCount, lpbiOut->biSizeImage));
  213. // check output format to make sure we can convert to this
  214. // must be full dib
  215. if(lpbiOut->biCompression == BI_RGB) {
  216. dprintf2((TEXT("$$$$$ RGB: BI_RGB output\n")));
  217. pinst->bRGB565 = FALSE;
  218. } else if ((lpbiOut->biCompression == BI_BITFIELDS) &&
  219. (lpbiOut->biBitCount == 16 || lpbiOut->biBitCount == 8) &&
  220. (((LPDWORD)(lpbiOut+1))[0] == 0x00f800) &&
  221. (((LPDWORD)(lpbiOut+1))[1] == 0x0007e0) &&
  222. (((LPDWORD)(lpbiOut+1))[2] == 0x00001f)) {
  223. dprintf2((TEXT("$$$$$ BITF: rgb565 output\n")));
  224. pinst->bRGB565 = TRUE;
  225. // Pass thru case:
  226. // !!! this is broken, since it will allow copying from
  227. // any of the three YUV formats to any of the others, and
  228. // we actually don't do this. If the AviDec allowed going from
  229. // YUV to YUV, we would see odd colors!
  230. } else if (lpbiOut->biCompression == FOURCC_UYVY ||
  231. lpbiOut->biCompression == FOURCC_YUY2 ||
  232. lpbiOut->biCompression == FOURCC_YVYU ) {
  233. if( lpbiIn->biCompression != lpbiOut->biCompression )
  234. {
  235. dprintf1((TEXT("cannot convert between YUV formats\n")));
  236. return (DWORD)ICERR_BADFORMAT;
  237. }
  238. dprintf2((TEXT("$$$$$ UYVY: rgb555 output\n")));
  239. pinst->bRGB565 = FALSE;
  240. } else {
  241. dprintf1((TEXT("bad compression for output\n")));
  242. return (DWORD)ICERR_BADFORMAT;
  243. }
  244. return ICERR_OK;
  245. }
  246. /*****************************************************************************
  247. ****************************************************************************/
  248. DWORD NEAR PASCAL DecompressGetFormat(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  249. {
  250. DWORD dw;
  251. // Check input format only since lpbiOut is being asked for
  252. dw = DecompressQuery(pinst, lpbiIn, NULL);
  253. if (dw != ICERR_OK) {
  254. return dw;
  255. }
  256. //
  257. // if lpbiOut == NULL then, return the size required to hold a output
  258. // format
  259. //
  260. if (lpbiOut == NULL) {
  261. dprintf2((TEXT("get format size query\n")));
  262. return (int)lpbiIn->biSize + (int)lpbiIn->biClrUsed * sizeof(RGBQUAD);
  263. }
  264. memcpy(lpbiOut, lpbiIn, (int)lpbiIn->biSize + (int)lpbiIn->biClrUsed * sizeof(RGBQUAD));
  265. lpbiOut->biCompression = BI_RGB;
  266. lpbiOut->biBitCount = 24; // we suggest 24 bit
  267. lpbiOut->biSizeImage = DIBSIZE( lpbiOut );
  268. dprintf2((TEXT("DeCmpGFmt: In:%dx%dx%d=%d; RGB565(%s); Out:%dx%dx%d=%d\n"),
  269. lpbiIn->biWidth, lpbiIn->biHeight, lpbiIn->biBitCount, lpbiIn->biSizeImage,
  270. pinst->bRGB565?TEXT("T"):TEXT("F"),
  271. lpbiOut->biWidth, lpbiOut->biHeight, lpbiOut->biBitCount, lpbiOut->biSizeImage));
  272. return ICERR_OK;
  273. }
  274. /*****************************************************************************
  275. ****************************************************************************/
  276. DWORD NEAR PASCAL DecompressBegin(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  277. {
  278. DWORD dw;
  279. /* check that the conversion formats are valid */
  280. dw = DecompressQuery(pinst, lpbiIn, lpbiOut);
  281. if (dw != ICERR_OK) {
  282. return dw;
  283. }
  284. dprintf2((TEXT("DeCmBegin: In4CC(%x,%s)<==>Out(%x,%s); RGB565(%s);\n"),
  285. lpbiIn->biCompression,
  286. (PTCHAR) &lpbiOut->biCompression, //"UYVY",
  287. lpbiOut->biCompression,
  288. lpbiOut->biCompression == BI_RGB ? "RGB" : (PTCHAR) &lpbiOut->biCompression,
  289. pinst->bRGB565?TEXT("T"):TEXT("F")));
  290. dprintf2((TEXT(" In:%dx%dx%d=%d; Out:%dx%dx%d=%d\n"),
  291. lpbiIn->biWidth, lpbiIn->biHeight, lpbiIn->biBitCount, lpbiIn->biSizeImage,
  292. lpbiOut->biWidth, lpbiOut->biHeight, lpbiOut->biBitCount, lpbiOut->biSizeImage));
  293. /* init the yuv-to-rgb55 xlate table if not already inited */
  294. /* free up the existing table if the formats differ */
  295. if (lpbiIn->biCompression != pinst->dwFormat) {
  296. if (pinst->pXlate != NULL) {
  297. DecompressEnd(pinst);
  298. }
  299. }
  300. if (pinst->pXlate == NULL) {
  301. switch(lpbiIn->biCompression) {
  302. case FOURCC_YUY2:
  303. case FOURCC_UYVY:
  304. case FOURCC_YVYU:
  305. {
  306. switch( lpbiOut->biBitCount ) {
  307. case 8:
  308. {
  309. dprintf3((TEXT("pinst->pXlate = BuildUYVYToRGB8()\n")));
  310. pinst->pXlate = BuildUYVYToRGB8(pinst);
  311. break;
  312. }
  313. case 16:
  314. {
  315. if (pinst->bRGB565) {
  316. dprintf3((TEXT("pinst->pXlate = BuildUYVYToRGB565()\n")));
  317. pinst->pXlate = BuildUYVYToRGB565(pinst);
  318. } else {
  319. dprintf3((TEXT("pinst->pXlate = BuildUYVYToRGB555()\n")));
  320. pinst->pXlate = BuildUYVYToRGB555(pinst);
  321. }
  322. break;
  323. }
  324. case 24:
  325. {
  326. dprintf3((TEXT("pinst->pXlate = BuildUYVYToRGB32()\n")));
  327. pinst->pXlate = BuildUYVYToRGB32(pinst);
  328. break;
  329. }
  330. case 32:
  331. {
  332. dprintf3((TEXT("pinst->pXlate = BuildUYVYToRGB32()\n")));
  333. pinst->pXlate = BuildUYVYToRGB32(pinst);
  334. break;
  335. }
  336. default:
  337. {
  338. dprintf1((TEXT("Supported UYUV->RGB but unsupported output bitcount (%d); return ICERR_BADFOPRMAT\n"), lpbiOut->biBitCount));
  339. return((DWORD) ICERR_BADFORMAT);
  340. }
  341. } // switch biBitCount
  342. break;
  343. } // case FOURCC_ACCEPTABLE
  344. default:
  345. dprintf1((TEXT("UnSupported FourCC; return ICERR_BADFOPRMAT\n")));
  346. return((DWORD) ICERR_BADFORMAT);
  347. }
  348. if( ( lpbiOut->biBitCount != 8 ) && ( pinst->pXlate == NULL ) ) {
  349. dprintf1((TEXT("return ICERR_MEMORY\n")));
  350. return((DWORD) ICERR_MEMORY);
  351. }
  352. pinst->dwFormat = lpbiIn->biCompression;
  353. }
  354. return(ICERR_OK);
  355. }
  356. /*****************************************************************************
  357. ****************************************************************************/
  358. DWORD NEAR PASCAL Decompress(INSTINFO * pinst, ICDECOMPRESS FAR *icinfo, DWORD dwSize)
  359. {
  360. ASSERT(pinst && icinfo);
  361. if (!pinst || !icinfo)
  362. return((DWORD) ICERR_ERROR);
  363. if (pinst->dwFormat == FOURCC_UYVY ||
  364. pinst->dwFormat == FOURCC_YUY2 ||
  365. pinst->dwFormat == FOURCC_YVYU) {
  366. switch( icinfo->lpbiOutput->biBitCount )
  367. {
  368. case 8:
  369. {
  370. UYVYToRGB8(pinst,
  371. icinfo->lpbiInput,
  372. icinfo->lpInput,
  373. icinfo->lpbiOutput,
  374. icinfo->lpOutput);
  375. break;
  376. }
  377. case 16:
  378. {
  379. /* must have been a DecompressBegin first */
  380. if (pinst->pXlate == NULL) {
  381. dprintf1((TEXT("Decompress: pinst->pXlate == NULL\n")));
  382. return((DWORD) ICERR_ERROR);
  383. }
  384. UYVYToRGB16(pinst,
  385. icinfo->lpbiInput,
  386. icinfo->lpInput,
  387. icinfo->lpbiOutput,
  388. icinfo->lpOutput);
  389. break;
  390. }
  391. case 24:
  392. {
  393. if (pinst->pXlate == NULL) {
  394. dprintf1((TEXT("Decompress: pinst->pXlate == NULL\n")));
  395. return((DWORD) ICERR_ERROR);
  396. }
  397. UYVYToRGB24(pinst,
  398. icinfo->lpbiInput,
  399. icinfo->lpInput,
  400. icinfo->lpbiOutput,
  401. icinfo->lpOutput);
  402. break;
  403. }
  404. case 32:
  405. {
  406. if (pinst->pXlate == NULL) {
  407. dprintf1((TEXT("Decompress: pinst->pXlate == NULL\n")));
  408. return((DWORD) ICERR_ERROR);
  409. }
  410. UYVYToRGB32(pinst,
  411. icinfo->lpbiInput,
  412. icinfo->lpInput,
  413. icinfo->lpbiOutput,
  414. icinfo->lpOutput);
  415. break;
  416. }
  417. default:
  418. {
  419. dprintf1((TEXT("Decompress: Unsupported output bitcount(%d)\n"), icinfo->lpbiOutput->biBitCount));
  420. }
  421. } // switch bit count
  422. }
  423. return ICERR_OK;
  424. }
  425. /*****************************************************************************
  426. ****************************************************************************/
  427. DWORD NEAR PASCAL DecompressEnd(INSTINFO * pinst)
  428. {
  429. if (pinst->pXlate) {
  430. // 16bit RGB LUT is built dynamically.
  431. FreeXlate(pinst);
  432. }
  433. pinst->dwFormat = 0;
  434. return ICERR_OK;
  435. }
  436. /*****************************************************************************
  437. ehr: DecompressExQuery and DecompressEx don't suppor what they should
  438. support. DecompressEx should also support "normal" decompressing, that is,
  439. the same thing that Decompress would support. But it doesn't, it only
  440. supports memcpying the bitmap, which is really odd.
  441. ****************************************************************************/
  442. /*
  443. ICM_DECOMPRESSEX_QUERY wParam = (DWORD) (LPVOID) &icdex;
  444. lParam = sizeof(ICDECOMPRESSEX);
  445. typedef struct {
  446. DWORD dwFlags;
  447. LPBITMAPINFOHEADER lpbiSrc;
  448. LPVOID lpSrc;
  449. LPBITMAPINFOHEADER lpbiDst;
  450. LPVOID lpDst;
  451. int xDst;
  452. int yDst;
  453. int dxDst;
  454. int dyDst;
  455. int xSrc;
  456. int ySrc;
  457. int dxSrc;
  458. int dySrc; } ICDECOMPRESSEX;
  459. */
  460. DWORD NEAR PASCAL DecompressExQuery(INSTINFO * pinst, ICDECOMPRESSEX * pICD, DWORD dwICDSize)
  461. {
  462. LPBITMAPINFOHEADER pbmSrc, pbmDst;
  463. if (pICD == NULL) {
  464. dprintf1(("DeCmQEx: pICD== NULL\n"));
  465. return (DWORD)ICERR_BADFORMAT;
  466. }
  467. pbmSrc = pICD->lpbiSrc;
  468. pbmDst = pICD->lpbiDst;
  469. //
  470. // determine if the input DIB data is in a format we like.
  471. //
  472. if (pbmSrc == NULL ||
  473. pbmSrc->biBitCount != 16 ||
  474. (pbmSrc->biCompression != FOURCC_UYVY &&
  475. pbmSrc->biCompression != FOURCC_YUY2 &&
  476. pbmSrc->biCompression != FOURCC_YVYU)) {
  477. dprintf1((TEXT("Bad input format: pbmSrc=%x; Src.biBitCount=%d; FourCC!= UYVY\n"), pbmSrc, pbmSrc->biBitCount));
  478. return (DWORD)ICERR_BADFORMAT;
  479. }
  480. dprintf2(("DeCmQEx: dwFlags=0x%x Src(%dx%dx%d=%d %s) Dst(%dx%dx%d=%d %s)\n",
  481. pICD->dwFlags,
  482. pbmSrc->biWidth, pbmSrc->biHeight, pbmSrc->biBitCount, pbmSrc->biSizeImage, (PTCHAR *) &pbmSrc->biCompression,
  483. pbmDst->biWidth, pbmDst->biHeight, pbmDst->biBitCount, pbmDst->biSizeImage, (PTCHAR *) &pbmDst->biCompression));
  484. dprintf2(("DeCmQEx: SrcPoint(%d,%d) SizeSrc(%d,%d); DstPoint(%d,%d) SizeDst(%d,%d);\n",
  485. pICD->xSrc, pICD->ySrc, pICD->dxSrc, pICD->dySrc,
  486. pICD->xDst, pICD->yDst, pICD->dxDst, pICD->dyDst));
  487. /* must be 1:1 (no stretching) */
  488. if ((pbmDst->biWidth != pbmSrc->biWidth) ||
  489. (abs(pbmDst->biHeight) != abs(pbmSrc->biHeight)) || // Sign is ignored for YUV->YUV
  490. (pbmDst->biBitCount != pbmSrc->biBitCount) ||
  491. (pbmDst->biCompression != pbmSrc->biCompression) || // Pass thru
  492. // Start from the same origin
  493. (pICD->xSrc != 0 ) ||
  494. (pICD->ySrc != 0 ) ||
  495. (pICD->xDst != 0 ) ||
  496. (pICD->yDst != 0 ) ||
  497. // 1:1
  498. (pICD->dxSrc != pbmSrc->biWidth ) ||
  499. (pICD->dySrc != abs(pbmSrc->biHeight)) ||
  500. (pICD->dxDst != pbmDst->biWidth ) ||
  501. (pICD->dyDst != abs(pbmDst->biHeight))
  502. ) {
  503. dprintf1((TEXT("DeCmQEx: Src/Dst format does not MATCH!\n")));
  504. return((DWORD) ICERR_BADFORMAT);
  505. }
  506. return (DWORD)ICERR_OK;
  507. }
  508. /*****************************************************************************
  509. This routine support transferring data to a DirectDraw rendering surface,
  510. which always uses a top-down orientation with its lowest video address
  511. in the upper-left corder.
  512. Note: no stretching is supported.
  513. ****************************************************************************/
  514. DWORD NEAR PASCAL DecompressEx(INSTINFO * pinst, ICDECOMPRESSEX * pICD, DWORD dwICDSize)
  515. {
  516. LPBITMAPINFOHEADER pbmSrc, pbmDst;
  517. PBYTE pSrc, pDst;
  518. int Height, Width, WidthBytes, StrideWidthBytes;
  519. if(pICD == NULL) {
  520. dprintf1((TEXT("DeCmEx: pICD== NULL\n")));
  521. return (DWORD)ICERR_BADFORMAT;
  522. }
  523. pbmSrc = pICD->lpbiSrc;
  524. pbmDst = pICD->lpbiDst;
  525. if(pbmSrc->biCompression != pbmDst->biCompression) {
  526. dprintf1((TEXT("DeCmEx: Compression does not match! In(%s) != Out(%s)\n"), (PTCHAR) &pbmSrc->biCompression, (PTCHAR) &pbmDst->biCompression));
  527. return (DWORD)ICERR_BADFORMAT;
  528. }
  529. // Since no stretching,
  530. // SrcHeight == DstHeight
  531. // SrcWidth == DstWidth
  532. Height = abs(pbmSrc->biHeight);
  533. Width = pbmSrc->biWidth;
  534. WidthBytes = Width * pbmSrc->biBitCount / 8;
  535. StrideWidthBytes = pbmDst->biWidth * pbmDst->biBitCount / 8;
  536. pSrc = (PBYTE) pICD->lpSrc;
  537. /*
  538. * adjust the destination to point to the start of the last line,
  539. * and work upwards (to flip vertically into DIB format)
  540. * if biHeight for In/Out are different. Else Top/down.
  541. */
  542. pDst = (PBYTE)pICD->lpDst;
  543. dprintf2(("DeCmEx: %dx%d; (%x %dx%dx%d=%d); (%x %dx%dx%d=%d); Stride=%d\n",
  544. Width, Height,
  545. (PCHAR) &pbmSrc->biCompression,
  546. pbmSrc->biWidth, pbmSrc->biHeight, pbmSrc->biBitCount, pbmSrc->biSizeImage,
  547. (PCHAR) &pbmDst->biCompression,
  548. pbmDst->biWidth, pbmDst->biHeight, pbmDst->biBitCount, pbmDst->biSizeImage,
  549. StrideWidthBytes));
  550. ASSERT((pbmDst->biSizeImage <= pbmSrc->biSizeImage));
  551. // No stretching
  552. // pbmSrc->biSizeImage may not been defined so the image size is calculated from its
  553. // known value of width, height and bitcount.
  554. memcpy(pDst, pSrc, Width * Height * pbmSrc->biBitCount / 8);
  555. return ICERR_OK;
  556. }
  557. /*****************************************************************************
  558. ****************************************************************************/
  559. DWORD NEAR PASCAL DecompressExBegin(INSTINFO * pinst, ICDECOMPRESSEX * pICD, DWORD dwICDSize)
  560. {
  561. DWORD dwRtn;
  562. LPBITMAPINFOHEADER pbmSrc, pbmDst;
  563. if (pICD == NULL) {
  564. dprintf1(("DeCmExBegin: pICD== NULL\n"));
  565. return (DWORD)ICERR_BADFORMAT;
  566. }
  567. pbmSrc = pICD->lpbiSrc;
  568. pbmDst = pICD->lpbiDst;
  569. /* check that the conversion formats are valid */
  570. dwRtn = DecompressExQuery(pinst, pICD, dwICDSize);
  571. if (dwRtn != ICERR_OK) {
  572. dprintf1(("DeCmExBegin return 0x%x", dwRtn));
  573. return dwRtn;
  574. }
  575. // No need to allocate any buffer
  576. dprintf1(("DeCmExBegin return ICERR_OK\n"));
  577. return ICERR_OK;
  578. }
  579. /*****************************************************************************
  580. ****************************************************************************/
  581. DWORD NEAR PASCAL DecompressExEnd(INSTINFO * pinst)
  582. {
  583. pinst->dwFormat = 0;
  584. return ICERR_OK;
  585. }