OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "SkTypes.h" | 9 #include "SkTypes.h" |
10 | 10 |
(...skipping 13 matching lines...) Expand all Loading... |
24 #undef UINT8_MAX | 24 #undef UINT8_MAX |
25 #undef INT16_MAX | 25 #undef INT16_MAX |
26 #undef UINT16_MAX | 26 #undef UINT16_MAX |
27 #undef INT32_MAX | 27 #undef INT32_MAX |
28 #undef UINT32_MAX | 28 #undef UINT32_MAX |
29 #undef INT64_MAX | 29 #undef INT64_MAX |
30 #undef UINT64_MAX | 30 #undef UINT64_MAX |
31 | 31 |
32 #include <wincodec.h> | 32 #include <wincodec.h> |
33 #include "SkAutoCoInitialize.h" | 33 #include "SkAutoCoInitialize.h" |
34 #include "SkImageDecoder.h" | |
35 #include "SkImageEncoder.h" | 34 #include "SkImageEncoder.h" |
36 #include "SkIStream.h" | 35 #include "SkIStream.h" |
37 #include "SkMovie.h" | 36 #include "SkMovie.h" |
38 #include "SkStream.h" | 37 #include "SkStream.h" |
39 #include "SkTScopedComPtr.h" | 38 #include "SkTScopedComPtr.h" |
40 #include "SkUnPreMultiply.h" | 39 #include "SkUnPreMultiply.h" |
41 | 40 |
42 //All Windows SDKs back to XPSP2 export the CLSID_WICImagingFactory symbol. | 41 //All Windows SDKs back to XPSP2 export the CLSID_WICImagingFactory symbol. |
43 //In the Windows8 SDK the CLSID_WICImagingFactory symbol is still exported | 42 //In the Windows8 SDK the CLSID_WICImagingFactory symbol is still exported |
44 //but CLSID_WICImagingFactory is then #defined to CLSID_WICImagingFactory2. | 43 //but CLSID_WICImagingFactory is then #defined to CLSID_WICImagingFactory2. |
45 //Undo this #define if it has been done so that we link against the symbols | 44 //Undo this #define if it has been done so that we link against the symbols |
46 //we intended to link against on all SDKs. | 45 //we intended to link against on all SDKs. |
47 #if defined(CLSID_WICImagingFactory) | 46 #if defined(CLSID_WICImagingFactory) |
48 #undef CLSID_WICImagingFactory | 47 #undef CLSID_WICImagingFactory |
49 #endif | 48 #endif |
50 | 49 |
51 class SkImageDecoder_WIC : public SkImageDecoder { | |
52 public: | |
53 // Decoding modes corresponding to SkImageDecoder::Mode, plus an extra mode
for decoding | |
54 // only the format. | |
55 enum WICModes { | |
56 kDecodeFormat_WICMode, | |
57 kDecodeBounds_WICMode, | |
58 kDecodePixels_WICMode, | |
59 }; | |
60 | |
61 /** | |
62 * Helper function to decode an SkStream. | |
63 * @param stream SkStream to decode. Must be at the beginning. | |
64 * @param bm SkBitmap to decode into. Only used if wicMode is kDecodeBoun
ds_WICMode or | |
65 * kDecodePixels_WICMode, in which case it must not be nullptr. | |
66 * @param format Out parameter for the SkImageDecoder::Format of the SkStre
am. Only used if | |
67 * wicMode is kDecodeFormat_WICMode. | |
68 */ | |
69 bool decodeStream(SkStream* stream, SkBitmap* bm, WICModes wicMode, Format*
format) const; | |
70 | |
71 protected: | |
72 Result onDecode(SkStream* stream, SkBitmap* bm, Mode mode) override; | |
73 }; | |
74 | |
75 struct FormatConversion { | |
76 GUID fGuidFormat; | |
77 SkImageDecoder::Format fFormat; | |
78 }; | |
79 | |
80 static const FormatConversion gFormatConversions[] = { | |
81 { GUID_ContainerFormatBmp, SkImageDecoder::kBMP_Format }, | |
82 { GUID_ContainerFormatGif, SkImageDecoder::kGIF_Format }, | |
83 { GUID_ContainerFormatIco, SkImageDecoder::kICO_Format }, | |
84 { GUID_ContainerFormatJpeg, SkImageDecoder::kJPEG_Format }, | |
85 { GUID_ContainerFormatPng, SkImageDecoder::kPNG_Format }, | |
86 }; | |
87 | |
88 static SkImageDecoder::Format GuidContainerFormat_to_Format(REFGUID guid) { | |
89 for (size_t i = 0; i < SK_ARRAY_COUNT(gFormatConversions); i++) { | |
90 if (IsEqualGUID(guid, gFormatConversions[i].fGuidFormat)) { | |
91 return gFormatConversions[i].fFormat; | |
92 } | |
93 } | |
94 return SkImageDecoder::kUnknown_Format; | |
95 } | |
96 | |
97 SkImageDecoder::Result SkImageDecoder_WIC::onDecode(SkStream* stream, SkBitmap*
bm, Mode mode) { | |
98 WICModes wicMode; | |
99 switch (mode) { | |
100 case SkImageDecoder::kDecodeBounds_Mode: | |
101 wicMode = kDecodeBounds_WICMode; | |
102 break; | |
103 case SkImageDecoder::kDecodePixels_Mode: | |
104 wicMode = kDecodePixels_WICMode; | |
105 break; | |
106 } | |
107 return this->decodeStream(stream, bm, wicMode, nullptr) ? kSuccess : kFailur
e; | |
108 } | |
109 | |
110 bool SkImageDecoder_WIC::decodeStream(SkStream* stream, SkBitmap* bm, WICModes w
icMode, | |
111 Format* format) const { | |
112 //Initialize COM. | |
113 SkAutoCoInitialize scopedCo; | |
114 if (!scopedCo.succeeded()) { | |
115 return false; | |
116 } | |
117 | |
118 HRESULT hr = S_OK; | |
119 | |
120 //Create Windows Imaging Component ImagingFactory. | |
121 SkTScopedComPtr<IWICImagingFactory> piImagingFactory; | |
122 if (SUCCEEDED(hr)) { | |
123 hr = CoCreateInstance( | |
124 CLSID_WICImagingFactory | |
125 , nullptr | |
126 , CLSCTX_INPROC_SERVER | |
127 , IID_PPV_ARGS(&piImagingFactory) | |
128 ); | |
129 } | |
130 | |
131 //Convert SkStream to IStream. | |
132 SkTScopedComPtr<IStream> piStream; | |
133 if (SUCCEEDED(hr)) { | |
134 hr = SkIStream::CreateFromSkStream(stream, false, &piStream); | |
135 } | |
136 | |
137 //Make sure we're at the beginning of the stream. | |
138 if (SUCCEEDED(hr)) { | |
139 LARGE_INTEGER liBeginning = { 0 }; | |
140 hr = piStream->Seek(liBeginning, STREAM_SEEK_SET, nullptr); | |
141 } | |
142 | |
143 //Create the decoder from the stream content. | |
144 SkTScopedComPtr<IWICBitmapDecoder> piBitmapDecoder; | |
145 if (SUCCEEDED(hr)) { | |
146 hr = piImagingFactory->CreateDecoderFromStream( | |
147 piStream.get() //Image to be decoded | |
148 , nullptr //No particular vendor | |
149 , WICDecodeMetadataCacheOnDemand //Cache metadata when needed | |
150 , &piBitmapDecoder //Pointer to the decoder | |
151 ); | |
152 } | |
153 | |
154 if (kDecodeFormat_WICMode == wicMode) { | |
155 SkASSERT(format != nullptr); | |
156 //Get the format | |
157 if (SUCCEEDED(hr)) { | |
158 GUID guidFormat; | |
159 hr = piBitmapDecoder->GetContainerFormat(&guidFormat); | |
160 if (SUCCEEDED(hr)) { | |
161 *format = GuidContainerFormat_to_Format(guidFormat); | |
162 return true; | |
163 } | |
164 } | |
165 return false; | |
166 } | |
167 | |
168 //Get the first frame from the decoder. | |
169 SkTScopedComPtr<IWICBitmapFrameDecode> piBitmapFrameDecode; | |
170 if (SUCCEEDED(hr)) { | |
171 hr = piBitmapDecoder->GetFrame(0, &piBitmapFrameDecode); | |
172 } | |
173 | |
174 //Get the BitmapSource interface of the frame. | |
175 SkTScopedComPtr<IWICBitmapSource> piBitmapSourceOriginal; | |
176 if (SUCCEEDED(hr)) { | |
177 hr = piBitmapFrameDecode->QueryInterface( | |
178 IID_PPV_ARGS(&piBitmapSourceOriginal) | |
179 ); | |
180 } | |
181 | |
182 //Get the size of the bitmap. | |
183 UINT width; | |
184 UINT height; | |
185 if (SUCCEEDED(hr)) { | |
186 hr = piBitmapSourceOriginal->GetSize(&width, &height); | |
187 } | |
188 | |
189 //Exit early if we're only looking for the bitmap bounds. | |
190 if (SUCCEEDED(hr)) { | |
191 bm->setInfo(SkImageInfo::MakeN32Premul(width, height)); | |
192 if (kDecodeBounds_WICMode == wicMode) { | |
193 return true; | |
194 } | |
195 if (!this->allocPixelRef(bm, nullptr)) { | |
196 return false; | |
197 } | |
198 } | |
199 | |
200 //Create a format converter. | |
201 SkTScopedComPtr<IWICFormatConverter> piFormatConverter; | |
202 if (SUCCEEDED(hr)) { | |
203 hr = piImagingFactory->CreateFormatConverter(&piFormatConverter); | |
204 } | |
205 | |
206 GUID destinationPixelFormat; | |
207 if (this->getRequireUnpremultipliedColors()) { | |
208 destinationPixelFormat = GUID_WICPixelFormat32bppBGRA; | |
209 } else { | |
210 destinationPixelFormat = GUID_WICPixelFormat32bppPBGRA; | |
211 } | |
212 | |
213 if (SUCCEEDED(hr)) { | |
214 hr = piFormatConverter->Initialize( | |
215 piBitmapSourceOriginal.get() //Input bitmap to convert | |
216 , destinationPixelFormat //Destination pixel format | |
217 , WICBitmapDitherTypeNone //Specified dither patterm | |
218 , nullptr //Specify a particular palette | |
219 , 0.f //Alpha threshold | |
220 , WICBitmapPaletteTypeCustom //Palette translation type | |
221 ); | |
222 } | |
223 | |
224 //Get the BitmapSource interface of the format converter. | |
225 SkTScopedComPtr<IWICBitmapSource> piBitmapSourceConverted; | |
226 if (SUCCEEDED(hr)) { | |
227 hr = piFormatConverter->QueryInterface( | |
228 IID_PPV_ARGS(&piBitmapSourceConverted) | |
229 ); | |
230 } | |
231 | |
232 //Copy the pixels into the bitmap. | |
233 if (SUCCEEDED(hr)) { | |
234 SkAutoLockPixels alp(*bm); | |
235 bm->eraseColor(SK_ColorTRANSPARENT); | |
236 const UINT stride = (UINT) bm->rowBytes(); | |
237 hr = piBitmapSourceConverted->CopyPixels( | |
238 nullptr, //Get all the pixels | |
239 stride, | |
240 stride * height, | |
241 reinterpret_cast<BYTE *>(bm->getPixels()) | |
242 ); | |
243 | |
244 // Note: we don't need to premultiply here since we specified PBGRA | |
245 if (SkBitmap::ComputeIsOpaque(*bm)) { | |
246 bm->setAlphaType(kOpaque_SkAlphaType); | |
247 } | |
248 } | |
249 | |
250 return SUCCEEDED(hr); | |
251 } | |
252 | |
253 ///////////////////////////////////////////////////////////////////////// | |
254 | |
255 extern SkImageDecoder* image_decoder_from_stream(SkStreamRewindable*); | |
256 | |
257 SkImageDecoder* SkImageDecoder::Factory(SkStreamRewindable* stream) { | |
258 SkImageDecoder* decoder = image_decoder_from_stream(stream); | |
259 if (nullptr == decoder) { | |
260 // If no image decoder specific to the stream exists, use SkImageDecoder
_WIC. | |
261 return new SkImageDecoder_WIC; | |
262 } else { | |
263 return decoder; | |
264 } | |
265 } | |
266 | |
267 ///////////////////////////////////////////////////////////////////////// | 50 ///////////////////////////////////////////////////////////////////////// |
268 | 51 |
269 SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) { | 52 SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) { |
270 return nullptr; | 53 return nullptr; |
271 } | 54 } |
272 | 55 |
273 ///////////////////////////////////////////////////////////////////////// | 56 ///////////////////////////////////////////////////////////////////////// |
274 | 57 |
275 class SkImageEncoder_WIC : public SkImageEncoder { | 58 class SkImageEncoder_WIC : public SkImageEncoder { |
276 public: | 59 public: |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 case SkImageEncoder::kPNG_Type: | 227 case SkImageEncoder::kPNG_Type: |
445 break; | 228 break; |
446 default: | 229 default: |
447 return nullptr; | 230 return nullptr; |
448 } | 231 } |
449 return new SkImageEncoder_WIC(t); | 232 return new SkImageEncoder_WIC(t); |
450 } | 233 } |
451 | 234 |
452 static SkImageEncoder_EncodeReg gEReg(sk_imageencoder_wic_factory); | 235 static SkImageEncoder_EncodeReg gEReg(sk_imageencoder_wic_factory); |
453 | 236 |
454 static SkImageDecoder::Format get_format_wic(SkStreamRewindable* stream) { | |
455 SkImageDecoder::Format format; | |
456 SkImageDecoder_WIC codec; | |
457 if (!codec.decodeStream(stream, nullptr, SkImageDecoder_WIC::kDecodeFormat_W
ICMode, &format)) { | |
458 format = SkImageDecoder::kUnknown_Format; | |
459 } | |
460 return format; | |
461 } | |
462 | |
463 static SkImageDecoder_FormatReg gFormatReg(get_format_wic); | |
464 | |
465 #endif // defined(SK_BUILD_FOR_WIN32) | 237 #endif // defined(SK_BUILD_FOR_WIN32) |
OLD | NEW |