1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 基于WIA的QT扫描仪程序

基于WIA的QT扫描仪程序

时间:2023-08-22 19:43:05

相关推荐

基于WIA的QT扫描仪程序

基于WIA的扫描仪程序,QT编写的,调用WIA api获取扫描仪属性,控制扫描仪,WIA提供了自带界面的方法,因为要嵌入自己的程序,所以我没有使用WIA自带的界面,Demo在Github上面,Github自取。详细资料请看官方文档。

目录

简介创建WIA设备管理器枚举系统设备读取设备属性创建设备传输图像数据

1.简介

Windows图像采集(WIA)是Windows操作系统家族中的静止图像采集平台,从Windows Millennium Edition(Windows Me)和Windows XP开始。WIA平台使成像/图形应用程序可以与成像硬件进行交互,并标准化不同应用程序和扫描仪之间的交互。这允许那些不同的应用程序与这些不同的扫描仪进行对话并交互,而无需应用程序编写器和扫描仪制造商针对每种应用程序-设备组合自定义其应用程序或驱动程序。

Windows为WIA驱动程序运行认证过程,因此,可以确保WIA应用程序与所有基于WIA的扫描仪基本兼容。WIA驱动程序已加载到WIA服务进程中,从而提供了更稳定的驱动程序环境。可以通过WIA子系统支持的推送事件从扫描仪扫描按钮启动应用程序。WIA包括所有驱动程序都可以利用的默认分段过滤器;这样,应用程序不必为进行多区域扫描而编写代码,而无需将诸如散布在平板扫描仪上的大量照片分离出来的目的。

2.创建WIA设备管理器

使用Windows Image Acquisition(WIA)服务的第一步是获取IWiaDevMgr接口指针,CLSID_WiaDevMgr和IID_IWiaDevMgr是WIA常数表示类ID和的接口ID IWiaDevMgr分别。CoCreateInstance调用的dwClsContext参数的值必须为CLSCTX_LOCAL_SERVER。

IWiaDevMgr *pWiaDevMgr = nullptr;HRESULT hr = CoCreateInstance( CLSID_WiaDevMgr, NULL, CLSCTX_LOCAL_SERVER, IID_IWiaDevMgr, (void**)&pWiaDevMgr );

3.枚举系统设备

使用IWiaDevMgr :: EnumDeviceInfo方法来枚举系统上安装的Windows Image Acquisition(WIA)设备。此方法为设备的属性创建一个枚举对象,并返回一个指向该枚举对象支持的IEnumWIA_DEV_INFO接口的指针。然后,可以使用IEnumWIA_DEV_INFO接口的方法来获取系统上安装的每个设备的IWiaPropertyStorage接口指针。

IEnumWIA_DEV_INFO *pWiaEnumDevInfo = NULL;HRESULT hr = pWiaDevMgr->EnumDeviceInfo( WIA_DEVINFO_ENUM_ALL, &pWiaEnumDevInfo );if (SUCCEEDED(hr)){// Loop until you get an error or pWiaEnumDevInfo->Next returns// S_FALSE to signal the end of the list.while (S_OK == hr){// Get the next device's property storage interface pointerIWiaPropertyStorage *pWiaPropertyStorage = NULL;hr = pWiaEnumDevInfo->Next( 1, &pWiaPropertyStorage, NULL );//..................接下来是获取设备信息并且创建设备,见第4节与第5节}}

4.读取设备属性

IWiaPropertyStorage接口读取和写入设备属性,设备属性包括有关设备的信息,这些信息描述了设备的功能和设置。有关这些属性的列表,请参见设备属性。

PROPSPEC PropSpec[3] = {0};PROPVARIANT PropVar[3] = {0};//// How many properties are you querying for?//const ULONG c_nPropertyCount = sizeof(PropSpec)/sizeof(PropSpec[0]);//// Define which properties you want to read:// Device ID. This is what you would use to create// the device.//PropSpec[0].ulKind = PRSPEC_PROPID;PropSpec[0].propid = WIA_DIP_DEV_ID;//// Device Name//PropSpec[1].ulKind = PRSPEC_PROPID;PropSpec[1].propid = WIA_DIP_DEV_NAME;//// Device description//PropSpec[2].ulKind = PRSPEC_PROPID;PropSpec[2].propid = WIA_DIP_DEV_DESC;//// Ask for the property values//HRESULT hr = pWiaPropertyStorage->ReadMultiple( c_nPropertyCount, PropSpec, PropVar );if (SUCCEEDED(hr)){//// IWiaPropertyStorage::ReadMultiple will return S_FALSE if some// properties could not be read, so you have to check the return// types for each requested item.////// Check the return type for the device ID//if (VT_BSTR == PropVar[0].vt){//// Do something with the device ID//_tprintf( TEXT("WIA_DIP_DEV_ID: %ws\n"), PropVar[0].bstrVal );}//// Check the return type for the device name//if (VT_BSTR == PropVar[1].vt){//// Do something with the device name//_tprintf( TEXT("WIA_DIP_DEV_NAME: %ws\n"), PropVar[1].bstrVal );}//// Check the return type for the device description//if (VT_BSTR == PropVar[2].vt){//// Do something with the device description//_tprintf( TEXT("WIA_DIP_DEV_DESC: %ws\n"), PropVar[2].bstrVal );}//// Free the returned PROPVARIANTs//FreePropVariantArray( c_nPropertyCount, PropVar );}

应用程序设置PROPVARIANT数组(分别为PropSpec和PropVar)来保存属性信息。这些数组作为参数传递给IWiaPropertyStorage指针pIWiaPropStg的IPropertyStorage :: ReadMultiple方法的调用。PropSpec数组的每个元素都包含设备属性的类型和名称。返回时,PropVar的每个元素都包含由PropSpec数组的相应元素表示的设备属性的值。然后,该应用程序调用IWiaPropertyStorage指针pWiaPropertyStorage的IPropertyStorage :: ReadMultiple属性以检索属性信息。

5.创建设备

一旦应用程序具有给定设备的设备ID,它就可以调用IWiaDevMgr :: CreateDevice,该方法将创建代表成像设备以及图像扫描床和文件夹的IWiaItem。

//// Create the WIA Device//bstrDeviceID为上一节获取的设备IDIWiaItem *pWiaDevice=NULL;HRESULT hr = pWiaDevMgr->CreateDevice( bstrDeviceID, &pWiaDevice );

6. 传输图像数据

传输图像数据是最复杂的,需要创建一个类实现IWiaDataCallback接口,主要方法如下代码。

// The IWiaDataTransfer::idtGetBandedData method periodically // calls the IWiaDataCallback::BandedDataCallback method with// status messages. It sends the callback method a data header// message followed by one or more data messages to transfer // data. It concludes by sending a termination message.HRESULT _stdcall DeviceModel::BandedDataCallback(LONG lMessage,LONG lStatus,LONG lPercentComplete,LONG lOffset,LONG lLength,LONG lReserved,LONG lResLength,BYTE* pbData){UNREFERENCED_PARAMETER(lReserved);UNREFERENCED_PARAMETER(lResLength);switch (lMessage){case IT_MSG_DATA_HEADER:{//// The data header contains the image's final size.//PWIA_DATA_CALLBACK_HEADER pHeader = reinterpret_cast<PWIA_DATA_CALLBACK_HEADER>(pbData);if (pHeader && pHeader->lBufferSize){//// Allocate a block of memory to hold the image//m_pBuffer = reinterpret_cast<PBYTE>(LocalAlloc(LPTR, pHeader->lBufferSize));if (m_pBuffer){//// Save the buffer size.//m_nBufferLength = pHeader->lBufferSize;//// Initialize the bytes transferred count.//m_nBytesTransfered = 0;//// Save the file format.//m_guidFormat = pHeader->guidFormatID;}}}break;case IT_MSG_DATA:{//// Make sure a block of memory has been created.//if (NULL != m_pBuffer){//// Copy the new band.//CopyMemory(m_pBuffer + lOffset, pbData, lLength);//// Increment the byte count.//m_nBytesTransfered += lLength;}}break;case IT_MSG_STATUS:{//// Display transfer phase//if (lStatus & IT_STATUS_TRANSFER_FROM_DEVICE){//_tprintf(TEXT("Transfer from device\n"));}else if (lStatus & IT_STATUS_PROCESSING_DATA){//_tprintf(TEXT("Processing Data\n"));}else if (lStatus & IT_STATUS_TRANSFER_TO_CLIENT){//_tprintf(TEXT("Transfer to Client\n"));}//// Display percent complete////_tprintf(TEXT("lPercentComplete: %d\n"), lPercentComplete);}break;}return S_OK;}

HRESULT DeviceModel::EnumerateItems(IWiaItem* pWiaItem, vector<IWiaItem*>* pItems){//// Validate arguments//if (NULL == pWiaItem){return E_INVALIDARG;}//// Get the item type for this item.//LONG lItemType = 0;HRESULT hr = pWiaItem->GetItemType(&lItemType);if (SUCCEEDED(hr)){//// If it is a folder, or it has attachments, enumerate its children.//if (lItemType & WiaItemTypeFolder || lItemType & WiaItemTypeHasAttachments){//// Get the child item enumerator for this item.//IEnumWiaItem* pEnumWiaItem = NULL; //vista and laterhr = pWiaItem->EnumChildItems(&pEnumWiaItem);if (SUCCEEDED(hr)){//// Loop until you get an error or pEnumWiaItem->Next returns// S_FALSE to signal the end of the list.//while (S_OK == hr){//// Get the next child item.//IWiaItem* pChildWiaItem = NULL; //vista and lasterhr = pEnumWiaItem->Next(1, &pChildWiaItem, NULL);//// pEnumWiaItem->Next will return S_FALSE when the list is// exhausted, so check for S_OK before using the returned// value.//if (S_OK == hr){//// Recurse into this item.//hr = EnumerateItems(pChildWiaItem, pItems);//// Release this item.////pChildWiaItem->Release();//pChildWiaItem = NULL;}}//// If the result of the enumeration is S_FALSE (which// is normal), change it to S_OK.//if (S_FALSE == hr){hr = S_OK;}//// Release the enumerator.////pEnumWiaItem->Release();//pEnumWiaItem = NULL;}}else pItems->push_back(pWiaItem);}return hr;}

void DeviceModel::ScanningSlot(int source, int pictrueType, int brightness, int contrast, int dpi, int size){//CoInitialize(NULL);vector<IWiaItem*> imageWiaItems;m_pWiaItemRoot->AnalyzeItem(0);HRESULT hr = EnumerateItems(m_pWiaItemRoot, &imageWiaItems);if (hr == S_OK){for (int i = 0; i < imageWiaItems.size(); ++i){IWiaPropertyStorage* pGetWiaProperty = nullptr;hr = imageWiaItems[i]->QueryInterface(IID_IWiaPropertyStorage, (void**)&pGetWiaProperty);if (hr != S_OK) continue;PROPSPEC propSpec[9];PROPVARIANT propVar[9];propSpec[0].ulKind = PRSPEC_PROPID;propSpec[0].propid = WIA_IPA_TYMED;propSpec[1].ulKind = PRSPEC_PROPID;propSpec[1].propid = WIA_IPA_FORMAT;propSpec[2].ulKind = PRSPEC_PROPID;propSpec[2].propid = WIA_DPS_PREVIEW;//propSpec[3].ulKind = PRSPEC_PROPID;//propSpec[3].propid = WIA_DPS_DOCUMENT_HANDLING_SELECT;propSpec[3].ulKind = PRSPEC_PROPID;propSpec[3].propid = WIA_IPS_CUR_INTENT;propSpec[4].ulKind = PRSPEC_PROPID;propSpec[4].propid = WIA_IPS_BRIGHTNESS;propSpec[5].ulKind = PRSPEC_PROPID;propSpec[5].propid = WIA_IPS_CONTRAST;propSpec[6].ulKind = PRSPEC_PROPID;propSpec[6].propid = WIA_IPS_XRES;propSpec[7].ulKind = PRSPEC_PROPID;propSpec[7].propid = WIA_IPS_YRES;propSpec[8].ulKind = PRSPEC_PROPID;propSpec[8].propid = WIA_IPS_PAGE_SIZE;CLSID guidOutputFormat1 = WiaImgFmt_MEMORYBMP;propVar[0].vt = VT_I4;propVar[0].lVal = TYMED_CALLBACK;propVar[1].vt = VT_CLSID;propVar[1].puuid = &guidOutputFormat1;propVar[2].vt = VT_I4;propVar[2].lVal = 0;//propVar[3].vt = VT_I4;//if (source == 0) propVar[3].lVal = FLATBED;//else propVar[3].lVal = FEEDER;propVar[3].vt = VT_I4;if (pictrueType == 0) propVar[3].lVal = WIA_INTENT_IMAGE_TYPE_COLOR;else if (pictrueType == 1) propVar[3].lVal = WIA_INTENT_IMAGE_TYPE_GRAYSCALE;else propVar[3].lVal = WIA_INTENT_IMAGE_TYPE_TEXT;propVar[4].vt = VT_I4;propVar[4].lVal = brightness;propVar[5].vt = VT_I4;propVar[5].lVal = contrast;propVar[6].vt = VT_I4;propVar[6].lVal = dpi;propVar[7].vt = VT_I4;propVar[7].lVal = dpi;propVar[8].vt = VT_I4;if (size == 0) propVar[8].lVal = WIA_PAGE_A4;else if (size == 1) propVar[8].lVal = WIA_PAGE_ISO_A5;else propVar[8].lVal = WIA_PAGE_ISO_A6;hr = pGetWiaProperty->WriteMultiple(sizeof(propSpec) / sizeof(propSpec[0]), propSpec, propVar, WIA_IPA_FIRST);if (hr != S_OK) continue;IWiaDataTransfer* pIWiaDataTransfer = nullptr;hr = imageWiaItems[i]->QueryInterface(IID_IWiaDataTransfer, (void**)&pIWiaDataTransfer);if (hr != S_OK) continue;PWIA_DATA_TRANSFER_INFO pdti = new WIA_DATA_TRANSFER_INFO;pdti->ulSize = sizeof(WIA_DATA_TRANSFER_INFO);pdti->ulBufferSize = 1024 * 1024;pdti->ulSection = 0;pdti->bDoubleBuffer = true;pdti->ulReserved1 = 0;pdti->ulReserved2 = 0;pdti->ulReserved3 = 0;while (true){hr = pIWiaDataTransfer->idtGetBandedData(pdti, this);if (hr == S_OK) WriteFile();else break;}if (pGetWiaProperty) pGetWiaProperty->Release();if (pIWiaDataTransfer) pIWiaDataTransfer->Release();imageWiaItems[i]->Release();}}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。