Udostępnij przez


Implementowanie elementu IWICBitmapDecoder

IWICBitmapDecoder

Gdy aplikacja żąda dekodera, pierwszym punktem interakcji z koderem jest interfejs IWICBitmapDecoder. Jest to interfejs umożliwiający dostęp do właściwości najwyższego poziomu kontenera i, co najważniejsze, modułów, które zawiera. Jest to podstawowy interfejs w klasie dekodera na poziomie kontenera.

interface IWICBitmapDecoder : IUnknown
{
// Required methods
   HRESULT QueryCapability (IStream *pIStream, 
      DWORD *pdwCapabilities );
   HRESULT Initialize ( IStream *pIStream,
      WICDecodeOptions cacheOptions );
   HRESULT GetContainerFormat ( GUID *pguidContainerFormat );
   HRESULT GetDecoderInfo ( IWICBitmapDecoderInfo **pIDecoderInfo );
   HRESULT GetFrameCount ( UINT *pCount );
   HRESULT GetFrame ( UINT index, 
      IWICBitmapFrameDecode **ppIBitmapFrame );

// Optional methods
   HRESULT GetPreview ( IWICBitmapSource **ppIPreview );
   HRESULT GetThumbnail ( IWICBitmapSource **ppIThumbnail );
   HRESULT GetColorContexts ( UINT cCount, 
      IWICColorContext **ppIColorContexts, 
      UINT *pcActualCount );
   HRESULT GetMetadataQueryReader ( IWICMetadataQueryReader **ppIMetadataQueryReader);
   HRESULT CopyPalette ( IWICPalette *pIPalette );
}

Niektóre formaty obrazów mają globalne miniatury, konteksty kolorów lub metadane, podczas gdy wiele formatów obrazów udostępnia je tylko dla poszczególnych ramek. Metody uzyskiwania dostępu do tych elementów są opcjonalne w IWICBitmapDecoder, ale są wymagane w IWICBitmapFrameDecode. Podobnie, niektóre kodeki nie używają indeksowanych formatów pikseli, więc nie muszą implementować metod CopyPalette na żadnym interfejsie. Aby uzyskać więcej informacji na temat opcjonalnych metod IWICBitmapDecoder, zapoznaj się z Implementowaniem IWICBitmapFrameDecode, gdzie najczęściej się je stosuje.

Możliwość wykonywania zapytań

QueryCapability to metoda używana do arbitrażu koderów. (Zobacz Discovery and Arbitration w temacie How The Windows Imaging Component Works (Jak działa składnik windows imaging). Jeśli dwie koderki mogą dekodować ten sam format obrazu lub jeśli wystąpi kolizja wzorca, w którym dwa koderki używają tego samego wzorca identyfikacji, ta metoda umożliwia wybranie kodera, który może najlepiej obsługiwać dowolny konkretny obraz.

Podczas wywoływania tej metody składnik Windows Imaging Component (WIC) przekazuje rzeczywisty strumień zawierający obraz. Należy sprawdzić, czy można dekodować każdą ramkę w obrazie i wyliczyć za pomocą bloków metadanych, aby dokładnie zadeklarować, jakie możliwości ma ten dekoder w odniesieniu do określonego strumienia plików przekazanego do niego. Jest to ważne dla wszystkich dekodatorów, ale szczególnie ważne w przypadku formatów obrazów opartych na kontenerach Formatu pliku obrazów oznaczonych tagiem (TIFF). Proces odnajdywania działa przez dopasowywanie wzorców skojarzonych z dekodownikami w rejestrze do wzorców w rzeczywistym pliku obrazu. Deklarowanie twojego wzorca identyfikacyjnego w rejestrze gwarantuje, że twój dekoder będzie zawsze wykrywany dla obrazów w twoim formacie obrazu. Jednak twój dekoder może nadal zostać wykryty dla obrazów w innych formatach. Na przykład wszystkie kontenery TIFF zawierają wzorzec TIFF, który jest prawidłowym wzorcem identyfikującym format obrazu TIFF. Oznacza to, że podczas odnajdywania co najmniej dwa wzorce identyfikujące będą znajdować się w plikach obrazów dla dowolnego formatu obrazu opartego na kontenerze w stylu TIFF. Jeden będzie wzorcem TIFF, a drugi będzie rzeczywistym wzorcem formatu obrazu. Chociaż mniej prawdopodobne, mogą istnieć kolizje wzorców między innymi niepowiązanymi formatami obrazów. Dlatego odnajdywanie i arbitraż jest procesem dwuetapowym. Zawsze sprawdź, czy strumień obrazu przekazany do QueryCapability jest w rzeczywistości prawidłowym wystąpieniem własnego formatu obrazu. Ponadto jeśli koder kodujący dekoduje format obrazu, dla którego nie jesteś właścicielem specyfikacji, implementacja QueryCapability powinna sprawdzić obecność dowolnej funkcji, która może być prawidłowa w specyfikacji formatu obrazu, której koder koder nie implementuje. Dzięki temu użytkownicy nie doświadczają niepotrzebnych błędów dekodowania ani nie będą otrzymywać nieoczekiwanych wyników z koderem koderowym.

Przed wykonaniem dowolnej operacji na obrazie należy zapisać bieżącą pozycję strumienia, aby można było przywrócić ją do oryginalnej pozycji przed powrotem z metody . Wyliczenie WICBitmapDecoderCapabilities określające możliwości jest definiowane w następujący sposób:

enum WICBitmapDecoderCapabilities
{   
   WICBitmapDecoderCapabilitySameEncoder,
   WICBitmapDecoderCapabilityCanDecodeAllImages,
   WICBitmapDecoderCapabilityCanDecodeSomeImages,
   WICBitmapDecoderCapabilityCanEnumerateMetadata,
   WICBitmapDecoderCapabilityCanDecodeThumbnail
}

Należy zadeklarować WICBitmapDecoderCapabilitySameEncoder tylko wtedy, gdy to twój koder zakodował obraz. Po sprawdzeniu, czy można dekodować każdą ramkę w kontenerze, zadeklaruj WICBitmapDecoderCapabilityCanDecodeSomeImages, jeśli można zdekodować niektóre, ale nie wszystkie ramki, WICBitmapDecoderCapabilityCanDecodeAllImages, jeśli można dekodować wszystkie ramki, lub żadną z tych opcji, jeśli nie można dekodować żadnej z nich. (Te dwa wyliczenia wzajemnie się wykluczają; jeśli zwrócisz WICBitmapDecoderCapabilityCanDecodeAllImages, WICBitmapDecoderCapabilityCanDecodeSomeImages zostaną zignorowane). Zadeklaruj WICBitmapDecoderCapabilityCanEnumerateMetadata po sprawdzeniu, czy można wyliczyć bloki metadanych w kontenerze obrazu. Nie musisz sprawdzać miniatury w każdej ramce. Jeśli istnieje miniatura globalna i można ją zdekodować, możesz zadeklarować WICBitmapDecoderCapabilityCanDecodeThumbnail. Jeśli nie ma miniatury globalnej, spróbuj zdekodować miniaturę dla ramki 0. Jeśli w żadnym z tych miejsc nie ma miniatury, nie deklaruj tej możliwości.

Po określeniu możliwości dekodera w odniesieniu do strumienia obrazu przekazanego do tej metody, wykonaj operację OR z WICBitmapDecoderCapabilities, aby potwierdzić, że ten dekoder może operować na tym obrazie, i zwróć wynik. Pamiętaj, aby przywrócić strumień do oryginalnej pozycji przed zwróceniem.

Zainicjuj

inicjalizacja jest wywoływana przez aplikację po tym, jak dekoder zostanie wybrany do dekodowania określonego obrazu. Strumień obrazu jest przekazywany do dekodera, a dzwoniący może opcjonalnie określić opcję WICDecodeOptions pamięci podręcznej do zarządzania metadanymi w pliku.

enum WICDecodeOptions
{
   WICDecodeMetadataCacheOnDemand,
   WICDecodeMetadataCacheOnLoad
}

Niektóre aplikacje używają metadanych więcej niż inne. Większość aplikacji nie musi uzyskiwać dostępu do wszystkich metadanych w pliku obrazu i żąda określonych metadanych, ponieważ ich potrzebują. Inne aplikacje wolałyby buforować wszystkie metadane z góry, a nie otwierać strumienia plików i wykonywać operacje we/wy dysku za każdym razem, gdy muszą uzyskiwać dostęp do metadanych. Jeśli dzwoniący nie określi opcji pamięci podręcznej metadanych, domyślne zachowanie buforowania powinno polegać na buforowaniu na żądanie. Oznacza to, że żadne metadane nie powinny być ładowane do pamięci, dopóki aplikacja nie zgłosi określonego żądania dla tych metadanych. Jeśli aplikacja określa WICDecodeMetadataCacheOnLoad, metadane powinny być natychmiast ładowane do pamięci i buforowane. Gdy metadane są buforowane podczas ładowania, strumień danych może zostać zwolniony po zbuforowaniu metadanych.

GetContainerFormat

Aby zaimplementować GetContainerFormat, wystarczy zwrócić identyfikator GUID formatu obrazu, dla którego zainicjowany jest dekoder. Ta metoda jest również implementowana w IWICMetadataBlockReader i IWICBitmapEncoder.

GetDecoderInfo

GetDecoderInfo zwraca obiekt IWICBitmapDecoderInfo. Aby uzyskać obiekt IWICBitmapDecoderInfo, wystarczy przekazać identyfikator GUID dekodera do metody CreateComponentInfo w IWICImagingFactory, a następnie zażądać interfejsu IWICBitMapDecoderInfo, jak pokazano w poniższym przykładzie.

IWICComponentInfo* pComponentInfo = NULL;
HRESULT hr;
 
hr = m_pImagingFactory->CreateComponentInfo(CLSID_This, &pComponentInfo);

hr = pComponentInfo->QueryInterface(IID_IWICBitmapDecoderInfo, (void**)ppIDecoderInfo);

GetFrameCount

GetFrameCount zwraca tylko liczbę ramek w kontenerze. Niektóre formaty kontenerów obsługują wiele ramek, a inne obsługują tylko jedną ramkę na kontener.

GetFrame

GetFrame jest ważną metodą interfejsuIWICBitmapDecoder, ponieważ ramka zawiera rzeczywiste bity obrazu, a obiekt dekodera ramki zwrócony z tej metody jest obiektem, który wykonuje rzeczywiste dekodowanie żądanego obrazu. Jest to drugi obiekt, który należy zaimplementować podczas pisania dekodera. Aby uzyskać więcej informacji na temat dekoderów ramek, zobacz Implementowanie IWICBitmapFrameDecode.

GetPreview

GetPreview zwraca podgląd obrazu. Szczegółowe omówienie wersji zapoznawczych można znaleźć w Implementowanie metody IWICBitmapEncoder w Implementowanie interfejsu IWICBitmapEncoder.

Jeśli format obrazu zawiera osadzony podgląd JPEG, zdecydowanie zaleca się, aby zamiast pisania własnego dekodera JPEG, delegować dekodowanie podglądów i miniatur do dekodera JPEG dostarczanego z platformą WIC. Aby to zrobić, poszukaj początku danych obrazu podglądowego wewnątrz strumienia i wywołaj metodę CreateDecoderFromStream w IWICImagingFactory.

IWICBitmapDecoder* pPreviewDecoder = NULL;
IWICBitmapFrameDecode* pPreviewFrame = NULL;
IWICBitmapSource* pPreview = NULL;
HRESULT hr;

hr = m_pImagingFactory->CreateDecoderFromStream(
                               m_pStream, NULL, 
                               WICDecodeMetadataCacheOnDemand, &pPreviewDecoder);
hr = pPreviewDecoder->GetFrame(0, pPreviewFrame);
hr = pPreviewFrame->QueryInterface(IID_IWICBitmapSource, (void**)&pPreview);

referencyjne

IWICBitmapDecoder

IWICBitmapFrameDecode

Koncepcja

interfejsy dekodera

Implementacja IWICBitmapCodecProgressNotification (Dekoder)

Jak napisać WIC-Enabled Codec

Składnik programu Windows Imaging — omówienie