windows-nt/Source/XPSP1/NT/printscan/wia/drivers/video/usd/transfer.cpp
2020-09-26 16:20:57 +08:00

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;
}