| 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 |