SkImageDecoder_WIC.cpp revision 955bb0751a0d48e47a341c7c0adda94977bc8170
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"
20242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
21242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comclass SkImageDecoder_WIC : public SkImageDecoder {
22242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comprotected:
239df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode);
24242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com};
25242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
26242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.combool SkImageDecoder_WIC::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
27242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Initialize COM.
28242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    AutoCoInitialize scopedCo;
29242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    HRESULT hr = scopedCo.getHR();
30242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
31242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create Windows Imaging Component ImagingFactory.
329df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICImagingFactory> piImagingFactory;
33242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
34242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = CoCreateInstance(
35242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            CLSID_WICImagingFactory
36242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , NULL
37242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , CLSCTX_INPROC_SERVER
38242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , IID_PPV_ARGS(&piImagingFactory)
39242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
40242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
41242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
42242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Convert SkStream to IStream.
439df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IStream> piStream;
44242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
459df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com        hr = SkIStream::CreateFromSkStream(stream, false, &piStream);
46242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
47242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
48242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Make sure we're at the beginning of the stream.
49242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
50242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        LARGE_INTEGER liBeginning = { 0 };
51242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piStream->Seek(liBeginning, STREAM_SEEK_SET, NULL);
52242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
53242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
54242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create the decoder from the stream content.
559df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapDecoder> piBitmapDecoder;
56242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
57242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piImagingFactory->CreateDecoderFromStream(
58242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            piStream.get()                    //Image to be decoded
59242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , NULL                            //No particular vendor
60242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , WICDecodeMetadataCacheOnDemand  //Cache metadata when needed
61242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , &piBitmapDecoder                //Pointer to the decoder
62242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
63242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
64242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
65242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Get the first frame from the decoder.
669df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapFrameDecode> piBitmapFrameDecode;
67242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
68242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapDecoder->GetFrame(0, &piBitmapFrameDecode);
69242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
70242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
71242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Get the BitmapSource interface of the frame.
729df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapSource> piBitmapSourceOriginal;
73242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
74242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameDecode->QueryInterface(
75242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            IID_PPV_ARGS(&piBitmapSourceOriginal)
76242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
77242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
78242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
79242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Get the size of the bitmap.
80242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    UINT width;
81242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    UINT height;
82242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
83242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapSourceOriginal->GetSize(&width, &height);
84242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
85242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
86242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Exit early if we're only looking for the bitmap bounds.
87242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
88242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        bm->setConfig(SkBitmap::kARGB_8888_Config, width, height);
89242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        if (SkImageDecoder::kDecodeBounds_Mode == mode) {
90242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return true;
91242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        }
92242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        if (!this->allocPixelRef(bm, NULL)) {
93242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return false;
94242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        }
95242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
96242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
97242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create a format converter.
989df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICFormatConverter> piFormatConverter;
99242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
100242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piImagingFactory->CreateFormatConverter(&piFormatConverter);
101242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
102242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
103242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
104242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piFormatConverter->Initialize(
105242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            piBitmapSourceOriginal.get()      //Input bitmap to convert
106242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , GUID_WICPixelFormat32bppPBGRA   //Destination pixel format
107242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , WICBitmapDitherTypeNone         //Specified dither patterm
108242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , NULL                            //Specify a particular palette
109242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , 0.f                             //Alpha threshold
110242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , WICBitmapPaletteTypeCustom      //Palette translation type
111242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
112242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
113242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
114242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Get the BitmapSource interface of the format converter.
1159df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapSource> piBitmapSourceConverted;
116242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
117242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piFormatConverter->QueryInterface(
118242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            IID_PPV_ARGS(&piBitmapSourceConverted)
119242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
120242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
121242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
122242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Copy the pixels into the bitmap.
123242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
124955bb0751a0d48e47a341c7c0adda94977bc8170bungeman@google.com        SkAutoLockPixels alp(*bm);
125242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        bm->eraseColor(0);
126242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        const int stride = bm->rowBytes();
127242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapSourceConverted->CopyPixels(
128242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            NULL,                             //Get all the pixels
129242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            stride,
130242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            stride * height,
131242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            reinterpret_cast<BYTE *>(bm->getPixels())
132242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
133242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
134242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
135242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    return SUCCEEDED(hr);
136242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
137242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
138242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com/////////////////////////////////////////////////////////////////////////
139242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
140242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comSkImageDecoder* SkImageDecoder::Factory(SkStream* stream) {
141242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    return SkNEW(SkImageDecoder_WIC);
142242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
143242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
144242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com/////////////////////////////////////////////////////////////////////////
145242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
146242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comSkMovie* SkMovie::DecodeStream(SkStream* stream) {
147242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    return NULL;
148242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
149242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
150242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com/////////////////////////////////////////////////////////////////////////
151242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
152242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comclass SkImageEncoder_WIC : public SkImageEncoder {
153242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.compublic:
154242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    SkImageEncoder_WIC(Type t) : fType(t) {}
155242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
156242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comprotected:
157242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality);
158242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
159242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comprivate:
160242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    Type fType;
161242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com};
162242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
163242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.combool SkImageEncoder_WIC::onEncode(SkWStream* stream
16422b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com                                , const SkBitmap& bitmapOrig
165242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com                                , int quality)
166242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com{
167242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    GUID type;
168242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    switch (fType) {
169242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        case kJPEG_Type:
170242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            type = GUID_ContainerFormatJpeg;
171242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            break;
172242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        case kPNG_Type:
173242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            type = GUID_ContainerFormatPng;
174242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            break;
175242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        default:
176242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return false;
177242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
178242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
17922b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    //Convert to 8888 if needed.
18022b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    const SkBitmap* bitmap;
18122b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    SkBitmap bitmapCopy;
18222b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    if (SkBitmap::kARGB_8888_Config == bitmapOrig.config()) {
18322b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com        bitmap = &bitmapOrig;
18422b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    } else {
18522b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com        if (!bitmapOrig.copyTo(&bitmapCopy, SkBitmap::kARGB_8888_Config)) {
18622b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com            return false;
18722b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com        }
18822b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com        bitmap = &bitmapCopy;
18922b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    }
19022b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com
191242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Initialize COM.
192242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    AutoCoInitialize scopedCo;
193242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    HRESULT hr = scopedCo.getHR();
194242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
195242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create Windows Imaging Component ImagingFactory.
1969df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICImagingFactory> piImagingFactory;
197242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
198242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = CoCreateInstance(
199242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            CLSID_WICImagingFactory
200242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , NULL
201242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , CLSCTX_INPROC_SERVER
202242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            , IID_PPV_ARGS(&piImagingFactory)
203242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        );
204242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
205242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
2069df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    //Convert the SkWStream to an IStream.
2079df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IStream> piStream;
208242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
2099df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com        hr = SkWIStream::CreateFromSkWStream(stream, &piStream);
210242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
211242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
212242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create an encode of the appropriate type.
2139df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapEncoder> piEncoder;
214242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
215242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piImagingFactory->CreateEncoder(type, NULL, &piEncoder);
216242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
217242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
218242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
219242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piEncoder->Initialize(piStream.get(), WICBitmapEncoderNoCache);
220242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
221242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
222242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Create a the frame.
2239df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IWICBitmapFrameEncode> piBitmapFrameEncode;
2249df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com    SkTScopedComPtr<IPropertyBag2> piPropertybag;
225242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
226242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piEncoder->CreateNewFrame(&piBitmapFrameEncode, &piPropertybag);
227242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
228242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
229242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
230242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        PROPBAG2 name = { 0 };
231242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        name.dwType = PROPBAG2_TYPE_DATA;
232242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        name.vt = VT_R4;
233242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        name.pstrName = L"ImageQuality";
234242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
235242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        VARIANT value;
236242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        VariantInit(&value);
237242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        value.vt = VT_R4;
238242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        value.fltVal = (FLOAT)(quality / 100.0);
239242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
240242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //Ignore result code.
241242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //  This returns E_FAIL if the named property is not in the bag.
242242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //TODO(bungeman) enumerate the properties,
243242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //  write and set hr iff property exists.
244242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        piPropertybag->Write(1, &name, &value);
245242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
246242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
247242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->Initialize(piPropertybag.get());
248242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
249242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
250242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Set the size of the frame.
25122b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    const UINT width = bitmap->width();
25222b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com    const UINT height = bitmap->height();
253242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
254242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->SetSize(width, height);
255242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
256242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
257242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Set the pixel format of the frame.
258242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    const WICPixelFormatGUID formatDesired = GUID_WICPixelFormat32bppBGRA;
259242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    WICPixelFormatGUID formatGUID = formatDesired;
260242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
261242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->SetPixelFormat(&formatGUID);
262242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
263242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
264242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        //Be sure the image format is the one requested.
265242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = IsEqualGUID(formatGUID, formatDesired) ? S_OK : E_FAIL;
266242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
267242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
268242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    //Write the pixels into the frame.
269242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
270955bb0751a0d48e47a341c7c0adda94977bc8170bungeman@google.com        SkAutoLockPixels alp(*bitmap);
271242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->WritePixels(
272242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            height
27322b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com            , bitmap->rowBytes()
27422b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com            , bitmap->rowBytes()*height
27522b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com            , reinterpret_cast<BYTE*>(bitmap->getPixels()));
276242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
277242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
278242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
279242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piBitmapFrameEncode->Commit();
280242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
281242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
282242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    if (SUCCEEDED(hr)) {
283242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        hr = piEncoder->Commit();
284242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
285242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
286242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    return SUCCEEDED(hr);
287242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
288242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
289242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comSkImageEncoder* SkImageEncoder::Create(Type t) {
290242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    switch (t) {
291242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        case kJPEG_Type:
292242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        case kPNG_Type:
293242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            break;
294242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com        default:
295242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com            return NULL;
296242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    }
297242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com    return SkNEW_ARGS(SkImageEncoder_WIC, (t));
298242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com}
299242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com
300