Source code of Windows XP (NT5)
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.

1153 lines
30 KiB

  1. //------------------------------------------------------------------------------
  2. // Copyright (c) 1999 Microsoft Corporation
  3. //
  4. // camxfer.cpp
  5. //
  6. // Abstract:
  7. //
  8. // Core ircamera (IrUseDevice object) imaging methods.
  9. //
  10. // Author:
  11. // Edward Reus 03-Aug-99
  12. // modeled after code by Mark Enstrom
  13. //
  14. //------------------------------------------------------------------------------
  15. #include <stdio.h>
  16. #include <objbase.h>
  17. #include <tchar.h>
  18. #include <sti.h>
  19. #include <malloc.h>
  20. #include "jpegutil.h"
  21. extern HINSTANCE g_hInst; // Global hInstance
  22. #include "ircamera.h"
  23. #if FALSE
  24. //------------------------------------------------------------------------------
  25. // IrUsdDevice::OpenAndMapJPEG()
  26. //
  27. // Open and memory map the JPEG file. The JPEG file is opened read only and
  28. // a pointer to the memory map is returned.
  29. //------------------------------------------------------------------------------
  30. HRESULT IrUsdDevice::OpenAndMapJPEG( IN IRCAM_IMAGE_CONTEXT *pIrCamContext,
  31. OUT BYTE **ppJpeg )
  32. {
  33. HRESULT hr = S_OK;
  34. *ppJpeg = 0;
  35. return hr;
  36. }
  37. #endif
  38. //------------------------------------------------------------------------------
  39. // IrUsdDevice::CamLoadPicture()
  40. //
  41. // Read a .JPG image from the disk and copy it to the application.
  42. //
  43. // Arguments:
  44. //
  45. // pIrCamContext --
  46. // pDataTransCtx --
  47. // plCamErrVal --
  48. //
  49. // Return Value:
  50. //
  51. // status
  52. //
  53. //------------------------------------------------------------------------------
  54. HRESULT IrUsdDevice::CamLoadPicture( IRCAM_IMAGE_CONTEXT *pIrCamContext,
  55. PMINIDRV_TRANSFER_CONTEXT pDataTransCtx,
  56. PLONG plCamErrVal )
  57. {
  58. HRESULT hr = S_OK;
  59. LONG cbNeeded;
  60. IWiaMiniDrvCallBack *pIProgressCB;
  61. WIAS_TRACE((g_hInst,"IrUsdDevice::CamLoadPicture()"));
  62. //
  63. // Verify call arguments:
  64. //
  65. if ( (!pIrCamContext) || (!plCamErrVal))
  66. {
  67. return E_INVALIDARG;
  68. }
  69. if (pDataTransCtx->guidFormatID != WiaImgFmt_JPEG)
  70. {
  71. return E_NOTIMPL;
  72. }
  73. pIProgressCB = pDataTransCtx->pIWiaMiniDrvCallBack;
  74. //
  75. // Simulate the download of data from the camera
  76. //
  77. if (pIProgressCB)
  78. {
  79. hr = pIProgressCB->MiniDrvCallback(
  80. IT_MSG_STATUS,
  81. IT_STATUS_TRANSFER_FROM_DEVICE,
  82. (LONG)0, // Percentage Complete,
  83. 0,
  84. 0,
  85. pDataTransCtx,
  86. 0);
  87. if (hr != S_OK)
  88. {
  89. return hr; // Client wants to cancel the transfer or error.
  90. }
  91. }
  92. HANDLE hFile = CreateFile(
  93. pIrCamContext->pszCameraImagePath,
  94. GENERIC_READ,
  95. FILE_SHARE_READ,
  96. NULL,
  97. OPEN_EXISTING,
  98. FILE_ATTRIBUTE_NORMAL,
  99. NULL );
  100. if (hFile == INVALID_HANDLE_VALUE)
  101. {
  102. hr = HRESULT_FROM_WIN32(::GetLastError());
  103. }
  104. else
  105. {
  106. if (pIProgressCB)
  107. {
  108. hr = pIProgressCB->MiniDrvCallback(
  109. IT_MSG_STATUS,
  110. IT_STATUS_TRANSFER_FROM_DEVICE,
  111. (LONG)25, // Percentage Complete,
  112. 0,
  113. 0,
  114. pDataTransCtx,
  115. 0);
  116. }
  117. }
  118. if (hr != S_OK)
  119. {
  120. if (hFile != INVALID_HANDLE_VALUE)
  121. {
  122. CloseHandle(hFile);
  123. }
  124. return hr;
  125. }
  126. //
  127. // Get the size of the JPEG:
  128. //
  129. BY_HANDLE_FILE_INFORMATION FileInfo;
  130. if (!GetFileInformationByHandle(hFile,&FileInfo))
  131. {
  132. hr = HRESULT_FROM_WIN32(::GetLastError());
  133. CloseHandle(hFile);
  134. return hr;
  135. }
  136. //
  137. // Map the JPEG into memory:
  138. //
  139. HANDLE hMap = CreateFileMapping( hFile,
  140. NULL,
  141. PAGE_READONLY,
  142. 0,
  143. 0,
  144. NULL );
  145. if (hMap == NULL)
  146. {
  147. hr = HRESULT_FROM_WIN32(::GetLastError());
  148. }
  149. else
  150. {
  151. if (pIProgressCB)
  152. {
  153. hr = pIProgressCB->MiniDrvCallback(
  154. IT_MSG_STATUS,
  155. IT_STATUS_TRANSFER_FROM_DEVICE,
  156. (LONG)50, // Percentage Complete,
  157. 0,
  158. 0,
  159. pDataTransCtx,
  160. 0 );
  161. }
  162. }
  163. if (hr != S_OK)
  164. {
  165. CloseHandle(hFile);
  166. return hr;
  167. }
  168. PBYTE pFile = (PBYTE)MapViewOfFile(
  169. hMap,
  170. FILE_MAP_READ,
  171. 0,
  172. 0,
  173. 0 );
  174. if (pFile == NULL)
  175. {
  176. hr = HRESULT_FROM_WIN32(::GetLastError());
  177. }
  178. else
  179. {
  180. if (pIProgressCB)
  181. {
  182. hr = pIProgressCB->MiniDrvCallback(
  183. IT_MSG_STATUS,
  184. IT_STATUS_TRANSFER_FROM_DEVICE,
  185. (LONG)100, // Percentage Complete,
  186. 0,
  187. 0,
  188. pDataTransCtx,
  189. 0);
  190. }
  191. }
  192. if (hr != S_OK)
  193. {
  194. CloseHandle(hFile);
  195. CloseHandle(hMap);
  196. return hr;
  197. }
  198. #if FALSE
  199. //
  200. // File contains BITMAPFILEHEADER + BITMAPINFO structure.
  201. //
  202. // DIB Data is located bfOffBits after start of file
  203. //
  204. PBITMAPFILEHEADER pbmFile = (PBITMAPFILEHEADER)pFile;
  205. PBITMAPINFO pbmi = (PBITMAPINFO)(pFile +
  206. sizeof(BITMAPFILEHEADER));
  207. //
  208. // validate bitmap
  209. //
  210. if (pbmFile->bfType != 'MB')
  211. {
  212. //
  213. // file is not a bitmap
  214. //
  215. UnmapViewOfFile(pFile);
  216. CloseHandle(hMap);
  217. CloseHandle(hFile);
  218. return(E_FAIL);
  219. }
  220. //
  221. // write image size
  222. //
  223. // make sure to align scanline to ULONG boundary
  224. //
  225. // calculate byte width
  226. //
  227. lScanLineWidth = pbmi->bmiHeader.biWidth * pbmi->bmiHeader.biBitCount;
  228. //
  229. // round up to nearenst DWORD
  230. //
  231. lScanLineWidth = (lScanLineWidth + 31) >> 3;
  232. lScanLineWidth &= 0xfffffffc;
  233. #endif
  234. cbNeeded = FileInfo.nFileSizeLow;
  235. if (cbNeeded > ((LONG)pDataTransCtx->lItemSize - (LONG)pDataTransCtx->cbOffset))
  236. {
  237. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  238. }
  239. else
  240. {
  241. //
  242. // Copy the JPEG image...
  243. //
  244. memcpy(
  245. pDataTransCtx->pTransferBuffer + pDataTransCtx->cbOffset,
  246. pFile,
  247. cbNeeded);
  248. }
  249. UnmapViewOfFile(pFile);
  250. CloseHandle(hMap);
  251. CloseHandle(hFile);
  252. return hr;
  253. }
  254. //------------------------------------------------------------------------------
  255. // IrUsdDevice::CamLoadPictureCB()
  256. //
  257. // Return data by filling the data buffer and calling back to the client.
  258. //
  259. // Arguments:
  260. //
  261. // pIrCamContext --
  262. // pTransCtx -- mini driver transfer contect
  263. // plCamErrVal --
  264. //
  265. // Return Value:
  266. //
  267. // HRESULT -- E_INVALIDARG
  268. // E_NOTIMPL
  269. // E_FAIL
  270. //
  271. //------------------------------------------------------------------------------
  272. HRESULT IrUsdDevice::CamLoadPictureCB( IRCAM_IMAGE_CONTEXT *pIrCamContext,
  273. MINIDRV_TRANSFER_CONTEXT *pTransCtx,
  274. PLONG plCamErrVal )
  275. {
  276. LONG lScanLineWidth;
  277. HRESULT hr = E_FAIL;
  278. WIAS_TRACE((g_hInst,"IrUsdDevice::CamLoadPictureCB()"));
  279. //
  280. // Verify parameters:
  281. //
  282. if ((!pIrCamContext) || (!plCamErrVal))
  283. {
  284. return E_INVALIDARG;
  285. }
  286. if (pTransCtx == NULL)
  287. {
  288. return E_INVALIDARG;
  289. }
  290. if (pTransCtx->guidFormatID != WiaImgFmt_JPEG)
  291. {
  292. return E_NOTIMPL;
  293. }
  294. //
  295. // try to open disk file
  296. //
  297. HANDLE hFile = CreateFile(
  298. pIrCamContext->pszCameraImagePath,
  299. GENERIC_READ,
  300. FILE_SHARE_READ,
  301. NULL,
  302. OPEN_EXISTING,
  303. FILE_ATTRIBUTE_NORMAL,
  304. NULL );
  305. if (hFile == INVALID_HANDLE_VALUE)
  306. {
  307. hr = HRESULT_FROM_WIN32(::GetLastError());
  308. return hr;
  309. }
  310. //
  311. // Get the size of the JPEG file:
  312. //
  313. BY_HANDLE_FILE_INFORMATION FileInfo;
  314. if (!GetFileInformationByHandle(hFile,&FileInfo))
  315. {
  316. hr = HRESULT_FROM_WIN32(::GetLastError());
  317. CloseHandle(hFile);
  318. return hr;
  319. }
  320. HANDLE hMap = CreateFileMapping( hFile,
  321. NULL,
  322. PAGE_READONLY,
  323. 0,
  324. 0,
  325. NULL );
  326. if (hMap == NULL)
  327. {
  328. hr = HRESULT_FROM_WIN32(::GetLastError());
  329. CloseHandle(hFile);
  330. return hr;
  331. }
  332. PBYTE pFile = (PBYTE)MapViewOfFile(
  333. hMap,
  334. FILE_MAP_READ,
  335. 0,
  336. 0,
  337. 0 );
  338. if (pFile == NULL)
  339. {
  340. hr = HRESULT_FROM_WIN32(::GetLastError());
  341. CloseHandle(hFile);
  342. CloseHandle(hMap);
  343. return hr;
  344. }
  345. //
  346. // Callback loop
  347. //
  348. PBYTE pSrc = pFile;
  349. LONG lBytesRemaining = FileInfo.nFileSizeLow;
  350. LONG lTransferSize;
  351. LONG lPercentComplete;
  352. do {
  353. PBYTE pDst = pTransCtx->pTransferBuffer;
  354. //
  355. // Transfer as much data as the transfer buffer will hold:
  356. //
  357. lTransferSize = lBytesRemaining;
  358. if (lBytesRemaining > pTransCtx->lBufferSize)
  359. {
  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. // increment pointers (redundant pointers here):
  381. //
  382. pSrc += lTransferSize;
  383. pTransCtx->cbOffset += lTransferSize;
  384. lBytesRemaining -= lTransferSize;
  385. if (hr != S_OK)
  386. {
  387. break;
  388. }
  389. } while (lBytesRemaining > 0);
  390. //
  391. // Cleanup:
  392. //
  393. UnmapViewOfFile(pFile);
  394. CloseHandle(hMap);
  395. CloseHandle(hFile);
  396. return hr;
  397. }
  398. //------------------------------------------------------------------------------
  399. // IrUsdDevice::CamGetPictureInfo()
  400. //
  401. // Load file and get information from image
  402. //
  403. // Arguments:
  404. //
  405. // pIrCamContext --
  406. // pPictInfo -- Infomation about the image
  407. // ppBITMAPINFO -- Alloc and fill out BITMAPINFO
  408. // pBITMAPINFOSize -- Size
  409. //
  410. // Return Value:
  411. //
  412. // HRESULT -- S_OK - No problem.
  413. // E_FAIL - If we can't parse the JPEG.
  414. // HRESULT mapped Win32 Errors from CreateFile()
  415. //
  416. //------------------------------------------------------------------------------
  417. HRESULT IrUsdDevice::CamGetPictureInfo(
  418. IRCAM_IMAGE_CONTEXT *pIrCamContext ,
  419. CAMERA_PICTURE_INFO *pPictInfo )
  420. {
  421. HRESULT hr = S_OK;
  422. FILETIME ftCreate;
  423. SYSTEMTIME stCreate;
  424. WIAS_TRACE((g_hInst,"IrUsdDevice::CamGetPictureInfo()"));
  425. memset(pPictInfo,0,sizeof(CAMERA_PICTURE_INFO));
  426. //
  427. // Try to open disk file
  428. //
  429. HANDLE hFile = CreateFile(
  430. pIrCamContext->pszCameraImagePath,
  431. GENERIC_READ,
  432. FILE_SHARE_READ,
  433. NULL,
  434. OPEN_EXISTING,
  435. FILE_ATTRIBUTE_NORMAL,
  436. NULL );
  437. if (hFile == INVALID_HANDLE_VALUE)
  438. {
  439. hr = HRESULT_FROM_WIN32(::GetLastError());
  440. return hr;
  441. }
  442. //
  443. // Get the size of the JPEG:
  444. //
  445. BY_HANDLE_FILE_INFORMATION FileInfo;
  446. if (!GetFileInformationByHandle(hFile,&FileInfo))
  447. {
  448. hr = HRESULT_FROM_WIN32(::GetLastError());
  449. CloseHandle(hFile);
  450. return hr;
  451. }
  452. //
  453. // Get the creation time for this image:
  454. //
  455. if ( !GetFileTime( hFile, &ftCreate, NULL, NULL)
  456. || !FileTimeToSystemTime( &ftCreate, &stCreate) )
  457. {
  458. //
  459. // If either of those fail, then return the system time:
  460. //
  461. GetLocalTime( &stCreate );
  462. }
  463. HANDLE hMap = CreateFileMapping(
  464. hFile,
  465. NULL,
  466. PAGE_READONLY,
  467. 0,
  468. 0,
  469. NULL
  470. );
  471. if (hMap == NULL)
  472. {
  473. CloseHandle(hFile);
  474. hr = HRESULT_FROM_WIN32(::GetLastError());
  475. return hr;
  476. }
  477. PBYTE pJpeg = (PBYTE)MapViewOfFile(
  478. hMap,
  479. FILE_MAP_READ,
  480. 0,
  481. 0,
  482. 0 );
  483. if (pJpeg == NULL)
  484. {
  485. CloseHandle(hFile);
  486. CloseHandle(hMap);
  487. hr = HRESULT_FROM_WIN32(::GetLastError());
  488. return hr;
  489. }
  490. //
  491. // Get JPEG image dimensions:
  492. //
  493. int iStatus;
  494. long lWidth = 0;
  495. long lHeight = 0;
  496. WORD wNumChannels = 0;
  497. DWORD dwJpegSize = FileInfo.nFileSizeLow;
  498. iStatus = GetJPEGDimensions( pJpeg,
  499. dwJpegSize,
  500. &lWidth,
  501. &lHeight,
  502. &wNumChannels );
  503. if (iStatus != JPEGERR_NO_ERROR)
  504. {
  505. UnmapViewOfFile(pJpeg);
  506. CloseHandle(hFile);
  507. CloseHandle(hMap);
  508. return E_FAIL;
  509. }
  510. //
  511. // Fill out image information:
  512. //
  513. pPictInfo->PictNumber = 0; // Unknown
  514. pPictInfo->ThumbWidth = 80;
  515. pPictInfo->ThumbHeight = 60;
  516. pPictInfo->PictWidth = lWidth;
  517. pPictInfo->PictHeight = lHeight;
  518. pPictInfo->PictCompSize = FileInfo.nFileSizeLow;
  519. pPictInfo->PictFormat = CF_JPEG;
  520. pPictInfo->PictBitsPerPixel = wNumChannels * 8;
  521. pPictInfo->PictBytesPerRow = lWidth*wNumChannels;
  522. memcpy( &pPictInfo->TimeStamp, &stCreate, sizeof(pPictInfo->TimeStamp) );
  523. //
  524. // Cleanup:
  525. //
  526. UnmapViewOfFile(pJpeg);
  527. CloseHandle(hMap);
  528. CloseHandle(hFile);
  529. return hr;
  530. }
  531. //--------------------------------------------------------------------------
  532. // IrUsdDevice::CamLoadThumbnail()
  533. //
  534. // Load the thumbnail of the specified picture. The picture is saved as
  535. // a .JPG file, so it needs to be uncompressed into a DIB, then the DIB
  536. // needs to be resized down to thumbnail size. The thumbnail DIBs are saved
  537. // into *.tmb files the first time that they are read so that we only need
  538. // to process them into DIBs once.
  539. //
  540. // Arguments:
  541. //
  542. // pCameraImage - image item
  543. // pThumbnail - buffer for thumbnail
  544. // pThumbSize - size of thumbnail
  545. //
  546. // Return Value:
  547. //
  548. // HRESULT: S_OK
  549. // E_OUTOFMEMORY
  550. // E_FAIL
  551. //
  552. //--------------------------------------------------------------------------
  553. HRESULT IrUsdDevice::CamLoadThumbnail(
  554. IN IRCAM_IMAGE_CONTEXT *pIrCamContext,
  555. OUT BYTE **ppThumbnail,
  556. OUT LONG *pThumbSize )
  557. {
  558. HRESULT hr = S_OK;
  559. DWORD dwStatus = 0;
  560. TCHAR pszThumbName[MAX_PATH];
  561. BOOL bThumbExists = TRUE; // True if there is a thumbnail file already.
  562. BOOL bCacheThumb = TRUE; // Should we try to cache the thumbnail if it
  563. // isn't already cached? (TRUE == Yes).
  564. BYTE *pTmbPixels = NULL;
  565. HBITMAP hbmThumb = NULL;
  566. BYTE *pThumb = NULL;
  567. HANDLE hTmbFile = INVALID_HANDLE_VALUE;
  568. HANDLE hTmbMap = NULL;
  569. BYTE *pTmbFile = NULL;
  570. HANDLE hFile = INVALID_HANDLE_VALUE;
  571. HANDLE hMap = NULL;
  572. BYTE *pFile = NULL;
  573. BYTE *pDIB = NULL;
  574. BITMAPINFO bmiDIB;
  575. BITMAPINFO bmiJPEG;
  576. HDC hdc = NULL;
  577. HDC hdcm1 = NULL;
  578. BY_HANDLE_FILE_INFORMATION FileInfo;
  579. long lThumbWidth;
  580. long lThumbHeight;
  581. double fImageWidth;
  582. double fImageHeight;
  583. double fAspect;
  584. double fDefAspect = 80.0 / 60.0;
  585. HBITMAP hbmDef;
  586. int iStatus;
  587. long lWidth;
  588. long lHeight;
  589. WORD wNumChannels;
  590. DWORD dwBytesPerScanLine;
  591. DWORD dwDIBSize;
  592. WIAS_TRACE((g_hInst,"IrUsdDevice::CamLoadThumbnail()"));
  593. //
  594. // Initialize the return values
  595. //
  596. *ppThumbnail = NULL;
  597. *pThumbSize = 0;
  598. //
  599. // Fill in the size of the tumbnail pixel buffer
  600. //
  601. bmiDIB.bmiHeader.biSizeImage = 80*60*3;
  602. //
  603. // Build thumbnail filename: <file>.bmp.tmb
  604. //
  605. _tcscpy(pszThumbName, pIrCamContext->pszCameraImagePath);
  606. _tcscat(pszThumbName, SZ_TMB );
  607. //
  608. // See if a saved copy of the thumbnail already exists:
  609. //
  610. hTmbFile = CreateFile( pszThumbName,
  611. GENERIC_READ | GENERIC_WRITE,
  612. FILE_SHARE_WRITE,
  613. NULL,
  614. OPEN_EXISTING,
  615. FILE_ATTRIBUTE_NORMAL,
  616. NULL );
  617. if (hTmbFile == INVALID_HANDLE_VALUE)
  618. {
  619. //
  620. // It didn't, try to create a new one:
  621. //
  622. hTmbFile = CreateFile( pszThumbName,
  623. GENERIC_READ | GENERIC_WRITE,
  624. FILE_SHARE_WRITE,
  625. NULL,
  626. CREATE_NEW,
  627. FILE_ATTRIBUTE_NORMAL,
  628. NULL );
  629. //
  630. // So, we need to write into the thumbnail file:
  631. //
  632. bThumbExists = FALSE;
  633. }
  634. //
  635. // If we could open (or create a new) .tmb file to hold the
  636. // cached thumbnail then we are Ok to go on...
  637. //
  638. if (hTmbFile == INVALID_HANDLE_VALUE)
  639. {
  640. hr = HRESULT_FROM_WIN32(::GetLastError());
  641. goto cleanup;
  642. }
  643. hTmbMap = CreateFileMapping( hTmbFile,
  644. NULL, // No special security
  645. PAGE_READWRITE,
  646. 0, // Size high 32bits.
  647. 80*60*3,// Size low 32bits. (80*60*3).
  648. NULL); // No handle name.
  649. if (hTmbMap != NULL)
  650. {
  651. pTmbFile = (PBYTE)MapViewOfFile(
  652. hTmbMap,
  653. FILE_MAP_READ | FILE_MAP_WRITE,
  654. 0, 0, // Offset (64bit).
  655. 0 ); // Map entire file.
  656. if (pTmbFile)
  657. {
  658. if (bThumbExists)
  659. {
  660. //
  661. // Allocate memory for thumbnail pixels:
  662. //
  663. pTmbPixels = (PBYTE)ALLOC(80*60*3);
  664. if (!pTmbPixels)
  665. {
  666. hr = E_OUTOFMEMORY;
  667. goto cleanup;
  668. }
  669. //
  670. // Pull the thumbnail from the cached file:
  671. //
  672. memcpy( pTmbPixels,
  673. pTmbFile,
  674. 80*60*3);
  675. //
  676. // All done for the cached thumbnail case, set
  677. // return values and goto cleanup...
  678. //
  679. *ppThumbnail = pTmbPixels;
  680. *pThumbSize = 80*60*3;
  681. goto cleanup;
  682. }
  683. else
  684. {
  685. //
  686. // No existing thumbnail file, but opened a new
  687. // file, so we will need to write out to cache:
  688. //
  689. bCacheThumb = TRUE;
  690. }
  691. }
  692. else
  693. {
  694. //
  695. // Couldn't memory map the thumbnail file, so don't
  696. // try to cache it:
  697. //
  698. bCacheThumb = FALSE;
  699. }
  700. }
  701. else
  702. {
  703. //
  704. // Can't open/create thumbnail file, so we can't cache
  705. // thumbnail:
  706. //
  707. bCacheThumb = FALSE;
  708. }
  709. //
  710. // Try to create a thumbnail from the full-size image
  711. // and cache it if the thumbnail cache file was created.
  712. //
  713. //
  714. // Open the .JPEG image file:
  715. //
  716. hFile = CreateFile(
  717. pIrCamContext->pszCameraImagePath,
  718. GENERIC_READ,
  719. FILE_SHARE_READ,
  720. NULL,
  721. OPEN_EXISTING,
  722. FILE_ATTRIBUTE_NORMAL,
  723. NULL );
  724. if (hFile == INVALID_HANDLE_VALUE)
  725. {
  726. hr = HRESULT_FROM_WIN32(::GetLastError());
  727. goto cleanup;
  728. }
  729. if (!GetFileInformationByHandle(hFile,&FileInfo))
  730. {
  731. hr = HRESULT_FROM_WIN32(::GetLastError());
  732. goto cleanup;
  733. }
  734. //
  735. // Map the file into memory:
  736. //
  737. hMap = CreateFileMapping( hFile,
  738. NULL, // No special security.
  739. PAGE_READONLY, // Only read needed.
  740. FileInfo.nFileSizeHigh, // File Size.
  741. FileInfo.nFileSizeLow,
  742. NULL ); // No handle name.
  743. if (hMap == NULL)
  744. {
  745. hr = HRESULT_FROM_WIN32(::GetLastError());
  746. goto cleanup;
  747. }
  748. pFile = (PBYTE)MapViewOfFile(
  749. hMap,
  750. FILE_MAP_READ,
  751. 0, 0, // 64-bit file offset = 0.
  752. 0 ); // Bytes to map. 0 == Entire file.
  753. if (pFile == NULL)
  754. {
  755. hr = HRESULT_FROM_WIN32(::GetLastError());
  756. goto cleanup;
  757. }
  758. //
  759. // Here is where we will parse out the full JPEG into a DIB. We
  760. // need to read the full JPEG, then squeeze it down to thumbnail
  761. // size.
  762. //
  763. // First, we need to dimensions of the JPEG image:
  764. //
  765. iStatus = GetJPEGDimensions( pFile,
  766. FileInfo.nFileSizeLow,
  767. &lWidth,
  768. &lHeight,
  769. &wNumChannels );
  770. if (iStatus != JPEGERR_NO_ERROR)
  771. {
  772. hr = E_FAIL;
  773. goto cleanup;
  774. }
  775. //
  776. // Allocate memory to hold a DIB of the entire JPEG:
  777. //
  778. dwBytesPerScanLine = lWidth * wNumChannels;
  779. dwBytesPerScanLine = (dwBytesPerScanLine + wNumChannels) & 0xFFFFFFFC;
  780. dwDIBSize = dwBytesPerScanLine * lHeight;
  781. pDIB = (BYTE*)ALLOC(dwDIBSize);
  782. if (!pDIB)
  783. {
  784. hr = E_OUTOFMEMORY;
  785. goto cleanup;
  786. }
  787. //
  788. // Convert the full JPEG image into a DIB:
  789. //
  790. iStatus = DecompJPEG( pFile,
  791. FileInfo.nFileSizeLow,
  792. pDIB,
  793. dwBytesPerScanLine );
  794. if (iStatus != JPEGERR_NO_ERROR)
  795. {
  796. hr = E_FAIL;
  797. goto cleanup;
  798. }
  799. //
  800. // Generate the thumbnail from the full-size image:
  801. //
  802. hdc = GetDC(NULL);
  803. hdcm1 = CreateCompatibleDC(hdc);
  804. SetStretchBltMode( hdcm1, COLORONCOLOR );
  805. //
  806. // Create a BITMAP for rendering the thumbnail:
  807. //
  808. bmiDIB.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  809. bmiDIB.bmiHeader.biBitCount = 24;
  810. bmiDIB.bmiHeader.biWidth = 80;
  811. bmiDIB.bmiHeader.biHeight = 60;
  812. bmiDIB.bmiHeader.biPlanes = 1;
  813. bmiDIB.bmiHeader.biCompression = BI_RGB;
  814. bmiDIB.bmiHeader.biXPelsPerMeter = 100;
  815. bmiDIB.bmiHeader.biYPelsPerMeter = 100;
  816. bmiDIB.bmiHeader.biClrUsed = 0;
  817. bmiDIB.bmiHeader.biClrImportant = 0;
  818. hbmThumb = CreateDIBSection( hdc,
  819. &bmiDIB,
  820. DIB_RGB_COLORS,
  821. (VOID**)&pThumb,
  822. NULL,
  823. 0 );
  824. if (!hbmThumb)
  825. {
  826. hr = HRESULT_FROM_WIN32(::GetLastError());
  827. goto cleanup;
  828. }
  829. hbmDef = (HBITMAP)SelectObject(hdcm1, hbmThumb);
  830. //
  831. // Initialize the DIB:
  832. //
  833. memset( pThumb, 0, bmiDIB.bmiHeader.biSizeImage );
  834. //
  835. // We want to create 80x60 thumbnail while preserving the original
  836. // image aspect ratio.
  837. //
  838. fImageWidth = (double)lWidth;
  839. fImageHeight = (double)lHeight;
  840. fAspect = fImageWidth / fImageHeight;
  841. if (fAspect > fDefAspect)
  842. {
  843. lThumbWidth = 80;
  844. lThumbHeight = (LONG)(80.0 / fAspect);
  845. }
  846. else
  847. {
  848. lThumbHeight = 60;
  849. lThumbWidth = (LONG)(60.0 * fAspect);
  850. }
  851. memset(&bmiJPEG,0,sizeof(bmiJPEG));
  852. bmiJPEG.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  853. bmiJPEG.bmiHeader.biBitCount = 24; // Use 0 for JPEG content.
  854. bmiJPEG.bmiHeader.biWidth = lWidth;
  855. bmiJPEG.bmiHeader.biHeight = lHeight;
  856. bmiJPEG.bmiHeader.biPlanes = 1;
  857. bmiJPEG.bmiHeader.biCompression = BI_RGB; // BI_JPEG;
  858. bmiJPEG.bmiHeader.biXPelsPerMeter = 1000;
  859. bmiJPEG.bmiHeader.biYPelsPerMeter = 1000;
  860. bmiJPEG.bmiHeader.biClrUsed = 0;
  861. bmiJPEG.bmiHeader.biClrImportant = 0;
  862. bmiJPEG.bmiHeader.biSizeImage = FileInfo.nFileSizeLow;
  863. iStatus = StretchDIBits( hdcm1,
  864. 0,
  865. 0,
  866. lThumbWidth,
  867. lThumbHeight,
  868. 0,
  869. 0,
  870. lWidth,
  871. lHeight,
  872. pDIB, // pFile is our JPEG.
  873. &bmiJPEG,
  874. DIB_RGB_COLORS,
  875. SRCCOPY );
  876. if (iStatus == GDI_ERROR)
  877. {
  878. dwStatus = ::GetLastError();
  879. hr = HRESULT_FROM_WIN32(dwStatus);
  880. }
  881. SelectObject(hdcm1, hbmDef);
  882. //
  883. // If necessary, cache the thumbnail:
  884. //
  885. if (bCacheThumb)
  886. {
  887. memcpy( pTmbFile, pThumb, bmiDIB.bmiHeader.biSizeImage );
  888. }
  889. //
  890. // Allocate memory for thumbnail pixels:
  891. //
  892. pTmbPixels = (PBYTE)ALLOC(bmiDIB.bmiHeader.biSizeImage);
  893. if (! pTmbPixels)
  894. {
  895. hr = E_OUTOFMEMORY;
  896. goto cleanup;
  897. }
  898. //
  899. // Write out the thumbnail data to the cache file:
  900. //
  901. memcpy( pTmbPixels, pThumb, bmiDIB.bmiHeader.biSizeImage);
  902. *ppThumbnail = pTmbPixels;
  903. *pThumbSize = bmiDIB.bmiHeader.biSizeImage;
  904. cleanup:
  905. if (pTmbFile)
  906. {
  907. UnmapViewOfFile(pTmbFile);
  908. }
  909. if (hTmbMap)
  910. {
  911. CloseHandle(hTmbMap);
  912. }
  913. if (hTmbFile != INVALID_HANDLE_VALUE)
  914. {
  915. CloseHandle(hTmbFile);
  916. }
  917. if (pFile)
  918. {
  919. UnmapViewOfFile(pFile);
  920. }
  921. if (hMap)
  922. {
  923. CloseHandle(hMap);
  924. }
  925. if (hFile != INVALID_HANDLE_VALUE)
  926. {
  927. CloseHandle(hFile);
  928. }
  929. if (hbmThumb)
  930. {
  931. DeleteObject(hbmThumb);
  932. }
  933. if (hdcm1)
  934. {
  935. DeleteDC(hdcm1);
  936. }
  937. if (hdc)
  938. {
  939. ReleaseDC(NULL, hdc);
  940. }
  941. return hr;
  942. }
  943. //--------------------------------------------------------------------------
  944. // CamDeletePicture()
  945. //
  946. // Delete the specified picture from the temp directory. In this case, all
  947. // that we have to do is delete image (.jpg) and the temporary thumbnail
  948. // file that we created (.tmb).
  949. //
  950. // Arguments:
  951. //
  952. // pIrCamContext --
  953. //
  954. // Return Value:
  955. //
  956. // HRESULT S_OK
  957. // S_FAIL
  958. //
  959. //--------------------------------------------------------------------------
  960. HRESULT IrUsdDevice::CamDeletePicture( IRCAM_IMAGE_CONTEXT *pIrCamContext )
  961. {
  962. DWORD dwStatus;
  963. WIAS_TRACE((g_hInst,"CamDeletePicture(): %s",pIrCamContext->pszCameraImagePath));
  964. //
  965. // First, delete the thumbnail (.tmb) file:
  966. //
  967. DWORD dwLen = _tcslen(pIrCamContext->pszCameraImagePath);
  968. TCHAR *pszThumb = (TCHAR*)_alloca(sizeof(TCHAR)*(dwLen+1) + sizeof(SZ_TMB));
  969. _tcscpy(pszThumb,pIrCamContext->pszCameraImagePath);
  970. _tcscat(pszThumb,SZ_TMB);
  971. if (!DeleteFile(pszThumb))
  972. {
  973. dwStatus = ::GetLastError();
  974. }
  975. //
  976. // Now, delete the image (.jpg):
  977. //
  978. if (!DeleteFile(pIrCamContext->pszCameraImagePath))
  979. {
  980. dwStatus = ::GetLastError();
  981. }
  982. return S_OK;
  983. }
  984. //--------------------------------------------------------------------------
  985. // CamTakePicture()
  986. //
  987. // Tell the camera to snap a picture. IrTran-P doesn't support this.
  988. //
  989. // Arguments:
  990. //
  991. // pIrCamContext --
  992. //
  993. // pHandle --
  994. //
  995. //
  996. // Return Value:
  997. //
  998. // HRESULT E_NOTIMPL
  999. //
  1000. //--------------------------------------------------------------------------
  1001. HRESULT CamTakePicture( IRCAM_IMAGE_CONTEXT *pIrCamContext ,
  1002. ULONG *pHandle)
  1003. {
  1004. return E_NOTIMPL;
  1005. }