/***************************************************************************** * * (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 #pragma hdrstop #include 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; }