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
1195 lines
30 KiB
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT MICROSOFT CORP., 1998
|
|
*
|
|
* TITLE: memcam.cpp
|
|
*
|
|
* VERSION: 2.0
|
|
*
|
|
* AUTHOR: Mark Enstrom [marke]
|
|
* Indy Zhu [indyz]
|
|
*
|
|
* DATE: 2/4/1998
|
|
* 5/18/1998
|
|
*
|
|
* DESCRIPTION:
|
|
* Implementation of an ImageIn test camera device object.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include <objbase.h>
|
|
#include <tchar.h>
|
|
#include <sti.h>
|
|
|
|
extern HINSTANCE g_hInst; // Global hInstance
|
|
|
|
#include "testusd.h"
|
|
|
|
|
|
VOID
|
|
VerticalFlip(
|
|
PBYTE pImageTop,
|
|
LONG iHeight,
|
|
LONG iWidthInBytes);
|
|
|
|
/**************************************************************************\
|
|
* CamLoadPicture
|
|
*
|
|
* load a bmp from disk and copy it to application
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pCameraImage - pointer to data structure with image info
|
|
* pDataTransCtx - pointer to minidriver transfer context
|
|
*
|
|
* Return Value:
|
|
*
|
|
* status
|
|
*
|
|
* History:
|
|
*
|
|
* 2/10/1998 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT
|
|
TestUsdDevice::CamLoadPicture(
|
|
MEMCAM_IMAGE_CONTEXT *pMCamContext,
|
|
PMINIDRV_TRANSFER_CONTEXT pDataTransCtx,
|
|
PLONG plCamErrVal)
|
|
{
|
|
LONG lScanLineWidth;
|
|
HRESULT hr = S_OK;
|
|
LONG cbNeeded;
|
|
IWiaMiniDrvCallBack *pIProgressCB;
|
|
|
|
WIAS_TRACE((g_hInst,"CamLoadPicture"));
|
|
|
|
//
|
|
// verify some params
|
|
//
|
|
|
|
if (! pMCamContext) {
|
|
return (E_INVALIDARG);
|
|
}
|
|
|
|
if (pDataTransCtx->guidFormatID != WiaImgFmt_BMP && pDataTransCtx->guidFormatID != WiaAudFmt_WAV) {
|
|
return (E_NOTIMPL);
|
|
}
|
|
|
|
pIProgressCB = pDataTransCtx->pIWiaMiniDrvCallBack;
|
|
|
|
//
|
|
// Simulate the download of data from the camera
|
|
//
|
|
|
|
if (pIProgressCB) {
|
|
hr = pIProgressCB->MiniDrvCallback(
|
|
IT_MSG_STATUS,
|
|
IT_STATUS_TRANSFER_FROM_DEVICE,
|
|
(LONG)0, // Percentage Complete,
|
|
0,
|
|
0,
|
|
pDataTransCtx,
|
|
0);
|
|
if (hr != S_OK) {
|
|
return (hr); // Client want to cancel the transfer or error
|
|
}
|
|
}
|
|
|
|
HANDLE hFile = CreateFile(
|
|
pMCamContext->pszCameraImagePath,
|
|
GENERIC_WRITE | GENERIC_READ ,
|
|
FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
return (hr);
|
|
}
|
|
|
|
if (pIProgressCB) {
|
|
hr = pIProgressCB->MiniDrvCallback(
|
|
IT_MSG_STATUS,
|
|
IT_STATUS_TRANSFER_FROM_DEVICE,
|
|
(LONG)25, // Percentage Complete,
|
|
0,
|
|
0,
|
|
pDataTransCtx,
|
|
0);
|
|
}
|
|
if (hr != S_OK) {
|
|
CloseHandle(hFile);
|
|
return (hr);
|
|
}
|
|
|
|
HANDLE hMap = CreateFileMapping(
|
|
hFile,
|
|
NULL,
|
|
PAGE_READWRITE,
|
|
0,
|
|
0,
|
|
NULL);
|
|
|
|
if (hMap == NULL) {
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
} else {
|
|
if (pIProgressCB) {
|
|
hr = pIProgressCB->MiniDrvCallback(
|
|
IT_MSG_STATUS,
|
|
IT_STATUS_TRANSFER_FROM_DEVICE,
|
|
(LONG)50, // Percentage Complete,
|
|
0,
|
|
0,
|
|
pDataTransCtx,
|
|
0);
|
|
}
|
|
}
|
|
|
|
if (hr != S_OK) {
|
|
CloseHandle(hFile);
|
|
return (hr);
|
|
}
|
|
|
|
PBYTE pFile = (PBYTE)MapViewOfFileEx(
|
|
hMap,
|
|
FILE_MAP_READ | FILE_MAP_WRITE,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL);
|
|
if (pFile == NULL) {
|
|
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
} else {
|
|
if (pIProgressCB) {
|
|
hr = pIProgressCB->MiniDrvCallback(
|
|
IT_MSG_STATUS,
|
|
IT_STATUS_TRANSFER_FROM_DEVICE,
|
|
(LONG)100, // Percentage Complete,
|
|
0,
|
|
0,
|
|
pDataTransCtx,
|
|
0);
|
|
}
|
|
}
|
|
|
|
if (hr != S_OK) {
|
|
CloseHandle(hFile);
|
|
CloseHandle(hMap);
|
|
return(hr);
|
|
}
|
|
|
|
if (pDataTransCtx->guidFormatID == WiaImgFmt_BMP)
|
|
{
|
|
|
|
|
|
//
|
|
// File contains BITMAPFILEHEADER + BITMAPINFO structure.
|
|
//
|
|
// DIB Data is located bfOffBits after start of file
|
|
//
|
|
|
|
PBITMAPFILEHEADER pbmFile = (PBITMAPFILEHEADER)pFile;
|
|
PBITMAPINFO pbmi = (PBITMAPINFO)(pFile +
|
|
sizeof(BITMAPFILEHEADER));
|
|
|
|
//
|
|
// validate bitmap
|
|
//
|
|
|
|
if (pbmFile->bfType != 'MB') {
|
|
|
|
//
|
|
// file is not a bitmap
|
|
//
|
|
|
|
UnmapViewOfFile(pFile);
|
|
CloseHandle(hMap);
|
|
CloseHandle(hFile);
|
|
return(E_FAIL);
|
|
}
|
|
|
|
//
|
|
// write image size
|
|
//
|
|
// make sure to align scanline to ULONG boundary
|
|
//
|
|
// calculate byte width
|
|
//
|
|
|
|
lScanLineWidth = pbmi->bmiHeader.biWidth * pbmi->bmiHeader.biBitCount;
|
|
|
|
//
|
|
// round up to nearenst DWORD
|
|
//
|
|
|
|
lScanLineWidth = (lScanLineWidth + 31) >> 3;
|
|
|
|
lScanLineWidth &= 0xfffffffc;
|
|
|
|
cbNeeded = lScanLineWidth * pbmi->bmiHeader.biHeight;
|
|
|
|
if (cbNeeded > ((LONG)pDataTransCtx->lItemSize - (LONG)pDataTransCtx->cbOffset)) {
|
|
|
|
hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
|
|
|
|
} else {
|
|
|
|
//
|
|
// copy only the bitmap bits (no headers)
|
|
//
|
|
|
|
memcpy(
|
|
pDataTransCtx->pTransferBuffer + pDataTransCtx->cbOffset,
|
|
pFile + pbmFile->bfOffBits,
|
|
cbNeeded);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
memcpy (pDataTransCtx->pTransferBuffer,
|
|
pFile,
|
|
pDataTransCtx->lItemSize);
|
|
}
|
|
UnmapViewOfFile(pFile);
|
|
CloseHandle(hMap);
|
|
CloseHandle(hFile);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CamLoadPictureCB
|
|
*
|
|
* return data by filling the data buffer and calling back to the client
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pCameraImage - image item
|
|
* pTransCtx - mini driver transfer contect
|
|
*
|
|
* Return Value:
|
|
*
|
|
* status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/10/1999 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT TestUsdDevice::CamLoadPictureCB(
|
|
MEMCAM_IMAGE_CONTEXT *pMCamContext,
|
|
MINIDRV_TRANSFER_CONTEXT *pTransCtx,
|
|
PLONG plCamErrVal)
|
|
{
|
|
LONG lScanLineWidth;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
WIAS_TRACE((g_hInst,"CamLoadPictureCB"));
|
|
|
|
//
|
|
// verify parameters
|
|
//
|
|
|
|
if (!pMCamContext) {
|
|
return (E_INVALIDARG);
|
|
}
|
|
|
|
if (pTransCtx == NULL) {
|
|
return (E_INVALIDARG);
|
|
}
|
|
|
|
if ((pTransCtx->guidFormatID != WiaImgFmt_BMP) &&
|
|
(pTransCtx->guidFormatID != WiaImgFmt_MEMORYBMP)) {
|
|
return (E_NOTIMPL);
|
|
}
|
|
|
|
//
|
|
// try to open disk file
|
|
//
|
|
|
|
HANDLE hFile = CreateFile(
|
|
pMCamContext->pszCameraImagePath,
|
|
GENERIC_WRITE | GENERIC_READ ,
|
|
FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
return(hr);
|
|
}
|
|
|
|
HANDLE hMap = CreateFileMapping(
|
|
hFile,
|
|
NULL,
|
|
PAGE_READWRITE,
|
|
0,
|
|
0,
|
|
NULL);
|
|
|
|
if (hMap == NULL) {
|
|
CloseHandle(hFile);
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
return(hr);
|
|
}
|
|
|
|
PBYTE pFile = (PBYTE)MapViewOfFileEx(
|
|
hMap,
|
|
FILE_MAP_READ | FILE_MAP_WRITE,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL);
|
|
if (pFile == NULL) {
|
|
|
|
CloseHandle(hFile);
|
|
CloseHandle(hMap);
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
return(hr);
|
|
}
|
|
|
|
//
|
|
// File contains BITMAPFILEHEADER + BITMAPINFO structure.
|
|
//
|
|
// DIB Data is located bfOffBits after start of file
|
|
//
|
|
|
|
PBITMAPFILEHEADER pbmFile = (PBITMAPFILEHEADER)pFile;
|
|
PBITMAPINFO pbmi = (PBITMAPINFO)(pFile +
|
|
sizeof(BITMAPFILEHEADER));
|
|
//
|
|
// validate bitmap
|
|
//
|
|
|
|
if (pbmFile->bfType != 'MB') {
|
|
|
|
//
|
|
// file is not a bitmap
|
|
//
|
|
|
|
UnmapViewOfFile(pFile);
|
|
CloseHandle(hMap);
|
|
CloseHandle(hFile);
|
|
return(E_FAIL);
|
|
}
|
|
|
|
//
|
|
// get image size
|
|
//
|
|
// make sure to align scanline to ULONG boundary
|
|
//
|
|
// calculate byte width
|
|
//
|
|
|
|
lScanLineWidth = pbmi->bmiHeader.biWidth * pbmi->bmiHeader.biBitCount;
|
|
|
|
//
|
|
// round up to nearenst DWORD
|
|
//
|
|
|
|
lScanLineWidth = (lScanLineWidth + 31) >> 3;
|
|
|
|
lScanLineWidth &= 0xfffffffc;
|
|
|
|
LONG lBytesRemaining = lScanLineWidth * pbmi->bmiHeader.biHeight;
|
|
|
|
//
|
|
// Flip the image vertically if WiaImgFmt_MEMORYBMP is requested
|
|
//
|
|
|
|
if (pTransCtx->guidFormatID == WiaImgFmt_MEMORYBMP) {
|
|
VerticalFlip(
|
|
(PBYTE)pFile + pbmFile->bfOffBits,
|
|
pbmi->bmiHeader.biHeight,
|
|
lScanLineWidth);
|
|
}
|
|
|
|
//
|
|
// callback loop
|
|
//
|
|
|
|
PBYTE pSrc = (PBYTE)pFile + pbmFile->bfOffBits;
|
|
|
|
LONG lTransferSize;
|
|
LONG lPercentComplete;
|
|
|
|
do {
|
|
|
|
PBYTE pDst = pTransCtx->pTransferBuffer;
|
|
|
|
//
|
|
// transfer up to entire buffer size
|
|
//
|
|
|
|
lTransferSize = lBytesRemaining;
|
|
|
|
if (lBytesRemaining > pTransCtx->lBufferSize) {
|
|
lTransferSize = pTransCtx->lBufferSize;
|
|
}
|
|
|
|
//
|
|
// copy data
|
|
//
|
|
|
|
memcpy(pDst, pSrc, lTransferSize);
|
|
|
|
lPercentComplete = 100 * (pTransCtx->cbOffset + lTransferSize);
|
|
lPercentComplete /= pTransCtx->lItemSize;
|
|
|
|
//
|
|
// make callback
|
|
//
|
|
|
|
hr = pTransCtx->pIWiaMiniDrvCallBack->MiniDrvCallback(
|
|
IT_MSG_DATA,
|
|
IT_STATUS_TRANSFER_TO_CLIENT,
|
|
lPercentComplete,
|
|
pTransCtx->cbOffset,
|
|
lTransferSize,
|
|
pTransCtx,
|
|
0);
|
|
//
|
|
// inc pointers (redundant pointers here)
|
|
//
|
|
|
|
pSrc += lTransferSize;
|
|
pTransCtx->cbOffset += lTransferSize;
|
|
lBytesRemaining -= lTransferSize;
|
|
|
|
if (hr != S_OK) {
|
|
break;
|
|
}
|
|
|
|
} while (lBytesRemaining > 0);
|
|
|
|
//
|
|
// Flip the image back if WiaImgFmt_MEMORYBMP is requested
|
|
//
|
|
|
|
if (pTransCtx->guidFormatID == WiaImgFmt_MEMORYBMP) {
|
|
VerticalFlip(
|
|
(PBYTE)pFile + pbmFile->bfOffBits,
|
|
pbmi->bmiHeader.biHeight,
|
|
lScanLineWidth);
|
|
}
|
|
|
|
//
|
|
// Garbage collection
|
|
//
|
|
|
|
UnmapViewOfFile(pFile);
|
|
CloseHandle(hMap);
|
|
CloseHandle(hFile);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************\
|
|
* CamGetPictureInfo
|
|
*
|
|
* Load file, get information from image
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pCameraImage - image item
|
|
* pPictInfo - fill out ino about image
|
|
* ppBITMAPINFO - alloc and fill out BITMAPINFO
|
|
* pBITMAPINFOSize - size
|
|
*
|
|
* Return Value:
|
|
*
|
|
* status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/17/1999 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT
|
|
TestUsdDevice::CamGetPictureInfo(
|
|
MEMCAM_IMAGE_CONTEXT *pMCamContext,
|
|
PCAMERA_PICTURE_INFO pPictInfo,
|
|
PBYTE *ppBITMAPINFO,
|
|
LONG *pBITMAPINFOSize)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
FILETIME ftCreate;
|
|
SYSTEMTIME stCreate;
|
|
|
|
WIAS_TRACE((g_hInst,"CamGetPictureInfo"));
|
|
|
|
//
|
|
// Try to open disk file
|
|
//
|
|
|
|
HANDLE hFile = CreateFile(
|
|
pMCamContext->pszCameraImagePath,
|
|
GENERIC_WRITE | GENERIC_READ,
|
|
FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
return(hr);
|
|
}
|
|
|
|
//
|
|
// Grab the creation time for this image
|
|
//
|
|
|
|
if (GetFileTime( hFile, &ftCreate, NULL, NULL)) {
|
|
FileTimeToSystemTime( &ftCreate, &stCreate );
|
|
} else {
|
|
//
|
|
// To return something, use the system time
|
|
//
|
|
|
|
GetLocalTime( &stCreate );
|
|
}
|
|
|
|
HANDLE hMap = CreateFileMapping(
|
|
hFile,
|
|
NULL,
|
|
PAGE_READWRITE,
|
|
0,
|
|
0,
|
|
NULL
|
|
);
|
|
if (hMap == NULL) {
|
|
CloseHandle(hFile);
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
return(hr);
|
|
}
|
|
|
|
PBYTE pFile = (PBYTE)MapViewOfFileEx(
|
|
hMap,
|
|
FILE_MAP_READ | FILE_MAP_WRITE,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL);
|
|
if (pFile == NULL) {
|
|
CloseHandle(hFile);
|
|
CloseHandle(hMap);
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
return(hr);
|
|
}
|
|
|
|
//
|
|
// File contains BITMAPFILEHEADER + BITMAPINFO structure.
|
|
//
|
|
// DIB Data is located bfOffBits after start of file
|
|
//
|
|
|
|
PBITMAPFILEHEADER pbmFile = (PBITMAPFILEHEADER)pFile;
|
|
PBITMAPINFOHEADER pbmiHeader =
|
|
(PBITMAPINFOHEADER)(pFile +
|
|
sizeof(BITMAPFILEHEADER));
|
|
PBYTE pDIBFile = pFile + pbmFile->bfOffBits;
|
|
|
|
//
|
|
// validate bitmap.
|
|
//
|
|
|
|
if (pbmFile->bfType != 'MB') {
|
|
//
|
|
// file is not a bitmap
|
|
//
|
|
|
|
|
|
UnmapViewOfFile(pFile);
|
|
CloseHandle(hFile);
|
|
CloseHandle(hMap);
|
|
return(E_FAIL);
|
|
}
|
|
|
|
//
|
|
// fill out image information
|
|
//
|
|
|
|
pPictInfo->PictNumber = 0; // ??? Should support picture handle ???
|
|
pPictInfo->ThumbWidth = 80;
|
|
pPictInfo->ThumbHeight = 60;
|
|
pPictInfo->PictWidth = pbmiHeader->biWidth;
|
|
pPictInfo->PictHeight = pbmiHeader->biHeight;
|
|
pPictInfo->PictCompSize = 0;
|
|
pPictInfo->PictFormat = 0;
|
|
pPictInfo->PictBitsPerPixel = pbmiHeader->biBitCount;
|
|
|
|
{
|
|
LONG lScanLineWidth = (pbmiHeader->biWidth *
|
|
pbmiHeader->biBitCount);
|
|
|
|
//
|
|
// round up to nearenst DWORD
|
|
//
|
|
|
|
lScanLineWidth = (lScanLineWidth + 31) >> 3;
|
|
|
|
//
|
|
// remove extra bytes
|
|
//
|
|
|
|
lScanLineWidth &= 0xfffffffc;
|
|
|
|
pPictInfo->PictBytesPerRow = lScanLineWidth;
|
|
}
|
|
|
|
//
|
|
// is there a color table
|
|
//
|
|
|
|
LONG ColorMapSize = 0;
|
|
LONG bmiSize;
|
|
|
|
if (pbmiHeader->biBitCount == 1) {
|
|
ColorMapSize = 2;
|
|
} else if (pbmiHeader->biBitCount == 4) {
|
|
ColorMapSize = 16;
|
|
} else if (pbmiHeader->biBitCount == 8) {
|
|
ColorMapSize = 256;
|
|
}
|
|
|
|
//
|
|
// Changed by Indy on 5/18/98 to BITMAPINFOHEADER
|
|
//
|
|
|
|
bmiSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * ColorMapSize;
|
|
|
|
*ppBITMAPINFO = (PBYTE)ALLOC(bmiSize);
|
|
|
|
if (*ppBITMAPINFO != NULL) {
|
|
memcpy(*ppBITMAPINFO, pbmiHeader, bmiSize);
|
|
*pBITMAPINFOSize = bmiSize;
|
|
} else {
|
|
|
|
UnmapViewOfFile(pFile);
|
|
CloseHandle(hFile);
|
|
CloseHandle(hMap);
|
|
return(E_OUTOFMEMORY);
|
|
}
|
|
|
|
//
|
|
// Set the time for the image
|
|
//
|
|
|
|
memcpy(&pPictInfo->TimeStamp, &stCreate, sizeof(pPictInfo->TimeStamp));
|
|
|
|
//
|
|
// close up the file
|
|
//
|
|
|
|
UnmapViewOfFile(pFile);
|
|
CloseHandle(hMap);
|
|
CloseHandle(hFile);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* CamLoadThumbnail
|
|
*
|
|
* Load the thumbnail of the specified picture
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pCameraImage - image item
|
|
* pThumbnail - buffer for thumbnail
|
|
* pThumbSize - size of thumbnail
|
|
*
|
|
* Return Value:
|
|
*
|
|
* status
|
|
*
|
|
* History:
|
|
*
|
|
* 2/9/1998 Mark Enstrom [marke]
|
|
* 6/9/1998 Indy Zhu [indyz]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT
|
|
TestUsdDevice::CamLoadThumbnail(
|
|
MEMCAM_IMAGE_CONTEXT *pMCamContext ,
|
|
PBYTE *pThumbnail,
|
|
LONG *pThumbSize
|
|
)
|
|
{
|
|
TCHAR pszThumbName[MAX_PATH];
|
|
HRESULT hr;
|
|
BOOL bCacheThumb = TRUE;
|
|
BOOL bThumbExists = TRUE;
|
|
|
|
PBYTE pTmbPixels;
|
|
HBITMAP hbmThumb = NULL;
|
|
PBYTE pThumb = NULL;
|
|
HANDLE hTmbFile = INVALID_HANDLE_VALUE;
|
|
HANDLE hTmbMap = NULL;
|
|
PBYTE pTmbFile = NULL;
|
|
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
HANDLE hMap = NULL;
|
|
PBYTE pFile = NULL;
|
|
|
|
BITMAPINFO bmiDIB;
|
|
HDC hdc = NULL;
|
|
HDC hdcm1 = NULL;
|
|
|
|
WIAS_TRACE((g_hInst,"CamLoadThumbnail"));
|
|
|
|
//
|
|
// Initialize the return values
|
|
//
|
|
|
|
*pThumbnail = NULL;
|
|
*pThumbSize = 0;
|
|
|
|
//
|
|
// Fill in the size of the tumbnail pixel buffer
|
|
//
|
|
|
|
bmiDIB.bmiHeader.biSizeImage = 80*60*3;
|
|
|
|
//
|
|
// Build thumbnail filename Image.bmp.tmb
|
|
//
|
|
|
|
_tcscpy(pszThumbName, pMCamContext->pszCameraImagePath);
|
|
_tcscat(pszThumbName, TEXT(".tmb"));
|
|
|
|
__try {
|
|
|
|
hTmbFile = CreateFile(
|
|
pszThumbName,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// See if cached thumbnail already exists
|
|
//
|
|
|
|
if (hTmbFile == INVALID_HANDLE_VALUE) {
|
|
|
|
//
|
|
// Try to create a new one
|
|
//
|
|
|
|
hTmbFile = CreateFile(
|
|
pszThumbName,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_WRITE,
|
|
NULL,
|
|
CREATE_NEW,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// Thumbnail need to be created
|
|
//
|
|
|
|
bThumbExists = FALSE;
|
|
|
|
}
|
|
|
|
//
|
|
// thumbnail file exists
|
|
//
|
|
|
|
if (hTmbFile != INVALID_HANDLE_VALUE) {
|
|
|
|
hTmbMap = CreateFileMapping(
|
|
hTmbFile,
|
|
NULL,
|
|
PAGE_READWRITE,
|
|
0,
|
|
80 * 60 * 3,
|
|
NULL);
|
|
|
|
if (hTmbMap != NULL) {
|
|
|
|
pTmbFile = (PBYTE)MapViewOfFileEx(
|
|
hTmbMap,
|
|
FILE_MAP_READ | FILE_MAP_WRITE,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL);
|
|
|
|
if (pTmbFile) {
|
|
|
|
if (bThumbExists) {
|
|
|
|
//
|
|
// Alloca memory for thumbnail pixels
|
|
//
|
|
|
|
pTmbPixels = (PBYTE)ALLOC(bmiDIB.bmiHeader.biSizeImage);
|
|
|
|
if (! pTmbPixels) {
|
|
return(E_OUTOFMEMORY);
|
|
}
|
|
|
|
//
|
|
// Pull the thumbnail from the cached file
|
|
//
|
|
|
|
memcpy(pTmbPixels, pTmbFile,
|
|
bmiDIB.bmiHeader.biSizeImage);
|
|
|
|
//
|
|
// All the handles will be closed in __finally block
|
|
//
|
|
|
|
*pThumbnail = pTmbPixels;
|
|
*pThumbSize = bmiDIB.bmiHeader.biSizeImage;
|
|
|
|
return(S_OK);
|
|
}
|
|
} else {
|
|
|
|
bCacheThumb = FALSE;
|
|
}
|
|
} else {
|
|
|
|
bCacheThumb = FALSE;
|
|
}
|
|
} else {
|
|
|
|
//
|
|
// Can't cache thumbnail
|
|
//
|
|
|
|
bCacheThumb = FALSE;
|
|
}
|
|
|
|
//
|
|
// Try to create a thumbnail from the full-size image
|
|
// and cache it if the thumbnail cache file is created
|
|
//
|
|
|
|
hFile = CreateFile(
|
|
pMCamContext->pszCameraImagePath,
|
|
GENERIC_WRITE | GENERIC_READ,
|
|
FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
|
|
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
return(hr);
|
|
}
|
|
|
|
hMap = CreateFileMapping(
|
|
hFile,
|
|
NULL,
|
|
PAGE_READWRITE,
|
|
0,
|
|
0,
|
|
NULL
|
|
);
|
|
if (hMap == NULL) {
|
|
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
return(hr);
|
|
}
|
|
|
|
pFile = (PBYTE)MapViewOfFileEx(
|
|
hMap,
|
|
FILE_MAP_READ | FILE_MAP_WRITE,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL
|
|
);
|
|
if (pFile == NULL) {
|
|
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
return(hr);
|
|
}
|
|
|
|
PBITMAPFILEHEADER pbmFile = (PBITMAPFILEHEADER)pFile;
|
|
PBITMAPINFO pbmi = (PBITMAPINFO)(pFile +
|
|
sizeof(BITMAPFILEHEADER));
|
|
PBYTE pPixels = pFile + pbmFile->bfOffBits;
|
|
|
|
//
|
|
// Generate the thumbnail from the full-size image
|
|
//
|
|
|
|
hdc = GetDC(NULL);
|
|
hdcm1 = CreateCompatibleDC(hdc);
|
|
SetStretchBltMode(hdcm1, COLORONCOLOR);
|
|
|
|
|
|
|
|
//
|
|
// Create a BITMAP for rendering the thumbnail
|
|
//
|
|
|
|
bmiDIB.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
bmiDIB.bmiHeader.biBitCount = 24;
|
|
bmiDIB.bmiHeader.biWidth = 80;
|
|
bmiDIB.bmiHeader.biHeight = 60;
|
|
bmiDIB.bmiHeader.biPlanes = 1;
|
|
bmiDIB.bmiHeader.biCompression = BI_RGB;
|
|
bmiDIB.bmiHeader.biXPelsPerMeter = 100;
|
|
bmiDIB.bmiHeader.biYPelsPerMeter = 100;
|
|
bmiDIB.bmiHeader.biClrUsed = 0;
|
|
bmiDIB.bmiHeader.biClrImportant = 0;
|
|
|
|
hbmThumb = CreateDIBSection(hdc, &bmiDIB, DIB_RGB_COLORS,
|
|
(VOID **)&pThumb, NULL, 0);
|
|
|
|
if (! hbmThumb) {
|
|
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
return hr;
|
|
}
|
|
|
|
HBITMAP hbmDef = (HBITMAP)SelectObject(hdcm1, hbmThumb);
|
|
|
|
//
|
|
// Init DIB
|
|
//
|
|
|
|
memset(pThumb, 0, bmiDIB.bmiHeader.biSizeImage);
|
|
|
|
//
|
|
// create 80x60 thumbnail while preserving image
|
|
// aspect ratio
|
|
//
|
|
|
|
LONG lThumbWidth;
|
|
LONG lThumbHeight;
|
|
|
|
double fImageWidth = (double)pbmi->bmiHeader.biWidth;
|
|
double fImageHeight = (double)pbmi->bmiHeader.biHeight;
|
|
double fAspect = fImageWidth / fImageHeight;
|
|
double fDefAspect = 80.0 / 60.0;
|
|
|
|
if (fAspect > fDefAspect) {
|
|
|
|
lThumbWidth = 80;
|
|
lThumbHeight = (LONG)(80.0 / fAspect);
|
|
} else {
|
|
|
|
lThumbHeight = 60;
|
|
lThumbWidth = (LONG)(60.0 * fAspect);
|
|
}
|
|
|
|
int i = StretchDIBits(
|
|
hdcm1,
|
|
0,
|
|
0,
|
|
lThumbWidth,
|
|
lThumbHeight,
|
|
0,
|
|
0,
|
|
pbmi->bmiHeader.biWidth,
|
|
pbmi->bmiHeader.biHeight,
|
|
pPixels,
|
|
pbmi,
|
|
DIB_RGB_COLORS,
|
|
SRCCOPY
|
|
);
|
|
|
|
SelectObject(hdcm1, hbmDef);
|
|
|
|
//
|
|
// Cache ?
|
|
//
|
|
|
|
if (bCacheThumb) {
|
|
memcpy(pTmbFile, pThumb, bmiDIB.bmiHeader.biSizeImage);
|
|
}
|
|
|
|
//
|
|
// Alloca memory for thumbnail pixels
|
|
//
|
|
pTmbPixels = (PBYTE)ALLOC(bmiDIB.bmiHeader.biSizeImage);
|
|
if (! pTmbPixels) {
|
|
return(E_OUTOFMEMORY);
|
|
}
|
|
|
|
//
|
|
// Write out data
|
|
//
|
|
|
|
memcpy(pTmbPixels, pThumb, bmiDIB.bmiHeader.biSizeImage);
|
|
*pThumbnail = pTmbPixels;
|
|
*pThumbSize = bmiDIB.bmiHeader.biSizeImage;
|
|
|
|
return(S_OK);
|
|
|
|
} // End of __try { ... } block
|
|
|
|
__finally {
|
|
|
|
if (pTmbFile) {
|
|
UnmapViewOfFile(pTmbFile);
|
|
}
|
|
if (hTmbMap) {
|
|
CloseHandle(hTmbMap);
|
|
}
|
|
if (hTmbFile != INVALID_HANDLE_VALUE) {
|
|
CloseHandle(hTmbFile);
|
|
}
|
|
|
|
if (pFile) {
|
|
UnmapViewOfFile(pFile);
|
|
}
|
|
if (hMap) {
|
|
CloseHandle(hMap);
|
|
}
|
|
if (hFile != INVALID_HANDLE_VALUE) {
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
if (hbmThumb) {
|
|
DeleteObject(hbmThumb);
|
|
}
|
|
|
|
if (hdcm1) {
|
|
DeleteDC(hdcm1);
|
|
}
|
|
if (hdc) {
|
|
ReleaseDC(NULL, hdc);
|
|
}
|
|
|
|
}
|
|
|
|
return(E_FAIL);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* CamDeletePicture
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
*
|
|
* 6/3/1998 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT
|
|
CamDeletePicture(
|
|
MEMCAM_IMAGE_CONTEXT *pMCamContext)
|
|
{
|
|
return(E_NOTIMPL);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* CamTakePicture
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
*
|
|
* 6/3/1998 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CamTakePicture(
|
|
MEMCAM_IMAGE_CONTEXT *pMCamContext ,
|
|
ULONG *pHandle)
|
|
{
|
|
return (E_NOTIMPL);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* VertivalFlip
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 11/18/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
VerticalFlip(
|
|
PBYTE pImageTop,
|
|
LONG iHeight,
|
|
LONG iWidthInBytes)
|
|
{
|
|
//
|
|
// try to allocat a temp scan line buffer
|
|
//
|
|
|
|
PBYTE pBuffer = (PBYTE)LocalAlloc(LPTR,iWidthInBytes);
|
|
|
|
if (pBuffer != NULL) {
|
|
|
|
LONG index;
|
|
PBYTE pImageBottom;
|
|
|
|
pImageBottom = pImageTop + (iHeight-1) * iWidthInBytes;
|
|
|
|
for (index = 0;index < (iHeight/2);index++) {
|
|
memcpy(pBuffer,pImageTop,iWidthInBytes);
|
|
memcpy(pImageTop,pImageBottom,iWidthInBytes);
|
|
memcpy(pImageBottom,pBuffer,iWidthInBytes);
|
|
|
|
pImageTop += iWidthInBytes;
|
|
pImageBottom -= iWidthInBytes;
|
|
}
|
|
|
|
LocalFree(pBuffer);
|
|
}
|
|
}
|
|
|