1e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com
2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com/*
3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2011 Google Inc.
4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com *
5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file.
7e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com */
8e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com
9685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com
10e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com#define WIN32_LEAN_AND_MEAN
11e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com#include <Windows.h>
12e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com#include <wincodec.h>
13fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com#include "SkAutoCoInitialize.h"
14e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com#include "SkImageDecoder.h"
15e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com#include "SkImageEncoder.h"
16fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com#include "SkIStream.h"
17e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com#include "SkMovie.h"
18e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com#include "SkStream.h"
19fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com#include "SkTScopedComPtr.h"
2069d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com#include "SkUnPreMultiply.h"
21e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com
22c83bd26b9bd5e6942de2cd4e1b7cdb8f939cb5cabungeman@google.com//All Windows SDKs back to XPSP2 export the CLSID_WICImagingFactory symbol.
23c83bd26b9bd5e6942de2cd4e1b7cdb8f939cb5cabungeman@google.com//In the Windows8 SDK the CLSID_WICImagingFactory symbol is still exported
24c83bd26b9bd5e6942de2cd4e1b7cdb8f939cb5cabungeman@google.com//but CLSID_WICImagingFactory is then #defined to CLSID_WICImagingFactory2.
25c83bd26b9bd5e6942de2cd4e1b7cdb8f939cb5cabungeman@google.com//Undo this #define if it has been done so that we link against the symbols
26c83bd26b9bd5e6942de2cd4e1b7cdb8f939cb5cabungeman@google.com//we intended to link against on all SDKs.
27c83bd26b9bd5e6942de2cd4e1b7cdb8f939cb5cabungeman@google.com#if defined(CLSID_WICImagingFactory)
28c83bd26b9bd5e6942de2cd4e1b7cdb8f939cb5cabungeman@google.com#undef CLSID_WICImagingFactory
29c83bd26b9bd5e6942de2cd4e1b7cdb8f939cb5cabungeman@google.com#endif
30c83bd26b9bd5e6942de2cd4e1b7cdb8f939cb5cabungeman@google.com
31e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.comclass SkImageDecoder_WIC : public SkImageDecoder {
3206a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.compublic:
3306a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    // Decoding modes corresponding to SkImageDecoder::Mode, plus an extra mode for decoding
3406a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    // only the format.
3506a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    enum WICModes {
3606a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        kDecodeFormat_WICMode,
3706a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        kDecodeBounds_WICMode,
3806a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        kDecodePixels_WICMode,
3906a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    };
4006a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com
4106a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    /**
4206a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com     *  Helper function to decode an SkStream.
4306a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com     *  @param stream SkStream to decode. Must be at the beginning.
4406a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com     *  @param bm   SkBitmap to decode into. Only used if wicMode is kDecodeBounds_WICMode or
4506a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com     *      kDecodePixels_WICMode, in which case it must not be NULL.
4606a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com     *  @param format Out parameter for the SkImageDecoder::Format of the SkStream. Only used if
4706a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com     *      wicMode is kDecodeFormat_WICMode.
4806a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com     */
4906a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    bool decodeStream(SkStream* stream, SkBitmap* bm, WICModes wicMode, Format* format) const;
5006a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com
51e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.comprotected:
5206a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode) SK_OVERRIDE;
5306a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com};
5406a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com
5506a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.comstruct FormatConversion {
5606a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    GUID                    fGuidFormat;
5706a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    SkImageDecoder::Format  fFormat;
58e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com};
59e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com
6006a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.comstatic const FormatConversion gFormatConversions[] = {
6106a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    { GUID_ContainerFormatBmp, SkImageDecoder::kBMP_Format },
6206a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    { GUID_ContainerFormatGif, SkImageDecoder::kGIF_Format },
6306a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    { GUID_ContainerFormatIco, SkImageDecoder::kICO_Format },
6406a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    { GUID_ContainerFormatJpeg, SkImageDecoder::kJPEG_Format },
6506a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    { GUID_ContainerFormatPng, SkImageDecoder::kPNG_Format },
6606a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com};
6706a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com
6806a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.comstatic SkImageDecoder::Format GuidContainerFormat_to_Format(REFGUID guid) {
6906a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gFormatConversions); i++) {
7006a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        if (IsEqualGUID(guid, gFormatConversions[i].fGuidFormat)) {
7106a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            return gFormatConversions[i].fFormat;
7206a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        }
7306a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    }
7406a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    return SkImageDecoder::kUnknown_Format;
7506a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com}
7606a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com
77e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.combool SkImageDecoder_WIC::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
7806a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    WICModes wicMode;
7906a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    switch (mode) {
8006a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        case SkImageDecoder::kDecodeBounds_Mode:
8106a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            wicMode = kDecodeBounds_WICMode;
8206a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            break;
8306a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        case SkImageDecoder::kDecodePixels_Mode:
8406a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            wicMode = kDecodePixels_WICMode;
8506a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            break;
8606a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    }
8706a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    return this->decodeStream(stream, bm, wicMode, NULL);
8806a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com}
8906a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com
9006a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.combool SkImageDecoder_WIC::decodeStream(SkStream* stream, SkBitmap* bm, WICModes wicMode,
9106a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com                                      Format* format) const {
92e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Initialize COM.
939560b5d45b5aa6461acd75f79f796619dd84d491bungeman@google.com    SkAutoCoInitialize scopedCo;
949560b5d45b5aa6461acd75f79f796619dd84d491bungeman@google.com    if (!scopedCo.succeeded()) {
959560b5d45b5aa6461acd75f79f796619dd84d491bungeman@google.com        return false;
969560b5d45b5aa6461acd75f79f796619dd84d491bungeman@google.com    }
97dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
989560b5d45b5aa6461acd75f79f796619dd84d491bungeman@google.com    HRESULT hr = S_OK;
99dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
100e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Create Windows Imaging Component ImagingFactory.
101fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com    SkTScopedComPtr<IWICImagingFactory> piImagingFactory;
102e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
103e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = CoCreateInstance(
104e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            CLSID_WICImagingFactory
105e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            , NULL
106e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            , CLSCTX_INPROC_SERVER
107e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            , IID_PPV_ARGS(&piImagingFactory)
108e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        );
109e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
110dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
111e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Convert SkStream to IStream.
112fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com    SkTScopedComPtr<IStream> piStream;
113e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
114fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com        hr = SkIStream::CreateFromSkStream(stream, false, &piStream);
115e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
116dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
117e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Make sure we're at the beginning of the stream.
118e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
119e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        LARGE_INTEGER liBeginning = { 0 };
120e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piStream->Seek(liBeginning, STREAM_SEEK_SET, NULL);
121e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
122dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
123e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Create the decoder from the stream content.
124fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com    SkTScopedComPtr<IWICBitmapDecoder> piBitmapDecoder;
125e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
126e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piImagingFactory->CreateDecoderFromStream(
127e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            piStream.get()                    //Image to be decoded
128e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            , NULL                            //No particular vendor
129e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            , WICDecodeMetadataCacheOnDemand  //Cache metadata when needed
130e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            , &piBitmapDecoder                //Pointer to the decoder
131e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        );
132e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
133dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
13406a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    if (kDecodeFormat_WICMode == wicMode) {
13506a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        SkASSERT(format != NULL);
13606a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        //Get the format
13706a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        if (SUCCEEDED(hr)) {
13806a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            GUID guidFormat;
13906a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            hr = piBitmapDecoder->GetContainerFormat(&guidFormat);
14006a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            if (SUCCEEDED(hr)) {
14106a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com                *format = GuidContainerFormat_to_Format(guidFormat);
14206a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com                return true;
14306a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com            }
14406a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        }
14506a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        return false;
14606a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    }
14706a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com
148e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Get the first frame from the decoder.
149fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com    SkTScopedComPtr<IWICBitmapFrameDecode> piBitmapFrameDecode;
150e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
151e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piBitmapDecoder->GetFrame(0, &piBitmapFrameDecode);
152e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
153dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
154e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Get the BitmapSource interface of the frame.
155fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com    SkTScopedComPtr<IWICBitmapSource> piBitmapSourceOriginal;
156e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
157e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piBitmapFrameDecode->QueryInterface(
158e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            IID_PPV_ARGS(&piBitmapSourceOriginal)
159e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        );
160e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
161dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
162e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Get the size of the bitmap.
163e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    UINT width;
164e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    UINT height;
165e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
166e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piBitmapSourceOriginal->GetSize(&width, &height);
167e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
168dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
169e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Exit early if we're only looking for the bitmap bounds.
170e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
171e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        bm->setConfig(SkBitmap::kARGB_8888_Config, width, height);
17206a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        if (kDecodeBounds_WICMode == wicMode) {
173e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            return true;
174e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        }
175e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        if (!this->allocPixelRef(bm, NULL)) {
176e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            return false;
177e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        }
178e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
179dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
180e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Create a format converter.
181fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com    SkTScopedComPtr<IWICFormatConverter> piFormatConverter;
182e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
183e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piImagingFactory->CreateFormatConverter(&piFormatConverter);
184e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
185dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
186746b6b83a7e954f59a6c6dd44e3e8216dc11a8bbscroggo@google.com    GUID destinationPixelFormat;
187746b6b83a7e954f59a6c6dd44e3e8216dc11a8bbscroggo@google.com    if (this->getRequireUnpremultipliedColors()) {
188746b6b83a7e954f59a6c6dd44e3e8216dc11a8bbscroggo@google.com        destinationPixelFormat = GUID_WICPixelFormat32bppBGRA;
189746b6b83a7e954f59a6c6dd44e3e8216dc11a8bbscroggo@google.com    } else {
190746b6b83a7e954f59a6c6dd44e3e8216dc11a8bbscroggo@google.com        destinationPixelFormat = GUID_WICPixelFormat32bppPBGRA;
191746b6b83a7e954f59a6c6dd44e3e8216dc11a8bbscroggo@google.com    }
192746b6b83a7e954f59a6c6dd44e3e8216dc11a8bbscroggo@google.com
193e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
194e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piFormatConverter->Initialize(
195e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            piBitmapSourceOriginal.get()      //Input bitmap to convert
196746b6b83a7e954f59a6c6dd44e3e8216dc11a8bbscroggo@google.com            , destinationPixelFormat          //Destination pixel format
197e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            , WICBitmapDitherTypeNone         //Specified dither patterm
198e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            , NULL                            //Specify a particular palette
199e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            , 0.f                             //Alpha threshold
200e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            , WICBitmapPaletteTypeCustom      //Palette translation type
201e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        );
202e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
203dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
204e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Get the BitmapSource interface of the format converter.
205fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com    SkTScopedComPtr<IWICBitmapSource> piBitmapSourceConverted;
206e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
207e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piFormatConverter->QueryInterface(
208e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            IID_PPV_ARGS(&piBitmapSourceConverted)
209e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        );
210e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
211dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
212e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Copy the pixels into the bitmap.
213e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
2149a92670322442238277aa5a998c0841762ba7d41bungeman@google.com        SkAutoLockPixels alp(*bm);
2156d7b99540d86e79bbc47dc0904f68a96eeb21c8cjunov@google.com        bm->eraseColor(SK_ColorTRANSPARENT);
21604f3a5586b17cb4b4d2dc1ea2389d0e6691182e6bungeman@google.com        const UINT stride = bm->rowBytes();
217e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piBitmapSourceConverted->CopyPixels(
218e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            NULL,                             //Get all the pixels
219e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            stride,
220e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            stride * height,
221e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            reinterpret_cast<BYTE *>(bm->getPixels())
222e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        );
22369d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com
22469d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com        // Note: we don't need to premultiply here since we specified PBGRA
22569d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com        bm->computeAndSetOpaquePredicate();
226e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
227dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
228e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    return SUCCEEDED(hr);
229e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com}
230e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com
231e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com/////////////////////////////////////////////////////////////////////////
232e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com
2339759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.comextern SkImageDecoder* image_decoder_from_stream(SkStream*);
2349759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com
235e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.comSkImageDecoder* SkImageDecoder::Factory(SkStream* stream) {
2369759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com    SkImageDecoder* decoder = image_decoder_from_stream(stream);
2379759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com    if (NULL == decoder) {
2389759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com        // If no image decoder specific to the stream exists, use SkImageDecoder_WIC.
2399759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com        return SkNEW(SkImageDecoder_WIC);
2409759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com    } else {
2419759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com        return decoder;
2429759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com    }
243e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com}
244e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com
245e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com/////////////////////////////////////////////////////////////////////////
246e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com
247e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.comSkMovie* SkMovie::DecodeStream(SkStream* stream) {
248e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    return NULL;
249e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com}
250e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com
251e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com/////////////////////////////////////////////////////////////////////////
252e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com
253e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.comclass SkImageEncoder_WIC : public SkImageEncoder {
254e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.compublic:
255e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    SkImageEncoder_WIC(Type t) : fType(t) {}
256e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com
257e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.comprotected:
258e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality);
259e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com
260e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.comprivate:
261e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    Type fType;
262e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com};
263e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com
264e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.combool SkImageEncoder_WIC::onEncode(SkWStream* stream
265513776788194d255b64831265c30e6fdebf95f87bungeman@google.com                                , const SkBitmap& bitmapOrig
266e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com                                , int quality)
267e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com{
268e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    GUID type;
269e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    switch (fType) {
2709759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com        case kBMP_Type:
2719759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com            type = GUID_ContainerFormatBmp;
2729759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com            break;
2739759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com        case kICO_Type:
2749759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com            type = GUID_ContainerFormatIco;
2759759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com            break;
276e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        case kJPEG_Type:
277e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            type = GUID_ContainerFormatJpeg;
278e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            break;
279e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        case kPNG_Type:
280e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            type = GUID_ContainerFormatPng;
281e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            break;
282e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        default:
283e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            return false;
284e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
285e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com
286513776788194d255b64831265c30e6fdebf95f87bungeman@google.com    //Convert to 8888 if needed.
287513776788194d255b64831265c30e6fdebf95f87bungeman@google.com    const SkBitmap* bitmap;
288513776788194d255b64831265c30e6fdebf95f87bungeman@google.com    SkBitmap bitmapCopy;
28969d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com    if (SkBitmap::kARGB_8888_Config == bitmapOrig.config() && bitmapOrig.isOpaque()) {
290513776788194d255b64831265c30e6fdebf95f87bungeman@google.com        bitmap = &bitmapOrig;
291513776788194d255b64831265c30e6fdebf95f87bungeman@google.com    } else {
292513776788194d255b64831265c30e6fdebf95f87bungeman@google.com        if (!bitmapOrig.copyTo(&bitmapCopy, SkBitmap::kARGB_8888_Config)) {
293513776788194d255b64831265c30e6fdebf95f87bungeman@google.com            return false;
294513776788194d255b64831265c30e6fdebf95f87bungeman@google.com        }
295513776788194d255b64831265c30e6fdebf95f87bungeman@google.com        bitmap = &bitmapCopy;
296513776788194d255b64831265c30e6fdebf95f87bungeman@google.com    }
297513776788194d255b64831265c30e6fdebf95f87bungeman@google.com
29869d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com    // We cannot use PBGRA so we need to unpremultiply ourselves
29969d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com    if (!bitmap->isOpaque()) {
30069d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com        SkAutoLockPixels alp(*bitmap);
30169d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com
30269d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com        uint8_t* pixels = reinterpret_cast<uint8_t*>(bitmap->getPixels());
30369d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com        for (int y = 0; y < bitmap->height(); ++y) {
30469d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com            for (int x = 0; x < bitmap->width(); ++x) {
30569d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com                uint8_t* bytes = pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel();
30669d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com
30769d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com                SkPMColor* src = reinterpret_cast<SkPMColor*>(bytes);
30869d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com                SkColor* dst = reinterpret_cast<SkColor*>(bytes);
30969d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com
31069d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com                *dst = SkUnPreMultiply::PMColorToColor(*src);
31169d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com            }
31269d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com        }
31369d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com    }
31469d808cde9dea1d0c77ee6ad86f1cf3cff639254robertphillips@google.com
315e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Initialize COM.
3169560b5d45b5aa6461acd75f79f796619dd84d491bungeman@google.com    SkAutoCoInitialize scopedCo;
3179560b5d45b5aa6461acd75f79f796619dd84d491bungeman@google.com    if (!scopedCo.succeeded()) {
3189560b5d45b5aa6461acd75f79f796619dd84d491bungeman@google.com        return false;
3199560b5d45b5aa6461acd75f79f796619dd84d491bungeman@google.com    }
320dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
3219560b5d45b5aa6461acd75f79f796619dd84d491bungeman@google.com    HRESULT hr = S_OK;
322dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
323e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Create Windows Imaging Component ImagingFactory.
324fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com    SkTScopedComPtr<IWICImagingFactory> piImagingFactory;
325e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
326e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = CoCreateInstance(
327e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            CLSID_WICImagingFactory
328e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            , NULL
329e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            , CLSCTX_INPROC_SERVER
330e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            , IID_PPV_ARGS(&piImagingFactory)
331e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        );
332e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
333dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
334fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com    //Convert the SkWStream to an IStream.
335fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com    SkTScopedComPtr<IStream> piStream;
336e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
337fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com        hr = SkWIStream::CreateFromSkWStream(stream, &piStream);
338e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
339dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
340e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Create an encode of the appropriate type.
341fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com    SkTScopedComPtr<IWICBitmapEncoder> piEncoder;
342e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
343e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piImagingFactory->CreateEncoder(type, NULL, &piEncoder);
344e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
345dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
346e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
347e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piEncoder->Initialize(piStream.get(), WICBitmapEncoderNoCache);
348e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
349dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
350e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Create a the frame.
351fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com    SkTScopedComPtr<IWICBitmapFrameEncode> piBitmapFrameEncode;
352fb1875a762d3cf7d7fdb2adb802a7eb5190031f4bungeman@google.com    SkTScopedComPtr<IPropertyBag2> piPropertybag;
353e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
354e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piEncoder->CreateNewFrame(&piBitmapFrameEncode, &piPropertybag);
355e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
356dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
357e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
358e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        PROPBAG2 name = { 0 };
359e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        name.dwType = PROPBAG2_TYPE_DATA;
360e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        name.vt = VT_R4;
361e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        name.pstrName = L"ImageQuality";
362dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
363e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        VARIANT value;
364e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        VariantInit(&value);
365e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        value.vt = VT_R4;
366e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        value.fltVal = (FLOAT)(quality / 100.0);
367dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
368e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        //Ignore result code.
369e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        //  This returns E_FAIL if the named property is not in the bag.
370e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        //TODO(bungeman) enumerate the properties,
371e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        //  write and set hr iff property exists.
372e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        piPropertybag->Write(1, &name, &value);
373e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
374e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
375e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piBitmapFrameEncode->Initialize(piPropertybag.get());
376e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
377dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
378e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Set the size of the frame.
379513776788194d255b64831265c30e6fdebf95f87bungeman@google.com    const UINT width = bitmap->width();
380513776788194d255b64831265c30e6fdebf95f87bungeman@google.com    const UINT height = bitmap->height();
381e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
382e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piBitmapFrameEncode->SetSize(width, height);
383e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
384dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
385e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Set the pixel format of the frame.
386e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    const WICPixelFormatGUID formatDesired = GUID_WICPixelFormat32bppBGRA;
387e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    WICPixelFormatGUID formatGUID = formatDesired;
388e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
389e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piBitmapFrameEncode->SetPixelFormat(&formatGUID);
390e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
391e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
392e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        //Be sure the image format is the one requested.
393e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = IsEqualGUID(formatGUID, formatDesired) ? S_OK : E_FAIL;
394e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
395dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
396e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    //Write the pixels into the frame.
397e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
3989a92670322442238277aa5a998c0841762ba7d41bungeman@google.com        SkAutoLockPixels alp(*bitmap);
39904f3a5586b17cb4b4d2dc1ea2389d0e6691182e6bungeman@google.com        const UINT stride = bitmap->rowBytes();
400e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piBitmapFrameEncode->WritePixels(
401e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            height
40204f3a5586b17cb4b4d2dc1ea2389d0e6691182e6bungeman@google.com            , stride
40304f3a5586b17cb4b4d2dc1ea2389d0e6691182e6bungeman@google.com            , stride * height
404513776788194d255b64831265c30e6fdebf95f87bungeman@google.com            , reinterpret_cast<BYTE*>(bitmap->getPixels()));
405e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
406dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
407e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
408e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piBitmapFrameEncode->Commit();
409e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
410dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
411e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    if (SUCCEEDED(hr)) {
412e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        hr = piEncoder->Commit();
413e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
414dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com
415e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    return SUCCEEDED(hr);
416e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com}
417e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com
4189759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com///////////////////////////////////////////////////////////////////////////////
4199759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com
4209759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com#include "SkTRegistry.h"
4219759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com
4229759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.comstatic SkImageEncoder* sk_imageencoder_wic_factory(SkImageEncoder::Type t) {
423e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    switch (t) {
4249759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com        case SkImageEncoder::kBMP_Type:
4259759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com        case SkImageEncoder::kICO_Type:
4269759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com        case SkImageEncoder::kJPEG_Type:
4279759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com        case SkImageEncoder::kPNG_Type:
428e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            break;
429e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com        default:
430e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com            return NULL;
431e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    }
432e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com    return SkNEW_ARGS(SkImageEncoder_WIC, (t));
433e1c204f635116e86d2be7250a2ebbc41a535ef30bungeman@google.com}
4349759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.com
4359759beb59fc6bb942229f2ace8980ca52dbf25f4scroggo@google.comstatic SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_imageencoder_wic_factory);
43606a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com
43706a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.comstatic SkImageDecoder::Format get_format_wic(SkStream* stream) {
43806a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    SkImageDecoder::Format format;
43906a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    SkImageDecoder_WIC codec;
44006a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    if (!codec.decodeStream(stream, NULL, SkImageDecoder_WIC::kDecodeFormat_WICMode, &format)) {
44106a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com        format = SkImageDecoder::kUnknown_Format;
44206a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    }
44306a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com    return format;
44406a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com}
44506a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.com
44606a7d944591332081e2e8a4d9b9ca88d76a2f9c8scroggo@google.comstatic SkTRegistry<SkImageDecoder::Format, SkStream*> gFormatReg(get_format_wic);
447