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" |
34 #include "SkImageEncoder.h" | 35 #include "SkImageEncoder.h" |
35 #include "SkIStream.h" | 36 #include "SkIStream.h" |
36 #include "SkMovie.h" | 37 #include "SkMovie.h" |
37 #include "SkStream.h" | 38 #include "SkStream.h" |
38 #include "SkTScopedComPtr.h" | 39 #include "SkTScopedComPtr.h" |
39 #include "SkUnPreMultiply.h" | 40 #include "SkUnPreMultiply.h" |
40 | 41 |
41 //All Windows SDKs back to XPSP2 export the CLSID_WICImagingFactory symbol. | 42 //All Windows SDKs back to XPSP2 export the CLSID_WICImagingFactory symbol. |
42 //In the Windows8 SDK the CLSID_WICImagingFactory symbol is still exported | 43 //In the Windows8 SDK the CLSID_WICImagingFactory symbol is still exported |
43 //but CLSID_WICImagingFactory is then #defined to CLSID_WICImagingFactory2. | 44 //but CLSID_WICImagingFactory is then #defined to CLSID_WICImagingFactory2. |
44 //Undo this #define if it has been done so that we link against the symbols | 45 //Undo this #define if it has been done so that we link against the symbols |
45 //we intended to link against on all SDKs. | 46 //we intended to link against on all SDKs. |
46 #if defined(CLSID_WICImagingFactory) | 47 #if defined(CLSID_WICImagingFactory) |
47 #undef CLSID_WICImagingFactory | 48 #undef CLSID_WICImagingFactory |
48 #endif | 49 #endif |
49 | 50 |
| 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 |
50 ///////////////////////////////////////////////////////////////////////// | 253 ///////////////////////////////////////////////////////////////////////// |
51 | 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 ///////////////////////////////////////////////////////////////////////// |
| 268 |
52 SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) { | 269 SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) { |
53 return nullptr; | 270 return nullptr; |
54 } | 271 } |
55 | 272 |
56 ///////////////////////////////////////////////////////////////////////// | 273 ///////////////////////////////////////////////////////////////////////// |
57 | 274 |
58 class SkImageEncoder_WIC : public SkImageEncoder { | 275 class SkImageEncoder_WIC : public SkImageEncoder { |
59 public: | 276 public: |
60 SkImageEncoder_WIC(Type t) : fType(t) {} | 277 SkImageEncoder_WIC(Type t) : fType(t) {} |
61 | |
62 // DO NOT USE this constructor. This exists only so SkForceLinking can | |
63 // link the WIC image encoder. | |
64 SkImageEncoder_WIC() {} | |
65 | 278 |
66 protected: | 279 protected: |
67 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality); | 280 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality); |
68 | 281 |
69 private: | 282 private: |
70 Type fType; | 283 Type fType; |
71 }; | 284 }; |
72 | 285 |
73 bool SkImageEncoder_WIC::onEncode(SkWStream* stream | 286 bool SkImageEncoder_WIC::onEncode(SkWStream* stream |
74 , const SkBitmap& bitmapOrig | 287 , const SkBitmap& bitmapOrig |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 case SkImageEncoder::kPNG_Type: | 444 case SkImageEncoder::kPNG_Type: |
232 break; | 445 break; |
233 default: | 446 default: |
234 return nullptr; | 447 return nullptr; |
235 } | 448 } |
236 return new SkImageEncoder_WIC(t); | 449 return new SkImageEncoder_WIC(t); |
237 } | 450 } |
238 | 451 |
239 static SkImageEncoder_EncodeReg gEReg(sk_imageencoder_wic_factory); | 452 static SkImageEncoder_EncodeReg gEReg(sk_imageencoder_wic_factory); |
240 | 453 |
241 DEFINE_ENCODER_CREATOR(ImageEncoder_WIC); | 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); |
242 | 464 |
243 #endif // defined(SK_BUILD_FOR_WIN32) | 465 #endif // defined(SK_BUILD_FOR_WIN32) |
OLD | NEW |