| Index: src/ports/SkImageGeneratorWIC.cpp
|
| diff --git a/src/ports/SkImageGeneratorWIC.cpp b/src/ports/SkImageGeneratorWIC.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f22cb5a7af871a10376304c4d2be13306ee274c5
|
| --- /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);
|
| +}
|
|
|