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.

1195 lines
30 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1998
  4. *
  5. * TITLE: memcam.cpp
  6. *
  7. * VERSION: 2.0
  8. *
  9. * AUTHOR: Mark Enstrom [marke]
  10. * Indy Zhu [indyz]
  11. *
  12. * DATE: 2/4/1998
  13. * 5/18/1998
  14. *
  15. * DESCRIPTION:
  16. * Implementation of an ImageIn test camera device object.
  17. *
  18. *******************************************************************************/
  19. #include <stdio.h>
  20. #include <objbase.h>
  21. #include <tchar.h>
  22. #include <sti.h>
  23. extern HINSTANCE g_hInst; // Global hInstance
  24. #include "testusd.h"
  25. VOID
  26. VerticalFlip(
  27. PBYTE pImageTop,
  28. LONG iHeight,
  29. LONG iWidthInBytes);
  30. /**************************************************************************\
  31. * CamLoadPicture
  32. *
  33. * load a bmp from disk and copy it to application
  34. *
  35. * Arguments:
  36. *
  37. * pCameraImage - pointer to data structure with image info
  38. * pDataTransCtx - pointer to minidriver transfer context
  39. *
  40. * Return Value:
  41. *
  42. * status
  43. *
  44. * History:
  45. *
  46. * 2/10/1998 Mark Enstrom [marke]
  47. *
  48. \**************************************************************************/
  49. HRESULT
  50. TestUsdDevice::CamLoadPicture(
  51. MEMCAM_IMAGE_CONTEXT *pMCamContext,
  52. PMINIDRV_TRANSFER_CONTEXT pDataTransCtx,
  53. PLONG plCamErrVal)
  54. {
  55. LONG lScanLineWidth;
  56. HRESULT hr = S_OK;
  57. LONG cbNeeded;
  58. IWiaMiniDrvCallBack *pIProgressCB;
  59. WIAS_TRACE((g_hInst,"CamLoadPicture"));
  60. //
  61. // verify some params
  62. //
  63. if (! pMCamContext) {
  64. return (E_INVALIDARG);
  65. }
  66. if (pDataTransCtx->guidFormatID != WiaImgFmt_BMP && pDataTransCtx->guidFormatID != WiaAudFmt_WAV) {
  67. return (E_NOTIMPL);
  68. }
  69. pIProgressCB = pDataTransCtx->pIWiaMiniDrvCallBack;
  70. //
  71. // Simulate the download of data from the camera
  72. //
  73. if (pIProgressCB) {
  74. hr = pIProgressCB->MiniDrvCallback(
  75. IT_MSG_STATUS,
  76. IT_STATUS_TRANSFER_FROM_DEVICE,
  77. (LONG)0, // Percentage Complete,
  78. 0,
  79. 0,
  80. pDataTransCtx,
  81. 0);
  82. if (hr != S_OK) {
  83. return (hr); // Client want to cancel the transfer or error
  84. }
  85. }
  86. HANDLE hFile = CreateFile(
  87. pMCamContext->pszCameraImagePath,
  88. GENERIC_WRITE | GENERIC_READ ,
  89. FILE_SHARE_WRITE,
  90. NULL,
  91. OPEN_EXISTING,
  92. FILE_ATTRIBUTE_NORMAL,
  93. NULL
  94. );
  95. if (hFile == INVALID_HANDLE_VALUE) {
  96. hr = HRESULT_FROM_WIN32(::GetLastError());
  97. return (hr);
  98. }
  99. if (pIProgressCB) {
  100. hr = pIProgressCB->MiniDrvCallback(
  101. IT_MSG_STATUS,
  102. IT_STATUS_TRANSFER_FROM_DEVICE,
  103. (LONG)25, // Percentage Complete,
  104. 0,
  105. 0,
  106. pDataTransCtx,
  107. 0);
  108. }
  109. if (hr != S_OK) {
  110. CloseHandle(hFile);
  111. return (hr);
  112. }
  113. HANDLE hMap = CreateFileMapping(
  114. hFile,
  115. NULL,
  116. PAGE_READWRITE,
  117. 0,
  118. 0,
  119. NULL);
  120. if (hMap == NULL) {
  121. hr = HRESULT_FROM_WIN32(::GetLastError());
  122. } else {
  123. if (pIProgressCB) {
  124. hr = pIProgressCB->MiniDrvCallback(
  125. IT_MSG_STATUS,
  126. IT_STATUS_TRANSFER_FROM_DEVICE,
  127. (LONG)50, // Percentage Complete,
  128. 0,
  129. 0,
  130. pDataTransCtx,
  131. 0);
  132. }
  133. }
  134. if (hr != S_OK) {
  135. CloseHandle(hFile);
  136. return (hr);
  137. }
  138. PBYTE pFile = (PBYTE)MapViewOfFileEx(
  139. hMap,
  140. FILE_MAP_READ | FILE_MAP_WRITE,
  141. 0,
  142. 0,
  143. 0,
  144. NULL);
  145. if (pFile == NULL) {
  146. hr = HRESULT_FROM_WIN32(::GetLastError());
  147. } else {
  148. if (pIProgressCB) {
  149. hr = pIProgressCB->MiniDrvCallback(
  150. IT_MSG_STATUS,
  151. IT_STATUS_TRANSFER_FROM_DEVICE,
  152. (LONG)100, // Percentage Complete,
  153. 0,
  154. 0,
  155. pDataTransCtx,
  156. 0);
  157. }
  158. }
  159. if (hr != S_OK) {
  160. CloseHandle(hFile);
  161. CloseHandle(hMap);
  162. return(hr);
  163. }
  164. if (pDataTransCtx->guidFormatID == WiaImgFmt_BMP)
  165. {
  166. //
  167. // File contains BITMAPFILEHEADER + BITMAPINFO structure.
  168. //
  169. // DIB Data is located bfOffBits after start of file
  170. //
  171. PBITMAPFILEHEADER pbmFile = (PBITMAPFILEHEADER)pFile;
  172. PBITMAPINFO pbmi = (PBITMAPINFO)(pFile +
  173. sizeof(BITMAPFILEHEADER));
  174. //
  175. // validate bitmap
  176. //
  177. if (pbmFile->bfType != 'MB') {
  178. //
  179. // file is not a bitmap
  180. //
  181. UnmapViewOfFile(pFile);
  182. CloseHandle(hMap);
  183. CloseHandle(hFile);
  184. return(E_FAIL);
  185. }
  186. //
  187. // write image size
  188. //
  189. // make sure to align scanline to ULONG boundary
  190. //
  191. // calculate byte width
  192. //
  193. lScanLineWidth = pbmi->bmiHeader.biWidth * pbmi->bmiHeader.biBitCount;
  194. //
  195. // round up to nearenst DWORD
  196. //
  197. lScanLineWidth = (lScanLineWidth + 31) >> 3;
  198. lScanLineWidth &= 0xfffffffc;
  199. cbNeeded = lScanLineWidth * pbmi->bmiHeader.biHeight;
  200. if (cbNeeded > ((LONG)pDataTransCtx->lItemSize - (LONG)pDataTransCtx->cbOffset)) {
  201. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  202. } else {
  203. //
  204. // copy only the bitmap bits (no headers)
  205. //
  206. memcpy(
  207. pDataTransCtx->pTransferBuffer + pDataTransCtx->cbOffset,
  208. pFile + pbmFile->bfOffBits,
  209. cbNeeded);
  210. }
  211. }
  212. else
  213. {
  214. memcpy (pDataTransCtx->pTransferBuffer,
  215. pFile,
  216. pDataTransCtx->lItemSize);
  217. }
  218. UnmapViewOfFile(pFile);
  219. CloseHandle(hMap);
  220. CloseHandle(hFile);
  221. return(S_OK);
  222. }
  223. /**************************************************************************\
  224. * CamLoadPictureCB
  225. *
  226. * return data by filling the data buffer and calling back to the client
  227. *
  228. * Arguments:
  229. *
  230. * pCameraImage - image item
  231. * pTransCtx - mini driver transfer contect
  232. *
  233. * Return Value:
  234. *
  235. * status
  236. *
  237. * History:
  238. *
  239. * 1/10/1999 Mark Enstrom [marke]
  240. *
  241. \**************************************************************************/
  242. HRESULT TestUsdDevice::CamLoadPictureCB(
  243. MEMCAM_IMAGE_CONTEXT *pMCamContext,
  244. MINIDRV_TRANSFER_CONTEXT *pTransCtx,
  245. PLONG plCamErrVal)
  246. {
  247. LONG lScanLineWidth;
  248. HRESULT hr = E_FAIL;
  249. WIAS_TRACE((g_hInst,"CamLoadPictureCB"));
  250. //
  251. // verify parameters
  252. //
  253. if (!pMCamContext) {
  254. return (E_INVALIDARG);
  255. }
  256. if (pTransCtx == NULL) {
  257. return (E_INVALIDARG);
  258. }
  259. if ((pTransCtx->guidFormatID != WiaImgFmt_BMP) &&
  260. (pTransCtx->guidFormatID != WiaImgFmt_MEMORYBMP)) {
  261. return (E_NOTIMPL);
  262. }
  263. //
  264. // try to open disk file
  265. //
  266. HANDLE hFile = CreateFile(
  267. pMCamContext->pszCameraImagePath,
  268. GENERIC_WRITE | GENERIC_READ ,
  269. FILE_SHARE_WRITE,
  270. NULL,
  271. OPEN_EXISTING,
  272. FILE_ATTRIBUTE_NORMAL,
  273. NULL
  274. );
  275. if (hFile == INVALID_HANDLE_VALUE) {
  276. hr = HRESULT_FROM_WIN32(::GetLastError());
  277. return(hr);
  278. }
  279. HANDLE hMap = CreateFileMapping(
  280. hFile,
  281. NULL,
  282. PAGE_READWRITE,
  283. 0,
  284. 0,
  285. NULL);
  286. if (hMap == NULL) {
  287. CloseHandle(hFile);
  288. hr = HRESULT_FROM_WIN32(::GetLastError());
  289. return(hr);
  290. }
  291. PBYTE pFile = (PBYTE)MapViewOfFileEx(
  292. hMap,
  293. FILE_MAP_READ | FILE_MAP_WRITE,
  294. 0,
  295. 0,
  296. 0,
  297. NULL);
  298. if (pFile == NULL) {
  299. CloseHandle(hFile);
  300. CloseHandle(hMap);
  301. hr = HRESULT_FROM_WIN32(::GetLastError());
  302. return(hr);
  303. }
  304. //
  305. // File contains BITMAPFILEHEADER + BITMAPINFO structure.
  306. //
  307. // DIB Data is located bfOffBits after start of file
  308. //
  309. PBITMAPFILEHEADER pbmFile = (PBITMAPFILEHEADER)pFile;
  310. PBITMAPINFO pbmi = (PBITMAPINFO)(pFile +
  311. sizeof(BITMAPFILEHEADER));
  312. //
  313. // validate bitmap
  314. //
  315. if (pbmFile->bfType != 'MB') {
  316. //
  317. // file is not a bitmap
  318. //
  319. UnmapViewOfFile(pFile);
  320. CloseHandle(hMap);
  321. CloseHandle(hFile);
  322. return(E_FAIL);
  323. }
  324. //
  325. // get image size
  326. //
  327. // make sure to align scanline to ULONG boundary
  328. //
  329. // calculate byte width
  330. //
  331. lScanLineWidth = pbmi->bmiHeader.biWidth * pbmi->bmiHeader.biBitCount;
  332. //
  333. // round up to nearenst DWORD
  334. //
  335. lScanLineWidth = (lScanLineWidth + 31) >> 3;
  336. lScanLineWidth &= 0xfffffffc;
  337. LONG lBytesRemaining = lScanLineWidth * pbmi->bmiHeader.biHeight;
  338. //
  339. // Flip the image vertically if WiaImgFmt_MEMORYBMP is requested
  340. //
  341. if (pTransCtx->guidFormatID == WiaImgFmt_MEMORYBMP) {
  342. VerticalFlip(
  343. (PBYTE)pFile + pbmFile->bfOffBits,
  344. pbmi->bmiHeader.biHeight,
  345. lScanLineWidth);
  346. }
  347. //
  348. // callback loop
  349. //
  350. PBYTE pSrc = (PBYTE)pFile + pbmFile->bfOffBits;
  351. LONG lTransferSize;
  352. LONG lPercentComplete;
  353. do {
  354. PBYTE pDst = pTransCtx->pTransferBuffer;
  355. //
  356. // transfer up to entire buffer size
  357. //
  358. lTransferSize = lBytesRemaining;
  359. if (lBytesRemaining > pTransCtx->lBufferSize) {
  360. lTransferSize = pTransCtx->lBufferSize;
  361. }
  362. //
  363. // copy data
  364. //
  365. memcpy(pDst, pSrc, lTransferSize);
  366. lPercentComplete = 100 * (pTransCtx->cbOffset + lTransferSize);
  367. lPercentComplete /= pTransCtx->lItemSize;
  368. //
  369. // make callback
  370. //
  371. hr = pTransCtx->pIWiaMiniDrvCallBack->MiniDrvCallback(
  372. IT_MSG_DATA,
  373. IT_STATUS_TRANSFER_TO_CLIENT,
  374. lPercentComplete,
  375. pTransCtx->cbOffset,
  376. lTransferSize,
  377. pTransCtx,
  378. 0);
  379. //
  380. // inc pointers (redundant pointers here)
  381. //
  382. pSrc += lTransferSize;
  383. pTransCtx->cbOffset += lTransferSize;
  384. lBytesRemaining -= lTransferSize;
  385. if (hr != S_OK) {
  386. break;
  387. }
  388. } while (lBytesRemaining > 0);
  389. //
  390. // Flip the image back if WiaImgFmt_MEMORYBMP is requested
  391. //
  392. if (pTransCtx->guidFormatID == WiaImgFmt_MEMORYBMP) {
  393. VerticalFlip(
  394. (PBYTE)pFile + pbmFile->bfOffBits,
  395. pbmi->bmiHeader.biHeight,
  396. lScanLineWidth);
  397. }
  398. //
  399. // Garbage collection
  400. //
  401. UnmapViewOfFile(pFile);
  402. CloseHandle(hMap);
  403. CloseHandle(hFile);
  404. return(hr);
  405. }
  406. /**************************************************************************\
  407. * CamGetPictureInfo
  408. *
  409. * Load file, get information from image
  410. *
  411. * Arguments:
  412. *
  413. * pCameraImage - image item
  414. * pPictInfo - fill out ino about image
  415. * ppBITMAPINFO - alloc and fill out BITMAPINFO
  416. * pBITMAPINFOSize - size
  417. *
  418. * Return Value:
  419. *
  420. * status
  421. *
  422. * History:
  423. *
  424. * 1/17/1999 Mark Enstrom [marke]
  425. *
  426. \**************************************************************************/
  427. HRESULT
  428. TestUsdDevice::CamGetPictureInfo(
  429. MEMCAM_IMAGE_CONTEXT *pMCamContext,
  430. PCAMERA_PICTURE_INFO pPictInfo,
  431. PBYTE *ppBITMAPINFO,
  432. LONG *pBITMAPINFOSize)
  433. {
  434. HRESULT hr = S_OK;
  435. FILETIME ftCreate;
  436. SYSTEMTIME stCreate;
  437. WIAS_TRACE((g_hInst,"CamGetPictureInfo"));
  438. //
  439. // Try to open disk file
  440. //
  441. HANDLE hFile = CreateFile(
  442. pMCamContext->pszCameraImagePath,
  443. GENERIC_WRITE | GENERIC_READ,
  444. FILE_SHARE_WRITE,
  445. NULL,
  446. OPEN_EXISTING,
  447. FILE_ATTRIBUTE_NORMAL,
  448. NULL
  449. );
  450. if (hFile == INVALID_HANDLE_VALUE) {
  451. hr = HRESULT_FROM_WIN32(::GetLastError());
  452. return(hr);
  453. }
  454. //
  455. // Grab the creation time for this image
  456. //
  457. if (GetFileTime( hFile, &ftCreate, NULL, NULL)) {
  458. FileTimeToSystemTime( &ftCreate, &stCreate );
  459. } else {
  460. //
  461. // To return something, use the system time
  462. //
  463. GetLocalTime( &stCreate );
  464. }
  465. HANDLE hMap = CreateFileMapping(
  466. hFile,
  467. NULL,
  468. PAGE_READWRITE,
  469. 0,
  470. 0,
  471. NULL
  472. );
  473. if (hMap == NULL) {
  474. CloseHandle(hFile);
  475. hr = HRESULT_FROM_WIN32(::GetLastError());
  476. return(hr);
  477. }
  478. PBYTE pFile = (PBYTE)MapViewOfFileEx(
  479. hMap,
  480. FILE_MAP_READ | FILE_MAP_WRITE,
  481. 0,
  482. 0,
  483. 0,
  484. NULL);
  485. if (pFile == NULL) {
  486. CloseHandle(hFile);
  487. CloseHandle(hMap);
  488. hr = HRESULT_FROM_WIN32(::GetLastError());
  489. return(hr);
  490. }
  491. //
  492. // File contains BITMAPFILEHEADER + BITMAPINFO structure.
  493. //
  494. // DIB Data is located bfOffBits after start of file
  495. //
  496. PBITMAPFILEHEADER pbmFile = (PBITMAPFILEHEADER)pFile;
  497. PBITMAPINFOHEADER pbmiHeader =
  498. (PBITMAPINFOHEADER)(pFile +
  499. sizeof(BITMAPFILEHEADER));
  500. PBYTE pDIBFile = pFile + pbmFile->bfOffBits;
  501. //
  502. // validate bitmap.
  503. //
  504. if (pbmFile->bfType != 'MB') {
  505. //
  506. // file is not a bitmap
  507. //
  508. UnmapViewOfFile(pFile);
  509. CloseHandle(hFile);
  510. CloseHandle(hMap);
  511. return(E_FAIL);
  512. }
  513. //
  514. // fill out image information
  515. //
  516. pPictInfo->PictNumber = 0; // ??? Should support picture handle ???
  517. pPictInfo->ThumbWidth = 80;
  518. pPictInfo->ThumbHeight = 60;
  519. pPictInfo->PictWidth = pbmiHeader->biWidth;
  520. pPictInfo->PictHeight = pbmiHeader->biHeight;
  521. pPictInfo->PictCompSize = 0;
  522. pPictInfo->PictFormat = 0;
  523. pPictInfo->PictBitsPerPixel = pbmiHeader->biBitCount;
  524. {
  525. LONG lScanLineWidth = (pbmiHeader->biWidth *
  526. pbmiHeader->biBitCount);
  527. //
  528. // round up to nearenst DWORD
  529. //
  530. lScanLineWidth = (lScanLineWidth + 31) >> 3;
  531. //
  532. // remove extra bytes
  533. //
  534. lScanLineWidth &= 0xfffffffc;
  535. pPictInfo->PictBytesPerRow = lScanLineWidth;
  536. }
  537. //
  538. // is there a color table
  539. //
  540. LONG ColorMapSize = 0;
  541. LONG bmiSize;
  542. if (pbmiHeader->biBitCount == 1) {
  543. ColorMapSize = 2;
  544. } else if (pbmiHeader->biBitCount == 4) {
  545. ColorMapSize = 16;
  546. } else if (pbmiHeader->biBitCount == 8) {
  547. ColorMapSize = 256;
  548. }
  549. //
  550. // Changed by Indy on 5/18/98 to BITMAPINFOHEADER
  551. //
  552. bmiSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * ColorMapSize;
  553. *ppBITMAPINFO = (PBYTE)ALLOC(bmiSize);
  554. if (*ppBITMAPINFO != NULL) {
  555. memcpy(*ppBITMAPINFO, pbmiHeader, bmiSize);
  556. *pBITMAPINFOSize = bmiSize;
  557. } else {
  558. UnmapViewOfFile(pFile);
  559. CloseHandle(hFile);
  560. CloseHandle(hMap);
  561. return(E_OUTOFMEMORY);
  562. }
  563. //
  564. // Set the time for the image
  565. //
  566. memcpy(&pPictInfo->TimeStamp, &stCreate, sizeof(pPictInfo->TimeStamp));
  567. //
  568. // close up the file
  569. //
  570. UnmapViewOfFile(pFile);
  571. CloseHandle(hMap);
  572. CloseHandle(hFile);
  573. return(hr);
  574. }
  575. /**************************************************************************\
  576. * CamLoadThumbnail
  577. *
  578. * Load the thumbnail of the specified picture
  579. *
  580. * Arguments:
  581. *
  582. * pCameraImage - image item
  583. * pThumbnail - buffer for thumbnail
  584. * pThumbSize - size of thumbnail
  585. *
  586. * Return Value:
  587. *
  588. * status
  589. *
  590. * History:
  591. *
  592. * 2/9/1998 Mark Enstrom [marke]
  593. * 6/9/1998 Indy Zhu [indyz]
  594. *
  595. \**************************************************************************/
  596. HRESULT
  597. TestUsdDevice::CamLoadThumbnail(
  598. MEMCAM_IMAGE_CONTEXT *pMCamContext ,
  599. PBYTE *pThumbnail,
  600. LONG *pThumbSize
  601. )
  602. {
  603. TCHAR pszThumbName[MAX_PATH];
  604. HRESULT hr;
  605. BOOL bCacheThumb = TRUE;
  606. BOOL bThumbExists = TRUE;
  607. PBYTE pTmbPixels;
  608. HBITMAP hbmThumb = NULL;
  609. PBYTE pThumb = NULL;
  610. HANDLE hTmbFile = INVALID_HANDLE_VALUE;
  611. HANDLE hTmbMap = NULL;
  612. PBYTE pTmbFile = NULL;
  613. HANDLE hFile = INVALID_HANDLE_VALUE;
  614. HANDLE hMap = NULL;
  615. PBYTE pFile = NULL;
  616. BITMAPINFO bmiDIB;
  617. HDC hdc = NULL;
  618. HDC hdcm1 = NULL;
  619. WIAS_TRACE((g_hInst,"CamLoadThumbnail"));
  620. //
  621. // Initialize the return values
  622. //
  623. *pThumbnail = NULL;
  624. *pThumbSize = 0;
  625. //
  626. // Fill in the size of the tumbnail pixel buffer
  627. //
  628. bmiDIB.bmiHeader.biSizeImage = 80*60*3;
  629. //
  630. // Build thumbnail filename Image.bmp.tmb
  631. //
  632. _tcscpy(pszThumbName, pMCamContext->pszCameraImagePath);
  633. _tcscat(pszThumbName, TEXT(".tmb"));
  634. __try {
  635. hTmbFile = CreateFile(
  636. pszThumbName,
  637. GENERIC_READ | GENERIC_WRITE,
  638. FILE_SHARE_WRITE,
  639. NULL,
  640. OPEN_EXISTING,
  641. FILE_ATTRIBUTE_NORMAL,
  642. NULL
  643. );
  644. //
  645. // See if cached thumbnail already exists
  646. //
  647. if (hTmbFile == INVALID_HANDLE_VALUE) {
  648. //
  649. // Try to create a new one
  650. //
  651. hTmbFile = CreateFile(
  652. pszThumbName,
  653. GENERIC_READ | GENERIC_WRITE,
  654. FILE_SHARE_WRITE,
  655. NULL,
  656. CREATE_NEW,
  657. FILE_ATTRIBUTE_NORMAL,
  658. NULL
  659. );
  660. //
  661. // Thumbnail need to be created
  662. //
  663. bThumbExists = FALSE;
  664. }
  665. //
  666. // thumbnail file exists
  667. //
  668. if (hTmbFile != INVALID_HANDLE_VALUE) {
  669. hTmbMap = CreateFileMapping(
  670. hTmbFile,
  671. NULL,
  672. PAGE_READWRITE,
  673. 0,
  674. 80 * 60 * 3,
  675. NULL);
  676. if (hTmbMap != NULL) {
  677. pTmbFile = (PBYTE)MapViewOfFileEx(
  678. hTmbMap,
  679. FILE_MAP_READ | FILE_MAP_WRITE,
  680. 0,
  681. 0,
  682. 0,
  683. NULL);
  684. if (pTmbFile) {
  685. if (bThumbExists) {
  686. //
  687. // Alloca memory for thumbnail pixels
  688. //
  689. pTmbPixels = (PBYTE)ALLOC(bmiDIB.bmiHeader.biSizeImage);
  690. if (! pTmbPixels) {
  691. return(E_OUTOFMEMORY);
  692. }
  693. //
  694. // Pull the thumbnail from the cached file
  695. //
  696. memcpy(pTmbPixels, pTmbFile,
  697. bmiDIB.bmiHeader.biSizeImage);
  698. //
  699. // All the handles will be closed in __finally block
  700. //
  701. *pThumbnail = pTmbPixels;
  702. *pThumbSize = bmiDIB.bmiHeader.biSizeImage;
  703. return(S_OK);
  704. }
  705. } else {
  706. bCacheThumb = FALSE;
  707. }
  708. } else {
  709. bCacheThumb = FALSE;
  710. }
  711. } else {
  712. //
  713. // Can't cache thumbnail
  714. //
  715. bCacheThumb = FALSE;
  716. }
  717. //
  718. // Try to create a thumbnail from the full-size image
  719. // and cache it if the thumbnail cache file is created
  720. //
  721. hFile = CreateFile(
  722. pMCamContext->pszCameraImagePath,
  723. GENERIC_WRITE | GENERIC_READ,
  724. FILE_SHARE_WRITE,
  725. NULL,
  726. OPEN_EXISTING,
  727. FILE_ATTRIBUTE_NORMAL,
  728. NULL
  729. );
  730. if (hFile == INVALID_HANDLE_VALUE) {
  731. hr = HRESULT_FROM_WIN32(::GetLastError());
  732. return(hr);
  733. }
  734. hMap = CreateFileMapping(
  735. hFile,
  736. NULL,
  737. PAGE_READWRITE,
  738. 0,
  739. 0,
  740. NULL
  741. );
  742. if (hMap == NULL) {
  743. hr = HRESULT_FROM_WIN32(::GetLastError());
  744. return(hr);
  745. }
  746. pFile = (PBYTE)MapViewOfFileEx(
  747. hMap,
  748. FILE_MAP_READ | FILE_MAP_WRITE,
  749. 0,
  750. 0,
  751. 0,
  752. NULL
  753. );
  754. if (pFile == NULL) {
  755. hr = HRESULT_FROM_WIN32(::GetLastError());
  756. return(hr);
  757. }
  758. PBITMAPFILEHEADER pbmFile = (PBITMAPFILEHEADER)pFile;
  759. PBITMAPINFO pbmi = (PBITMAPINFO)(pFile +
  760. sizeof(BITMAPFILEHEADER));
  761. PBYTE pPixels = pFile + pbmFile->bfOffBits;
  762. //
  763. // Generate the thumbnail from the full-size image
  764. //
  765. hdc = GetDC(NULL);
  766. hdcm1 = CreateCompatibleDC(hdc);
  767. SetStretchBltMode(hdcm1, COLORONCOLOR);
  768. //
  769. // Create a BITMAP for rendering the thumbnail
  770. //
  771. bmiDIB.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  772. bmiDIB.bmiHeader.biBitCount = 24;
  773. bmiDIB.bmiHeader.biWidth = 80;
  774. bmiDIB.bmiHeader.biHeight = 60;
  775. bmiDIB.bmiHeader.biPlanes = 1;
  776. bmiDIB.bmiHeader.biCompression = BI_RGB;
  777. bmiDIB.bmiHeader.biXPelsPerMeter = 100;
  778. bmiDIB.bmiHeader.biYPelsPerMeter = 100;
  779. bmiDIB.bmiHeader.biClrUsed = 0;
  780. bmiDIB.bmiHeader.biClrImportant = 0;
  781. hbmThumb = CreateDIBSection(hdc, &bmiDIB, DIB_RGB_COLORS,
  782. (VOID **)&pThumb, NULL, 0);
  783. if (! hbmThumb) {
  784. hr = HRESULT_FROM_WIN32(::GetLastError());
  785. return hr;
  786. }
  787. HBITMAP hbmDef = (HBITMAP)SelectObject(hdcm1, hbmThumb);
  788. //
  789. // Init DIB
  790. //
  791. memset(pThumb, 0, bmiDIB.bmiHeader.biSizeImage);
  792. //
  793. // create 80x60 thumbnail while preserving image
  794. // aspect ratio
  795. //
  796. LONG lThumbWidth;
  797. LONG lThumbHeight;
  798. double fImageWidth = (double)pbmi->bmiHeader.biWidth;
  799. double fImageHeight = (double)pbmi->bmiHeader.biHeight;
  800. double fAspect = fImageWidth / fImageHeight;
  801. double fDefAspect = 80.0 / 60.0;
  802. if (fAspect > fDefAspect) {
  803. lThumbWidth = 80;
  804. lThumbHeight = (LONG)(80.0 / fAspect);
  805. } else {
  806. lThumbHeight = 60;
  807. lThumbWidth = (LONG)(60.0 * fAspect);
  808. }
  809. int i = StretchDIBits(
  810. hdcm1,
  811. 0,
  812. 0,
  813. lThumbWidth,
  814. lThumbHeight,
  815. 0,
  816. 0,
  817. pbmi->bmiHeader.biWidth,
  818. pbmi->bmiHeader.biHeight,
  819. pPixels,
  820. pbmi,
  821. DIB_RGB_COLORS,
  822. SRCCOPY
  823. );
  824. SelectObject(hdcm1, hbmDef);
  825. //
  826. // Cache ?
  827. //
  828. if (bCacheThumb) {
  829. memcpy(pTmbFile, pThumb, bmiDIB.bmiHeader.biSizeImage);
  830. }
  831. //
  832. // Alloca memory for thumbnail pixels
  833. //
  834. pTmbPixels = (PBYTE)ALLOC(bmiDIB.bmiHeader.biSizeImage);
  835. if (! pTmbPixels) {
  836. return(E_OUTOFMEMORY);
  837. }
  838. //
  839. // Write out data
  840. //
  841. memcpy(pTmbPixels, pThumb, bmiDIB.bmiHeader.biSizeImage);
  842. *pThumbnail = pTmbPixels;
  843. *pThumbSize = bmiDIB.bmiHeader.biSizeImage;
  844. return(S_OK);
  845. } // End of __try { ... } block
  846. __finally {
  847. if (pTmbFile) {
  848. UnmapViewOfFile(pTmbFile);
  849. }
  850. if (hTmbMap) {
  851. CloseHandle(hTmbMap);
  852. }
  853. if (hTmbFile != INVALID_HANDLE_VALUE) {
  854. CloseHandle(hTmbFile);
  855. }
  856. if (pFile) {
  857. UnmapViewOfFile(pFile);
  858. }
  859. if (hMap) {
  860. CloseHandle(hMap);
  861. }
  862. if (hFile != INVALID_HANDLE_VALUE) {
  863. CloseHandle(hFile);
  864. }
  865. if (hbmThumb) {
  866. DeleteObject(hbmThumb);
  867. }
  868. if (hdcm1) {
  869. DeleteDC(hdcm1);
  870. }
  871. if (hdc) {
  872. ReleaseDC(NULL, hdc);
  873. }
  874. }
  875. return(E_FAIL);
  876. }
  877. /**************************************************************************\
  878. * CamDeletePicture
  879. *
  880. *
  881. * Arguments:
  882. *
  883. *
  884. *
  885. * Return Value:
  886. *
  887. *
  888. *
  889. * History:
  890. *
  891. * 6/3/1998 Mark Enstrom [marke]
  892. *
  893. \**************************************************************************/
  894. HRESULT
  895. CamDeletePicture(
  896. MEMCAM_IMAGE_CONTEXT *pMCamContext)
  897. {
  898. return(E_NOTIMPL);
  899. }
  900. /**************************************************************************\
  901. * CamTakePicture
  902. *
  903. *
  904. * Arguments:
  905. *
  906. *
  907. *
  908. * Return Value:
  909. *
  910. *
  911. *
  912. * History:
  913. *
  914. * 6/3/1998 Mark Enstrom [marke]
  915. *
  916. \**************************************************************************/
  917. HRESULT
  918. CamTakePicture(
  919. MEMCAM_IMAGE_CONTEXT *pMCamContext ,
  920. ULONG *pHandle)
  921. {
  922. return (E_NOTIMPL);
  923. }
  924. /**************************************************************************\
  925. * VertivalFlip
  926. *
  927. *
  928. *
  929. * Arguments:
  930. *
  931. *
  932. *
  933. * Return Value:
  934. *
  935. * Status
  936. *
  937. * History:
  938. *
  939. * 11/18/1998 Original Version
  940. *
  941. \**************************************************************************/
  942. VOID
  943. VerticalFlip(
  944. PBYTE pImageTop,
  945. LONG iHeight,
  946. LONG iWidthInBytes)
  947. {
  948. //
  949. // try to allocat a temp scan line buffer
  950. //
  951. PBYTE pBuffer = (PBYTE)LocalAlloc(LPTR,iWidthInBytes);
  952. if (pBuffer != NULL) {
  953. LONG index;
  954. PBYTE pImageBottom;
  955. pImageBottom = pImageTop + (iHeight-1) * iWidthInBytes;
  956. for (index = 0;index < (iHeight/2);index++) {
  957. memcpy(pBuffer,pImageTop,iWidthInBytes);
  958. memcpy(pImageTop,pImageBottom,iWidthInBytes);
  959. memcpy(pImageBottom,pBuffer,iWidthInBytes);
  960. pImageTop += iWidthInBytes;
  961. pImageBottom -= iWidthInBytes;
  962. }
  963. LocalFree(pBuffer);
  964. }
  965. }