1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2016 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkStream.h" 9cb93a386Sopenharmony_ci#include "include/ports/SkImageGeneratorWIC.h" 10cb93a386Sopenharmony_ci#include "include/private/SkTemplates.h" 11cb93a386Sopenharmony_ci#include "src/utils/win/SkIStream.h" 12cb93a386Sopenharmony_ci#include "src/utils/win/SkTScopedComPtr.h" 13cb93a386Sopenharmony_ci 14cb93a386Sopenharmony_ci#include <wincodec.h> 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ci// All Windows SDKs back to XPSP2 export the CLSID_WICImagingFactory symbol. 17cb93a386Sopenharmony_ci// In the Windows8 SDK the CLSID_WICImagingFactory symbol is still exported 18cb93a386Sopenharmony_ci// but CLSID_WICImagingFactory is then #defined to CLSID_WICImagingFactory2. 19cb93a386Sopenharmony_ci// Undo this #define if it has been done so that we link against the symbols 20cb93a386Sopenharmony_ci// we intended to link against on all SDKs. 21cb93a386Sopenharmony_ci#if defined(CLSID_WICImagingFactory) 22cb93a386Sopenharmony_ci #undef CLSID_WICImagingFactory 23cb93a386Sopenharmony_ci#endif 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_cinamespace { 26cb93a386Sopenharmony_ciclass ImageGeneratorWIC : public SkImageGenerator { 27cb93a386Sopenharmony_cipublic: 28cb93a386Sopenharmony_ci /* 29cb93a386Sopenharmony_ci * Takes ownership of the imagingFactory 30cb93a386Sopenharmony_ci * Takes ownership of the imageSource 31cb93a386Sopenharmony_ci */ 32cb93a386Sopenharmony_ci ImageGeneratorWIC(const SkImageInfo& info, IWICImagingFactory* imagingFactory, 33cb93a386Sopenharmony_ci IWICBitmapSource* imageSource, sk_sp<SkData>); 34cb93a386Sopenharmony_ciprotected: 35cb93a386Sopenharmony_ci sk_sp<SkData> onRefEncodedData() override; 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ci bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options&) 38cb93a386Sopenharmony_ci override; 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_ciprivate: 41cb93a386Sopenharmony_ci SkTScopedComPtr<IWICImagingFactory> fImagingFactory; 42cb93a386Sopenharmony_ci SkTScopedComPtr<IWICBitmapSource> fImageSource; 43cb93a386Sopenharmony_ci sk_sp<SkData> fData; 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_ci using INHERITED = SkImageGenerator; 46cb93a386Sopenharmony_ci}; 47cb93a386Sopenharmony_ci} // namespace 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_cistd::unique_ptr<SkImageGenerator> SkImageGeneratorWIC::MakeFromEncodedWIC(sk_sp<SkData> data) { 50cb93a386Sopenharmony_ci // Create Windows Imaging Component ImagingFactory. 51cb93a386Sopenharmony_ci SkTScopedComPtr<IWICImagingFactory> imagingFactory; 52cb93a386Sopenharmony_ci HRESULT hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, 53cb93a386Sopenharmony_ci IID_PPV_ARGS(&imagingFactory)); 54cb93a386Sopenharmony_ci if (FAILED(hr)) { 55cb93a386Sopenharmony_ci return nullptr; 56cb93a386Sopenharmony_ci } 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ci // Create an IStream. 59cb93a386Sopenharmony_ci SkTScopedComPtr<IStream> iStream; 60cb93a386Sopenharmony_ci // Note that iStream will take ownership of the new memory stream because 61cb93a386Sopenharmony_ci // we set |deleteOnRelease| to true. 62cb93a386Sopenharmony_ci hr = SkIStream::CreateFromSkStream(std::make_unique<SkMemoryStream>(data), &iStream); 63cb93a386Sopenharmony_ci if (FAILED(hr)) { 64cb93a386Sopenharmony_ci return nullptr; 65cb93a386Sopenharmony_ci } 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci // Create the decoder from the stream. 68cb93a386Sopenharmony_ci SkTScopedComPtr<IWICBitmapDecoder> decoder; 69cb93a386Sopenharmony_ci hr = imagingFactory->CreateDecoderFromStream(iStream.get(), nullptr, 70cb93a386Sopenharmony_ci WICDecodeMetadataCacheOnDemand, &decoder); 71cb93a386Sopenharmony_ci if (FAILED(hr)) { 72cb93a386Sopenharmony_ci return nullptr; 73cb93a386Sopenharmony_ci } 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci // Select the first frame from the decoder. 76cb93a386Sopenharmony_ci SkTScopedComPtr<IWICBitmapFrameDecode> imageFrame; 77cb93a386Sopenharmony_ci hr = decoder->GetFrame(0, &imageFrame); 78cb93a386Sopenharmony_ci if (FAILED(hr)) { 79cb93a386Sopenharmony_ci return nullptr; 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_ci // Treat the frame as an image source. 83cb93a386Sopenharmony_ci SkTScopedComPtr<IWICBitmapSource> imageSource; 84cb93a386Sopenharmony_ci hr = imageFrame->QueryInterface(IID_PPV_ARGS(&imageSource)); 85cb93a386Sopenharmony_ci if (FAILED(hr)) { 86cb93a386Sopenharmony_ci return nullptr; 87cb93a386Sopenharmony_ci } 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_ci // Get the size of the image. 90cb93a386Sopenharmony_ci UINT width; 91cb93a386Sopenharmony_ci UINT height; 92cb93a386Sopenharmony_ci hr = imageSource->GetSize(&width, &height); 93cb93a386Sopenharmony_ci if (FAILED(hr)) { 94cb93a386Sopenharmony_ci return nullptr; 95cb93a386Sopenharmony_ci } 96cb93a386Sopenharmony_ci 97cb93a386Sopenharmony_ci // Get the encoded pixel format. 98cb93a386Sopenharmony_ci WICPixelFormatGUID format; 99cb93a386Sopenharmony_ci hr = imageSource->GetPixelFormat(&format); 100cb93a386Sopenharmony_ci if (FAILED(hr)) { 101cb93a386Sopenharmony_ci return nullptr; 102cb93a386Sopenharmony_ci } 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_ci // Recommend kOpaque if the image is opaque and kPremul otherwise. 105cb93a386Sopenharmony_ci // FIXME: We are stuck recommending kPremul for all indexed formats 106cb93a386Sopenharmony_ci // (Ex: GUID_WICPixelFormat8bppIndexed) because we don't have 107cb93a386Sopenharmony_ci // a way to check if the image has alpha. 108cb93a386Sopenharmony_ci SkAlphaType alphaType = kPremul_SkAlphaType; 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci if (GUID_WICPixelFormat16bppBGR555 == format || 111cb93a386Sopenharmony_ci GUID_WICPixelFormat16bppBGR565 == format || 112cb93a386Sopenharmony_ci GUID_WICPixelFormat32bppBGR101010 == format || 113cb93a386Sopenharmony_ci GUID_WICPixelFormatBlackWhite == format || 114cb93a386Sopenharmony_ci GUID_WICPixelFormat2bppGray == format || 115cb93a386Sopenharmony_ci GUID_WICPixelFormat4bppGray == format || 116cb93a386Sopenharmony_ci GUID_WICPixelFormat8bppGray == format || 117cb93a386Sopenharmony_ci GUID_WICPixelFormat16bppGray == format || 118cb93a386Sopenharmony_ci GUID_WICPixelFormat16bppGrayFixedPoint == format || 119cb93a386Sopenharmony_ci GUID_WICPixelFormat16bppGrayHalf == format || 120cb93a386Sopenharmony_ci GUID_WICPixelFormat32bppGrayFloat == format || 121cb93a386Sopenharmony_ci GUID_WICPixelFormat32bppGrayFixedPoint == format || 122cb93a386Sopenharmony_ci GUID_WICPixelFormat32bppRGBE == format || 123cb93a386Sopenharmony_ci GUID_WICPixelFormat24bppRGB == format || 124cb93a386Sopenharmony_ci GUID_WICPixelFormat24bppBGR == format || 125cb93a386Sopenharmony_ci GUID_WICPixelFormat32bppBGR == format || 126cb93a386Sopenharmony_ci GUID_WICPixelFormat48bppRGB == format || 127cb93a386Sopenharmony_ci GUID_WICPixelFormat48bppBGR == format || 128cb93a386Sopenharmony_ci GUID_WICPixelFormat48bppRGBFixedPoint == format || 129cb93a386Sopenharmony_ci GUID_WICPixelFormat48bppBGRFixedPoint == format || 130cb93a386Sopenharmony_ci GUID_WICPixelFormat48bppRGBHalf == format || 131cb93a386Sopenharmony_ci GUID_WICPixelFormat64bppRGBFixedPoint == format || 132cb93a386Sopenharmony_ci GUID_WICPixelFormat64bppRGBHalf == format || 133cb93a386Sopenharmony_ci GUID_WICPixelFormat96bppRGBFixedPoint == format || 134cb93a386Sopenharmony_ci GUID_WICPixelFormat128bppRGBFloat == format || 135cb93a386Sopenharmony_ci GUID_WICPixelFormat128bppRGBFixedPoint == format || 136cb93a386Sopenharmony_ci GUID_WICPixelFormat32bppRGB == format || 137cb93a386Sopenharmony_ci GUID_WICPixelFormat64bppRGB == format || 138cb93a386Sopenharmony_ci GUID_WICPixelFormat96bppRGBFloat == format || 139cb93a386Sopenharmony_ci GUID_WICPixelFormat32bppCMYK == format || 140cb93a386Sopenharmony_ci GUID_WICPixelFormat64bppCMYK == format || 141cb93a386Sopenharmony_ci GUID_WICPixelFormat8bppY == format || 142cb93a386Sopenharmony_ci GUID_WICPixelFormat8bppCb == format || 143cb93a386Sopenharmony_ci GUID_WICPixelFormat8bppCr == format || 144cb93a386Sopenharmony_ci GUID_WICPixelFormat16bppCbCr == format) 145cb93a386Sopenharmony_ci { 146cb93a386Sopenharmony_ci alphaType = kOpaque_SkAlphaType; 147cb93a386Sopenharmony_ci } 148cb93a386Sopenharmony_ci 149cb93a386Sopenharmony_ci // FIXME: If we change the implementation to handle swizzling ourselves, 150cb93a386Sopenharmony_ci // we can support more output formats. 151cb93a386Sopenharmony_ci SkImageInfo info = SkImageInfo::MakeS32(width, height, alphaType); 152cb93a386Sopenharmony_ci return std::unique_ptr<SkImageGenerator>( 153cb93a386Sopenharmony_ci new ImageGeneratorWIC(info, imagingFactory.release(), imageSource.release(), 154cb93a386Sopenharmony_ci std::move(data))); 155cb93a386Sopenharmony_ci} 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_ciImageGeneratorWIC::ImageGeneratorWIC(const SkImageInfo& info, 158cb93a386Sopenharmony_ci IWICImagingFactory* imagingFactory, IWICBitmapSource* imageSource, sk_sp<SkData> data) 159cb93a386Sopenharmony_ci : INHERITED(info) 160cb93a386Sopenharmony_ci , fImagingFactory(imagingFactory) 161cb93a386Sopenharmony_ci , fImageSource(imageSource) 162cb93a386Sopenharmony_ci , fData(std::move(data)) 163cb93a386Sopenharmony_ci{} 164cb93a386Sopenharmony_ci 165cb93a386Sopenharmony_cisk_sp<SkData> ImageGeneratorWIC::onRefEncodedData() { 166cb93a386Sopenharmony_ci return fData; 167cb93a386Sopenharmony_ci} 168cb93a386Sopenharmony_ci 169cb93a386Sopenharmony_cibool ImageGeneratorWIC::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, 170cb93a386Sopenharmony_ci const Options&) { 171cb93a386Sopenharmony_ci if (kN32_SkColorType != info.colorType()) { 172cb93a386Sopenharmony_ci return false; 173cb93a386Sopenharmony_ci } 174cb93a386Sopenharmony_ci 175cb93a386Sopenharmony_ci // Create a format converter. 176cb93a386Sopenharmony_ci SkTScopedComPtr<IWICFormatConverter> formatConverter; 177cb93a386Sopenharmony_ci HRESULT hr = fImagingFactory->CreateFormatConverter(&formatConverter); 178cb93a386Sopenharmony_ci if (FAILED(hr)) { 179cb93a386Sopenharmony_ci return false; 180cb93a386Sopenharmony_ci } 181cb93a386Sopenharmony_ci 182cb93a386Sopenharmony_ci GUID format = GUID_WICPixelFormat32bppPBGRA; 183cb93a386Sopenharmony_ci if (kUnpremul_SkAlphaType == info.alphaType()) { 184cb93a386Sopenharmony_ci format = GUID_WICPixelFormat32bppBGRA; 185cb93a386Sopenharmony_ci } 186cb93a386Sopenharmony_ci 187cb93a386Sopenharmony_ci hr = formatConverter->Initialize(fImageSource.get(), format, WICBitmapDitherTypeNone, nullptr, 188cb93a386Sopenharmony_ci 0.0, WICBitmapPaletteTypeCustom); 189cb93a386Sopenharmony_ci if (FAILED(hr)) { 190cb93a386Sopenharmony_ci return false; 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_ci // Treat the format converter as an image source. 194cb93a386Sopenharmony_ci SkTScopedComPtr<IWICBitmapSource> formatConverterSrc; 195cb93a386Sopenharmony_ci hr = formatConverter->QueryInterface(IID_PPV_ARGS(&formatConverterSrc)); 196cb93a386Sopenharmony_ci if (FAILED(hr)) { 197cb93a386Sopenharmony_ci return false; 198cb93a386Sopenharmony_ci } 199cb93a386Sopenharmony_ci 200cb93a386Sopenharmony_ci // Set the destination pixels. 201cb93a386Sopenharmony_ci hr = formatConverterSrc->CopyPixels(nullptr, (UINT) rowBytes, (UINT) rowBytes * info.height(), 202cb93a386Sopenharmony_ci (BYTE*) pixels); 203cb93a386Sopenharmony_ci 204cb93a386Sopenharmony_ci return SUCCEEDED(hr); 205cb93a386Sopenharmony_ci} 206