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
1185302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com// Workaround for:
1285302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com// http://connect.microsoft.com/VisualStudio/feedback/details/621653/
1385302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com// http://crbug.com/225822
1485302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com// In VS2010 both intsafe.h and stdint.h define the following without guards.
1585302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com// SkTypes brought in windows.h and stdint.h and the following defines are
1685302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com// not used by this file. However, they may be re-introduced by wincodec.h.
1785302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef INT8_MIN
1885302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef INT16_MIN
1985302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef INT32_MIN
2085302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef INT64_MIN
2185302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef INT8_MAX
2285302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef UINT8_MAX
2385302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef INT16_MAX
2485302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef UINT16_MAX
2585302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef INT32_MAX
2685302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef UINT32_MAX
2785302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef INT64_MAX
2885302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com#undef UINT64_MAX
29ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
30242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include <wincodec.h>
319df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com#include "SkAutoCoInitialize.h"
32242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "SkImageDecoder.h"
33242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "SkImageEncoder.h"
349df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com#include "SkIStream.h"
35242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "SkMovie.h"
36242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "SkStream.h"
379df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com#include "SkTScopedComPtr.h"
3859bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com#include "SkUnPreMultiply.h"
39242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
40c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com//All Windows SDKs back to XPSP2 export the CLSID_WICImagingFactory symbol.
41c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com//In the Windows8 SDK the CLSID_WICImagingFactory symbol is still exported
42c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com//but CLSID_WICImagingFactory is then #defined to CLSID_WICImagingFactory2.
43c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com//Undo this #define if it has been done so that we link against the symbols
44c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com//we intended to link against on all SDKs.
45c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#if defined(CLSID_WICImagingFactory)
46c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#undef CLSID_WICImagingFactory
47c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#endif
48c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com
49242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comclass SkImageDecoder_WIC : public SkImageDecoder {
5039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.compublic:
5139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    // Decoding modes corresponding to SkImageDecoder::Mode, plus an extra mode for decoding
5239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    // only the format.
5339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    enum WICModes {
5439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        kDecodeFormat_WICMode,
5539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        kDecodeBounds_WICMode,
5639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        kDecodePixels_WICMode,
5739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    };
5839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
5939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    /**
6039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     *  Helper function to decode an SkStream.
6139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     *  @param stream SkStream to decode. Must be at the beginning.
6239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     *  @param bm   SkBitmap to decode into. Only used if wicMode is kDecodeBounds_WICMode or
6339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     *      kDecodePixels_WICMode, in which case it must not be NULL.
6439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     *  @param format Out parameter for the SkImageDecoder::Format of the SkStream. Only used if
6539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     *      wicMode is kDecodeFormat_WICMode.
6639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     */
6739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    bool decodeStream(SkStream* stream, SkBitmap* bm, WICModes wicMode, Format* format) const;
6839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
69242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comprotected:
7039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode) SK_OVERRIDE;
7139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com};
7239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
7339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comstruct FormatConversion {
7439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    GUID                    fGuidFormat;
7539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    SkImageDecoder::Format  fFormat;
76242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com};
77242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
7839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comstatic const FormatConversion gFormatConversions[] = {
7939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    { GUID_ContainerFormatBmp, SkImageDecoder::kBMP_Format },
8039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    { GUID_ContainerFormatGif, SkImageDecoder::kGIF_Format },
8139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    { GUID_ContainerFormatIco, SkImageDecoder::kICO_Format },
8239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    { GUID_ContainerFormatJpeg, SkImageDecoder::kJPEG_Format },
8339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    { GUID_ContainerFormatPng, SkImageDecoder::kPNG_Format },
8439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com};
8539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
8639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comstatic SkImageDecoder::Format GuidContainerFormat_to_Format(REFGUID guid) {
8739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gFormatConversions); i++) {
8839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        if (IsEqualGUID(guid, gFormatConversions[i].fGuidFormat)) {
8939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            return gFormatConversions[i].fFormat;
9039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        }
9139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    }
9239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    return SkImageDecoder::kUnknown_Format;
9339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com}
9439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
95242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.combool SkImageDecoder_WIC::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
9639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    WICModes wicMode;
9739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    switch (mode) {
9839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        case SkImageDecoder::kDecodeBounds_Mode:
9939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            wicMode = kDecodeBounds_WICMode;
10039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            break;
10139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        case SkImageDecoder::kDecodePixels_Mode:
10239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            wicMode = kDecodePixels_WICMode;
10339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            break;
10439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    }
10539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    return this->decodeStream(stream, bm, wicMode, NULL);
10639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com}
10739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
10839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.combool SkImageDecoder_WIC::decodeStream(SkStream* stream, SkBitmap* bm, WICModes wicMode,
10939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com                                      Format* format) const {
110242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Initialize COM.
1112e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    SkAutoCoInitialize scopedCo;
1122e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    if (!scopedCo.succeeded()) {
1132e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com        return false;
1142e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    }
115d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
1162e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    HRESULT hr = S_OK;
117d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
118242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create Windows Imaging Component ImagingFactory.
1199df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICImagingFactory> piImagingFactory;
120242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
121242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = CoCreateInstance(
122242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            CLSID_WICImagingFactory
123242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , NULL
124242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , CLSCTX_INPROC_SERVER
125242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , IID_PPV_ARGS(&piImagingFactory)
126242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
127242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
128d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
129242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Convert SkStream to IStream.
1309df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IStream> piStream;
131242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
1329df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com        hr = SkIStream::CreateFromSkStream(stream, false, &piStream);
133242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
134d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
135242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Make sure we're at the beginning of the stream.
136242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
137242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        LARGE_INTEGER liBeginning = { 0 };
138242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piStream->Seek(liBeginning, STREAM_SEEK_SET, NULL);
139242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
140d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
141242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create the decoder from the stream content.
1429df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapDecoder> piBitmapDecoder;
143242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
144242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piImagingFactory->CreateDecoderFromStream(
145242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            piStream.get()                    //Image to be decoded
146242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , NULL                            //No particular vendor
147242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , WICDecodeMetadataCacheOnDemand  //Cache metadata when needed
148242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , &piBitmapDecoder                //Pointer to the decoder
149242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
150242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
151d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
15239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    if (kDecodeFormat_WICMode == wicMode) {
15339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        SkASSERT(format != NULL);
15439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        //Get the format
15539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        if (SUCCEEDED(hr)) {
15639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            GUID guidFormat;
15739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            hr = piBitmapDecoder->GetContainerFormat(&guidFormat);
15839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            if (SUCCEEDED(hr)) {
15939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com                *format = GuidContainerFormat_to_Format(guidFormat);
16039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com                return true;
16139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            }
16239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        }
16339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        return false;
16439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    }
16539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
166242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Get the first frame from the decoder.
1679df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapFrameDecode> piBitmapFrameDecode;
168242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
169242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapDecoder->GetFrame(0, &piBitmapFrameDecode);
170242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
171d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
172242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Get the BitmapSource interface of the frame.
1739df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapSource> piBitmapSourceOriginal;
174242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
175242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameDecode->QueryInterface(
176242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            IID_PPV_ARGS(&piBitmapSourceOriginal)
177242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
178242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
179d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
180242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Get the size of the bitmap.
181242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    UINT width;
182242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    UINT height;
183242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
184242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapSourceOriginal->GetSize(&width, &height);
185242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
186d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
187242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Exit early if we're only looking for the bitmap bounds.
188242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
189a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org        bm->setInfo(SkImageInfo::MakeN32Premul(width, height));
19039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        if (kDecodeBounds_WICMode == wicMode) {
191242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return true;
192242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        }
193242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        if (!this->allocPixelRef(bm, NULL)) {
194242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return false;
195242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        }
196242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
197d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
198242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create a format converter.
1999df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICFormatConverter> piFormatConverter;
200242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
201242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piImagingFactory->CreateFormatConverter(&piFormatConverter);
202242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
203d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
2042bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    GUID destinationPixelFormat;
2052bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    if (this->getRequireUnpremultipliedColors()) {
2062bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        destinationPixelFormat = GUID_WICPixelFormat32bppBGRA;
2072bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    } else {
2082bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        destinationPixelFormat = GUID_WICPixelFormat32bppPBGRA;
2092bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    }
2102bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
211242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
212242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piFormatConverter->Initialize(
213242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            piBitmapSourceOriginal.get()      //Input bitmap to convert
2142bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            , destinationPixelFormat          //Destination pixel format
215242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , WICBitmapDitherTypeNone         //Specified dither patterm
216242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , NULL                            //Specify a particular palette
217242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , 0.f                             //Alpha threshold
218242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , WICBitmapPaletteTypeCustom      //Palette translation type
219242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
220242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
221d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
222242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Get the BitmapSource interface of the format converter.
2239df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapSource> piBitmapSourceConverted;
224242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
225242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piFormatConverter->QueryInterface(
226242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            IID_PPV_ARGS(&piBitmapSourceConverted)
227242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
228242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
229d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
230242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Copy the pixels into the bitmap.
231242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
232955bb0751a0d48e47a341c7c0adda94977bc8170bungeman@google.com        SkAutoLockPixels alp(*bm);
233dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com        bm->eraseColor(SK_ColorTRANSPARENT);
2348b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com        const UINT stride = (UINT) bm->rowBytes();
235242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapSourceConverted->CopyPixels(
236242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            NULL,                             //Get all the pixels
237242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            stride,
238242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            stride * height,
239242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            reinterpret_cast<BYTE *>(bm->getPixels())
240242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
24159bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com
24259bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com        // Note: we don't need to premultiply here since we specified PBGRA
243e7e29b7815e97e9c4db55fa9dac48b419352b2c6reed@google.com        if (SkBitmap::ComputeIsOpaque(*bm)) {
244383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com            bm->setAlphaType(kOpaque_SkAlphaType);
245383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com        }
246242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
247d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
248242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    return SUCCEEDED(hr);
249242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
250242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
251242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com/////////////////////////////////////////////////////////////////////////
252242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
253b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comextern SkImageDecoder* image_decoder_from_stream(SkStreamRewindable*);
2544c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com
255b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comSkImageDecoder* SkImageDecoder::Factory(SkStreamRewindable* stream) {
2564c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com    SkImageDecoder* decoder = image_decoder_from_stream(stream);
2574c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com    if (NULL == decoder) {
2584c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        // If no image decoder specific to the stream exists, use SkImageDecoder_WIC.
2594c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        return SkNEW(SkImageDecoder_WIC);
2604c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com    } else {
2614c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        return decoder;
2624c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com    }
263242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
264242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
265242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com/////////////////////////////////////////////////////////////////////////
266242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
267b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comSkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) {
268242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    return NULL;
269242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
270242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
271242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com/////////////////////////////////////////////////////////////////////////
272242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
273242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comclass SkImageEncoder_WIC : public SkImageEncoder {
274242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.compublic:
275242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    SkImageEncoder_WIC(Type t) : fType(t) {}
276242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
277242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comprotected:
278242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality);
279242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
280242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comprivate:
281242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    Type fType;
282242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com};
283242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
284242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.combool SkImageEncoder_WIC::onEncode(SkWStream* stream
28522b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com                                , const SkBitmap& bitmapOrig
286242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com                                , int quality)
287242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com{
288242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    GUID type;
289242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    switch (fType) {
2904c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case kBMP_Type:
2914c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com            type = GUID_ContainerFormatBmp;
2924c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com            break;
2934c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case kICO_Type:
2944c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com            type = GUID_ContainerFormatIco;
2954c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com            break;
296242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        case kJPEG_Type:
297242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            type = GUID_ContainerFormatJpeg;
298242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            break;
299242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        case kPNG_Type:
300242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            type = GUID_ContainerFormatPng;
301242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            break;
302242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        default:
303242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return false;
304242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
305242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
30622b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    //Convert to 8888 if needed.
30722b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    const SkBitmap* bitmap;
30822b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    SkBitmap bitmapCopy;
30928fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    if (kN32_SkColorType == bitmapOrig.colorType() && bitmapOrig.isOpaque()) {
31022b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com        bitmap = &bitmapOrig;
31122b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    } else {
31228fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        if (!bitmapOrig.copyTo(&bitmapCopy, kN32_SkColorType)) {
31322b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com            return false;
31422b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com        }
31522b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com        bitmap = &bitmapCopy;
31622b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    }
31722b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com
31859bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com    // We cannot use PBGRA so we need to unpremultiply ourselves
31959bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com    if (!bitmap->isOpaque()) {
32059bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com        SkAutoLockPixels alp(*bitmap);
32159bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com
32259bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com        uint8_t* pixels = reinterpret_cast<uint8_t*>(bitmap->getPixels());
32359bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com        for (int y = 0; y < bitmap->height(); ++y) {
32459bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com            for (int x = 0; x < bitmap->width(); ++x) {
32559bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com                uint8_t* bytes = pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel();
32659bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com
32759bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com                SkPMColor* src = reinterpret_cast<SkPMColor*>(bytes);
32859bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com                SkColor* dst = reinterpret_cast<SkColor*>(bytes);
32959bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com
33059bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com                *dst = SkUnPreMultiply::PMColorToColor(*src);
33159bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com            }
33259bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com        }
33359bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com    }
33459bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com
335242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Initialize COM.
3362e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    SkAutoCoInitialize scopedCo;
3372e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    if (!scopedCo.succeeded()) {
3382e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com        return false;
3392e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    }
340d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
3412e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    HRESULT hr = S_OK;
342d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
343242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create Windows Imaging Component ImagingFactory.
3449df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICImagingFactory> piImagingFactory;
345242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
346242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = CoCreateInstance(
347242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            CLSID_WICImagingFactory
348242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , NULL
349242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , CLSCTX_INPROC_SERVER
350242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , IID_PPV_ARGS(&piImagingFactory)
351242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
352242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
353d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
3549df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    //Convert the SkWStream to an IStream.
3559df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IStream> piStream;
356242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
3579df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com        hr = SkWIStream::CreateFromSkWStream(stream, &piStream);
358242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
359d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
360242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create an encode of the appropriate type.
3619df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapEncoder> piEncoder;
362242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
363242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piImagingFactory->CreateEncoder(type, NULL, &piEncoder);
364242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
365d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
366242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
367242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piEncoder->Initialize(piStream.get(), WICBitmapEncoderNoCache);
368242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
369d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
370242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create a the frame.
3719df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapFrameEncode> piBitmapFrameEncode;
3729df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IPropertyBag2> piPropertybag;
373242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
374242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piEncoder->CreateNewFrame(&piBitmapFrameEncode, &piPropertybag);
375242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
376d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
377242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
378242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        PROPBAG2 name = { 0 };
379242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        name.dwType = PROPBAG2_TYPE_DATA;
380242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        name.vt = VT_R4;
381242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        name.pstrName = L"ImageQuality";
382d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
383242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        VARIANT value;
384242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        VariantInit(&value);
385242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        value.vt = VT_R4;
386242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        value.fltVal = (FLOAT)(quality / 100.0);
387d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
388242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //Ignore result code.
389242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //  This returns E_FAIL if the named property is not in the bag.
390242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //TODO(bungeman) enumerate the properties,
391242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //  write and set hr iff property exists.
392242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        piPropertybag->Write(1, &name, &value);
393242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
394242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
395242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->Initialize(piPropertybag.get());
396242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
397d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
398242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Set the size of the frame.
39922b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    const UINT width = bitmap->width();
40022b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    const UINT height = bitmap->height();
401242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
402242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->SetSize(width, height);
403242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
404d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
405242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Set the pixel format of the frame.
406242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    const WICPixelFormatGUID formatDesired = GUID_WICPixelFormat32bppBGRA;
407242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    WICPixelFormatGUID formatGUID = formatDesired;
408242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
409242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->SetPixelFormat(&formatGUID);
410242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
411242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
412242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //Be sure the image format is the one requested.
413242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = IsEqualGUID(formatGUID, formatDesired) ? S_OK : E_FAIL;
414242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
415d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
416242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Write the pixels into the frame.
417242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
418955bb0751a0d48e47a341c7c0adda94977bc8170bungeman@google.com        SkAutoLockPixels alp(*bitmap);
4198b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com        const UINT stride = (UINT) bitmap->rowBytes();
420242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->WritePixels(
421242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            height
4224b18f5767ab1df7fedf0ff2e3a9eac7f7c500c36bungeman@google.com            , stride
4234b18f5767ab1df7fedf0ff2e3a9eac7f7c500c36bungeman@google.com            , stride * height
42422b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com            , reinterpret_cast<BYTE*>(bitmap->getPixels()));
425242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
426d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
427242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
428242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->Commit();
429242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
430d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
431242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
432242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piEncoder->Commit();
433242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
434d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
435242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    return SUCCEEDED(hr);
436242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
437242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
4384c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com///////////////////////////////////////////////////////////////////////////////
4394c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com
4404c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.comstatic SkImageEncoder* sk_imageencoder_wic_factory(SkImageEncoder::Type t) {
441242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    switch (t) {
4424c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case SkImageEncoder::kBMP_Type:
4434c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case SkImageEncoder::kICO_Type:
4444c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case SkImageEncoder::kJPEG_Type:
4454c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case SkImageEncoder::kPNG_Type:
446242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            break;
447242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        default:
448242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return NULL;
449242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
450242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    return SkNEW_ARGS(SkImageEncoder_WIC, (t));
451242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
4524c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com
453b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comstatic SkImageEncoder_EncodeReg gEReg(sk_imageencoder_wic_factory);
45439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
455b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comstatic SkImageDecoder::Format get_format_wic(SkStreamRewindable* stream) {
45639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    SkImageDecoder::Format format;
45739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    SkImageDecoder_WIC codec;
45839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    if (!codec.decodeStream(stream, NULL, SkImageDecoder_WIC::kDecodeFormat_WICMode, &format)) {
45939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        format = SkImageDecoder::kUnknown_Format;
46039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    }
46139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    return format;
46239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com}
46339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
464b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comstatic SkImageDecoder_FormatReg gFormatReg(get_format_wic);
465