1242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com */
8242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
985302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#include "SkTypes.h"
1085302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com
111ee76510f5dbf632d30975fc3509ef4f609156d2mtklein#if defined(SK_BUILD_FOR_WIN32)
121ee76510f5dbf632d30975fc3509ef4f609156d2mtklein
1385302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com// Workaround for:
1485302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com// http://connect.microsoft.com/VisualStudio/feedback/details/621653/
1585302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com// http://crbug.com/225822
1685302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com// In VS2010 both intsafe.h and stdint.h define the following without guards.
1785302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com// SkTypes brought in windows.h and stdint.h and the following defines are
1885302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com// not used by this file. However, they may be re-introduced by wincodec.h.
1985302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef INT8_MIN
2085302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef INT16_MIN
2185302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef INT32_MIN
2285302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef INT64_MIN
2385302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef INT8_MAX
2485302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef UINT8_MAX
2585302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef INT16_MAX
2685302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef UINT16_MAX
2785302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef INT32_MAX
2885302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef UINT32_MAX
2985302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef INT64_MAX
3085302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef UINT64_MAX
31ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
32242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include <wincodec.h>
339df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com#include "SkAutoCoInitialize.h"
34242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "SkImageDecoder.h"
35242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "SkImageEncoder.h"
369df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com#include "SkIStream.h"
37242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "SkMovie.h"
38242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "SkStream.h"
399df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com#include "SkTScopedComPtr.h"
4059bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com#include "SkUnPreMultiply.h"
41242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
42c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com//All Windows SDKs back to XPSP2 export the CLSID_WICImagingFactory symbol.
43c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com//In the Windows8 SDK the CLSID_WICImagingFactory symbol is still exported
44c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com//but CLSID_WICImagingFactory is then #defined to CLSID_WICImagingFactory2.
45c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com//Undo this #define if it has been done so that we link against the symbols
46c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com//we intended to link against on all SDKs.
47c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#if defined(CLSID_WICImagingFactory)
48c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#undef CLSID_WICImagingFactory
49c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#endif
50c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com
51242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comclass SkImageDecoder_WIC : public SkImageDecoder {
5239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.compublic:
5339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    // Decoding modes corresponding to SkImageDecoder::Mode, plus an extra mode for decoding
5439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    // only the format.
5539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    enum WICModes {
5639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        kDecodeFormat_WICMode,
5739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        kDecodeBounds_WICMode,
5839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        kDecodePixels_WICMode,
5939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    };
6039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
6139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    /**
6239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     *  Helper function to decode an SkStream.
6339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     *  @param stream SkStream to decode. Must be at the beginning.
6439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     *  @param bm   SkBitmap to decode into. Only used if wicMode is kDecodeBounds_WICMode or
6596fcdcc219d2a0d3579719b84b28bede76efba64halcanary     *      kDecodePixels_WICMode, in which case it must not be nullptr.
6639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     *  @param format Out parameter for the SkImageDecoder::Format of the SkStream. Only used if
6739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     *      wicMode is kDecodeFormat_WICMode.
6839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     */
6939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    bool decodeStream(SkStream* stream, SkBitmap* bm, WICModes wicMode, Format* format) const;
7039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
71242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comprotected:
7236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    Result onDecode(SkStream* stream, SkBitmap* bm, Mode mode) override;
7339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com};
7439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
7539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comstruct FormatConversion {
7639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    GUID                    fGuidFormat;
7739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    SkImageDecoder::Format  fFormat;
78242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com};
79242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
8039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comstatic const FormatConversion gFormatConversions[] = {
8139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    { GUID_ContainerFormatBmp, SkImageDecoder::kBMP_Format },
8239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    { GUID_ContainerFormatGif, SkImageDecoder::kGIF_Format },
8339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    { GUID_ContainerFormatIco, SkImageDecoder::kICO_Format },
8439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    { GUID_ContainerFormatJpeg, SkImageDecoder::kJPEG_Format },
8539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    { GUID_ContainerFormatPng, SkImageDecoder::kPNG_Format },
8639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com};
8739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
8839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comstatic SkImageDecoder::Format GuidContainerFormat_to_Format(REFGUID guid) {
8939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gFormatConversions); i++) {
9039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        if (IsEqualGUID(guid, gFormatConversions[i].fGuidFormat)) {
9139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            return gFormatConversions[i].fFormat;
9239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        }
9339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    }
9439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    return SkImageDecoder::kUnknown_Format;
9539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com}
9639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
972a1208017dd676f94a53bbb228197c3978dbdd8ascroggoSkImageDecoder::Result SkImageDecoder_WIC::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
9839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    WICModes wicMode;
9939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    switch (mode) {
10039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        case SkImageDecoder::kDecodeBounds_Mode:
10139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            wicMode = kDecodeBounds_WICMode;
10239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            break;
10339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        case SkImageDecoder::kDecodePixels_Mode:
10439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            wicMode = kDecodePixels_WICMode;
10539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            break;
10639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    }
10796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return this->decodeStream(stream, bm, wicMode, nullptr) ? kSuccess : kFailure;
10839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com}
10939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
11039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.combool SkImageDecoder_WIC::decodeStream(SkStream* stream, SkBitmap* bm, WICModes wicMode,
11139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com                                      Format* format) const {
112242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Initialize COM.
1132e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    SkAutoCoInitialize scopedCo;
1142e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    if (!scopedCo.succeeded()) {
1152e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com        return false;
1162e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    }
117d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
1182e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    HRESULT hr = S_OK;
119d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
120242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create Windows Imaging Component ImagingFactory.
1219df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICImagingFactory> piImagingFactory;
122242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
123242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = CoCreateInstance(
124242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            CLSID_WICImagingFactory
12596fcdcc219d2a0d3579719b84b28bede76efba64halcanary            , nullptr
126242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , CLSCTX_INPROC_SERVER
127242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , IID_PPV_ARGS(&piImagingFactory)
128242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
129242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
130d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
131242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Convert SkStream to IStream.
1329df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IStream> piStream;
133242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
1349df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com        hr = SkIStream::CreateFromSkStream(stream, false, &piStream);
135242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
136d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
137242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Make sure we're at the beginning of the stream.
138242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
139242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        LARGE_INTEGER liBeginning = { 0 };
14096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        hr = piStream->Seek(liBeginning, STREAM_SEEK_SET, nullptr);
141242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
142d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
143242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create the decoder from the stream content.
1449df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapDecoder> piBitmapDecoder;
145242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
146242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piImagingFactory->CreateDecoderFromStream(
147242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            piStream.get()                    //Image to be decoded
14896fcdcc219d2a0d3579719b84b28bede76efba64halcanary            , nullptr                            //No particular vendor
149242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , WICDecodeMetadataCacheOnDemand  //Cache metadata when needed
150242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , &piBitmapDecoder                //Pointer to the decoder
151242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
152242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
153d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
15439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    if (kDecodeFormat_WICMode == wicMode) {
15596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        SkASSERT(format != nullptr);
15639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        //Get the format
15739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        if (SUCCEEDED(hr)) {
15839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            GUID guidFormat;
15939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            hr = piBitmapDecoder->GetContainerFormat(&guidFormat);
16039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            if (SUCCEEDED(hr)) {
16139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com                *format = GuidContainerFormat_to_Format(guidFormat);
16239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com                return true;
16339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            }
16439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        }
16539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        return false;
16639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    }
16739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
168242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Get the first frame from the decoder.
1699df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapFrameDecode> piBitmapFrameDecode;
170242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
171242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapDecoder->GetFrame(0, &piBitmapFrameDecode);
172242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
173d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
174242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Get the BitmapSource interface of the frame.
1759df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapSource> piBitmapSourceOriginal;
176242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
177242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameDecode->QueryInterface(
178242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            IID_PPV_ARGS(&piBitmapSourceOriginal)
179242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
180242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
181d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
182242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Get the size of the bitmap.
183242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    UINT width;
184242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    UINT height;
185242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
186242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapSourceOriginal->GetSize(&width, &height);
187242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
188d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
189242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Exit early if we're only looking for the bitmap bounds.
190242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
191a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org        bm->setInfo(SkImageInfo::MakeN32Premul(width, height));
19239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        if (kDecodeBounds_WICMode == wicMode) {
193242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return true;
194242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        }
19596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (!this->allocPixelRef(bm, nullptr)) {
196242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return false;
197242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        }
198242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
199d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
200242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create a format converter.
2019df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICFormatConverter> piFormatConverter;
202242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
203242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piImagingFactory->CreateFormatConverter(&piFormatConverter);
204242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
205d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
2062bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    GUID destinationPixelFormat;
2072bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    if (this->getRequireUnpremultipliedColors()) {
2082bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        destinationPixelFormat = GUID_WICPixelFormat32bppBGRA;
2092bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    } else {
2102bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        destinationPixelFormat = GUID_WICPixelFormat32bppPBGRA;
2112bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    }
2122bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
213242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
214242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piFormatConverter->Initialize(
215242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            piBitmapSourceOriginal.get()      //Input bitmap to convert
2162bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            , destinationPixelFormat          //Destination pixel format
217242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , WICBitmapDitherTypeNone         //Specified dither patterm
21896fcdcc219d2a0d3579719b84b28bede76efba64halcanary            , nullptr                            //Specify a particular palette
219242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , 0.f                             //Alpha threshold
220242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , WICBitmapPaletteTypeCustom      //Palette translation type
221242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
222242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
223d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
224242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Get the BitmapSource interface of the format converter.
2259df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapSource> piBitmapSourceConverted;
226242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
227242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piFormatConverter->QueryInterface(
228242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            IID_PPV_ARGS(&piBitmapSourceConverted)
229242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
230242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
231d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
232242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Copy the pixels into the bitmap.
233242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
234955bb0751a0d48e47a341c7c0adda94977bc8170bungeman@google.com        SkAutoLockPixels alp(*bm);
235dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com        bm->eraseColor(SK_ColorTRANSPARENT);
2368b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com        const UINT stride = (UINT) bm->rowBytes();
237242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapSourceConverted->CopyPixels(
23896fcdcc219d2a0d3579719b84b28bede76efba64halcanary            nullptr,                             //Get all the pixels
239242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            stride,
240242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            stride * height,
241242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            reinterpret_cast<BYTE *>(bm->getPixels())
242242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
24359bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com
24459bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com        // Note: we don't need to premultiply here since we specified PBGRA
245e7e29b7815e97e9c4db55fa9dac48b419352b2c6reed@google.com        if (SkBitmap::ComputeIsOpaque(*bm)) {
246383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com            bm->setAlphaType(kOpaque_SkAlphaType);
247383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com        }
248242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
249d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
250242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    return SUCCEEDED(hr);
251242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
252242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
253242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com/////////////////////////////////////////////////////////////////////////
254242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
255b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comextern SkImageDecoder* image_decoder_from_stream(SkStreamRewindable*);
2564c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com
257b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comSkImageDecoder* SkImageDecoder::Factory(SkStreamRewindable* stream) {
2584c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com    SkImageDecoder* decoder = image_decoder_from_stream(stream);
25996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == decoder) {
2604c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        // If no image decoder specific to the stream exists, use SkImageDecoder_WIC.
261385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        return new SkImageDecoder_WIC;
2624c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com    } else {
2634c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        return decoder;
2644c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com    }
265242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
266242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
267242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com/////////////////////////////////////////////////////////////////////////
268242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
269b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comSkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) {
27096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return nullptr;
271242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
272242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
273242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com/////////////////////////////////////////////////////////////////////////
274242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
275242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comclass SkImageEncoder_WIC : public SkImageEncoder {
276242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.compublic:
277242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    SkImageEncoder_WIC(Type t) : fType(t) {}
278242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
279242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comprotected:
280242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality);
281242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
282242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comprivate:
283242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    Type fType;
284242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com};
285242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
286242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.combool SkImageEncoder_WIC::onEncode(SkWStream* stream
28722b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com                                , const SkBitmap& bitmapOrig
288242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com                                , int quality)
289242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com{
290242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    GUID type;
291242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    switch (fType) {
2924c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case kBMP_Type:
2934c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com            type = GUID_ContainerFormatBmp;
2944c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com            break;
2954c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case kICO_Type:
2964c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com            type = GUID_ContainerFormatIco;
2974c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com            break;
298242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        case kJPEG_Type:
299242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            type = GUID_ContainerFormatJpeg;
300242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            break;
301242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        case kPNG_Type:
302242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            type = GUID_ContainerFormatPng;
303242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            break;
304242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        default:
305242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return false;
306242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
307242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
30822b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    //Convert to 8888 if needed.
30922b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    const SkBitmap* bitmap;
31022b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    SkBitmap bitmapCopy;
31128fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    if (kN32_SkColorType == bitmapOrig.colorType() && bitmapOrig.isOpaque()) {
31222b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com        bitmap = &bitmapOrig;
31322b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    } else {
31428fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        if (!bitmapOrig.copyTo(&bitmapCopy, kN32_SkColorType)) {
31522b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com            return false;
31622b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com        }
31722b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com        bitmap = &bitmapCopy;
31822b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    }
31922b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com
32059bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com    // We cannot use PBGRA so we need to unpremultiply ourselves
32159bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com    if (!bitmap->isOpaque()) {
32259bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com        SkAutoLockPixels alp(*bitmap);
32359bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com
32459bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com        uint8_t* pixels = reinterpret_cast<uint8_t*>(bitmap->getPixels());
32559bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com        for (int y = 0; y < bitmap->height(); ++y) {
32659bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com            for (int x = 0; x < bitmap->width(); ++x) {
32759bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com                uint8_t* bytes = pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel();
32859bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com
32959bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com                SkPMColor* src = reinterpret_cast<SkPMColor*>(bytes);
33059bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com                SkColor* dst = reinterpret_cast<SkColor*>(bytes);
33159bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com
33259bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com                *dst = SkUnPreMultiply::PMColorToColor(*src);
33359bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com            }
33459bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com        }
33559bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com    }
33659bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com
337242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Initialize COM.
3382e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    SkAutoCoInitialize scopedCo;
3392e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    if (!scopedCo.succeeded()) {
3402e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com        return false;
3412e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    }
342d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
3432e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    HRESULT hr = S_OK;
344d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
345242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create Windows Imaging Component ImagingFactory.
3469df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICImagingFactory> piImagingFactory;
347242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
348242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = CoCreateInstance(
349242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            CLSID_WICImagingFactory
35096fcdcc219d2a0d3579719b84b28bede76efba64halcanary            , nullptr
351242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , CLSCTX_INPROC_SERVER
352242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , IID_PPV_ARGS(&piImagingFactory)
353242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
354242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
355d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
3569df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    //Convert the SkWStream to an IStream.
3579df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IStream> piStream;
358242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
3599df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com        hr = SkWIStream::CreateFromSkWStream(stream, &piStream);
360242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
361d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
362242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create an encode of the appropriate type.
3639df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapEncoder> piEncoder;
364242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
36596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        hr = piImagingFactory->CreateEncoder(type, nullptr, &piEncoder);
366242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
367d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
368242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
369242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piEncoder->Initialize(piStream.get(), WICBitmapEncoderNoCache);
370242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
371d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
372242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create a the frame.
3739df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapFrameEncode> piBitmapFrameEncode;
3749df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IPropertyBag2> piPropertybag;
375242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
376242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piEncoder->CreateNewFrame(&piBitmapFrameEncode, &piPropertybag);
377242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
378d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
379242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
380242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        PROPBAG2 name = { 0 };
381242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        name.dwType = PROPBAG2_TYPE_DATA;
382242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        name.vt = VT_R4;
383242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        name.pstrName = L"ImageQuality";
384d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
385242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        VARIANT value;
386242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        VariantInit(&value);
387242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        value.vt = VT_R4;
388242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        value.fltVal = (FLOAT)(quality / 100.0);
389d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
390242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //Ignore result code.
391242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //  This returns E_FAIL if the named property is not in the bag.
392242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //TODO(bungeman) enumerate the properties,
393242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //  write and set hr iff property exists.
394242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        piPropertybag->Write(1, &name, &value);
395242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
396242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
397242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->Initialize(piPropertybag.get());
398242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
399d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
400242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Set the size of the frame.
40122b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    const UINT width = bitmap->width();
40222b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    const UINT height = bitmap->height();
403242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
404242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->SetSize(width, height);
405242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
406d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
407242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Set the pixel format of the frame.
408242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    const WICPixelFormatGUID formatDesired = GUID_WICPixelFormat32bppBGRA;
409242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    WICPixelFormatGUID formatGUID = formatDesired;
410242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
411242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->SetPixelFormat(&formatGUID);
412242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
413242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
414242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //Be sure the image format is the one requested.
415242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = IsEqualGUID(formatGUID, formatDesired) ? S_OK : E_FAIL;
416242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
417d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
418242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Write the pixels into the frame.
419242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
420955bb0751a0d48e47a341c7c0adda94977bc8170bungeman@google.com        SkAutoLockPixels alp(*bitmap);
4218b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com        const UINT stride = (UINT) bitmap->rowBytes();
422242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->WritePixels(
423242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            height
4244b18f5767ab1df7fedf0ff2e3a9eac7f7c500c36bungeman@google.com            , stride
4254b18f5767ab1df7fedf0ff2e3a9eac7f7c500c36bungeman@google.com            , stride * height
42622b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com            , reinterpret_cast<BYTE*>(bitmap->getPixels()));
427242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
428d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
429242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
430242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->Commit();
431242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
432d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
433242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
434242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piEncoder->Commit();
435242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
436d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
437242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    return SUCCEEDED(hr);
438242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
439242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
4404c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com///////////////////////////////////////////////////////////////////////////////
4414c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com
4424c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.comstatic SkImageEncoder* sk_imageencoder_wic_factory(SkImageEncoder::Type t) {
443242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    switch (t) {
4444c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case SkImageEncoder::kBMP_Type:
4454c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case SkImageEncoder::kICO_Type:
4464c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case SkImageEncoder::kJPEG_Type:
4474c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case SkImageEncoder::kPNG_Type:
448242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            break;
449242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        default:
45096fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
451242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
452385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    return new SkImageEncoder_WIC(t);
453242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
4544c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com
455b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comstatic SkImageEncoder_EncodeReg gEReg(sk_imageencoder_wic_factory);
45639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
457b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comstatic SkImageDecoder::Format get_format_wic(SkStreamRewindable* stream) {
45839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    SkImageDecoder::Format format;
45939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    SkImageDecoder_WIC codec;
46096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (!codec.decodeStream(stream, nullptr, SkImageDecoder_WIC::kDecodeFormat_WICMode, &format)) {
46139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        format = SkImageDecoder::kUnknown_Format;
46239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    }
46339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    return format;
46439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com}
46539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
466b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comstatic SkImageDecoder_FormatReg gFormatReg(get_format_wic);
4671ee76510f5dbf632d30975fc3509ef4f609156d2mtklein
4681ee76510f5dbf632d30975fc3509ef4f609156d2mtklein#endif // defined(SK_BUILD_FOR_WIN32)
469