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