📄 imagefilter.cpp
字号:
if (SUCCEEDED(hr))
{
m_pWiaItem = pWiaItem;
m_pWiaItem->AddRef();
m_pAppWiaTransferCallback = pWiaTransferCallback;
m_pAppWiaTransferCallback->AddRef();
}
return hr;
}
/*****************************************************************************
*
* @func STDMETHODIMP | CImageFilter::SetNewCallback | Sets new callback for image processing filter to use
*
* @parm IWiaTransferCallback | pWiaTransferCallback |
* The new application callback which the filter should use.
*
* @comm
* Since an application can change the callback to use in the IWiaPreview::UpdatePreview call the image
* processing filter must "get notified" of this.
* Note, the image processing filter is always required to release its current callback even if it is
* passed NULL for the callback.
*
* @rvalue S_OK |
* The function succeeded.
* @rvalue E_XXX |
* The function failed
*
*****************************************************************************/
STDMETHODIMP
CImageFilter::SetNewCallback(
__in_opt __callback IN IWiaTransferCallback *pWiaTransferCallback)
{
if (m_pAppWiaTransferCallback)
{
m_pAppWiaTransferCallback->Release();
m_pAppWiaTransferCallback = NULL;
}
if (pWiaTransferCallback)
{
m_pAppWiaTransferCallback = pWiaTransferCallback;
m_pAppWiaTransferCallback->AddRef();
}
return S_OK;
}
/*****************************************************************************
*
* @func STDMETHODIMP | CImageFilter::FilterPreviewImage | FilterPreviewImage implementation
*
* @parm IWiaItem2 | pWiaChildItem |
* pWiaChildItem2 is the item which the image process is to process.
* This item must be a child item of the item, m_pWiaItem, that was passed into InitializeFilter.
*
* @parm RECT | InputImageExtents |
* The coordinates (on the flatbed scanner) of the image that the preview component caches internally,
* which is also the image that is passed into the pInputStream parameter.
* We need this parameter since it is possible that the cached image (pInputStream) was not captured
* with XPOS=YPOS=0.
*
* @parm IStream | pInputStream |
* Unfiltered image that is stored by WIA Preview Component.
*
* @comm
* FilterPreviewImage is called by the preview component, when an application calls UpdatePreview.
* We simply read all the properties from pWiaChildItem that are required for us to do the filtering
* and then retrieve the application stream. The actual filtering is then performed in DoFiltering.
*
* @rvalue S_OK |
* The function succeeded.
* @rvalue E_XXX |
* The function failed
*
*****************************************************************************/
STDMETHODIMP
CImageFilter::FilterPreviewImage(
IN LONG lFlags,
__in IN IWiaItem2 *pWiaChildItem,
IN RECT InputImageExtents,
__in IN IStream *pInputStream)
{
IStream *pAppStream = NULL;
BSTR bstrItemName = NULL;
BSTR bstrFullItemName = NULL;
GUID guidItemCategory = {0};
LONG xpos = 0, ypos = 0, width = 0, height = 0;
LONG lBrightness = 0;
LONG lContrast = 0;
LONG lDeskewX = 0;
LONG lDeskewY = 0;
LONG lRotation = PORTRAIT;
HRESULT hr;
//
// Parameter validation
//
hr = (pWiaChildItem && pInputStream) ? S_OK : E_INVALIDARG;
if (SUCCEEDED(hr))
{
//
// Check whether the image extents are correct.
// Error if the right or bottom coordinate is zero.
// Or Left >= Right or Top >= Bottom.
//
if ((0 == InputImageExtents.right) ||
(0 == InputImageExtents.bottom) ||
(InputImageExtents.left >= InputImageExtents.right) ||
(InputImageExtents.top >= InputImageExtents.bottom))
{
hr = E_INVALIDARG;
}
}
if (SUCCEEDED(hr))
{
hr = m_pAppWiaTransferCallback ? S_OK : E_UNEXPECTED;
}
//
// Read all properties we need
//
if (SUCCEEDED(hr))
{
CWiaItem *pWiaItemWrapper = new CWiaItem();
hr = pWiaItemWrapper ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr))
{
hr = pWiaItemWrapper->SetIWiaItem(pWiaChildItem);
}
if (SUCCEEDED(hr))
{
hr = pWiaItemWrapper->ReadRequiredPropertyGUID(WIA_IPA_ITEM_CATEGORY, &guidItemCategory);
if (SUCCEEDED(hr) && ((guidItemCategory == WIA_CATEGORY_FINISHED_FILE) || (WIA_CATEGORY_FOLDER == guidItemCategory)))
{
//
// We should never get here for storage items!
//
hr = E_INVALIDARG;
}
}
//
// Error if the following is not satisfied:
// WIA_IPS_MIN_HORIZONTAL_SIZE <= right - left <= WIA_IPS_MAX_HORIZONTAL_SIZE
// WIA_IPS_MIN_VERTICAL_SIZE <= bottom - top <= WIA_IPS_MAX_VERTICAL_SIZE
//
if (SUCCEEDED(hr))
{
LONG lHorMin = 0, lHorMax = 0, lHorExtent = InputImageExtents.right - InputImageExtents.left;
LONG lVerMin = 0, lVerMax = 0, lVerExtent = InputImageExtents.bottom - InputImageExtents.top;
if (SUCCEEDED(hr))
{
hr = pWiaItemWrapper->ReadRequiredPropertyLong(WIA_IPS_MIN_HORIZONTAL_SIZE, &lHorMin);
}
if (SUCCEEDED(hr))
{
hr = pWiaItemWrapper->ReadRequiredPropertyLong(WIA_IPS_MAX_HORIZONTAL_SIZE, &lHorMax);
}
if (SUCCEEDED(hr))
{
hr = pWiaItemWrapper->ReadRequiredPropertyLong(WIA_IPS_MIN_VERTICAL_SIZE, &lVerMin);
}
if (SUCCEEDED(hr))
{
hr = pWiaItemWrapper->ReadRequiredPropertyLong(WIA_IPS_MAX_VERTICAL_SIZE, &lVerMax);
}
if (SUCCEEDED(hr))
{
if ((lHorExtent < lHorMin) || (lHorExtent > lHorMax) ||
(lVerExtent < lVerMin) || (lVerExtent > lVerMax))
{
hr = E_INVALIDARG;
}
}
}
if(SUCCEEDED(hr))
{
GUID guidItemFormat = {0};
hr = pWiaItemWrapper->ReadRequiredPropertyGUID(WIA_IPA_FORMAT, &guidItemFormat);
if((SUCCEEDED(hr)) && (IsEqualGUID(guidItemFormat, WiaImgFmt_RAW)))
{
//
// Raw data must be passed "as is" to the application, do not attempt to modify in any way:
//
hr = E_INVALIDARG;
}
}
if (SUCCEEDED(hr))
{
hr = pWiaItemWrapper->ReadRequiredPropertyLong(WIA_IPS_XPOS, &xpos);
}
if (SUCCEEDED(hr))
{
hr = pWiaItemWrapper->ReadRequiredPropertyLong(WIA_IPS_YPOS, &ypos);
}
if (SUCCEEDED(hr))
{
hr = pWiaItemWrapper->ReadRequiredPropertyLong(WIA_IPS_XEXTENT, &width);
}
if (SUCCEEDED(hr))
{
hr = pWiaItemWrapper->ReadRequiredPropertyLong(WIA_IPS_YEXTENT, &height);
}
if (SUCCEEDED(hr))
{
hr = pWiaItemWrapper->ReadRequiredPropertyBSTR(WIA_IPA_ITEM_NAME, &bstrItemName);
}
if (SUCCEEDED(hr))
{
hr = pWiaItemWrapper->ReadRequiredPropertyBSTR(WIA_IPA_FULL_ITEM_NAME, &bstrFullItemName);
}
if (SUCCEEDED(hr))
{
hr = pWiaItemWrapper->ReadRequiredPropertyLong(WIA_IPS_BRIGHTNESS, &lBrightness);
}
if (SUCCEEDED(hr))
{
hr = pWiaItemWrapper->ReadRequiredPropertyLong(WIA_IPS_CONTRAST, &lContrast);
}
if (SUCCEEDED(hr))
{
hr = pWiaItemWrapper->ReadRequiredPropertyLong(WIA_IPS_ROTATION, &lRotation);
}
if (SUCCEEDED(hr))
{
hr = pWiaItemWrapper->ReadRequiredPropertyLong(WIA_IPS_DESKEW_X, &lDeskewX);
}
if (SUCCEEDED(hr))
{
hr = pWiaItemWrapper->ReadRequiredPropertyLong(WIA_IPS_DESKEW_Y, &lDeskewY);
}
if (pWiaItemWrapper)
{
delete pWiaItemWrapper;
}
}
//
// If the upper left corner of the passed image does not correspond to (0,0)
// on the flatbed we have to adjust xpos and ypos accordingly in order for us
// to "cut out" the correct region represented by pWiaChildItem
//
if (SUCCEEDED(hr))
{
xpos = xpos - InputImageExtents.left;
ypos = ypos - InputImageExtents.top;
}
//
// Now get the application stream and write to it
//
if (SUCCEEDED(hr))
{
hr = m_pAppWiaTransferCallback->GetNextStream(0, bstrItemName, bstrFullItemName, &pAppStream);
}
//
// Do "actual" filtering
//
ULONG64 ulBytesWrittenToOutputStream = 0;
if (SUCCEEDED(hr))
{
hr = DoFiltering(lBrightness,
lContrast,
lRotation,
lDeskewX,
lDeskewY,
pInputStream,
pAppStream,
&ulBytesWrittenToOutputStream,
xpos,
ypos,
width,
height
);
}
if (pAppStream)
{
pAppStream->Release();
}
return hr;
}
/*****************************************************************************
*
* @func STDMETHODIMP | CImageFilter::ApplyProperties | Apply properties after filtering.
*
* @parm IWiaPropertyStorage | pWiaPropertyStorage |
* Pointer to property storage that the image processing filter can write properties to.
*
* @comm
* ApplyProperties is called by the WIA service after the image processing filter has processed
* the raw data. This method allows the image processing filter to write data back to the driver and device.
* This may be necessary for filters that implement things such as auto-exposure.
* Note, an image processing filter should only use the WriteMultiple method to write properties into
* the provided storage.
*
* @rvalue S_OK |
* The function succeeded.
* @rvalue E_XXX |
* The function failed
*
*****************************************************************************/
STDMETHODIMP
CImageFilter::ApplyProperties(
__inout IN IWiaPropertyStorage *pWiaPropertyStorage)
{
HRESULT hr = S_OK;
hr = pWiaPropertyStorage ? S_OK : E_INVALIDARG;
//
// This filter only writes the MY_TEST_FILTER_PROP property for
// illustrational purposes.
// In general if a filter does not need to write any properties it
// should just return S_OK.
//
if (SUCCEEDED(hr))
{
PROPSPEC PropSpec[1] = {0};
PROPVARIANT PropVariant[1] = {0};
PropVariantInit(PropVariant);
PropSpec[0].ulKind = PRSPEC_PROPID;
PropSpec[0].propid = MY_TEST_FILTER_PROP;
PropVariant[0].vt = VT_I4;
PropVariant[0].lVal = 1;
//
// Set the properties
//
hr = pWiaPropertyStorage->WriteMultiple( 1, PropSpec, PropVariant, WIA_IPA_FIRST );
}
return hr;
}
/*****************************************************************************
*
* @func STDMETHODIMP | CImageFilter::TransferCallback | TransferCallback implementation
*
* @parm LONG | lFlags |
* Flags
*
* @parm WiaTransferParams | pWiaTransferParams |
* Contains transfer status
*
* @comm
* TransferCallback delegates to the application's callback. It changes the
* number of bytes written since we always cache all the data before writing to
* the application's stream. We do however not change the percentage since this
* represents percentage of total transfer time (a "real" implementation probably
* would take the filtering into account here).
* We do not write the data to the application's stream until when we receive
* a WIA_TRANSFER_MSG_END_OF_STREAM message.
*
* @rvalue S_OK |
* The function succeeded.
* @rvalue E_XXX |
* The function failed
*
*****************************************************************************/
STDMETHODIMP
CImageFilter::TransferCallback(
IN LONG lFlags,
__in IN WiaTransferParams *pWiaTransferParams)
{
HRESULT hr = S_OK;
if (!m_pAppWiaTransferCallback)
{
hr = E_UNEXPECTED;
}
if ((SUCCEEDED(hr)) && (!pWiaTransferParams))
{
hr = E_INVALIDARG;
}
if (SUCCEEDED(hr))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -