Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
O serviço WIA baseia-se nas informações fornecidas na estrutura MINIDRV_TRANSFER_CONTEXT para realizar uma transferência de dados adequada.
Os membros desta estrutura que são relevantes para o minidriver WIA são:
bClassDrvAllocBuf − Alocação de serviços WIA Booleano.
pTransferBuffer − Ponteiro para a memória alocada para os dados transferidos.
lBufferSize − Tamanho da memória apontado pelo membro pTransferBuffer .
Se o membro bClassDrvAllocBuf da estrutura MINIDRV_TRANSFER_CONTEXT estiver definido como TRUE, o serviço WIA alocou memória para o minidriver. Se o membro bClassDrvAllocBuf estiver definido como FALSE, o serviço WIA não alocou nenhuma memória para o minidriver.
O minidriver deve alocar memória usando a função CoTaskMemAlloc (descrita na documentação do SDK do Microsoft Windows). O minidriver deve então armazenar o ponteiro para o local da memória em pTransferBuffer e o tamanho da memória em lBufferSize (em bytes).
O membro bClassDrvAllocBuff é definido como FALSE somente se a propriedade WIA_IPA_TYMED estiver definida como TYMED_FILE ou TYMED_MULTIPAGE_FILE e a propriedade WIA_IPA_ITEM_SIZE estiver definida como zero.
O minidriver deve ter cuidado para não sobrecarregar o buffer apontado pelo membro pTransferBuffer . Você pode evitar isso gravando dados em quantidades menores ou iguais ao valor armazenado no membro lBufferSize .
Melhorando o desempenho da transferência de dados usando o tamanho mínimo do buffer
O minidriver WIA pode controlar a quantidade de memória usada durante a transferência de dados, definindo as propriedades WIA_IPA_ITEM_SIZE e WIA_IPA_BUFFER_SIZE .
Um aplicativo WIA usa a propriedade WIA_IPA_BUFFER_SIZE para determinar o tamanho mínimo do buffer de transferência a ser solicitado durante uma transferência de memória. Quanto maior for esse valor, maior será o tamanho da banda solicitada. Se um aplicativo WIA solicitar um buffer menor em tamanho do que o valor na propriedade WIA_IPA_BUFFER_SIZE, o serviço WIA ignorará esse tamanho solicitado e solicitará ao minidriver WIA um buffer de WIA_IPA_BUFFER_SIZE bytes de tamanho. O serviço WIA sempre solicita ao minidriver WIA buffers com pelo menos WIA_IPA_BUFFER_SIZE bytes de tamanho.
O valor que a propriedade WIA_IPA_BUFFER_SIZE contém é a quantidade mínima de dados que um aplicativo pode solicitar a qualquer momento. Quanto maior o tamanho do buffer, maiores serão as solicitações para o dispositivo. Tamanhos de buffer muito pequenos podem retardar o desempenho da transferência de dados.
É recomendável que você defina a propriedade WIA_IPA_BUFFER_SIZE para um tamanho razoável para permitir que o dispositivo transfira dados a uma taxa eficiente. Faça isso equilibrando o número de solicitações (tamanho do buffer não muito pequeno) e o número de solicitações demoradas (buffer muito grande) para o seu dispositivo, a fim de garantir o desempenho ideal.
Você deve definir a propriedade WIA_IPA_ITEM_SIZE como zero se o minidriver WIA puder transferir dados. Se o tipo de transferência for TYMED_FILE ou TYMED_MULTIPAGE_FILE, é responsabilidade do minidriver alocar memória para que o buffer de dados seja passado para a função de serviço WIA que grava no ficheiro. Isso fornece consistência na implementação do método IWiaMiniDrv::d rvAcquireItemData .
O método IWiaMiniDrv::d rvAcquireItemData é chamado pelo serviço WIA quando pretende transferir dados do dispositivo para um aplicativo. O driver WIA deve determinar qual o tipo de transferência (através do serviço WIA) que a aplicação está tentando, lendo o membro tymed do MINIDRV_TRANSFER_CONTEXT:
O membro vinculado , que é definido pelo aplicativo, pode ter um dos seguintes quatro valores:
TYMED_FILE
Transfira dados para um arquivo.
TYMED_MULTIPAGE_FILE
Transfira dados para um formato de arquivo de várias páginas.
TYMED_CALLBACK
Transfira dados para a memória.
TYMED_MULTIPAGE_CALLBACK
Transfira várias páginas de dados para a memória.
As diferentes configurações TYMED XXX_CALLBACK e XXX_FILE alteram o modo de chamada para a interface de retorno de chamada do aplicativo.
TYMED_CALLBACK e TYMED_MULTIPAGE_CALLBACK
Para uma transferência de memória, execute uma chamada de retorno IWiaMiniDrvCallBack::MiniDrvCallback:
(pmdtc->pIWiaMiniDrvCallBack->MiniDrvCallback no seguinte exemplo de código-fonte)
Faça o retorno de chamada usando os seguintes valores:
IT_MSG_DATA
O controlador está a transferir dados.
ESTADO_TRANSFERÊNCIA_PARA_CLIENTE
A mensagem de transferência de dados.
PercentagemConcluída
A percentagem da transferência concluída.
pmdtc-cbOffset>
Atualize isso para o local atual onde o aplicativo deve gravar o próximo bloco de dados.
lBytesReceived
O número de bytes no bloco de dados que está sendo enviado para o aplicativo.
PMDTC
Ponteiro para uma estrutura de MINIDRV_TRANSFER_CONTEXT que contém os valores de transferência de dados.
TYMED_FILE e TYMED_MULTIPAGE_FILE
Para uma transferência de arquivo, emita um retorno de chamada IWiaMiniDrvCallBack::MiniDrvCallback ::
(pmdtc->pIWiaMiniDrvCallBack->MiniDrvCallback no seguinte exemplo de código-fonte)
Faça o retorno de chamada usando os seguintes valores.
STATUS_DA_MENSAGEM_TI
O driver está enviando apenas o status (sem dados).
TRANSFERÊNCIA_DE_ESTADO_PARA_CLIENTE
A mensagem de transferência de dados.
lPercentConcluído
A percentagem da transferência concluída.
Se o membro ItemSize da estrutura MINIDRV_TRANSFER_CONTEXT estiver definido como zero, isso indica ao aplicativo que o driver WIA não sabe o tamanho da imagem resultante e, em seguida, alocará seus próprios buffers de dados. O driver WIA lerá a propriedade WIA_IPA_BUFFER_SIZE e alocará memória para uma única faixa de dados. O driver WIA pode alocar qualquer quantidade de memória necessária aqui, mas recomenda-se que a alocação seja mantida pequena.
Para ver se o serviço WIA alocou memória para o driver, verifique o indicador pmdtc-bClassDrvAllocBuf>. Se estiver definido como TRUE, o serviço WIA alocou memória para o driver. Para descobrir quanta memória foi alocada, verifique o valor em pmdtc-lBufferSize>.
Para alocar a sua própria memória, use CoTaskMemAlloc (descrito na documentação do SDK do Microsoft Windows) e utilize o ponteiro localizado em pmdtc->pTransferBuffer. (Lembre-se de que o driver alocou essa memória, então o driver também deve liberá-la.) Defina pmdtc-lBufferSize> para o tamanho alocado. Como dito anteriormente, este driver de exemplo WIA aloca um buffer cujo tamanho, em bytes, é igual ao valor contido em WIA_IPA_BUFFER_SIZE. Em seguida, o driver usa essa memória.
O exemplo a seguir mostra uma implementação do método IWiaMiniDrv::d rvAcquireItemData . Este exemplo pode lidar com ambos os casos de alocação de memória.
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;
}