diff options
author | 2016-03-17 13:50:17 -0700 | |
---|---|---|
committer | 2016-03-17 13:50:18 -0700 | |
commit | fc0b6d1053bb56698f2844bd5ca30bced7bb389d (patch) | |
tree | 017a37474cd1a510a0603aab76fea25c72a7a0ca /src/ports | |
parent | 3bcef213d19b457baf2e6d1f42046ae9afd4e97f (diff) |
Add SkImageGeneratorWIC
This will be a replacement for SkImageDecoder_WIC.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1785613010
CQ_EXTRA_TRYBOTS=client.skia.compile:Build-Ubuntu-GCC-x86_64-Release-CMake-Trybot,Build-Mac-Clang-x86_64-Release-CMake-Trybot
Review URL: https://codereview.chromium.org/1785613010
Diffstat (limited to 'src/ports')
-rw-r--r-- | src/ports/SkImageGeneratorWIC.cpp | 175 | ||||
-rw-r--r-- | src/ports/SkImageGeneratorWIC.h | 63 |
2 files changed, 238 insertions, 0 deletions
diff --git a/src/ports/SkImageGeneratorWIC.cpp b/src/ports/SkImageGeneratorWIC.cpp new file mode 100644 index 0000000000..f22cb5a7af --- /dev/null +++ b/src/ports/SkImageGeneratorWIC.cpp @@ -0,0 +1,175 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkImageGeneratorWIC.h" +#include "SkIStream.h" +#include "SkStream.h" + +// All Windows SDKs back to XPSP2 export the CLSID_WICImagingFactory symbol. +// In the Windows8 SDK the CLSID_WICImagingFactory symbol is still exported +// but CLSID_WICImagingFactory is then #defined to CLSID_WICImagingFactory2. +// Undo this #define if it has been done so that we link against the symbols +// we intended to link against on all SDKs. +#if defined(CLSID_WICImagingFactory) + #undef CLSID_WICImagingFactory +#endif + +SkImageGenerator* SkImageGeneratorWIC::NewFromEncodedWIC(SkData* data) { + // Create Windows Imaging Component ImagingFactory. + SkTScopedComPtr<IWICImagingFactory> imagingFactory; + HRESULT hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&imagingFactory)); + if (FAILED(hr)) { + return nullptr; + } + + // Create an IStream. + SkTScopedComPtr<IStream> iStream; + // Note that iStream will take ownership of the new memory stream because + // we set |deleteOnRelease| to true. + hr = SkIStream::CreateFromSkStream(new SkMemoryStream(data), true, &iStream); + if (FAILED(hr)) { + return nullptr; + } + + // Create the decoder from the stream. + SkTScopedComPtr<IWICBitmapDecoder> decoder; + hr = imagingFactory->CreateDecoderFromStream(iStream.get(), nullptr, + WICDecodeMetadataCacheOnDemand, &decoder); + if (FAILED(hr)) { + return nullptr; + } + + // Select the first frame from the decoder. + SkTScopedComPtr<IWICBitmapFrameDecode> imageFrame; + hr = decoder->GetFrame(0, &imageFrame); + if (FAILED(hr)) { + return nullptr; + } + + // Treat the frame as an image source. + SkTScopedComPtr<IWICBitmapSource> imageSource; + hr = imageFrame->QueryInterface(IID_PPV_ARGS(&imageSource)); + if (FAILED(hr)) { + return nullptr; + } + + // Get the size of the image. + UINT width; + UINT height; + hr = imageSource->GetSize(&width, &height); + if (FAILED(hr)) { + return nullptr; + } + + // Get the encoded pixel format. + WICPixelFormatGUID format; + hr = imageSource->GetPixelFormat(&format); + if (FAILED(hr)) { + return nullptr; + } + + // Recommend kOpaque if the image is opaque and kPremul otherwise. + // FIXME: We are stuck recommending kPremul for all indexed formats + // (Ex: GUID_WICPixelFormat8bppIndexed) because we don't have + // a way to check if the image has alpha. + SkAlphaType alphaType = kPremul_SkAlphaType; + + if (GUID_WICPixelFormat16bppBGR555 == format || + GUID_WICPixelFormat16bppBGR565 == format || + GUID_WICPixelFormat32bppBGR101010 == format || + GUID_WICPixelFormatBlackWhite == format || + GUID_WICPixelFormat2bppGray == format || + GUID_WICPixelFormat4bppGray == format || + GUID_WICPixelFormat8bppGray == format || + GUID_WICPixelFormat16bppGray == format || + GUID_WICPixelFormat16bppGrayFixedPoint == format || + GUID_WICPixelFormat16bppGrayHalf == format || + GUID_WICPixelFormat32bppGrayFloat == format || + GUID_WICPixelFormat32bppGrayFixedPoint == format || + GUID_WICPixelFormat32bppRGBE == format || + GUID_WICPixelFormat24bppRGB == format || + GUID_WICPixelFormat24bppBGR == format || + GUID_WICPixelFormat32bppBGR == format || + GUID_WICPixelFormat48bppRGB == format || + GUID_WICPixelFormat48bppBGR == format || + GUID_WICPixelFormat48bppRGBFixedPoint == format || + GUID_WICPixelFormat48bppBGRFixedPoint == format || + GUID_WICPixelFormat48bppRGBHalf == format || + GUID_WICPixelFormat64bppRGBFixedPoint == format || + GUID_WICPixelFormat64bppRGBHalf == format || + GUID_WICPixelFormat96bppRGBFixedPoint == format || + GUID_WICPixelFormat128bppRGBFloat == format || + GUID_WICPixelFormat128bppRGBFixedPoint == format || + GUID_WICPixelFormat32bppRGB == format || + GUID_WICPixelFormat64bppRGB == format || + GUID_WICPixelFormat96bppRGBFloat == format || + GUID_WICPixelFormat32bppCMYK == format || + GUID_WICPixelFormat64bppCMYK == format || + GUID_WICPixelFormat8bppY == format || + GUID_WICPixelFormat8bppCb == format || + GUID_WICPixelFormat8bppCr == format || + GUID_WICPixelFormat16bppCbCr == format) + { + alphaType = kOpaque_SkAlphaType; + } + + // FIXME: If we change the implementation to handle swizzling ourselves, + // we can support more output formats. + SkImageInfo info = SkImageInfo::MakeN32(width, height, alphaType); + return new SkImageGeneratorWIC(info, imagingFactory.release(), imageSource.release(), data); +} + +SkImageGeneratorWIC::SkImageGeneratorWIC(const SkImageInfo& info, + IWICImagingFactory* imagingFactory, IWICBitmapSource* imageSource, SkData* data) + : INHERITED(info) + , fImagingFactory(imagingFactory) + , fImageSource(imageSource) + , fData(SkRef(data)) +{} + +SkData* SkImageGeneratorWIC::onRefEncodedData(SK_REFENCODEDDATA_CTXPARAM) { + return SkRef(fData.get()); +} + +bool SkImageGeneratorWIC::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, + SkPMColor ctable[], int* ctableCount) { + if (kN32_SkColorType != info.colorType()) { + return false; + } + + // Create a format converter. + SkTScopedComPtr<IWICFormatConverter> formatConverter; + HRESULT hr = fImagingFactory->CreateFormatConverter(&formatConverter); + if (FAILED(hr)) { + return false; + } + + GUID format = GUID_WICPixelFormat32bppPBGRA; + if (kUnpremul_SkAlphaType == info.alphaType()) { + format = GUID_WICPixelFormat32bppBGRA; + } + + hr = formatConverter->Initialize(fImageSource.get(), format, WICBitmapDitherTypeNone, nullptr, + 0.0, WICBitmapPaletteTypeCustom); + if (FAILED(hr)) { + return false; + } + + // Treat the format converter as an image source. + SkTScopedComPtr<IWICBitmapSource> formatConverterSrc; + hr = formatConverter->QueryInterface(IID_PPV_ARGS(&formatConverterSrc)); + if (FAILED(hr)) { + return false; + } + + // Set the destination pixels. + hr = formatConverterSrc->CopyPixels(nullptr, (UINT) rowBytes, (UINT) rowBytes * info.height(), + (BYTE*) pixels); + + return SUCCEEDED(hr); +} diff --git a/src/ports/SkImageGeneratorWIC.h b/src/ports/SkImageGeneratorWIC.h new file mode 100644 index 0000000000..1366333350 --- /dev/null +++ b/src/ports/SkImageGeneratorWIC.h @@ -0,0 +1,63 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkTypes.h" + +#if defined(SK_BUILD_FOR_WIN) + +#include "SkData.h" +#include "SkImageGenerator.h" +#include "SkTemplates.h" +#include "SkTScopedComPtr.h" + +#include <wincodec.h> + +/* + * Any Windows program that uses COM must initialize the COM library by calling + * the CoInitializeEx function. In addition, each thread that uses a COM + * interface must make a separate call to this function. + * + * For every successful call to CoInitializeEx, the thread must call + * CoUninitialize before it exits. + * + * SkImageGeneratorWIC requires the COM library and leaves it to the client to + * initialize COM for their application. + * + * For more information on initializing COM, please see: + * https://msdn.microsoft.com/en-us/library/windows/desktop/ff485844.aspx + */ +class SkImageGeneratorWIC : public SkImageGenerator { +public: + /* + * Refs the data if an image generator can be returned. Otherwise does + * not affect the data. + */ + static SkImageGenerator* NewFromEncodedWIC(SkData* data); + +protected: + SkData* onRefEncodedData(SK_REFENCODEDDATA_CTXPARAM) override; + + bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[], + int* ctableCount) override; + +private: + /* + * Takes ownership of the imagingFactory + * Takes ownership of the imageSource + * Refs the data + */ + SkImageGeneratorWIC(const SkImageInfo& info, IWICImagingFactory* imagingFactory, + IWICBitmapSource* imageSource, SkData* data); + + SkTScopedComPtr<IWICImagingFactory> fImagingFactory; + SkTScopedComPtr<IWICBitmapSource> fImageSource; + SkAutoTUnref<SkData> fData; + + typedef SkImageGenerator INHERITED; +}; + +#endif // SK_BUILD_FOR_WIN |