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.
Um codificador grava dados de imagem em um fluxo. Os codificadores podem compactar, criptografar e alterar os pixels da imagem de várias maneiras antes de gravá-los no fluxo. O uso de alguns codificadores resulta em compensações — por exemplo, JPEG, que troca informações de cor por uma melhor compactação. Outros codificadores não resultam em tais perdas, por exemplo, bitmap (BMP). Como muitos codecs usam tecnologia proprietária para obter melhor compressão e fidelidade de imagem, os detalhes sobre como uma imagem é codificada são de responsabilidade do desenvolvedor do codec.
IWICBitmapEncoder
IWICBitmapEncoder é a interface principal para codificar uma imagem para o formato de destino e usada para serializar os componentes de uma imagem, como miniatura (SetThumbnail) e quadros (CreateNewFrame), para o arquivo de imagem.
Como e quando a serialização ocorre é deixado para o desenvolvedor do codec. Cada bloco individual de dados no formato de arquivo de destino deve poder ser configurado independentemente da sua ordem, no entanto, esta é novamente a decisão do desenvolvedor do codec. Uma vez que o método Commit é chamado, no entanto, as alterações na imagem não devem ser permitidas e o fluxo deve ser fechado.
IWICBitmapFrameEncode
IWICBitmapFrameEncode é a interface para codificar os quadros individuais de uma imagem. Ele fornece métodos para definir componentes de imagem de quadro individuais, como miniaturas e quadros, bem como dimensões de imagem, DPI e formatos de pixel.
Quadros individuais podem ser codificados com metadados específicos de quadros, portanto, IWICBitmapFrameEncode fornece acesso a um gravador de metadados por meio do método GetMetadataQueryWriter .
O método Commit do quadro confirma todas as alterações no quadro individual e indica que as alterações nesse quadro não devem mais ser aceitas.
Exemplo de codificação (TIFF)
No exemplo a seguir, uma imagem TIFF (Tagged Image File Format) é codificada usando IWICBitmapEncoder e um IWICBitmapFrameEncode. A saída TIFF é personalizada usando o WICTiffCompressionOption e o quadro de bitmap é inicializado usando as opções fornecidas. Uma vez que a imagem tenha sido criada usando WritePixels, o quadro é confirmado por meio de Commit e a imagem é salva usando Commit.
IWICImagingFactory *piFactory = NULL;
IWICBitmapEncoder *piEncoder = NULL;
IWICBitmapFrameEncode *piBitmapFrame = NULL;
IPropertyBag2 *pPropertybag = NULL;
IWICStream *piStream = NULL;
UINT uiWidth = 640;
UINT uiHeight = 480;
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
(LPVOID*) &piFactory);
if (SUCCEEDED(hr))
{
hr = piFactory->CreateStream(&piStream);
}
if (SUCCEEDED(hr))
{
hr = piStream->InitializeFromFilename(L"output.tif", GENERIC_WRITE);
}
if (SUCCEEDED(hr))
{
hr = piFactory->CreateEncoder(GUID_ContainerFormatTiff, NULL, &piEncoder);
}
if (SUCCEEDED(hr))
{
hr = piEncoder->Initialize(piStream, WICBitmapEncoderNoCache);
}
if (SUCCEEDED(hr))
{
hr = piEncoder->CreateNewFrame(&piBitmapFrame, &pPropertybag);
}
if (SUCCEEDED(hr))
{
// This is how you customize the TIFF output.
PROPBAG2 option = { 0 };
option.pstrName = L"TiffCompressionMethod";
VARIANT varValue;
VariantInit(&varValue);
varValue.vt = VT_UI1;
varValue.bVal = WICTiffCompressionZIP;
hr = pPropertybag->Write(1, &option, &varValue);
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->Initialize(pPropertybag);
}
}
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->SetSize(uiWidth, uiHeight);
}
WICPixelFormatGUID formatGUID = GUID_WICPixelFormat24bppBGR;
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->SetPixelFormat(&formatGUID);
}
if (SUCCEEDED(hr))
{
// We're expecting to write out 24bppRGB. Fail if the encoder cannot do it.
hr = IsEqualGUID(formatGUID, GUID_WICPixelFormat24bppBGR) ? S_OK : E_FAIL;
}
if (SUCCEEDED(hr))
{
UINT cbStride = (uiWidth * 24 + 7)/8/***WICGetStride***/;
UINT cbBufferSize = uiHeight * cbStride;
BYTE *pbBuffer = new BYTE[cbBufferSize];
if (pbBuffer != NULL)
{
for (UINT i = 0; i < cbBufferSize; i++)
{
pbBuffer[i] = static_cast<BYTE>(rand());
}
hr = piBitmapFrame->WritePixels(uiHeight, cbStride, cbBufferSize, pbBuffer);
delete[] pbBuffer;
}
else
{
hr = E_OUTOFMEMORY;
}
}
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->Commit();
}
if (SUCCEEDED(hr))
{
hr = piEncoder->Commit();
}
if (piFactory)
piFactory->Release();
if (piEncoder)
piEncoder->Release();
if (piBitmapFrame)
piBitmapFrame->Release();
if (pPropertybag)
pPropertybag->Release();
if (piStream)
piStream->Release();
return hr;
Uso das opções do codificador
Codificadores diferentes para formatos diferentes precisam expor diferentes opções de como uma imagem é codificada. O Windows Imaging Component (WIC) fornece um mecanismo consistente para expressar se as opções de codificação são necessárias e, ao mesmo tempo, permitir que os aplicativos trabalhem com vários codificadores sem exigir conhecimento de um formato específico. Isso é feito fornecendo um parâmetro IPropertyBag no método CreateNewFrame e no método Initialize .
A fábrica de componentes fornece um ponto de criação fácil para criar um conjunto de propriedades de opções do codificador. Codecs podem usar este serviço se eles precisam fornecer um conjunto simples, intuitivo e não conflitante de opções de codificador. O pacote de propriedades de imagem deve ser inicializado durante a criação com todas as opções do codificador relevantes para esse codec. Para opções de codificador do conjunto canônico, o intervalo de valores será imposto durante a escrita. Para necessidades mais avançadas, os codecs devem escrever a sua própria implementação de conjunto de propriedades.
Um aplicativo recebe o pacote de opções do codificador durante a criação do quadro e deve configurar quaisquer valores antes de inicializar o quadro do codificador. Para um aplicativo controlado por interface do usuário, ele pode oferecer uma interface do usuário fixa para as opções canônicas do codificador e uma exibição avançada para as opções restantes. As alterações podem ser feitas uma de cada vez através do método Write e qualquer erro será reportado através do IErrorLog. O aplicativo de interface do usuário deve sempre reler e exibir todas as opções depois de fazer uma alteração, caso a alteração tenha causado um efeito cascata. Um aplicativo deve estar preparado para lidar com a inicialização de quadro com falha para codecs que fornecem apenas relatórios de erros mínimos por meio de seu pacote de propriedades.
Opções do codificador
Um aplicativo pode esperar encontrar o seguinte conjunto de opções de codificador. As opções do encoder refletem as capacidades de um encoder e do formato de contêiner subjacente e, portanto, não são, por natureza, realmente independentes do codec. Quando possível, novas opções devem ser normalizadas para que possam ser aplicadas a novos codecs que surjam.
| Nome da propriedade | VARTYPE | Valor | Codecs aplicáveis |
|---|---|---|---|
| BitmapTransform | VT_UI1 | WICBitmapTransformOptions | JPEG, JPEG XL, HEIF |
| Qualidade de Compressão | VT_R4 | 0-1.0 | TIFF, JPEG XL |
| HeifCompressionMethod | VT_UI1 | WICHeifCompressionOption | HEIF |
| Qualidade de Imagem | VT_R4 | 0-1.0 | JPEG, JPEG XL, HDPhoto, HEIF |
| Sem perdas | VT_BOOL | VERDADEIRO,FALSO | JPEG XL, HDPhoto |
ImageQualty de 0.0 significa a menor representação de fidelidade possível e 1.0 significa a maior fidelidade, o que também pode implicar sem perdas, dependendo do codec.
Qualidade de Compressão de 0,0 significa o esquema de compressão menos eficiente disponível, normalmente resulta numa codificação rápida, mas numa saída maior. Um valor de 1,0 significa o esquema mais eficiente disponível, normalmente levando mais tempo para codificar, mas produzindo resultados menores. Dependendo das capacidades do codec, este intervalo pode ser mapeado em um conjunto discreto de métodos de compressão disponíveis.
"Sem perdas significa que o codec codifica a imagem sem perder dados de imagem." Se Lossless estiver ativado, ImageQuality será ignorado.
Além das opções de codificador genérico acima, os codecs fornecidos com WIC suportam as seguintes opções. Se um codec tiver a necessidade de suportar uma opção que seja consistente com o uso nesses codecs fornecidos, ele é encorajado a fazê-lo.
| Nome da propriedade | VARTYPE | Valor | Codecs aplicáveis |
|---|---|---|---|
| Opção de Entrelaçamento | VT_BOOL | Ligado/Desligado | PNG |
| Opção de Filtro | VT_UI1 | WICPngFilterOption | PNG |
| Método de Compressão TIFF | VT_UI1 | WICTiffCompressionOption | TIFF |
| Luminância | VT_UI4/VT_ARRAY | 64 Entradas (DCT) | JPEG |
| Crominância | VT_UI4/VT_ARRAY | 64 Entradas (DCT) | JPEG |
| JpegYCrCbSubsampling | VT_UI1 | WICJpegYCrCbSubsamplingOption | JPEG |
| SuprimirApp0 | VT_BOOL | JPEG | |
| EnableV5Header32bppBGRA | VT_BOOL | Ligado/Desligado | BMP |
Use VT_EMPTY para indicar *not set* como padrão. Se propriedades adicionais forem definidas, mas não suportadas, o codificador deverá ignorá-las; Isso permite que os aplicativos codificem menos lógica se quiserem um recurso que pode ou não estar presente.
Exemplos de opções do codificador
No exemplo de codificação TIFF acima, uma opção de codificador específica é definida. O membro pstrName da estrutura PROPBAG2 é definido como o nome da propriedade apropriada e o VARIANT é definido como o VARTYPE correspondente e o valor desejado — neste caso, um membro da enumeração WICTiffCompressionOption .
if (SUCCEEDED(hr))
{
hr = piEncoder->CreateNewFrame(&piBitmapFrame, &pPropertybag);
}
if (SUCCEEDED(hr))
{
// This is how you customize the TIFF output.
PROPBAG2 option = { 0 };
option.pstrName = L"TiffCompressionMethod";
VARIANT varValue;
VariantInit(&varValue);
varValue.vt = VT_UI1;
varValue.bVal = WICTiffCompressionZIP;
hr = pPropertybag->Write(1, &option, &varValue);
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->Initialize(pPropertybag);
}
}
Para usar as opções padrão do codificador, basta inicializar o quadro de bitmap com o pacote de propriedades retornado quando o quadro foi criado.
if (SUCCEEDED(hr))
{
hr = piEncoder->CreateNewFrame(&piBitmapFrame, &pPropertybag);
}
if (SUCCEEDED(hr))
{
// Accept the default encoder options.
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->Initialize(pPropertybag);
}
}
Também é possível eliminar o conjunto de propriedades quando não estão a ser consideradas opções de codificador.
if (SUCCEEDED(hr))
{
hr = piEncoder->CreateNewFrame(&piBitmapFrame, 0);
}
if (SUCCEEDED(hr))
{
// No encoder options.
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->Initialize(0);
}
}