blob: 2726f886a22b79a741712bfb361336d84268a803 [file] [log] [blame]
msarettfc0b6d12016-03-17 13:50:17 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkImageGeneratorWIC.h"
9#include "SkIStream.h"
10#include "SkStream.h"
11
12// All Windows SDKs back to XPSP2 export the CLSID_WICImagingFactory symbol.
13// In the Windows8 SDK the CLSID_WICImagingFactory symbol is still exported
14// but CLSID_WICImagingFactory is then #defined to CLSID_WICImagingFactory2.
15// Undo this #define if it has been done so that we link against the symbols
16// we intended to link against on all SDKs.
17#if defined(CLSID_WICImagingFactory)
18 #undef CLSID_WICImagingFactory
19#endif
20
Leon Scroggins IIIa57488a2018-06-25 14:01:29 -040021std::unique_ptr<SkImageGenerator> SkImageGeneratorWIC::MakeFromEncodedWIC(sk_sp<SkData> data) {
msarettfc0b6d12016-03-17 13:50:17 -070022 // Create Windows Imaging Component ImagingFactory.
23 SkTScopedComPtr<IWICImagingFactory> imagingFactory;
24 HRESULT hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER,
25 IID_PPV_ARGS(&imagingFactory));
26 if (FAILED(hr)) {
27 return nullptr;
28 }
29
30 // Create an IStream.
31 SkTScopedComPtr<IStream> iStream;
32 // Note that iStream will take ownership of the new memory stream because
33 // we set |deleteOnRelease| to true.
Leon Scroggins IIIa57488a2018-06-25 14:01:29 -040034 hr = SkIStream::CreateFromSkStream(new SkMemoryStream(data), true, &iStream);
msarettfc0b6d12016-03-17 13:50:17 -070035 if (FAILED(hr)) {
36 return nullptr;
37 }
38
39 // Create the decoder from the stream.
40 SkTScopedComPtr<IWICBitmapDecoder> decoder;
41 hr = imagingFactory->CreateDecoderFromStream(iStream.get(), nullptr,
42 WICDecodeMetadataCacheOnDemand, &decoder);
43 if (FAILED(hr)) {
44 return nullptr;
45 }
46
47 // Select the first frame from the decoder.
48 SkTScopedComPtr<IWICBitmapFrameDecode> imageFrame;
49 hr = decoder->GetFrame(0, &imageFrame);
50 if (FAILED(hr)) {
51 return nullptr;
52 }
53
54 // Treat the frame as an image source.
55 SkTScopedComPtr<IWICBitmapSource> imageSource;
56 hr = imageFrame->QueryInterface(IID_PPV_ARGS(&imageSource));
57 if (FAILED(hr)) {
58 return nullptr;
59 }
60
61 // Get the size of the image.
62 UINT width;
63 UINT height;
64 hr = imageSource->GetSize(&width, &height);
65 if (FAILED(hr)) {
66 return nullptr;
67 }
68
69 // Get the encoded pixel format.
70 WICPixelFormatGUID format;
71 hr = imageSource->GetPixelFormat(&format);
72 if (FAILED(hr)) {
73 return nullptr;
74 }
75
76 // Recommend kOpaque if the image is opaque and kPremul otherwise.
77 // FIXME: We are stuck recommending kPremul for all indexed formats
78 // (Ex: GUID_WICPixelFormat8bppIndexed) because we don't have
79 // a way to check if the image has alpha.
80 SkAlphaType alphaType = kPremul_SkAlphaType;
81
82 if (GUID_WICPixelFormat16bppBGR555 == format ||
83 GUID_WICPixelFormat16bppBGR565 == format ||
84 GUID_WICPixelFormat32bppBGR101010 == format ||
85 GUID_WICPixelFormatBlackWhite == format ||
86 GUID_WICPixelFormat2bppGray == format ||
87 GUID_WICPixelFormat4bppGray == format ||
88 GUID_WICPixelFormat8bppGray == format ||
89 GUID_WICPixelFormat16bppGray == format ||
90 GUID_WICPixelFormat16bppGrayFixedPoint == format ||
91 GUID_WICPixelFormat16bppGrayHalf == format ||
92 GUID_WICPixelFormat32bppGrayFloat == format ||
93 GUID_WICPixelFormat32bppGrayFixedPoint == format ||
94 GUID_WICPixelFormat32bppRGBE == format ||
95 GUID_WICPixelFormat24bppRGB == format ||
96 GUID_WICPixelFormat24bppBGR == format ||
97 GUID_WICPixelFormat32bppBGR == format ||
98 GUID_WICPixelFormat48bppRGB == format ||
99 GUID_WICPixelFormat48bppBGR == format ||
100 GUID_WICPixelFormat48bppRGBFixedPoint == format ||
101 GUID_WICPixelFormat48bppBGRFixedPoint == format ||
102 GUID_WICPixelFormat48bppRGBHalf == format ||
103 GUID_WICPixelFormat64bppRGBFixedPoint == format ||
104 GUID_WICPixelFormat64bppRGBHalf == format ||
105 GUID_WICPixelFormat96bppRGBFixedPoint == format ||
106 GUID_WICPixelFormat128bppRGBFloat == format ||
107 GUID_WICPixelFormat128bppRGBFixedPoint == format ||
108 GUID_WICPixelFormat32bppRGB == format ||
109 GUID_WICPixelFormat64bppRGB == format ||
110 GUID_WICPixelFormat96bppRGBFloat == format ||
111 GUID_WICPixelFormat32bppCMYK == format ||
112 GUID_WICPixelFormat64bppCMYK == format ||
113 GUID_WICPixelFormat8bppY == format ||
114 GUID_WICPixelFormat8bppCb == format ||
115 GUID_WICPixelFormat8bppCr == format ||
116 GUID_WICPixelFormat16bppCbCr == format)
117 {
118 alphaType = kOpaque_SkAlphaType;
119 }
120
121 // FIXME: If we change the implementation to handle swizzling ourselves,
122 // we can support more output formats.
Matt Sarett1e86044d2016-12-16 09:02:18 -0500123 SkImageInfo info = SkImageInfo::MakeS32(width, height, alphaType);
Leon Scroggins IIIa57488a2018-06-25 14:01:29 -0400124 return std::unique_ptr<SkImageGenerator>(
125 new SkImageGeneratorWIC(info, imagingFactory.release(), imageSource.release(),
126 std::move(data)));
msarettfc0b6d12016-03-17 13:50:17 -0700127}
128
129SkImageGeneratorWIC::SkImageGeneratorWIC(const SkImageInfo& info,
Leon Scroggins IIIa57488a2018-06-25 14:01:29 -0400130 IWICImagingFactory* imagingFactory, IWICBitmapSource* imageSource, sk_sp<SkData> data)
msarettfc0b6d12016-03-17 13:50:17 -0700131 : INHERITED(info)
132 , fImagingFactory(imagingFactory)
133 , fImageSource(imageSource)
Leon Scroggins IIIa57488a2018-06-25 14:01:29 -0400134 , fData(std::move(data))
msarettfc0b6d12016-03-17 13:50:17 -0700135{}
136
Ben Wagnerbdf54332018-05-15 14:12:14 -0400137sk_sp<SkData> SkImageGeneratorWIC::onRefEncodedData() {
138 return fData;
139}
msarettfc0b6d12016-03-17 13:50:17 -0700140
141bool SkImageGeneratorWIC::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
Matt Sarettebb1b5c2017-05-12 11:41:27 -0400142 const Options&) {
msarettfc0b6d12016-03-17 13:50:17 -0700143 if (kN32_SkColorType != info.colorType()) {
144 return false;
145 }
146
147 // Create a format converter.
148 SkTScopedComPtr<IWICFormatConverter> formatConverter;
149 HRESULT hr = fImagingFactory->CreateFormatConverter(&formatConverter);
150 if (FAILED(hr)) {
151 return false;
152 }
153
154 GUID format = GUID_WICPixelFormat32bppPBGRA;
155 if (kUnpremul_SkAlphaType == info.alphaType()) {
156 format = GUID_WICPixelFormat32bppBGRA;
157 }
158
159 hr = formatConverter->Initialize(fImageSource.get(), format, WICBitmapDitherTypeNone, nullptr,
160 0.0, WICBitmapPaletteTypeCustom);
161 if (FAILED(hr)) {
162 return false;
163 }
164
165 // Treat the format converter as an image source.
166 SkTScopedComPtr<IWICBitmapSource> formatConverterSrc;
167 hr = formatConverter->QueryInterface(IID_PPV_ARGS(&formatConverterSrc));
168 if (FAILED(hr)) {
169 return false;
170 }
171
172 // Set the destination pixels.
173 hr = formatConverterSrc->CopyPixels(nullptr, (UINT) rowBytes, (UINT) rowBytes * info.height(),
174 (BYTE*) pixels);
175
176 return SUCCEEDED(hr);
177}