Windows NT 4.0 source code leak
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.

1222 lines
36 KiB

4 years ago
  1. /*----------------------------------------------------------------------+
  2. | msvidc.c - Microsoft Video 1 Compressor |
  3. | |
  4. | Copyright (c) 1990-1995 Microsoft Corporation. |
  5. | Portions Copyright Media Vision Inc. |
  6. | All Rights Reserved. |
  7. | |
  8. | You have a non-exclusive, worldwide, royalty-free, and perpetual |
  9. | license to use this source code in developing hardware, software |
  10. | (limited to drivers and other software required for hardware |
  11. | functionality), and firmware for video display and/or processing |
  12. | boards. Microsoft makes no warranties, express or implied, with |
  13. | respect to the Video 1 codec, including without limitation warranties |
  14. | of merchantability or fitness for a particular purpose. Microsoft |
  15. | shall not be liable for any damages whatsoever, including without |
  16. | limitation consequential damages arising from your use of the Video 1 |
  17. | codec. |
  18. | |
  19. | |
  20. +----------------------------------------------------------------------*/
  21. #include <win32.h>
  22. #include <ole2.h>
  23. #include <mmsystem.h>
  24. #include <aviffmt.h>
  25. #include <compddk.h>
  26. #ifdef _WIN32
  27. #define abs(x) ((x) < 0 ? -(x) : (x))
  28. #endif
  29. #ifdef _WIN32
  30. #include <memory.h> /* for memcpy */
  31. #endif
  32. #ifdef _WIN32
  33. #define _FPInit() 0
  34. #define _FPTerm(x)
  35. #else
  36. void _acrtused2(void) {}
  37. extern LPVOID WINAPI _FPInit(void);
  38. extern void WINAPI _FPTerm(LPVOID);
  39. #endif
  40. #include "msvidc.h"
  41. #ifdef _WIN32
  42. #include "profile.h"
  43. #endif
  44. #ifndef _WIN32
  45. static BOOL gf286 = FALSE;
  46. #endif
  47. #define FOURCC_MSVC mmioFOURCC('M','S','V','C')
  48. #define FOURCC_CRAM mmioFOURCC('C','R','A','M')
  49. #define FOURCC_Cram mmioFOURCC('C','r','a','m')
  50. #define TWOCC_XX aviTWOCC('d', 'c')
  51. #define QUALITY_DEFAULT 2500
  52. #define VERSION 0x00010000 // 1.0
  53. ICSTATE DefaultState = {75};
  54. BOOL FAR PASCAL _LOADDS ConfigureDlgProc(HWND hdlg, UINT msg, UINT wParam, LONG lParam);
  55. #ifndef _WIN32
  56. //
  57. // put the compress stuff in the "rare" segment
  58. //
  59. #pragma alloc_text(_TEXT, ConfigureDlgProc)
  60. #pragma alloc_text(_TEXT, CompressBegin)
  61. #pragma alloc_text(_TEXT, CompressQuery)
  62. #pragma alloc_text(_TEXT, CompressGetFormat)
  63. #pragma alloc_text(_TEXT, Compress)
  64. #pragma alloc_text(_TEXT, CompressGetSize)
  65. #pragma alloc_text(_TEXT, CompressEnd)
  66. #endif
  67. /*****************************************************************************
  68. * dither stuff..
  69. ****************************************************************************/
  70. #include <dith775.h>
  71. LPVOID lpDitherTable;
  72. //////////////////////////////////////////////////////////////////////////////
  73. //
  74. // Dither16InitScale()
  75. //
  76. //////////////////////////////////////////////////////////////////////////////
  77. #pragma optimize("", off)
  78. STATICFN LPVOID Dither16InitScale()
  79. {
  80. LPVOID p;
  81. LPBYTE pbLookup;
  82. LPWORD pwScale;
  83. UINT r,g,b;
  84. p = GlobalAllocPtr(GMEM_MOVEABLE|GMEM_SHARE, 32768l*2+64000);
  85. if (p == NULL)
  86. return NULL;
  87. pwScale = (LPWORD)p;
  88. for (r=0; r<32; r++)
  89. for (g=0; g<32; g++)
  90. for (b=0; b<32; b++)
  91. *pwScale++ = 1600 * r + 40 * g + b;
  92. pbLookup = (LPBYTE)(((WORD _huge *)p) + 32768l);
  93. for (r=0; r<40; r++)
  94. for (g=0; g<40; g++)
  95. for (b=0; b<40; b++)
  96. *pbLookup++ = lookup775[35*rlevel[r] + 5*glevel[g] + blevel[b]];
  97. return p;
  98. }
  99. #pragma optimize("", on)
  100. /*****************************************************************************
  101. ****************************************************************************/
  102. #ifndef _WIN32
  103. BOOL NEAR PASCAL VideoLoad(void)
  104. {
  105. gf286 = (BOOL)(GetWinFlags() & WF_CPU286);
  106. #ifdef DEBUG
  107. gf286 = GetProfileIntA("Debug", "cpu", gf286 ? 286 : 386) == 286;
  108. #endif
  109. return TRUE;
  110. }
  111. #endif
  112. /*****************************************************************************
  113. ****************************************************************************/
  114. void NEAR PASCAL VideoFree()
  115. {
  116. // CompressFrameFree(); // let compression stuff clean up...
  117. if (lpDitherTable != NULL) {
  118. GlobalFreePtr(lpDitherTable);
  119. lpDitherTable = NULL;
  120. }
  121. }
  122. /*****************************************************************************
  123. ****************************************************************************/
  124. INSTINFO * NEAR PASCAL VideoOpen(ICOPEN FAR * icinfo)
  125. {
  126. INSTINFO * pinst;
  127. //
  128. // refuse to open if we are not being opened as a Video compressor
  129. //
  130. if (icinfo->fccType != ICTYPE_VIDEO)
  131. return NULL;
  132. pinst = (INSTINFO *)LocalAlloc(LPTR, sizeof(INSTINFO));
  133. if (!pinst) {
  134. icinfo->dwError = (DWORD)ICERR_MEMORY;
  135. return NULL;
  136. }
  137. //
  138. // init structure
  139. //
  140. pinst->dwFlags = icinfo->dwFlags;
  141. pinst->nCompress = 0;
  142. pinst->nDecompress = 0;
  143. pinst->nDraw = 0;
  144. //
  145. // set the default state.
  146. //
  147. SetState(pinst, NULL, 0);
  148. //
  149. // return success.
  150. //
  151. icinfo->dwError = ICERR_OK;
  152. return pinst;
  153. }
  154. /*****************************************************************************
  155. ****************************************************************************/
  156. LONG NEAR PASCAL VideoClose(INSTINFO * pinst)
  157. {
  158. while (pinst->nCompress > 0)
  159. CompressEnd(pinst);
  160. while (pinst->nDecompress > 0)
  161. DecompressEnd(pinst);
  162. while (pinst->nDraw > 0)
  163. DrawEnd(pinst);
  164. LocalFree((HLOCAL)pinst);
  165. return 1;
  166. }
  167. /*****************************************************************************
  168. ****************************************************************************/
  169. #ifndef QueryAbout
  170. BOOL NEAR PASCAL QueryAbout(INSTINFO * pinst)
  171. {
  172. return TRUE;
  173. }
  174. #endif
  175. LONG NEAR PASCAL About(INSTINFO * pinst, HWND hwnd)
  176. {
  177. char achDescription[128];
  178. char achAbout[64];
  179. LoadStringA(ghModule, IDS_DESCRIPTION, achDescription, sizeof(achDescription));
  180. LoadStringA(ghModule, IDS_ABOUT, achAbout, sizeof(achAbout));
  181. MessageBoxA(hwnd,achDescription,achAbout,
  182. MB_OK|MB_ICONINFORMATION);
  183. return ICERR_OK;
  184. }
  185. /*****************************************************************************
  186. ****************************************************************************/
  187. #ifndef QueryConfigure
  188. BOOL NEAR PASCAL QueryConfigure(INSTINFO * pinst)
  189. {
  190. return TRUE;
  191. }
  192. #endif
  193. LONG NEAR PASCAL Configure(INSTINFO * pinst, HWND hwnd)
  194. {
  195. return DialogBoxParam(ghModule,TEXT("Configure"),hwnd,ConfigureDlgProc, (LONG)(UINT)pinst);
  196. }
  197. /*****************************************************************************
  198. ****************************************************************************/
  199. LONG NEAR PASCAL GetState(INSTINFO * pinst, LPVOID pv, DWORD dwSize)
  200. {
  201. if (pv == NULL || dwSize == 0)
  202. return sizeof(ICSTATE);
  203. if (dwSize < sizeof(ICSTATE))
  204. return 0;
  205. *((ICSTATE FAR *)pv) = pinst->CurrentState;
  206. // return number of bytes copied
  207. return sizeof(ICSTATE);
  208. }
  209. /*****************************************************************************
  210. ****************************************************************************/
  211. LONG NEAR PASCAL SetState(INSTINFO * pinst, LPVOID pv, DWORD dwSize)
  212. {
  213. if (pv == NULL)
  214. pinst->CurrentState = DefaultState;
  215. else if (dwSize == sizeof(ICSTATE))
  216. pinst->CurrentState = *((ICSTATE FAR *)pv);
  217. else
  218. return 0;
  219. // return number of bytes copied
  220. return sizeof(ICSTATE);
  221. }
  222. #if !defined NUMELMS
  223. #define NUMELMS(aa) (sizeof(aa)/sizeof((aa)[0]))
  224. #endif
  225. #if defined _WIN32 && !defined UNICODE
  226. int LoadUnicodeString(HINSTANCE hinst, UINT wID, LPWSTR lpBuffer, int cchBuffer)
  227. {
  228. char ach[128];
  229. int i;
  230. i = LoadString(hinst, wID, ach, sizeof(ach));
  231. if (i > 0)
  232. MultiByteToWideChar(CP_ACP, 0, ach, -1, lpBuffer, cchBuffer);
  233. return i;
  234. }
  235. #else
  236. #define LoadUnicodeString LoadString
  237. #endif
  238. /*****************************************************************************
  239. ****************************************************************************/
  240. LONG NEAR PASCAL GetInfo(INSTINFO * pinst, ICINFO FAR *icinfo, DWORD dwSize)
  241. {
  242. if (icinfo == NULL)
  243. return sizeof(ICINFO);
  244. if (dwSize < sizeof(ICINFO))
  245. return 0;
  246. icinfo->dwSize = sizeof(ICINFO);
  247. icinfo->fccType = ICTYPE_VIDEO;
  248. icinfo->fccHandler = FOURCC_MSVC;
  249. icinfo->dwFlags = VIDCF_QUALITY | // supports quality
  250. VIDCF_TEMPORAL; // supports inter-frame
  251. icinfo->dwVersion = VERSION;
  252. icinfo->dwVersionICM = ICVERSION;
  253. LoadUnicodeString(ghModule, IDS_DESCRIPTION, icinfo->szDescription, NUMELMS(icinfo->szDescription));
  254. LoadUnicodeString(ghModule, IDS_NAME, icinfo->szName, NUMELMS(icinfo->szName));
  255. return sizeof(ICINFO);
  256. }
  257. /*****************************************************************************
  258. ****************************************************************************/
  259. LONG FAR PASCAL CompressQuery(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  260. {
  261. if (lpbiOut)
  262. DPF(("CompressQuery %dx%dx%d --> %dx%dx%d'%4.4hs'", (int)lpbiIn->biWidth, (int)lpbiIn->biHeight, (int)lpbiIn->biBitCount, (int)lpbiOut->biWidth, (int)lpbiOut->biHeight, (int)lpbiOut->biBitCount, (LPSTR)&lpbiOut->biCompression));
  263. else
  264. DPF(("CompressQuery %dx%dx%d", (int)lpbiIn->biWidth, (int)lpbiIn->biHeight, (int)lpbiIn->biBitCount));
  265. //
  266. // determine if the input DIB data is in a format we like.
  267. //
  268. if (lpbiIn == NULL ||
  269. !(lpbiIn->biBitCount == 8 ||
  270. lpbiIn->biBitCount == 16 ||
  271. lpbiIn->biBitCount == 24 ||
  272. lpbiIn->biBitCount == 32) ||
  273. lpbiIn->biPlanes != 1 ||
  274. lpbiIn->biWidth < 4 ||
  275. lpbiIn->biHeight < 4 ||
  276. lpbiIn->biCompression != BI_RGB)
  277. return ICERR_BADFORMAT;
  278. //
  279. // are we being asked to query just the input format?
  280. //
  281. if (lpbiOut == NULL)
  282. return ICERR_OK;
  283. //
  284. // make sure we can handle the format to compress to also.
  285. //
  286. if (!(lpbiOut->biCompression == FOURCC_MSVC || // must be 'MSVC' or 'CRAM'
  287. lpbiOut->biCompression == FOURCC_CRAM) ||
  288. !(lpbiOut->biBitCount == 16 || // must be 8 or 16
  289. lpbiOut->biBitCount == 8) ||
  290. (lpbiOut->biPlanes != 1) ||
  291. (lpbiOut->biWidth & ~3) != (lpbiIn->biWidth & ~3) || // must be 1:1 (no stretch)
  292. (lpbiOut->biHeight & ~3) != (lpbiIn->biHeight & ~3))
  293. return ICERR_BADFORMAT;
  294. return ICERR_OK;
  295. }
  296. /*****************************************************************************
  297. ****************************************************************************/
  298. LONG FAR PASCAL CompressGetFormat(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  299. {
  300. LONG l;
  301. if (l = CompressQuery(pinst, lpbiIn, NULL))
  302. return l;
  303. if (lpbiIn->biBitCount == 8)
  304. {
  305. //
  306. // if lpbiOut == NULL then, return the size required to hold a output
  307. // format
  308. //
  309. l = lpbiIn->biSize + (int)lpbiIn->biClrUsed * sizeof(RGBQUAD);
  310. if (lpbiOut == NULL)
  311. return l;
  312. hmemcpy(lpbiOut, lpbiIn, (int)l);
  313. lpbiOut->biBitCount = 8;
  314. }
  315. else
  316. {
  317. //
  318. // if lpbiOut == NULL then, return the size required to hold a output
  319. // format
  320. //
  321. if (lpbiOut == NULL)
  322. return (int)lpbiIn->biSize;
  323. *lpbiOut = *lpbiIn;
  324. lpbiOut->biClrUsed = 0;
  325. lpbiOut->biBitCount = 16;
  326. }
  327. lpbiOut->biWidth = lpbiIn->biWidth & ~3;
  328. lpbiOut->biHeight = lpbiIn->biHeight & ~3;
  329. lpbiOut->biCompression = FOURCC_CRAM;
  330. lpbiOut->biSizeImage = CompressGetSize(pinst, lpbiIn, lpbiOut);
  331. return ICERR_OK;
  332. }
  333. /*****************************************************************************
  334. ****************************************************************************/
  335. LONG FAR PASCAL CompressBegin(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  336. {
  337. LONG l;
  338. if (l = CompressQuery(pinst, lpbiIn, lpbiOut))
  339. return l;
  340. DPF(("CompressBegin %dx%dx%d --> %dx%dx%d'%4.4ls'", (int)lpbiIn->biWidth, (int)lpbiIn->biHeight, (int)lpbiIn->biBitCount, (int)lpbiOut->biWidth, (int)lpbiOut->biHeight, (int)lpbiOut->biBitCount,(LPSTR)&lpbiOut->biCompression));
  341. //
  342. // initialize for compression, for real....
  343. //
  344. pinst->nCompress = 1;
  345. return CompressFrameBegin(lpbiIn, lpbiOut, &pinst->lpITable, pinst->rgbqOut);
  346. }
  347. /*****************************************************************************
  348. ****************************************************************************/
  349. LONG FAR PASCAL CompressGetSize(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  350. {
  351. int dx,dy;
  352. dx = (int)lpbiIn->biWidth;
  353. dy = (int)lpbiIn->biHeight;
  354. /* maximum compressed size *** your code here *** */
  355. if (lpbiOut->biBitCount == 8)
  356. // worst case size of data 10 bytes per 16 pixels (8 colors + mask)
  357. // remember the EOF code!
  358. return ((DWORD)dx * (DWORD)dy * 10l) / 16l + 2l;
  359. else
  360. // worst case size of data 18 bytes per 16 pixels (8 colors + mask)
  361. // remember the EOF code!
  362. return ((DWORD)dx * (DWORD)dy * 10l) / 8l + 2l; // 10/8 ~= 18/16
  363. ////////return ((DWORD)dx * (DWORD)dy * 18l) / 16l + 2l;
  364. }
  365. /*****************************************************************************
  366. ****************************************************************************/
  367. LONG FAR PASCAL Compress(INSTINFO * pinst, ICCOMPRESS FAR *icinfo, DWORD dwSize)
  368. {
  369. LONG l;
  370. LPBITMAPINFOHEADER lpbiIn = icinfo->lpbiInput;
  371. LPBITMAPINFOHEADER lpbiOut = icinfo->lpbiOutput;
  372. DWORD threshold;
  373. DWORD thresholdPrev;
  374. DWORD dwQualityPrev;
  375. DWORD dwQuality;
  376. BOOL fBegin;
  377. LPVOID smag;
  378. PCELLS compressTemp;
  379. if (l = CompressQuery(pinst, icinfo->lpbiInput, icinfo->lpbiOutput))
  380. return l;
  381. //
  382. // check for being called without a BEGIN message, and do the begin for
  383. // the caller
  384. //
  385. if (fBegin = (pinst->nCompress == 0))
  386. {
  387. if (l = CompressBegin(pinst, icinfo->lpbiInput, icinfo->lpbiOutput))
  388. return l;
  389. }
  390. smag = _FPInit();
  391. DPF(("Compress %dx%dx%d --> %dx%dx%d'%4.4ls'", (int)lpbiIn->biWidth, (int)lpbiIn->biHeight, (int)lpbiIn->biBitCount, (int)lpbiOut->biWidth, (int)lpbiOut->biHeight, (int)lpbiOut->biBitCount, (LPSTR)&lpbiOut->biCompression));
  392. if (icinfo->dwQuality == ICQUALITY_DEFAULT)
  393. dwQuality = QUALITY_DEFAULT;
  394. else
  395. dwQuality = ICQUALITY_HIGH - icinfo->dwQuality;
  396. dwQualityPrev = MulDiv((UINT)dwQuality,100,pinst->CurrentState.wTemporalRatio);
  397. threshold = QualityToThreshold(dwQuality);
  398. thresholdPrev = QualityToThreshold(dwQualityPrev);
  399. if (pinst->Status)
  400. pinst->Status(pinst->lParam, ICSTATUS_START, 0);
  401. // For Win16, this needs to be in the data segment so we
  402. // can use a near pointer to it.
  403. compressTemp = (PCELLS) LocalAlloc(LPTR, sizeof(CELLS));
  404. if (!compressTemp)
  405. return ICERR_MEMORY;
  406. if (lpbiOut->biBitCount == 8)
  407. l = CompressFrame8(
  408. icinfo->lpbiInput, // DIB header to compress
  409. icinfo->lpInput, // DIB bits to compress
  410. icinfo->lpOutput, // put compressed data here
  411. threshold, // edge threshold
  412. thresholdPrev, // inter-frame threshold
  413. icinfo->lpbiPrev, // previous frame
  414. icinfo->lpPrev, // previous frame
  415. pinst->Status, // status callback
  416. pinst->lParam,
  417. compressTemp,
  418. pinst->lpITable,
  419. pinst->rgbqOut);
  420. else
  421. l = CompressFrame16(
  422. icinfo->lpbiInput, // DIB header to compress
  423. icinfo->lpInput, // DIB bits to compress
  424. icinfo->lpOutput, // put compressed data here
  425. threshold, // edge threshold
  426. thresholdPrev, // inter-frame threshold
  427. icinfo->lpbiPrev, // previous frame
  428. icinfo->lpPrev, // previous frame
  429. pinst->Status, // status callback
  430. pinst->lParam,
  431. compressTemp);
  432. LocalFree((HLOCAL) compressTemp);
  433. if (pinst->Status)
  434. pinst->Status(pinst->lParam, ICSTATUS_END, 0);
  435. _FPTerm(smag);
  436. if (l == -1)
  437. return ICERR_ERROR;
  438. lpbiOut->biWidth = lpbiIn->biWidth & ~3;
  439. lpbiOut->biHeight = lpbiIn->biHeight & ~3;
  440. lpbiOut->biCompression = FOURCC_CRAM;
  441. lpbiOut->biSizeImage = l;
  442. ////lpbiOut->biBitCount = 16;
  443. //
  444. // return the chunk id
  445. //
  446. if (icinfo->lpckid)
  447. *icinfo->lpckid = TWOCC_XX;
  448. //
  449. // set the AVI index flags,
  450. //
  451. // make it a keyframe?
  452. //
  453. if (icinfo->lpdwFlags) {
  454. *icinfo->lpdwFlags = AVIIF_TWOCC;
  455. if (icinfo->lpbiPrev == NULL || numberOfSkips == 0)
  456. *icinfo->lpdwFlags |= AVIIF_KEYFRAME;
  457. }
  458. if (fBegin)
  459. CompressEnd(pinst);
  460. return ICERR_OK;
  461. }
  462. /*****************************************************************************
  463. ****************************************************************************/
  464. LONG FAR PASCAL CompressEnd(INSTINFO * pinst)
  465. {
  466. if (pinst->nCompress == 0)
  467. return ICERR_ERROR;
  468. pinst->nCompress = 0;
  469. return CompressFrameEnd(&pinst->lpITable);
  470. }
  471. /*****************************************************************************
  472. *
  473. * decompress tables
  474. *
  475. * indexed by:
  476. * SRC: 0=8 bit Cram 1=16 bit Cram
  477. * STRETCH: 0=1:1, 1=1:2
  478. * DST: 0=8, 1=16, 2=24, 3=32
  479. *
  480. ****************************************************************************/
  481. #ifdef _WIN32
  482. DECOMPPROC DecompressWin32[2][2][5] = {
  483. DecompressFrame8, // Cram8 1:1 to 8
  484. NULL, // Cram8 1:1 to 16 (555)
  485. NULL, // Cram8 1:1 to 24
  486. NULL, // Cram8 1:1 to 32
  487. NULL, // Cram8 1:1 to 565
  488. DecompressFrame8X2C, // Cram8 1:2 to 8
  489. NULL, // Cram8 1:2 to 16 (555)
  490. NULL, // Cram8 1:2 to 24
  491. NULL, // Cram8 1:2 to 32
  492. NULL, // Cram8 1:2 to 565
  493. DecompressFrame16To8C, // Cram16 1:1 to 8
  494. DecompressFrame16To555C, // Cram16 1:1 to 16 (555)
  495. DecompressFrame24, // Cram16 1:1 to 24
  496. NULL, // Cram16 1:1 to 32
  497. DecompressFrame16To565C, // Cram16 1:1 to 565
  498. DecompressFrame16To8X2C, // Cram16 1:2 to 8
  499. NULL, // Cram16 1:2 to 16 (555)
  500. NULL, // Cram16 1:2 to 24
  501. NULL, // Cram16 1:2 to 32
  502. NULL}; // Cram16 1:2 to 565
  503. #else
  504. DECOMPPROC Decompress386[2][2][5] = {
  505. DecompressCram8, // Cram8 1:1 to 8
  506. NULL, // Cram8 1:1 to 16 (555)
  507. NULL, // Cram8 1:1 to 24
  508. NULL, // Cram8 1:1 to 32
  509. NULL, // Cram8 1:1 to 565
  510. DecompressCram8x2, // Cram8 1:2 to 8
  511. NULL, // Cram8 1:2 to 16 (555)
  512. NULL, // Cram8 1:2 to 24
  513. NULL, // Cram8 1:2 to 32
  514. NULL, // Cram8 1:2 to 565
  515. DecompressCram168, // Cram16 1:1 to 8
  516. DecompressCram16, // Cram16 1:1 to 16 (555)
  517. NULL, // Cram16 1:1 to 24
  518. NULL /* DecompressCram32 */, // Cram16 1:1 to 32
  519. NULL /* DecompressFrame16To565C */, // Cram16 1:1 to 565
  520. NULL, // Cram16 1:2 to 8
  521. DecompressCram16x2, // Cram16 1:2 to 16 (555)
  522. NULL, // Cram16 1:2 to 24
  523. NULL, // Cram16 1:2 to 32
  524. NULL}; // Cram16 1:2 to 565
  525. DECOMPPROC Decompress286[2][2][5] = {
  526. DecompressCram8_286, // Cram8 1:1 to 8
  527. NULL, // Cram8 1:1 to 16 (555)
  528. NULL, // Cram8 1:1 to 24
  529. NULL, // Cram8 1:1 to 32
  530. NULL, // Cram8 1:1 to 565
  531. NULL, // Cram8 1:2 to 8
  532. NULL, // Cram8 1:2 to 16 (555)
  533. NULL, // Cram8 1:2 to 24
  534. NULL, // Cram8 1:2 to 32
  535. NULL, // Cram8 1:2 to 565
  536. NULL, // Cram16 1:1 to 8
  537. DecompressCram16_286, // Cram16 1:1 to 16 (555)
  538. NULL, // Cram16 1:1 to 24
  539. NULL, // Cram16 1:1 to 32
  540. NULL, // Cram16 1:1 to 565
  541. NULL, // Cram16 1:2 to 8
  542. NULL, // Cram16 1:2 to 16 (555)
  543. NULL, // Cram16 1:2 to 24
  544. NULL, // Cram16 1:2 to 32
  545. NULL}; // Cram16 1:2 to 565
  546. #endif
  547. /*****************************************************************************
  548. ****************************************************************************/
  549. LONG NEAR PASCAL DecompressQueryFmt(
  550. INSTINFO * pinst,
  551. LPBITMAPINFOHEADER lpbiSrc)
  552. {
  553. //
  554. // determine if the input DIB data is in a format we like.
  555. //
  556. if (lpbiSrc == NULL ||
  557. !(lpbiSrc->biBitCount == 16 || lpbiSrc->biBitCount == 8) ||
  558. (lpbiSrc->biPlanes != 1) ||
  559. !(lpbiSrc->biCompression == FOURCC_MSVC ||
  560. lpbiSrc->biCompression == FOURCC_CRAM))
  561. return ICERR_BADFORMAT;
  562. return ICERR_OK;
  563. }
  564. /*****************************************************************************
  565. ****************************************************************************/
  566. LONG NEAR PASCAL DecompressQuery(
  567. INSTINFO * pinst,
  568. DWORD dwFlags,
  569. LPBITMAPINFOHEADER lpbiSrc,
  570. LPVOID pSrc,
  571. int xSrc,
  572. int ySrc,
  573. int dxSrc,
  574. int dySrc,
  575. LPBITMAPINFOHEADER lpbiDst,
  576. LPVOID pDst,
  577. int xDst,
  578. int yDst,
  579. int dxDst,
  580. int dyDst)
  581. {
  582. #ifndef _WIN32
  583. DWORD biSizeImage;
  584. #endif
  585. DECOMPPROC fn;
  586. int s,d,n;
  587. //
  588. // determine if the input DIB data is in a format we like.
  589. //
  590. if (DecompressQueryFmt(pinst, lpbiSrc))
  591. return ICERR_BADFORMAT;
  592. //
  593. // allow (-1) as a default width/height
  594. //
  595. if (dxSrc == -1)
  596. dxSrc = (int)lpbiSrc->biWidth;
  597. if (dySrc == -1)
  598. dySrc = (int)lpbiSrc->biHeight;
  599. //
  600. // we cant clip the source.
  601. //
  602. if (xSrc != 0 || ySrc != 0)
  603. return ICERR_BADPARAM;
  604. if ((dxSrc != (int)lpbiSrc->biWidth) || (dySrc != (int)lpbiSrc->biHeight))
  605. return ICERR_BADPARAM;
  606. //
  607. // are we being asked to query just the input format?
  608. //
  609. if (lpbiDst == NULL)
  610. return ICERR_OK;
  611. //
  612. // allow (-1) as a default width/height
  613. //
  614. if (dxDst == -1)
  615. dxDst = (int)lpbiDst->biWidth;
  616. if (dyDst == -1)
  617. dyDst = abs((int)lpbiDst->biHeight);
  618. #ifndef _WIN32
  619. if (gf286)
  620. biSizeImage = (DWORD)(UINT)abs((int)lpbiDst->biHeight)*(DWORD)(WORD)DIBWIDTHBYTES(*lpbiDst);
  621. #endif
  622. s = lpbiSrc->biBitCount/8-1; // s = 0,1
  623. #ifdef _WIN32
  624. // Can't support 16:32 access in our C version, of course....
  625. if (lpbiDst->biCompression == BI_1632) {
  626. return ICERR_BADFORMAT;
  627. }
  628. #endif
  629. if (lpbiDst->biBitCount != 8 && lpbiDst->biBitCount != 16 && lpbiDst->biBitCount != 24 && lpbiDst->biBitCount != 32)
  630. {
  631. return ICERR_BADFORMAT;
  632. }
  633. // must be full dib or a '1632' DIB
  634. if (lpbiDst->biCompression != BI_RGB &&
  635. lpbiDst->biCompression != BI_1632) {
  636. // allow 565 dibs
  637. if ((lpbiDst->biCompression == BI_BITFIELDS) &&
  638. (lpbiDst->biBitCount == 16) &&
  639. (((LPDWORD)(lpbiDst+1))[0] == 0x00f800) &&
  640. (((LPDWORD)(lpbiDst+1))[1] == 0x0007e0) &&
  641. (((LPDWORD)(lpbiDst+1))[2] == 0x00001f) ) {
  642. // ok - its 565 format
  643. d = 4;
  644. } else {
  645. DPF(("Bad bitmask (%lX %lX %lX) in %d-bit BI_BITMAP case!",
  646. lpbiDst->biBitCount,
  647. ((LPDWORD)(lpbiDst+1))[0],
  648. ((LPDWORD)(lpbiDst+1))[1],
  649. ((LPDWORD)(lpbiDst+1))[2]));
  650. return ICERR_BADFORMAT;
  651. }
  652. } else {
  653. d = lpbiDst->biBitCount/8-1; // d = 0,1,2,3
  654. if (lpbiDst->biCompression == BI_1632 && lpbiDst->biBitCount == 16) {
  655. if ((((LPDWORD)(lpbiDst+1))[0] == 0x007400) &&
  656. (((LPDWORD)(lpbiDst+1))[1] == 0x0003f0) &&
  657. (((LPDWORD)(lpbiDst+1))[2] == 0x00000f) ) {
  658. // ok - it's 555 format
  659. } else if ((((LPDWORD)(lpbiDst+1))[0] == 0x00f800) &&
  660. (((LPDWORD)(lpbiDst+1))[1] == 0x0007e0) &&
  661. (((LPDWORD)(lpbiDst+1))[2] == 0x00001f) ) {
  662. // ok - it's 565 format
  663. d = 4;
  664. } else {
  665. DPF(("Bad bitmask (%lX %lX %lX) in 16-bit BI_1632 case!",
  666. ((LPDWORD)(lpbiDst+1))[0],
  667. ((LPDWORD)(lpbiDst+1))[1],
  668. ((LPDWORD)(lpbiDst+1))[2]));
  669. return ICERR_BADFORMAT;
  670. }
  671. }
  672. // What about 24-bit BI_1632? Should we check the masks?
  673. }
  674. //
  675. // n = 0 for 1:1, 1 for 1:2
  676. //
  677. if (dxDst == dxSrc && dyDst == dySrc)
  678. n = 0;
  679. else if (dxDst == dxSrc*2 && dyDst == dySrc*2)
  680. n = 1;
  681. else
  682. return ICERR_BADSIZE;
  683. #ifdef DEBUG
  684. DPF(("DecompressQuery %dx%dx%d [%d,%d,%d,%d] --> %dx%dx%d (565) [%d,%d,%d,%d]",
  685. (int)lpbiSrc->biWidth, (int)lpbiSrc->biHeight, (int)lpbiSrc->biBitCount,
  686. xSrc, ySrc, dxSrc, dySrc,
  687. (int)lpbiDst->biWidth, (int)lpbiDst->biHeight, (int)lpbiDst->biBitCount,
  688. d == 4 ? "(565)" : "",
  689. xDst, yDst, dxDst, dyDst));
  690. #endif
  691. #ifdef _WIN32
  692. fn = DecompressWin32[s][n][d];
  693. #else
  694. if (gf286)
  695. {
  696. fn = Decompress286[s][n][d];
  697. if (fn && biSizeImage > 64l*1024)
  698. fn = fn==DecompressCram8_286 ? DecompressFrame8 : NULL;
  699. }
  700. else
  701. {
  702. fn = Decompress386[s][n][d];
  703. }
  704. #endif
  705. if (fn == NULL)
  706. return ICERR_BADFORMAT;
  707. pinst->DecompressTest = fn; // return this to DecompressBegin.
  708. return ICERR_OK;
  709. }
  710. /*****************************************************************************
  711. ****************************************************************************/
  712. LONG NEAR PASCAL DecompressGetFormat(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  713. {
  714. LONG l;
  715. int dx,dy;
  716. if (l = DecompressQueryFmt(pinst, lpbiIn))
  717. return l;
  718. //
  719. // if lpbiOut == NULL then, return the size required to hold a output
  720. // format
  721. //
  722. if (lpbiOut == NULL)
  723. return (int)lpbiIn->biSize + (int)lpbiIn->biClrUsed * sizeof(RGBQUAD);
  724. hmemcpy(lpbiOut, lpbiIn,
  725. (int)lpbiIn->biSize + (int)lpbiIn->biClrUsed * sizeof(RGBQUAD));
  726. dx = (int)lpbiIn->biWidth & ~3;
  727. dy = (int)lpbiIn->biHeight & ~3;
  728. lpbiOut->biWidth = dx;
  729. lpbiOut->biHeight = dy;
  730. lpbiOut->biBitCount = lpbiIn->biBitCount; // convert 8->8 16->16
  731. lpbiOut->biPlanes = 1;
  732. lpbiOut->biCompression = BI_RGB;
  733. lpbiOut->biSizeImage = (DWORD)(WORD)abs(dy)*(DWORD)(WORD)DIBWIDTHBYTES(*lpbiOut);
  734. return ICERR_OK;
  735. }
  736. /*****************************************************************************
  737. ****************************************************************************/
  738. LONG NEAR PASCAL DecompressBegin(
  739. INSTINFO * pinst,
  740. DWORD dwFlags,
  741. LPBITMAPINFOHEADER lpbiSrc,
  742. LPVOID pSrc,
  743. int xSrc,
  744. int ySrc,
  745. int dxSrc,
  746. int dySrc,
  747. LPBITMAPINFOHEADER lpbiDst,
  748. LPVOID pDst,
  749. int xDst,
  750. int yDst,
  751. int dxDst,
  752. int dyDst)
  753. {
  754. LONG l;
  755. if (l = DecompressQuery(pinst, dwFlags, lpbiSrc, pSrc, xSrc, ySrc, dxSrc, dySrc, lpbiDst, pDst, xDst, yDst, dxDst, dyDst))
  756. return l;
  757. pinst->DecompressProc = pinst->DecompressTest;
  758. //
  759. // make sure biSizeImage is set, the decompress code needs it to be
  760. //
  761. if (lpbiDst->biSizeImage == 0)
  762. lpbiDst->biSizeImage = (DWORD)(WORD)abs((int)lpbiDst->biHeight)*(DWORD)(WORD)DIBWIDTHBYTES(*lpbiDst);
  763. //
  764. // init the dither tables !!! call MSVIDEO, dont have code here!!!
  765. //
  766. if (lpbiSrc->biBitCount == 16 &&
  767. lpbiDst->biBitCount == 8)
  768. {
  769. if (lpDitherTable == NULL)
  770. lpDitherTable = Dither16InitScale();
  771. if (lpDitherTable == NULL)
  772. return ICERR_MEMORY;
  773. }
  774. pinst->nDecompress = 1;
  775. return ICERR_OK;
  776. }
  777. /*****************************************************************************
  778. *
  779. * Decompress
  780. *
  781. * we can assume certain things here because DecompressQuery() only lets
  782. * valid stuff in.
  783. *
  784. * the source rect is always the entire source.
  785. * the dest rect is either 1:1 or 1:2
  786. *
  787. ****************************************************************************/
  788. LONG NEAR PASCAL Decompress(
  789. INSTINFO * pinst,
  790. DWORD dwFlags,
  791. LPBITMAPINFOHEADER lpbiSrc,
  792. LPVOID pSrc,
  793. int xSrc,
  794. int ySrc,
  795. int dxSrc,
  796. int dySrc,
  797. LPBITMAPINFOHEADER lpbiDst,
  798. LPVOID pDst,
  799. int xDst,
  800. int yDst,
  801. int dxDst,
  802. int dyDst)
  803. {
  804. //
  805. // if we are called without a begin do the begin now, but dont make
  806. // the begin "stick"
  807. //
  808. if (pinst->nDecompress == 0)
  809. {
  810. LONG err;
  811. if (err = DecompressBegin(pinst, dwFlags, lpbiSrc, pSrc, xSrc, ySrc, dxSrc, dySrc, lpbiDst, pDst, xDst, yDst, dxDst, dyDst))
  812. return err;
  813. pinst->nDecompress = 0;
  814. }
  815. #ifdef DEBUG
  816. if (lpbiDst->biSizeImage == 0)
  817. DebugBreak();
  818. if (pinst->DecompressProc == NULL)
  819. DebugBreak();
  820. #endif
  821. (*pinst->DecompressProc)(lpbiSrc,pSrc,lpbiDst,pDst,xDst,yDst);
  822. return ICERR_OK;
  823. }
  824. /*****************************************************************************
  825. *
  826. * DecompressGetPalette() implements ICM_GET_PALETTE
  827. *
  828. * This function has no Compress...() equivalent
  829. *
  830. * It is used to pull the palette from a frame in order to possibly do
  831. * a palette change.
  832. *
  833. ****************************************************************************/
  834. LONG NEAR PASCAL DecompressGetPalette(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  835. {
  836. LONG l;
  837. int i;
  838. RGBQUAD FAR * prgb;
  839. DPF(("DecompressGetPalette()"));
  840. if (l = DecompressQueryFmt(pinst, lpbiIn))
  841. return l;
  842. if (lpbiOut->biBitCount != 8)
  843. return ICERR_BADFORMAT;
  844. //
  845. // if you decompress full-color to 8 bit you need to put the "dither"
  846. // palette in lpbiOut
  847. //
  848. if (lpbiIn->biBitCount != 8)
  849. {
  850. lpbiOut->biClrUsed = 256;
  851. prgb = (LPVOID)(lpbiOut + 1);
  852. for (i=0; i<256; i++)
  853. {
  854. prgb[i].rgbRed = dpal775[i][0];
  855. prgb[i].rgbGreen = dpal775[i][1];
  856. prgb[i].rgbBlue = dpal775[i][2];
  857. prgb[i].rgbReserved = 0;
  858. }
  859. return ICERR_OK;
  860. }
  861. if (lpbiIn->biClrUsed == 0)
  862. lpbiIn->biClrUsed = 256;
  863. //
  864. // return the 8bit palette used for decompression.
  865. //
  866. hmemcpy(
  867. (LPBYTE)lpbiOut + (int)lpbiOut->biSize,
  868. (LPBYTE)lpbiIn + (int)lpbiIn->biSize,
  869. (int)lpbiIn->biClrUsed * sizeof(RGBQUAD));
  870. lpbiOut->biClrUsed = lpbiIn->biClrUsed;
  871. return ICERR_OK;
  872. }
  873. /*****************************************************************************
  874. ****************************************************************************/
  875. LONG NEAR PASCAL DecompressEnd(INSTINFO * pinst)
  876. {
  877. if (pinst->nDecompress == 0)
  878. return ICERR_ERROR;
  879. pinst->nDecompress = 0;
  880. return ICERR_OK;
  881. }
  882. /*****************************************************************************
  883. ****************************************************************************/
  884. LONG NEAR PASCAL DrawBegin(INSTINFO * pinst,ICDRAWBEGIN FAR *icinfo, DWORD dwSize)
  885. {
  886. return ICERR_UNSUPPORTED;
  887. }
  888. /*****************************************************************************
  889. ****************************************************************************/
  890. LONG NEAR PASCAL Draw(INSTINFO * pinst, ICDRAW FAR *icinfo, DWORD dwSize)
  891. {
  892. return ICERR_UNSUPPORTED;
  893. }
  894. /*****************************************************************************
  895. ****************************************************************************/
  896. LONG NEAR PASCAL DrawEnd(INSTINFO * pinst)
  897. {
  898. return ICERR_UNSUPPORTED;
  899. }
  900. /*****************************************************************************
  901. ****************************************************************************/
  902. BOOL FAR PASCAL _LOADDS ConfigureDlgProc(HWND hdlg, UINT msg, UINT wParam, LONG lParam)
  903. {
  904. int i;
  905. HWND hsb;
  906. TCHAR ach[10];
  907. static TCHAR chDecimal = TEXT('.');
  908. static INSTINFO *pinst;
  909. #define SCROLL_MIN 1 // 0.00
  910. #define SCROLL_MAX 100 // 1.00
  911. switch (msg)
  912. {
  913. case WM_COMMAND:
  914. switch (wParam)
  915. {
  916. case IDOK:
  917. hsb = GetDlgItem(hdlg,ID_SCROLL);
  918. pinst->CurrentState.wTemporalRatio = GetScrollPos(hsb,SB_CTL);
  919. EndDialog(hdlg,TRUE);
  920. break;
  921. case IDCANCEL:
  922. EndDialog(hdlg,FALSE);
  923. break;
  924. }
  925. break;
  926. case WM_HSCROLL:
  927. hsb = GET_WM_HSCROLL_HWND(wParam, lParam);
  928. i = GetScrollPos(hsb,SB_CTL);
  929. switch (GET_WM_HSCROLL_CODE(wParam, lParam))
  930. {
  931. case SB_LINEDOWN: i += 1; break;
  932. case SB_LINEUP: i -= 1; break;
  933. case SB_PAGEDOWN: i += 10; break;
  934. case SB_PAGEUP: i -= 10; break;
  935. case SB_THUMBTRACK:
  936. case SB_THUMBPOSITION:
  937. i = (int)GET_WM_HSCROLL_POS(wParam, lParam);
  938. break;
  939. default:
  940. return TRUE;
  941. }
  942. i = max(SCROLL_MIN,min(SCROLL_MAX,i));
  943. SetScrollPos(hsb,SB_CTL,i,TRUE);
  944. wsprintf(ach, TEXT("%d%c%02d"), i/100, chDecimal, i%100);
  945. SetDlgItemText(hdlg,ID_TEXT,ach);
  946. return TRUE;
  947. case WM_INITDIALOG:
  948. pinst = (INSTINFO *)lParam;
  949. ach[0] = chDecimal;
  950. ach[1] = 0;
  951. GetProfileString(TEXT("intl"), TEXT("sDecimal"), ach, ach, sizeof(ach));
  952. chDecimal = ach[0];
  953. hsb = GetDlgItem(hdlg,ID_SCROLL);
  954. i = pinst->CurrentState.wTemporalRatio;
  955. SetScrollRange(hsb,SB_CTL,SCROLL_MIN, SCROLL_MAX, TRUE);
  956. SetScrollPos(hsb,SB_CTL,i,TRUE);
  957. wsprintf(ach, TEXT("%d%c%02d"), i/100, chDecimal, i%100);
  958. SetDlgItemText(hdlg,ID_TEXT,ach);
  959. return TRUE;
  960. }
  961. return FALSE;
  962. }
  963. /*****************************************************************************
  964. ****************************************************************************/
  965. #ifdef DEBUG
  966. #define _WINDLL
  967. #include <stdarg.h>
  968. #ifdef _WIN32
  969. #define GetProfileIntA mmGetProfileIntA
  970. #endif
  971. void FAR CDECL dprintf(LPSTR szFormat, ...)
  972. {
  973. char ach[128];
  974. static BOOL fDebug = -1;
  975. va_list va;
  976. va_start(va, szFormat);
  977. if (fDebug == -1)
  978. fDebug = GetProfileIntA("Debug", "MSVIDC", FALSE);
  979. if (!fDebug)
  980. return;
  981. #ifdef _WIN32
  982. wsprintfA(ach, "MSVIDC32: (tid %x) ", GetCurrentThreadId());
  983. wvsprintfA(ach+strlen(ach),szFormat,va);
  984. #else
  985. lstrcpyA(ach, "MSVIDC: ");
  986. wvsprintfA(ach+8,szFormat,va);
  987. #endif
  988. lstrcatA(ach, "\r\n");
  989. OutputDebugStringA(ach);
  990. va_end(va);
  991. }
  992. #endif