Poznámka
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Služba WIA spoléhá na informace zadané ve struktuře MINIDRV_TRANSFER_CONTEXT k provedení správného přenosu dat.
Členy této struktury, které jsou relevantní pro minidriver WIA, jsou:
bClassDrvAllocBuf − Booleovská hodnota přidělování služby WIA.
pTransferBuffer − Ukazatel na paměť přidělenou pro přenášená data.
lBufferSize − Velikost paměti, na kterou odkazuje pTransferBuffer člen.
Pokud je bClassDrvAllocBuf člen struktury MINIDRV_TRANSFER_CONTEXT nastaven na TRUE, pak služba WIA přidělila paměť minidriveru. Pokud je bClassDrvAllocBuf člen nastaven na FALSE, služba WIA nepřidělila žádné paměti pro minidriver.
Minidriver by měl přidělit paměť pomocí funkce CoTaskMemAlloc (popsané v dokumentaci k sadě Microsoft Windows SDK). Minidriver by pak měl uložit ukazatel na umístění paměti v pTransferBuffer a velikost paměti v lBufferSize (v bajtech).
bClassDrvAllocBuff člen je nastaven na FALSE pouze v případě, že je vlastnost WIA_IPA_TYMED nastavena na TYMED_FILE nebo TYMED_MULTIPAGE_FILE a vlastnost WIA_IPA_ITEM_SIZE je nastavena na nulu.
Minidriver musí být opatrný, aby nepřeplnil vyrovnávací paměť, na kterou odkazuje člen pTransferBuffer. Můžete tomu zabránit tak, že zapíšete data v množstvích menších než nebo rovných hodnotě uložené v lBufferSize prvku.
Zvýšení výkonu přenosu dat pomocí minimální velikosti vyrovnávací paměti
Minidriver WIA může řídit množství paměti používané při přenosu dat nastavením WIA_IPA_ITEM_SIZE a WIA_IPA_BUFFER_SIZE vlastností.
Aplikace WIA používá vlastnost WIA_IPA_BUFFER_SIZE k určení minimální velikosti vyrovnávací paměti požadované při přenosu paměti. Čím větší je tato hodnota, tím větší bude požadovaná velikost pásma. Pokud aplikace WIA požaduje vyrovnávací paměť, která je menší než hodnota ve vlastnosti WIA_IPA_BUFFER_SIZE, služba WIA tuto požadovanou velikost ignoruje a požádá minidriver WIA o vyrovnávací paměť, která je WIA_IPA_BUFFER_SIZE bajty velikosti. Služba WIA vždy požádá minidriver WIA o vyrovnávací paměti, které jsou alespoň WIA_IPA_BUFFER_SIZE bajty velikosti.
Hodnota, kterou vlastnost WIA_IPA_BUFFER_SIZE obsahuje, je minimální množství dat, které může aplikace kdykoli požadovat. Čím větší velikost vyrovnávací paměti, tím větší budou požadavky na zařízení. Velikosti vyrovnávací paměti, které jsou příliš malé, můžou zpomalit výkon přenosu dat.
Doporučujeme nastavit vlastnost WIA_IPA_BUFFER_SIZE na přiměřenou velikost, aby zařízení mohlo přenášet data efektivně. Uděláte to tak, že vyrovnáte počet požadavků (velikost vyrovnávací paměti není příliš malá) a počet časově náročných požadavků (příliš velký vyrovnávací paměť) pro vaše zařízení, aby se zajistil optimální výkon.
Pokud minidriver WIA dokáže přenášet data, měli byste vlastnost WIA_IPA_ITEM_SIZE nastavit na nulu. Pokud je typ přenosu nastaven na TYMED_FILE nebo TYMED_MULTIPAGE_FILE, minidriver je zodpovědný za přidělení paměti pro datový buffer, který bude předán do funkce služby WIA, která zapisuje do souboru. To poskytuje konzistenci při implementaci metody IWiaMiniDrv::drvAcquireItemData.
Metoda IWiaMiniDrv::drvAcquireItemData je volána službou WIA, když má v úmyslu přenášet data ze zařízení do aplikace. Ovladač WIA by měl určit, jaký typ přenosu (prostřednictvím služby WIA) se aplikace pokouší, načtením tymed člena MINIDRV_TRANSFER_CONTEXT:
vázaný člen, který je nastaven aplikací, může mít jednu z následujících čtyř hodnot:
TYMED_FILE
Přenos dat do souboru
TYMED_MULTIPAGE_FILE
Přenos dat do formátu souboru s více stránkami
TYMED_CALLBACK
Přenos dat do paměti
TYMED_MULTIPAGE_CALLBACK
Umožňuje přenést více stránek dat do paměti.
Různá nastavení TYMED XXX_CALLBACK a XXX_FILE mění využití rozhraní zpětného volání aplikace.
TYMED_CALLBACK a TYMED_MULTIPAGE_CALLBACK
Při přenosu paměti vydejte příkaz IWiaMiniDrvCallBack::MiniDrvCallback pro zpětné volání:
(pmdtc->pIWiaMiniDrvCallBack->MiniDrvCallback v následujícím ukázkovém zdrojovém kódu)
Zpětné volání proveďte pomocí následujících hodnot:
IT_MSG_DATA
Ovladač přenáší data.
STAV_IT_PŘEVOD_KLIENTOVI
Zpráva o přenosu dat.
Procent dokončeno
Procento dokončeného převodu
pmdtc->cbOffset
Aktualizujte ji na aktuální umístění, kde by aplikace měla zapisovat další blok dat.
lBytesReceived
Počet bajtů v datovém bloku, který se odesílá do aplikace.
pmdtc
Ukazatel na MINIDRV_TRANSFER_CONTEXT strukturu, která obsahuje hodnoty přenosu dat.
Soubory TYMED_FILE a TYMED_MULTIPAGE_FILE
V případě přenosu souborů zadejte IWiaMiniDrvCallBack::MiniDrvCallback zpětné volání::
(pmdtc->pIWiaMiniDrvCallBack->MiniDrvCallback v následujícím ukázkovém zdrojovém kódu)
Zpětné volání proveďte pomocí následujících hodnot.
IT_MSG_STATUS
Ovladač odesílá pouze stav (žádná data).
IT_STATUS_PŘENOS_KLIENTOVI
Zpráva o přenosu dat.
lPercentComplete
Procento dokončeného převodu
Pokud je člen ItemSize struktury MINIDRV_TRANSFER_CONTEXT nastaven na nulu, informuje to aplikaci, že ovladač WIA nezná výslednou velikost obrázku, a aplikace pak přidělí vlastní datové vyrovnávací paměti. Ovladač WIA přečte vlastnost WIA_IPA_BUFFER_SIZE a přidělí paměť pro jednu skupinu dat. Ovladač WIA může přidělit libovolné množství paměti, kterou potřebuje, ale doporučuje se udržovat přidělení malým.
Pokud chcete zjistit, jestli má služba WIA přidělenou paměť pro ovladač, zkontrolujte příznak pmdtc->bClassDrvAllocBuf. Pokud je nastavena na TRUE, služba WIA má přidělenou paměť pro ovladač. Pokud chcete zjistit, kolik paměti bylo přiděleno, zkontrolujte hodnotu v pmdtc->lBufferSize.
Pokud chcete přidělit vlastní paměť, použijte coTaskMemAlloc (popsané v dokumentaci k sadě Microsoft Windows SDK) a použijte ukazatel umístěný v pmdtc->pTransferBuffer. (Nezapomeňte, že ovladač přidělil tuto paměť, takže ji musí také uvolnit.) Nastavte pmdtc->lBufferSize na velikost, kterou jste přidělili. Jak již bylo uvedeno dříve, tento ukázkový ovladač WIA přiděluje vyrovnávací paměť, jejíž velikost v bajtech je rovna hodnotě obsažené v WIA_IPA_BUFFER_SIZE. Ovladač pak použije danou paměť.
Následující příklad ukazuje implementaci metody IWiaMiniDrv::drvAcquireItemData. Tento příklad dokáže zpracovat oba případy přidělení paměti.
HRESULT _stdcall CWIADevice::drvAcquireItemData(
BYTE *pWiasContext,
LONG lFlags,
PMINIDRV_TRANSFER_CONTEXT pmdtc,
LONG *plDevErrVal)
{
//
// If the caller did not pass in the correct parameters,
// then fail the call with E_INVALIDARG.
//
if (!pWiasContext) {
return E_INVALIDARG;
}
if (!pmdtc) {
return E_INVALIDARG;
}
if (!plDevErrVal) {
return E_INVALIDARG;
}
*plDevErrVal = 0;
HRESULT hr = E_FAIL;
LONG lBytesTransferredToApplication = 0;
LONG lClassDrvAllocSize = 0;
//
// (1) Memory allocation
//
if (pmdtc->bClassDrvAllocBuf) {
//
// WIA allocated the buffer for data transfers
//
lClassDrvAllocSize = pmdtc->lBufferSize;
hr = S_OK;
} else {
//
// Driver allocated the buffer for data transfers
//
hr = wiasReadPropLong(pWiasContext, WIA_IPA_BUFFER_SIZE, &lClassDrvAllocSize,NULL,TRUE);
if (FAILED(hr)) {
//
// no memory was allocated, here so we can return early
//
return hr;
}
//
// allocate memory of WIA_IPA_BUFFER_SIZE (own min buffer size)
//
pmdtc->pTransferBuffer = (PBYTE) CoTaskMemAlloc(lClassDrvAllocSize);
if (!pmdtc->pTransferBuffer) {
//
// no memory was allocated, here so we can return early
//
return E_OUTOFMEMORY;
}
//
// set the lBufferSize member
//
pmdtc->lBufferSize = lClassDrvAllocSize;
}
//
// (2) Gather all information about data transfer settings and
// calculate the total data amount to transfer
//
if (hr == S_OK) {
//
// WIA service will populate the MINIDRV_TRANSFER_CONTEXT by reading the WIA properties.
//
// The following values will be written as a result of the
// wiasGetImageInformation() call
//
// pmdtc->lWidthInPixels
// pmdtc->lLines
// pmdtc->lDepth
// pmdtc->lXRes
// pmdtc->lYRes
// pmdtc->lCompression
// pmdtc->lItemSize
// pmdtc->guidFormatID
// pmdtc->tymed
//
// if the FORMAT is set to BMP or MEMORYBMP, the
// following values will also be set automatically
//
// pmdtc->cbWidthInBytes
// pmdtc->lImageSize
// pmdtc->lHeaderSize
// pmdtc->lItemSize (will be updated using the known image format information)
//
hr = wiasGetImageInformation(pWiasContext,0,pmdtc);
if (hr == S_OK) {
//
// (3) Send the image data to the application
//
LONG lDepth = 0;
hr = wiasReadPropLong(pWiasContext, WIA_IPA_DEPTH, &lDepth,NULL,TRUE);
if (hr == S_OK) {
LONG lPixelsPerLine = 0;
hr = wiasReadPropLong(pWiasContext, WIA_IPA_PIXELS_PER_LINE, &lPixelsPerLine,NULL,TRUE);
if (hr == S_OK) {
LONG lBytesPerLineRaw = ((lPixelsPerLine * lDepth) + 7) / 8;
LONG lBytesPerLineAligned = (lPixelsPerLine * lDepth) + 31;
lBytesPerLineAligned = (lBytesPerLineAligned / 8) & 0xfffffffc;
LONG lTotalImageBytes = pmdtc->lImageSize + pmdtc->lHeaderSize;
LONG lBytesReceived = pmdtc->lHeaderSize;
lBytesTransferredToApplication = 0;
pmdtc->cbOffset = 0;
while ((lBytesReceived)) {
LONG lPercentComplete = (LONG)(((float)lBytesTransferredToApplication/(float)lTotalImageBytes) * 100.0f);
switch (pmdtc->tymed) {
case TYMED_MULTIPAGE_CALLBACK:
case TYMED_CALLBACK:
{
hr = pmdtc->pIWiaMiniDrvCallBack->MiniDrvCallback(IT_MSG_DATA,IT_STATUS_TRANSFER_TO_CLIENT,
lPercentComplete,pmdtc->cbOffset,lBytesReceived,pmdtc,0);
pmdtc->cbOffset += lBytesReceived;
lBytesTransferredToApplication += lBytesReceived;
}
break;
case TYMED_MULTIPAGE_FILE:
case TYMED_FILE:
{
//
// lItemSize is the amount that wiasWriteBufToFile will write to FILE
//
pmdtc->lItemSize = lBytesReceived;
hr = wiasWriteBufToFile(0,pmdtc);
if (FAILED(hr)) {
break;
}
hr = pmdtc->pIWiaMiniDrvCallBack->MiniDrvCallback(IT_MSG_STATUS,IT_STATUS_TRANSFER_TO_CLIENT,
lPercentComplete,0,0,NULL,0);
lBytesTransferredToApplication += lBytesReceived;
}
break;
default:
{
hr = E_FAIL;
}
break;
}
//
// scan from device, requesting ytesToReadFromDevice
//
LONG lBytesRemainingToTransfer = (lTotalImageBytes - lBytesTransferredToApplication);
if (lBytesRemainingToTransfer <= 0) {
break;
}
//
// calculate number of bytes to request from device
//
LONG lBytesToReadFromDevice = (lBytesRemainingToTransfer > pmdtc->lBufferSize) ? pmdtc->lBufferSize : lBytesRemainingToTransfer;
// RAW data request
lBytesToReadFromDevice = (lBytesToReadFromDevice / lBytesPerLineAligned) * lBytesPerLineRaw;
// Aligned data request
// lBytesToReadFromDevice = (lBytesToReadFromDevice / lBytesPerLineAligned) * lBytesPerLineAligned;
if ((hr == S_FALSE)||FAILED(hr)) {
//
// user canceled or the callback failed for some reason
//
break;
}
//
// request byte amount from device
//
hr = GetDataFromMyDevice(pmdtc->pTransferBuffer, lBytesToReadFromDevice, (DWORD*)&lBytesReceived);
if (FAILED(hr)) {
break;
}
//
// this device returns raw data. If your device does this too, then you should call the AlignInPlace
// helper function to align the data.
//
lBytesReceived = AlignMyRawData(pmdtc->pTransferBuffer,lBytesReceived,lBytesPerLineAligned,lBytesPerLineRaw);
} // while ((lBytesReceived))
}
}
}
}
//
// free any allocated memory for buffers
//
if (!pmdtc->bClassDrvAllocBuf) {
CoTaskMemFree(pmdtc->pTransferBuffer);
pmdtc->pTransferBuffer = NULL;
pmdtc->lBufferSize = 0;
}
return hr;
}