596 lines
17 KiB
C++
596 lines
17 KiB
C++
|
/*****************************************************************************
|
||
|
*
|
||
|
* (C) COPYRIGHT MICROSOFT CORPORATION, 1999-2000
|
||
|
*
|
||
|
* TITLE: Transfer.cpp
|
||
|
*
|
||
|
* VERSION: 1.0
|
||
|
*
|
||
|
* AUTHOR: RickTu
|
||
|
*
|
||
|
* DATE: 9/10/99 RickTu
|
||
|
* 2000/11/09 OrenR
|
||
|
*
|
||
|
* DESCRIPTION: This was originally in camera.cpp but was broken out for
|
||
|
* clarity. The functions in this file are responsible for
|
||
|
* transfering the image to the requesting application.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
#include <precomp.h>
|
||
|
#pragma hdrstop
|
||
|
#include <gphelper.h>
|
||
|
|
||
|
using namespace Gdiplus;
|
||
|
|
||
|
/*****************************************************************************
|
||
|
|
||
|
CVideoStiUsd::DoBandedTransfer
|
||
|
|
||
|
hand back the given bits in the specified chunk sizes
|
||
|
|
||
|
*****************************************************************************/
|
||
|
|
||
|
STDMETHODIMP
|
||
|
CVideoStiUsd::DoBandedTransfer(MINIDRV_TRANSFER_CONTEXT *pTransCtx,
|
||
|
PBYTE pSrc,
|
||
|
LONG lBytesToTransfer)
|
||
|
{
|
||
|
HRESULT hr = E_FAIL;
|
||
|
|
||
|
DBG_FN("CVideoStiUsd::DoBandedTransfer");
|
||
|
|
||
|
//
|
||
|
// Check for bad args
|
||
|
//
|
||
|
|
||
|
if ((pTransCtx == NULL) ||
|
||
|
(pSrc == NULL) ||
|
||
|
(lBytesToTransfer == 0))
|
||
|
{
|
||
|
hr = E_INVALIDARG;
|
||
|
CHECK_S_OK2(hr, ("CVideoStiUsd::DoBandedTransfer, received "
|
||
|
"NULL param"));
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// callback loop
|
||
|
//
|
||
|
|
||
|
LONG lTransferSize = 0;
|
||
|
LONG lPercentComplete = 0;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
|
||
|
PBYTE pDst = pTransCtx->pTransferBuffer;
|
||
|
|
||
|
//
|
||
|
// transfer up to entire buffer size
|
||
|
//
|
||
|
|
||
|
lTransferSize = lBytesToTransfer;
|
||
|
|
||
|
if (lBytesToTransfer > pTransCtx->lBufferSize)
|
||
|
{
|
||
|
lTransferSize = pTransCtx->lBufferSize;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// copy data
|
||
|
//
|
||
|
|
||
|
DBG_TRC(("memcpy(src=0x%x,dst=0x%x,size=0x%x)",
|
||
|
pDst,
|
||
|
pSrc,
|
||
|
lTransferSize));
|
||
|
|
||
|
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);
|
||
|
|
||
|
CHECK_S_OK2(hr,("pTransCtx->pWiaMiniDrvCallback->MiniDrvCallback"));
|
||
|
|
||
|
DBG_TRC(("%d percent complete",lPercentComplete));
|
||
|
|
||
|
//
|
||
|
// inc pointers (redundant pointers here)
|
||
|
//
|
||
|
|
||
|
pSrc += lTransferSize;
|
||
|
pTransCtx->cbOffset += lTransferSize;
|
||
|
lBytesToTransfer -= lTransferSize;
|
||
|
|
||
|
if (hr != S_OK)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} while (lBytesToTransfer > 0);
|
||
|
|
||
|
|
||
|
CHECK_S_OK(hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
|
||
|
CVideoStiUsd::DoTransfer
|
||
|
|
||
|
Transfers the given bits all at once
|
||
|
|
||
|
*****************************************************************************/
|
||
|
|
||
|
STDMETHODIMP
|
||
|
CVideoStiUsd::DoTransfer(MINIDRV_TRANSFER_CONTEXT *pTransCtx,
|
||
|
PBYTE pSrc,
|
||
|
LONG lBytesToTransfer)
|
||
|
{
|
||
|
|
||
|
HRESULT hr = E_FAIL;
|
||
|
|
||
|
DBG_FN("CVideoStiUsd::DoTransfer");
|
||
|
|
||
|
//
|
||
|
// Check for bad args
|
||
|
//
|
||
|
|
||
|
if ((pTransCtx == NULL) ||
|
||
|
(pSrc == NULL) ||
|
||
|
(lBytesToTransfer == 0))
|
||
|
{
|
||
|
hr = E_INVALIDARG;
|
||
|
CHECK_S_OK2(hr, ("CVideoStiUsd::DoTransfer, received "
|
||
|
"NULL param"));
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
if (lBytesToTransfer > (LONG)(pTransCtx->lBufferSize - pTransCtx->cbOffset))
|
||
|
{
|
||
|
DBG_TRC(("lBytesToTransfer = %d, (lBufferSize = %d) - "
|
||
|
"(cbOffset = %d) is %d",
|
||
|
lBytesToTransfer,
|
||
|
pTransCtx->lBufferSize,
|
||
|
pTransCtx->cbOffset,
|
||
|
(pTransCtx->lBufferSize - pTransCtx->cbOffset)));
|
||
|
|
||
|
DBG_ERR(("lBytesToTransfer is bigger than supplied buffer!"));
|
||
|
|
||
|
hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// Show 20% completion
|
||
|
//
|
||
|
|
||
|
if (pTransCtx->pIWiaMiniDrvCallBack)
|
||
|
{
|
||
|
pTransCtx->pIWiaMiniDrvCallBack->MiniDrvCallback(
|
||
|
IT_MSG_STATUS,
|
||
|
IT_STATUS_TRANSFER_FROM_DEVICE,
|
||
|
(LONG)20, // Percentage Complete,
|
||
|
0,
|
||
|
0,
|
||
|
pTransCtx,
|
||
|
0);
|
||
|
}
|
||
|
|
||
|
|
||
|
PBYTE pDst = pTransCtx->pTransferBuffer;
|
||
|
pDst += pTransCtx->cbOffset;
|
||
|
|
||
|
//
|
||
|
// copy the bits
|
||
|
//
|
||
|
|
||
|
memcpy(pDst, pSrc, lBytesToTransfer);
|
||
|
|
||
|
hr = S_OK;
|
||
|
|
||
|
// Since we are copying all the bits in one shot, any status
|
||
|
// callback is just a simulation anyway. So lets give enough
|
||
|
// increments to bring the progress dialog up to 100 %.
|
||
|
|
||
|
if (pTransCtx->pIWiaMiniDrvCallBack)
|
||
|
{
|
||
|
|
||
|
// Show 60% completion
|
||
|
pTransCtx->pIWiaMiniDrvCallBack->MiniDrvCallback(
|
||
|
IT_MSG_STATUS,
|
||
|
IT_STATUS_TRANSFER_FROM_DEVICE,
|
||
|
(LONG)60, // Percentage Complete,
|
||
|
0,
|
||
|
0,
|
||
|
pTransCtx,
|
||
|
0);
|
||
|
|
||
|
// Show 90% completion
|
||
|
pTransCtx->pIWiaMiniDrvCallBack->MiniDrvCallback(
|
||
|
IT_MSG_STATUS,
|
||
|
IT_STATUS_TRANSFER_FROM_DEVICE,
|
||
|
(LONG)90, // Percentage Complete,
|
||
|
0,
|
||
|
0,
|
||
|
pTransCtx,
|
||
|
0);
|
||
|
|
||
|
// Show 99% completion
|
||
|
pTransCtx->pIWiaMiniDrvCallBack->MiniDrvCallback(
|
||
|
IT_MSG_STATUS,
|
||
|
IT_STATUS_TRANSFER_FROM_DEVICE,
|
||
|
(LONG)99, // Percentage Complete,
|
||
|
0,
|
||
|
0,
|
||
|
pTransCtx,
|
||
|
0);
|
||
|
|
||
|
|
||
|
// Show 100% completion
|
||
|
pTransCtx->pIWiaMiniDrvCallBack->MiniDrvCallback(
|
||
|
IT_MSG_STATUS,
|
||
|
IT_STATUS_TRANSFER_FROM_DEVICE,
|
||
|
(LONG)100, // Percentage Complete,
|
||
|
0,
|
||
|
0,
|
||
|
pTransCtx,
|
||
|
0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CHECK_S_OK(hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
|
||
|
CVideoUsd::StreamJPEGBits
|
||
|
|
||
|
Transfers the JPEG bits of a file
|
||
|
|
||
|
*****************************************************************************/
|
||
|
|
||
|
STDMETHODIMP
|
||
|
CVideoStiUsd::StreamJPEGBits(STILLCAM_IMAGE_CONTEXT *pContext,
|
||
|
MINIDRV_TRANSFER_CONTEXT *pTransCtx,
|
||
|
BOOL bBanded)
|
||
|
{
|
||
|
HRESULT hr = E_FAIL;
|
||
|
PBYTE pSrc = NULL;
|
||
|
|
||
|
DBG_FN("CVideoStiUsd::StreamJPEGBits");
|
||
|
|
||
|
//
|
||
|
// Check for invalid args
|
||
|
//
|
||
|
|
||
|
if ((pContext == NULL) ||
|
||
|
(pContext->pImage == NULL) ||
|
||
|
(pTransCtx == NULL))
|
||
|
{
|
||
|
hr = E_INVALIDARG;
|
||
|
CHECK_S_OK2(hr, ("CVideoStiUsd::StreamJPEGBits received NULL "
|
||
|
"params"));
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// try to open mapping to disk file -- we will use this if it is a JPEG
|
||
|
// file because we just want to stream the bits back.
|
||
|
//
|
||
|
|
||
|
CMappedView cmvImage(pContext->pImage->ActualImagePath(),
|
||
|
0,
|
||
|
OPEN_EXISTING);
|
||
|
|
||
|
pSrc = cmvImage.Bits();
|
||
|
|
||
|
if (pSrc)
|
||
|
{
|
||
|
//
|
||
|
// We only handle 2GB of data (that's all WIA handles as well)
|
||
|
//
|
||
|
|
||
|
LARGE_INTEGER liSize = cmvImage.FileSize();
|
||
|
LONG lBytes = liSize.LowPart;
|
||
|
|
||
|
if (bBanded)
|
||
|
{
|
||
|
hr = DoBandedTransfer(pTransCtx, pSrc, lBytes);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = DoTransfer(pTransCtx, pSrc, lBytes);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CHECK_S_OK(hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
|
||
|
CVideoStiUsd::StreamBMPBits
|
||
|
|
||
|
Transfers the BMP bits of a file
|
||
|
|
||
|
*****************************************************************************/
|
||
|
|
||
|
STDMETHODIMP
|
||
|
CVideoStiUsd::StreamBMPBits(STILLCAM_IMAGE_CONTEXT *pContext,
|
||
|
MINIDRV_TRANSFER_CONTEXT *pTransCtx,
|
||
|
BOOL bBanded)
|
||
|
{
|
||
|
DBG_FN("CVideoStiUsd::StreamBMPBits");
|
||
|
|
||
|
//
|
||
|
// Assume failure
|
||
|
//
|
||
|
HRESULT hr = E_FAIL;
|
||
|
|
||
|
if ((pContext == NULL) ||
|
||
|
(pContext->pImage == NULL) ||
|
||
|
(pTransCtx == NULL))
|
||
|
{
|
||
|
hr = E_INVALIDARG;
|
||
|
CHECK_S_OK2(hr, ("CVideoStiUsd::StreamBMPBits received NULL params"));
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Open the file
|
||
|
//
|
||
|
Bitmap SourceBitmap(CSimpleStringConvert::WideString(
|
||
|
CSimpleString(
|
||
|
pContext->pImage->ActualImagePath())));
|
||
|
|
||
|
if (Ok == SourceBitmap.GetLastStatus())
|
||
|
{
|
||
|
//
|
||
|
// Get the image dimensions
|
||
|
//
|
||
|
UINT nSourceWidth = SourceBitmap.GetWidth();
|
||
|
UINT nSourceHeight = SourceBitmap.GetHeight();
|
||
|
if (nSourceWidth && nSourceHeight)
|
||
|
{
|
||
|
//
|
||
|
// Create the target bitmap
|
||
|
//
|
||
|
Bitmap TargetBitmap( nSourceWidth, nSourceWidth );
|
||
|
if (Ok == TargetBitmap.GetLastStatus())
|
||
|
{
|
||
|
//
|
||
|
// Assume failure
|
||
|
//
|
||
|
bool bDrawSucceeded = false;
|
||
|
|
||
|
//
|
||
|
// Create a graphics object
|
||
|
//
|
||
|
Graphics *pGraphics = Graphics::FromImage(&TargetBitmap);
|
||
|
if (pGraphics)
|
||
|
{
|
||
|
//
|
||
|
// Make sure it is valid
|
||
|
//
|
||
|
if (pGraphics->GetLastStatus() == Ok)
|
||
|
{
|
||
|
//
|
||
|
// Flip the image, if they asked for a BMP
|
||
|
//
|
||
|
if (pTransCtx->guidFormatID == WiaImgFmt_BMP)
|
||
|
{
|
||
|
//
|
||
|
// Set up the parallelogram to flip the image
|
||
|
//
|
||
|
Point SourcePoints[3];
|
||
|
SourcePoints[0].X = 0;
|
||
|
SourcePoints[0].Y = nSourceHeight;
|
||
|
SourcePoints[1].X = nSourceWidth;
|
||
|
SourcePoints[1].Y = nSourceHeight;
|
||
|
SourcePoints[2].X = 0;
|
||
|
SourcePoints[2].Y = 0;
|
||
|
|
||
|
//
|
||
|
// Draw the image, flipped
|
||
|
//
|
||
|
if (pGraphics->DrawImage(&SourceBitmap,
|
||
|
SourcePoints, 3) == Ok)
|
||
|
{
|
||
|
//
|
||
|
// We've got a good target image
|
||
|
//
|
||
|
bDrawSucceeded = true;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Draw the image normally
|
||
|
//
|
||
|
if (pGraphics->DrawImage(&SourceBitmap,0,0) == Ok)
|
||
|
{
|
||
|
//
|
||
|
// We've got a good target image
|
||
|
//
|
||
|
bDrawSucceeded = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Clean up our dynamically allocated graphics
|
||
|
//
|
||
|
delete pGraphics;
|
||
|
}
|
||
|
|
||
|
if (bDrawSucceeded)
|
||
|
{
|
||
|
Rect rcTarget( 0, 0, nSourceWidth, nSourceHeight );
|
||
|
Gdiplus::BitmapData BitmapData;
|
||
|
|
||
|
//
|
||
|
// Get to the bits of the image
|
||
|
//
|
||
|
if (Ok == TargetBitmap.LockBits(&rcTarget,
|
||
|
ImageLockModeRead,
|
||
|
PixelFormat24bppRGB,
|
||
|
&BitmapData))
|
||
|
{
|
||
|
if (bBanded)
|
||
|
{
|
||
|
//
|
||
|
// This will be our return value
|
||
|
//
|
||
|
hr = DoBandedTransfer(
|
||
|
pTransCtx,
|
||
|
(PBYTE)BitmapData.Scan0,
|
||
|
(BitmapData.Stride * BitmapData.Height));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// This will be our return value
|
||
|
//
|
||
|
hr = DoTransfer(
|
||
|
pTransCtx,
|
||
|
(PBYTE)BitmapData.Scan0,
|
||
|
(BitmapData.Stride * BitmapData.Height));
|
||
|
}
|
||
|
|
||
|
TargetBitmap.UnlockBits( &BitmapData );
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CHECK_S_OK(hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
|
||
|
CVideoUsd::LoadImageCB
|
||
|
|
||
|
Loads an image one piece at a time.
|
||
|
|
||
|
*****************************************************************************/
|
||
|
|
||
|
STDMETHODIMP
|
||
|
CVideoStiUsd::LoadImageCB(STILLCAM_IMAGE_CONTEXT *pContext,
|
||
|
MINIDRV_TRANSFER_CONTEXT *pTransCtx,
|
||
|
PLONG plDevErrVal)
|
||
|
{
|
||
|
HRESULT hr = E_FAIL;
|
||
|
|
||
|
DBG_FN("CVideoStiUsd::LoadImageCB");
|
||
|
|
||
|
//
|
||
|
// verify parameters
|
||
|
//
|
||
|
|
||
|
if ((pContext == NULL) ||
|
||
|
(pContext->pImage == NULL) ||
|
||
|
(pTransCtx == NULL))
|
||
|
{
|
||
|
hr = E_INVALIDARG;
|
||
|
CHECK_S_OK2(hr, ("CVideoStiUsd::LoadImageCB received NULL params"));
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
if (pTransCtx->guidFormatID == WiaImgFmt_JPEG)
|
||
|
{
|
||
|
hr = StreamJPEGBits( pContext, pTransCtx, TRUE );
|
||
|
}
|
||
|
else if (pTransCtx->guidFormatID == WiaImgFmt_BMP)
|
||
|
{
|
||
|
hr = StreamBMPBits( pContext, pTransCtx, TRUE );
|
||
|
}
|
||
|
else if (pTransCtx->guidFormatID == WiaImgFmt_MEMORYBMP)
|
||
|
{
|
||
|
hr = StreamBMPBits( pContext, pTransCtx, TRUE );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DBG_ERR(("Asking for unsupported format"));
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
CHECK_S_OK(hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
|
||
|
CVideoStiUsd::LoadImage
|
||
|
|
||
|
Loads an image in a single transfer
|
||
|
|
||
|
*****************************************************************************/
|
||
|
|
||
|
STDMETHODIMP
|
||
|
CVideoStiUsd::LoadImage(STILLCAM_IMAGE_CONTEXT *pContext,
|
||
|
MINIDRV_TRANSFER_CONTEXT *pTransCtx,
|
||
|
PLONG plDevErrVal)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
DBG_FN("CVideoStiUsd::LoadImage");
|
||
|
|
||
|
//
|
||
|
// verify some params
|
||
|
//
|
||
|
|
||
|
if ((pContext == NULL) ||
|
||
|
(pTransCtx == NULL))
|
||
|
{
|
||
|
hr = E_INVALIDARG;
|
||
|
CHECK_S_OK2(hr, ("CVideoStiUsd::LoadImage received NULL params"));
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
if ((pTransCtx->guidFormatID == WiaImgFmt_BMP))
|
||
|
{
|
||
|
hr = StreamBMPBits( pContext, pTransCtx, FALSE );
|
||
|
}
|
||
|
else if (pTransCtx->guidFormatID == WiaImgFmt_JPEG)
|
||
|
{
|
||
|
hr = StreamJPEGBits( pContext, pTransCtx, FALSE );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DBG_ERR(("Unsupported format"));
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
CHECK_S_OK(hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|