| OLD | NEW |
| (Empty) |
| 1 | |
| 2 /* | |
| 3 * Copyright 2011 Google Inc. | |
| 4 * | |
| 5 * Use of this source code is governed by a BSD-style license that can be | |
| 6 * found in the LICENSE file. | |
| 7 */ | |
| 8 | |
| 9 #include "SkTypes.h" | |
| 10 | |
| 11 #if defined(SK_BUILD_FOR_WIN32) | |
| 12 | |
| 13 // Workaround for: | |
| 14 // http://connect.microsoft.com/VisualStudio/feedback/details/621653/ | |
| 15 // http://crbug.com/225822 | |
| 16 // In VS2010 both intsafe.h and stdint.h define the following without guards. | |
| 17 // SkTypes brought in windows.h and stdint.h and the following defines are | |
| 18 // not used by this file. However, they may be re-introduced by wincodec.h. | |
| 19 #undef INT8_MIN | |
| 20 #undef INT16_MIN | |
| 21 #undef INT32_MIN | |
| 22 #undef INT64_MIN | |
| 23 #undef INT8_MAX | |
| 24 #undef UINT8_MAX | |
| 25 #undef INT16_MAX | |
| 26 #undef UINT16_MAX | |
| 27 #undef INT32_MAX | |
| 28 #undef UINT32_MAX | |
| 29 #undef INT64_MAX | |
| 30 #undef UINT64_MAX | |
| 31 | |
| 32 #include <wincodec.h> | |
| 33 #include "SkAutoCoInitialize.h" | |
| 34 #include "SkImageEncoder.h" | |
| 35 #include "SkIStream.h" | |
| 36 #include "SkMovie.h" | |
| 37 #include "SkStream.h" | |
| 38 #include "SkTScopedComPtr.h" | |
| 39 #include "SkUnPreMultiply.h" | |
| 40 | |
| 41 //All Windows SDKs back to XPSP2 export the CLSID_WICImagingFactory symbol. | |
| 42 //In the Windows8 SDK the CLSID_WICImagingFactory symbol is still exported | |
| 43 //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 //we intended to link against on all SDKs. | |
| 46 #if defined(CLSID_WICImagingFactory) | |
| 47 #undef CLSID_WICImagingFactory | |
| 48 #endif | |
| 49 | |
| 50 ///////////////////////////////////////////////////////////////////////// | |
| 51 | |
| 52 SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) { | |
| 53 return nullptr; | |
| 54 } | |
| 55 | |
| 56 ///////////////////////////////////////////////////////////////////////// | |
| 57 | |
| 58 class SkImageEncoder_WIC : public SkImageEncoder { | |
| 59 public: | |
| 60 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 | |
| 66 protected: | |
| 67 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality); | |
| 68 | |
| 69 private: | |
| 70 Type fType; | |
| 71 }; | |
| 72 | |
| 73 bool SkImageEncoder_WIC::onEncode(SkWStream* stream | |
| 74 , const SkBitmap& bitmapOrig | |
| 75 , int quality) | |
| 76 { | |
| 77 GUID type; | |
| 78 switch (fType) { | |
| 79 case kBMP_Type: | |
| 80 type = GUID_ContainerFormatBmp; | |
| 81 break; | |
| 82 case kICO_Type: | |
| 83 type = GUID_ContainerFormatIco; | |
| 84 break; | |
| 85 case kJPEG_Type: | |
| 86 type = GUID_ContainerFormatJpeg; | |
| 87 break; | |
| 88 case kPNG_Type: | |
| 89 type = GUID_ContainerFormatPng; | |
| 90 break; | |
| 91 default: | |
| 92 return false; | |
| 93 } | |
| 94 | |
| 95 //Convert to 8888 if needed. | |
| 96 const SkBitmap* bitmap; | |
| 97 SkBitmap bitmapCopy; | |
| 98 if (kN32_SkColorType == bitmapOrig.colorType() && bitmapOrig.isOpaque()) { | |
| 99 bitmap = &bitmapOrig; | |
| 100 } else { | |
| 101 if (!bitmapOrig.copyTo(&bitmapCopy, kN32_SkColorType)) { | |
| 102 return false; | |
| 103 } | |
| 104 bitmap = &bitmapCopy; | |
| 105 } | |
| 106 | |
| 107 // We cannot use PBGRA so we need to unpremultiply ourselves | |
| 108 if (!bitmap->isOpaque()) { | |
| 109 SkAutoLockPixels alp(*bitmap); | |
| 110 | |
| 111 uint8_t* pixels = reinterpret_cast<uint8_t*>(bitmap->getPixels()); | |
| 112 for (int y = 0; y < bitmap->height(); ++y) { | |
| 113 for (int x = 0; x < bitmap->width(); ++x) { | |
| 114 uint8_t* bytes = pixels + y * bitmap->rowBytes() + x * bitmap->b
ytesPerPixel(); | |
| 115 | |
| 116 SkPMColor* src = reinterpret_cast<SkPMColor*>(bytes); | |
| 117 SkColor* dst = reinterpret_cast<SkColor*>(bytes); | |
| 118 | |
| 119 *dst = SkUnPreMultiply::PMColorToColor(*src); | |
| 120 } | |
| 121 } | |
| 122 } | |
| 123 | |
| 124 //Initialize COM. | |
| 125 SkAutoCoInitialize scopedCo; | |
| 126 if (!scopedCo.succeeded()) { | |
| 127 return false; | |
| 128 } | |
| 129 | |
| 130 HRESULT hr = S_OK; | |
| 131 | |
| 132 //Create Windows Imaging Component ImagingFactory. | |
| 133 SkTScopedComPtr<IWICImagingFactory> piImagingFactory; | |
| 134 if (SUCCEEDED(hr)) { | |
| 135 hr = CoCreateInstance( | |
| 136 CLSID_WICImagingFactory | |
| 137 , nullptr | |
| 138 , CLSCTX_INPROC_SERVER | |
| 139 , IID_PPV_ARGS(&piImagingFactory) | |
| 140 ); | |
| 141 } | |
| 142 | |
| 143 //Convert the SkWStream to an IStream. | |
| 144 SkTScopedComPtr<IStream> piStream; | |
| 145 if (SUCCEEDED(hr)) { | |
| 146 hr = SkWIStream::CreateFromSkWStream(stream, &piStream); | |
| 147 } | |
| 148 | |
| 149 //Create an encode of the appropriate type. | |
| 150 SkTScopedComPtr<IWICBitmapEncoder> piEncoder; | |
| 151 if (SUCCEEDED(hr)) { | |
| 152 hr = piImagingFactory->CreateEncoder(type, nullptr, &piEncoder); | |
| 153 } | |
| 154 | |
| 155 if (SUCCEEDED(hr)) { | |
| 156 hr = piEncoder->Initialize(piStream.get(), WICBitmapEncoderNoCache); | |
| 157 } | |
| 158 | |
| 159 //Create a the frame. | |
| 160 SkTScopedComPtr<IWICBitmapFrameEncode> piBitmapFrameEncode; | |
| 161 SkTScopedComPtr<IPropertyBag2> piPropertybag; | |
| 162 if (SUCCEEDED(hr)) { | |
| 163 hr = piEncoder->CreateNewFrame(&piBitmapFrameEncode, &piPropertybag); | |
| 164 } | |
| 165 | |
| 166 if (SUCCEEDED(hr)) { | |
| 167 PROPBAG2 name = { 0 }; | |
| 168 name.dwType = PROPBAG2_TYPE_DATA; | |
| 169 name.vt = VT_R4; | |
| 170 name.pstrName = L"ImageQuality"; | |
| 171 | |
| 172 VARIANT value; | |
| 173 VariantInit(&value); | |
| 174 value.vt = VT_R4; | |
| 175 value.fltVal = (FLOAT)(quality / 100.0); | |
| 176 | |
| 177 //Ignore result code. | |
| 178 // This returns E_FAIL if the named property is not in the bag. | |
| 179 //TODO(bungeman) enumerate the properties, | |
| 180 // write and set hr iff property exists. | |
| 181 piPropertybag->Write(1, &name, &value); | |
| 182 } | |
| 183 if (SUCCEEDED(hr)) { | |
| 184 hr = piBitmapFrameEncode->Initialize(piPropertybag.get()); | |
| 185 } | |
| 186 | |
| 187 //Set the size of the frame. | |
| 188 const UINT width = bitmap->width(); | |
| 189 const UINT height = bitmap->height(); | |
| 190 if (SUCCEEDED(hr)) { | |
| 191 hr = piBitmapFrameEncode->SetSize(width, height); | |
| 192 } | |
| 193 | |
| 194 //Set the pixel format of the frame. If native encoded format cannot match
BGRA, | |
| 195 //it will choose the closest pixel format that it supports. | |
| 196 const WICPixelFormatGUID formatDesired = GUID_WICPixelFormat32bppBGRA; | |
| 197 WICPixelFormatGUID formatGUID = formatDesired; | |
| 198 if (SUCCEEDED(hr)) { | |
| 199 hr = piBitmapFrameEncode->SetPixelFormat(&formatGUID); | |
| 200 } | |
| 201 if (SUCCEEDED(hr)) { | |
| 202 //Be sure the image format is the one requested. | |
| 203 hr = IsEqualGUID(formatGUID, formatDesired) ? S_OK : E_FAIL; | |
| 204 } | |
| 205 | |
| 206 //Write the pixels into the frame. | |
| 207 if (SUCCEEDED(hr)) { | |
| 208 SkAutoLockPixels alp(*bitmap); | |
| 209 const UINT stride = (UINT) bitmap->rowBytes(); | |
| 210 hr = piBitmapFrameEncode->WritePixels( | |
| 211 height | |
| 212 , stride | |
| 213 , stride * height | |
| 214 , reinterpret_cast<BYTE*>(bitmap->getPixels())); | |
| 215 } | |
| 216 | |
| 217 if (SUCCEEDED(hr)) { | |
| 218 hr = piBitmapFrameEncode->Commit(); | |
| 219 } | |
| 220 | |
| 221 if (SUCCEEDED(hr)) { | |
| 222 hr = piEncoder->Commit(); | |
| 223 } | |
| 224 | |
| 225 return SUCCEEDED(hr); | |
| 226 } | |
| 227 | |
| 228 /////////////////////////////////////////////////////////////////////////////// | |
| 229 | |
| 230 static SkImageEncoder* sk_imageencoder_wic_factory(SkImageEncoder::Type t) { | |
| 231 switch (t) { | |
| 232 case SkImageEncoder::kBMP_Type: | |
| 233 case SkImageEncoder::kICO_Type: | |
| 234 case SkImageEncoder::kPNG_Type: | |
| 235 break; | |
| 236 default: | |
| 237 return nullptr; | |
| 238 } | |
| 239 return new SkImageEncoder_WIC(t); | |
| 240 } | |
| 241 | |
| 242 static SkImageEncoder_EncodeReg gEReg(sk_imageencoder_wic_factory); | |
| 243 | |
| 244 DEFINE_ENCODER_CREATOR(ImageEncoder_WIC); | |
| 245 | |
| 246 #endif // defined(SK_BUILD_FOR_WIN32) | |
| OLD | NEW |