SkImageDecoder_WIC.cpp revision 39edf4cd94e6fbeb8c1187a588b314e9795c81e4
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
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
10242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#define WIN32_LEAN_AND_MEAN
11242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include <Windows.h>
12242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include <wincodec.h>
139df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com#include "SkAutoCoInitialize.h"
14242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "SkImageDecoder.h"
15242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "SkImageEncoder.h"
169df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com#include "SkIStream.h"
17242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "SkMovie.h"
18242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "SkStream.h"
199df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com#include "SkTScopedComPtr.h"
2059bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com#include "SkUnPreMultiply.h"
21242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
22c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com//All Windows SDKs back to XPSP2 export the CLSID_WICImagingFactory symbol.
23c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com//In the Windows8 SDK the CLSID_WICImagingFactory symbol is still exported
24c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com//but CLSID_WICImagingFactory is then #defined to CLSID_WICImagingFactory2.
25c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com//Undo this #define if it has been done so that we link against the symbols
26c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com//we intended to link against on all SDKs.
27c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#if defined(CLSID_WICImagingFactory)
28c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#undef CLSID_WICImagingFactory
29c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#endif
30c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com
31242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comclass SkImageDecoder_WIC : public SkImageDecoder {
3239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.compublic:
3339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    // Decoding modes corresponding to SkImageDecoder::Mode, plus an extra mode for decoding
3439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    // only the format.
3539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    enum WICModes {
3639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        kDecodeFormat_WICMode,
3739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        kDecodeBounds_WICMode,
3839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        kDecodePixels_WICMode,
3939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    };
4039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
4139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    /**
4239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     *  Helper function to decode an SkStream.
4339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     *  @param stream SkStream to decode. Must be at the beginning.
4439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     *  @param bm   SkBitmap to decode into. Only used if wicMode is kDecodeBounds_WICMode or
4539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     *      kDecodePixels_WICMode, in which case it must not be NULL.
4639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     *  @param format Out parameter for the SkImageDecoder::Format of the SkStream. Only used if
4739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     *      wicMode is kDecodeFormat_WICMode.
4839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com     */
4939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    bool decodeStream(SkStream* stream, SkBitmap* bm, WICModes wicMode, Format* format) const;
5039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
51242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comprotected:
5239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode) SK_OVERRIDE;
5339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com};
5439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
5539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comstruct FormatConversion {
5639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    GUID                    fGuidFormat;
5739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    SkImageDecoder::Format  fFormat;
58242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com};
59242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
6039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comstatic const FormatConversion gFormatConversions[] = {
6139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    { GUID_ContainerFormatBmp, SkImageDecoder::kBMP_Format },
6239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    { GUID_ContainerFormatGif, SkImageDecoder::kGIF_Format },
6339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    { GUID_ContainerFormatIco, SkImageDecoder::kICO_Format },
6439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    { GUID_ContainerFormatJpeg, SkImageDecoder::kJPEG_Format },
6539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    { GUID_ContainerFormatPng, SkImageDecoder::kPNG_Format },
6639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com};
6739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
6839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comstatic SkImageDecoder::Format GuidContainerFormat_to_Format(REFGUID guid) {
6939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gFormatConversions); i++) {
7039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        if (IsEqualGUID(guid, gFormatConversions[i].fGuidFormat)) {
7139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            return gFormatConversions[i].fFormat;
7239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        }
7339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    }
7439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    return SkImageDecoder::kUnknown_Format;
7539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com}
7639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
77242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.combool SkImageDecoder_WIC::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
7839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    WICModes wicMode;
7939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    switch (mode) {
8039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        case SkImageDecoder::kDecodeBounds_Mode:
8139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            wicMode = kDecodeBounds_WICMode;
8239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            break;
8339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        case SkImageDecoder::kDecodePixels_Mode:
8439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            wicMode = kDecodePixels_WICMode;
8539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            break;
8639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    }
8739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    return this->decodeStream(stream, bm, wicMode, NULL);
8839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com}
8939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
9039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.combool SkImageDecoder_WIC::decodeStream(SkStream* stream, SkBitmap* bm, WICModes wicMode,
9139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com                                      Format* format) const {
92242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Initialize COM.
932e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    SkAutoCoInitialize scopedCo;
942e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    if (!scopedCo.succeeded()) {
952e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com        return false;
962e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    }
97d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
982e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    HRESULT hr = S_OK;
99d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
100242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create Windows Imaging Component ImagingFactory.
1019df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICImagingFactory> piImagingFactory;
102242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
103242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = CoCreateInstance(
104242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            CLSID_WICImagingFactory
105242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , NULL
106242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , CLSCTX_INPROC_SERVER
107242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , IID_PPV_ARGS(&piImagingFactory)
108242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
109242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
110d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
111242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Convert SkStream to IStream.
1129df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IStream> piStream;
113242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
1149df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com        hr = SkIStream::CreateFromSkStream(stream, false, &piStream);
115242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
116d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
117242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Make sure we're at the beginning of the stream.
118242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
119242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        LARGE_INTEGER liBeginning = { 0 };
120242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piStream->Seek(liBeginning, STREAM_SEEK_SET, NULL);
121242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
122d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
123242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create the decoder from the stream content.
1249df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapDecoder> piBitmapDecoder;
125242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
126242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piImagingFactory->CreateDecoderFromStream(
127242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            piStream.get()                    //Image to be decoded
128242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , NULL                            //No particular vendor
129242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , WICDecodeMetadataCacheOnDemand  //Cache metadata when needed
130242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , &piBitmapDecoder                //Pointer to the decoder
131242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
132242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
133d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
13439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    if (kDecodeFormat_WICMode == wicMode) {
13539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        SkASSERT(format != NULL);
13639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        //Get the format
13739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        if (SUCCEEDED(hr)) {
13839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            GUID guidFormat;
13939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            hr = piBitmapDecoder->GetContainerFormat(&guidFormat);
14039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            if (SUCCEEDED(hr)) {
14139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com                *format = GuidContainerFormat_to_Format(guidFormat);
14239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com                return true;
14339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            }
14439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        }
14539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        return false;
14639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    }
14739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
148242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Get the first frame from the decoder.
1499df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapFrameDecode> piBitmapFrameDecode;
150242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
151242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapDecoder->GetFrame(0, &piBitmapFrameDecode);
152242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
153d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
154242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Get the BitmapSource interface of the frame.
1559df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapSource> piBitmapSourceOriginal;
156242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
157242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameDecode->QueryInterface(
158242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            IID_PPV_ARGS(&piBitmapSourceOriginal)
159242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
160242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
161d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
162242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Get the size of the bitmap.
163242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    UINT width;
164242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    UINT height;
165242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
166242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapSourceOriginal->GetSize(&width, &height);
167242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
168d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
169242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Exit early if we're only looking for the bitmap bounds.
170242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
171242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        bm->setConfig(SkBitmap::kARGB_8888_Config, width, height);
17239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        if (kDecodeBounds_WICMode == wicMode) {
173242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return true;
174242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        }
175242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        if (!this->allocPixelRef(bm, NULL)) {
176242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return false;
177242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        }
178242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
179d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
180242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create a format converter.
1819df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICFormatConverter> piFormatConverter;
182242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
183242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piImagingFactory->CreateFormatConverter(&piFormatConverter);
184242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
185d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
186242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
187242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piFormatConverter->Initialize(
188242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            piBitmapSourceOriginal.get()      //Input bitmap to convert
189242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , GUID_WICPixelFormat32bppPBGRA   //Destination pixel format
190242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , WICBitmapDitherTypeNone         //Specified dither patterm
191242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , NULL                            //Specify a particular palette
192242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , 0.f                             //Alpha threshold
193242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , WICBitmapPaletteTypeCustom      //Palette translation type
194242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
195242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
196d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
197242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Get the BitmapSource interface of the format converter.
1989df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapSource> piBitmapSourceConverted;
199242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
200242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piFormatConverter->QueryInterface(
201242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            IID_PPV_ARGS(&piBitmapSourceConverted)
202242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
203242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
204d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
205242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Copy the pixels into the bitmap.
206242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
207955bb0751a0d48e47a341c7c0adda94977bc8170bungeman@google.com        SkAutoLockPixels alp(*bm);
208dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com        bm->eraseColor(SK_ColorTRANSPARENT);
209242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        const int stride = bm->rowBytes();
210242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapSourceConverted->CopyPixels(
211242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            NULL,                             //Get all the pixels
212242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            stride,
213242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            stride * height,
214242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            reinterpret_cast<BYTE *>(bm->getPixels())
215242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
21659bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com
21759bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com        // Note: we don't need to premultiply here since we specified PBGRA
21859bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com        bm->computeAndSetOpaquePredicate();
219242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
220d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
221242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    return SUCCEEDED(hr);
222242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
223242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
224242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com/////////////////////////////////////////////////////////////////////////
225242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
2264c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.comextern SkImageDecoder* image_decoder_from_stream(SkStream*);
2274c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com
228242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comSkImageDecoder* SkImageDecoder::Factory(SkStream* stream) {
2294c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com    SkImageDecoder* decoder = image_decoder_from_stream(stream);
2304c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com    if (NULL == decoder) {
2314c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        // If no image decoder specific to the stream exists, use SkImageDecoder_WIC.
2324c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        return SkNEW(SkImageDecoder_WIC);
2334c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com    } else {
2344c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        return decoder;
2354c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com    }
236242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
237242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
238242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com/////////////////////////////////////////////////////////////////////////
239242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
240242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comSkMovie* SkMovie::DecodeStream(SkStream* stream) {
241242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    return NULL;
242242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
243242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
244242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com/////////////////////////////////////////////////////////////////////////
245242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
246242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comclass SkImageEncoder_WIC : public SkImageEncoder {
247242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.compublic:
248242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    SkImageEncoder_WIC(Type t) : fType(t) {}
249242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
250242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comprotected:
251242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality);
252242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
253242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comprivate:
254242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    Type fType;
255242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com};
256242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
257242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.combool SkImageEncoder_WIC::onEncode(SkWStream* stream
25822b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com                                , const SkBitmap& bitmapOrig
259242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com                                , int quality)
260242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com{
261242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    GUID type;
262242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    switch (fType) {
2634c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case kBMP_Type:
2644c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com            type = GUID_ContainerFormatBmp;
2654c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com            break;
2664c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case kICO_Type:
2674c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com            type = GUID_ContainerFormatIco;
2684c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com            break;
269242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        case kJPEG_Type:
270242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            type = GUID_ContainerFormatJpeg;
271242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            break;
272242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        case kPNG_Type:
273242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            type = GUID_ContainerFormatPng;
274242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            break;
275242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        default:
276242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return false;
277242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
278242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
27922b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    //Convert to 8888 if needed.
28022b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    const SkBitmap* bitmap;
28122b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    SkBitmap bitmapCopy;
28259bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com    if (SkBitmap::kARGB_8888_Config == bitmapOrig.config() && bitmapOrig.isOpaque()) {
28322b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com        bitmap = &bitmapOrig;
28422b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    } else {
28522b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com        if (!bitmapOrig.copyTo(&bitmapCopy, SkBitmap::kARGB_8888_Config)) {
28622b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com            return false;
28722b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com        }
28822b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com        bitmap = &bitmapCopy;
28922b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    }
29022b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com
29159bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com    // We cannot use PBGRA so we need to unpremultiply ourselves
29259bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com    if (!bitmap->isOpaque()) {
29359bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com        SkAutoLockPixels alp(*bitmap);
29459bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com
29559bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com        uint8_t* pixels = reinterpret_cast<uint8_t*>(bitmap->getPixels());
29659bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com        for (int y = 0; y < bitmap->height(); ++y) {
29759bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com            for (int x = 0; x < bitmap->width(); ++x) {
29859bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com                uint8_t* bytes = pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel();
29959bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com
30059bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com                SkPMColor* src = reinterpret_cast<SkPMColor*>(bytes);
30159bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com                SkColor* dst = reinterpret_cast<SkColor*>(bytes);
30259bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com
30359bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com                *dst = SkUnPreMultiply::PMColorToColor(*src);
30459bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com            }
30559bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com        }
30659bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com    }
30759bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com
308242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Initialize COM.
3092e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    SkAutoCoInitialize scopedCo;
3102e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    if (!scopedCo.succeeded()) {
3112e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com        return false;
3122e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    }
313d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
3142e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com    HRESULT hr = S_OK;
315d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
316242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create Windows Imaging Component ImagingFactory.
3179df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICImagingFactory> piImagingFactory;
318242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
319242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = CoCreateInstance(
320242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            CLSID_WICImagingFactory
321242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , NULL
322242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , CLSCTX_INPROC_SERVER
323242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , IID_PPV_ARGS(&piImagingFactory)
324242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
325242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
326d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
3279df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    //Convert the SkWStream to an IStream.
3289df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IStream> piStream;
329242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
3309df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com        hr = SkWIStream::CreateFromSkWStream(stream, &piStream);
331242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
332d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
333242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create an encode of the appropriate type.
3349df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapEncoder> piEncoder;
335242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
336242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piImagingFactory->CreateEncoder(type, NULL, &piEncoder);
337242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
338d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
339242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
340242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piEncoder->Initialize(piStream.get(), WICBitmapEncoderNoCache);
341242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
342d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
343242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create a the frame.
3449df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapFrameEncode> piBitmapFrameEncode;
3459df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IPropertyBag2> piPropertybag;
346242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
347242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piEncoder->CreateNewFrame(&piBitmapFrameEncode, &piPropertybag);
348242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
349d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
350242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
351242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        PROPBAG2 name = { 0 };
352242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        name.dwType = PROPBAG2_TYPE_DATA;
353242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        name.vt = VT_R4;
354242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        name.pstrName = L"ImageQuality";
355d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
356242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        VARIANT value;
357242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        VariantInit(&value);
358242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        value.vt = VT_R4;
359242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        value.fltVal = (FLOAT)(quality / 100.0);
360d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
361242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //Ignore result code.
362242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //  This returns E_FAIL if the named property is not in the bag.
363242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //TODO(bungeman) enumerate the properties,
364242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //  write and set hr iff property exists.
365242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        piPropertybag->Write(1, &name, &value);
366242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
367242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
368242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->Initialize(piPropertybag.get());
369242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
370d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
371242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Set the size of the frame.
37222b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    const UINT width = bitmap->width();
37322b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    const UINT height = bitmap->height();
374242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
375242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->SetSize(width, height);
376242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
377d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
378242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Set the pixel format of the frame.
379242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    const WICPixelFormatGUID formatDesired = GUID_WICPixelFormat32bppBGRA;
380242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    WICPixelFormatGUID formatGUID = formatDesired;
381242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
382242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->SetPixelFormat(&formatGUID);
383242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
384242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
385242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //Be sure the image format is the one requested.
386242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = IsEqualGUID(formatGUID, formatDesired) ? S_OK : E_FAIL;
387242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
388d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
389242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Write the pixels into the frame.
390242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
391955bb0751a0d48e47a341c7c0adda94977bc8170bungeman@google.com        SkAutoLockPixels alp(*bitmap);
392242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->WritePixels(
393242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            height
39422b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com            , bitmap->rowBytes()
39522b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com            , bitmap->rowBytes()*height
39622b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com            , reinterpret_cast<BYTE*>(bitmap->getPixels()));
397242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
398d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
399242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
400242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->Commit();
401242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
402d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
403242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
404242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piEncoder->Commit();
405242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
406d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
407242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    return SUCCEEDED(hr);
408242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
409242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
4104c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com///////////////////////////////////////////////////////////////////////////////
4114c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com
4124c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com#include "SkTRegistry.h"
4134c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com
4144c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.comstatic SkImageEncoder* sk_imageencoder_wic_factory(SkImageEncoder::Type t) {
415242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    switch (t) {
4164c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case SkImageEncoder::kBMP_Type:
4174c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case SkImageEncoder::kICO_Type:
4184c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case SkImageEncoder::kJPEG_Type:
4194c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com        case SkImageEncoder::kPNG_Type:
420242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            break;
421242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        default:
422242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return NULL;
423242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
424242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    return SkNEW_ARGS(SkImageEncoder_WIC, (t));
425242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
4264c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com
4274c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.comstatic SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_imageencoder_wic_factory);
42839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
42939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comstatic SkImageDecoder::Format get_format_wic(SkStream* stream) {
43039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    SkImageDecoder::Format format;
43139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    SkImageDecoder_WIC codec;
43239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    if (!codec.decodeStream(stream, NULL, SkImageDecoder_WIC::kDecodeFormat_WICMode, &format)) {
43339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        format = SkImageDecoder::kUnknown_Format;
43439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    }
43539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    return format;
43639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com}
43739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
43839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comstatic SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_wic);
439