gfx/skia/trunk/src/ports/SkImageDecoder_WIC.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     2 /*
     3  * Copyright 2011 Google Inc.
     4  *
     5  * Use of this source code is governed by a BSD-style license that can be
     6  * found in the LICENSE file.
     7  */
     9 #include "SkTypes.h"
    11 // Workaround for:
    12 // http://connect.microsoft.com/VisualStudio/feedback/details/621653/
    13 // http://crbug.com/225822
    14 // In VS2010 both intsafe.h and stdint.h define the following without guards.
    15 // SkTypes brought in windows.h and stdint.h and the following defines are
    16 // not used by this file. However, they may be re-introduced by wincodec.h.
    17 #undef INT8_MIN
    18 #undef INT16_MIN
    19 #undef INT32_MIN
    20 #undef INT64_MIN
    21 #undef INT8_MAX
    22 #undef UINT8_MAX
    23 #undef INT16_MAX
    24 #undef UINT16_MAX
    25 #undef INT32_MAX
    26 #undef UINT32_MAX
    27 #undef INT64_MAX
    28 #undef UINT64_MAX
    30 #include <wincodec.h>
    31 #include "SkAutoCoInitialize.h"
    32 #include "SkImageDecoder.h"
    33 #include "SkImageEncoder.h"
    34 #include "SkIStream.h"
    35 #include "SkMovie.h"
    36 #include "SkStream.h"
    37 #include "SkTScopedComPtr.h"
    38 #include "SkUnPreMultiply.h"
    40 //All Windows SDKs back to XPSP2 export the CLSID_WICImagingFactory symbol.
    41 //In the Windows8 SDK the CLSID_WICImagingFactory symbol is still exported
    42 //but CLSID_WICImagingFactory is then #defined to CLSID_WICImagingFactory2.
    43 //Undo this #define if it has been done so that we link against the symbols
    44 //we intended to link against on all SDKs.
    45 #if defined(CLSID_WICImagingFactory)
    46 #undef CLSID_WICImagingFactory
    47 #endif
    49 class SkImageDecoder_WIC : public SkImageDecoder {
    50 public:
    51     // Decoding modes corresponding to SkImageDecoder::Mode, plus an extra mode for decoding
    52     // only the format.
    53     enum WICModes {
    54         kDecodeFormat_WICMode,
    55         kDecodeBounds_WICMode,
    56         kDecodePixels_WICMode,
    57     };
    59     /**
    60      *  Helper function to decode an SkStream.
    61      *  @param stream SkStream to decode. Must be at the beginning.
    62      *  @param bm   SkBitmap to decode into. Only used if wicMode is kDecodeBounds_WICMode or
    63      *      kDecodePixels_WICMode, in which case it must not be NULL.
    64      *  @param format Out parameter for the SkImageDecoder::Format of the SkStream. Only used if
    65      *      wicMode is kDecodeFormat_WICMode.
    66      */
    67     bool decodeStream(SkStream* stream, SkBitmap* bm, WICModes wicMode, Format* format) const;
    69 protected:
    70     virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode) SK_OVERRIDE;
    71 };
    73 struct FormatConversion {
    74     GUID                    fGuidFormat;
    75     SkImageDecoder::Format  fFormat;
    76 };
    78 static const FormatConversion gFormatConversions[] = {
    79     { GUID_ContainerFormatBmp, SkImageDecoder::kBMP_Format },
    80     { GUID_ContainerFormatGif, SkImageDecoder::kGIF_Format },
    81     { GUID_ContainerFormatIco, SkImageDecoder::kICO_Format },
    82     { GUID_ContainerFormatJpeg, SkImageDecoder::kJPEG_Format },
    83     { GUID_ContainerFormatPng, SkImageDecoder::kPNG_Format },
    84 };
    86 static SkImageDecoder::Format GuidContainerFormat_to_Format(REFGUID guid) {
    87     for (size_t i = 0; i < SK_ARRAY_COUNT(gFormatConversions); i++) {
    88         if (IsEqualGUID(guid, gFormatConversions[i].fGuidFormat)) {
    89             return gFormatConversions[i].fFormat;
    90         }
    91     }
    92     return SkImageDecoder::kUnknown_Format;
    93 }
    95 bool SkImageDecoder_WIC::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
    96     WICModes wicMode;
    97     switch (mode) {
    98         case SkImageDecoder::kDecodeBounds_Mode:
    99             wicMode = kDecodeBounds_WICMode;
   100             break;
   101         case SkImageDecoder::kDecodePixels_Mode:
   102             wicMode = kDecodePixels_WICMode;
   103             break;
   104     }
   105     return this->decodeStream(stream, bm, wicMode, NULL);
   106 }
   108 bool SkImageDecoder_WIC::decodeStream(SkStream* stream, SkBitmap* bm, WICModes wicMode,
   109                                       Format* format) const {
   110     //Initialize COM.
   111     SkAutoCoInitialize scopedCo;
   112     if (!scopedCo.succeeded()) {
   113         return false;
   114     }
   116     HRESULT hr = S_OK;
   118     //Create Windows Imaging Component ImagingFactory.
   119     SkTScopedComPtr<IWICImagingFactory> piImagingFactory;
   120     if (SUCCEEDED(hr)) {
   121         hr = CoCreateInstance(
   122             CLSID_WICImagingFactory
   123             , NULL
   124             , CLSCTX_INPROC_SERVER
   125             , IID_PPV_ARGS(&piImagingFactory)
   126         );
   127     }
   129     //Convert SkStream to IStream.
   130     SkTScopedComPtr<IStream> piStream;
   131     if (SUCCEEDED(hr)) {
   132         hr = SkIStream::CreateFromSkStream(stream, false, &piStream);
   133     }
   135     //Make sure we're at the beginning of the stream.
   136     if (SUCCEEDED(hr)) {
   137         LARGE_INTEGER liBeginning = { 0 };
   138         hr = piStream->Seek(liBeginning, STREAM_SEEK_SET, NULL);
   139     }
   141     //Create the decoder from the stream content.
   142     SkTScopedComPtr<IWICBitmapDecoder> piBitmapDecoder;
   143     if (SUCCEEDED(hr)) {
   144         hr = piImagingFactory->CreateDecoderFromStream(
   145             piStream.get()                    //Image to be decoded
   146             , NULL                            //No particular vendor
   147             , WICDecodeMetadataCacheOnDemand  //Cache metadata when needed
   148             , &piBitmapDecoder                //Pointer to the decoder
   149         );
   150     }
   152     if (kDecodeFormat_WICMode == wicMode) {
   153         SkASSERT(format != NULL);
   154         //Get the format
   155         if (SUCCEEDED(hr)) {
   156             GUID guidFormat;
   157             hr = piBitmapDecoder->GetContainerFormat(&guidFormat);
   158             if (SUCCEEDED(hr)) {
   159                 *format = GuidContainerFormat_to_Format(guidFormat);
   160                 return true;
   161             }
   162         }
   163         return false;
   164     }
   166     //Get the first frame from the decoder.
   167     SkTScopedComPtr<IWICBitmapFrameDecode> piBitmapFrameDecode;
   168     if (SUCCEEDED(hr)) {
   169         hr = piBitmapDecoder->GetFrame(0, &piBitmapFrameDecode);
   170     }
   172     //Get the BitmapSource interface of the frame.
   173     SkTScopedComPtr<IWICBitmapSource> piBitmapSourceOriginal;
   174     if (SUCCEEDED(hr)) {
   175         hr = piBitmapFrameDecode->QueryInterface(
   176             IID_PPV_ARGS(&piBitmapSourceOriginal)
   177         );
   178     }
   180     //Get the size of the bitmap.
   181     UINT width;
   182     UINT height;
   183     if (SUCCEEDED(hr)) {
   184         hr = piBitmapSourceOriginal->GetSize(&width, &height);
   185     }
   187     //Exit early if we're only looking for the bitmap bounds.
   188     if (SUCCEEDED(hr)) {
   189         bm->setConfig(SkImageInfo::MakeN32Premul(width, height));
   190         if (kDecodeBounds_WICMode == wicMode) {
   191             return true;
   192         }
   193         if (!this->allocPixelRef(bm, NULL)) {
   194             return false;
   195         }
   196     }
   198     //Create a format converter.
   199     SkTScopedComPtr<IWICFormatConverter> piFormatConverter;
   200     if (SUCCEEDED(hr)) {
   201         hr = piImagingFactory->CreateFormatConverter(&piFormatConverter);
   202     }
   204     GUID destinationPixelFormat;
   205     if (this->getRequireUnpremultipliedColors()) {
   206         destinationPixelFormat = GUID_WICPixelFormat32bppBGRA;
   207     } else {
   208         destinationPixelFormat = GUID_WICPixelFormat32bppPBGRA;
   209     }
   211     if (SUCCEEDED(hr)) {
   212         hr = piFormatConverter->Initialize(
   213             piBitmapSourceOriginal.get()      //Input bitmap to convert
   214             , destinationPixelFormat          //Destination pixel format
   215             , WICBitmapDitherTypeNone         //Specified dither patterm
   216             , NULL                            //Specify a particular palette
   217             , 0.f                             //Alpha threshold
   218             , WICBitmapPaletteTypeCustom      //Palette translation type
   219         );
   220     }
   222     //Get the BitmapSource interface of the format converter.
   223     SkTScopedComPtr<IWICBitmapSource> piBitmapSourceConverted;
   224     if (SUCCEEDED(hr)) {
   225         hr = piFormatConverter->QueryInterface(
   226             IID_PPV_ARGS(&piBitmapSourceConverted)
   227         );
   228     }
   230     //Copy the pixels into the bitmap.
   231     if (SUCCEEDED(hr)) {
   232         SkAutoLockPixels alp(*bm);
   233         bm->eraseColor(SK_ColorTRANSPARENT);
   234         const UINT stride = (UINT) bm->rowBytes();
   235         hr = piBitmapSourceConverted->CopyPixels(
   236             NULL,                             //Get all the pixels
   237             stride,
   238             stride * height,
   239             reinterpret_cast<BYTE *>(bm->getPixels())
   240         );
   242         // Note: we don't need to premultiply here since we specified PBGRA
   243         if (SkBitmap::ComputeIsOpaque(*bm)) {
   244             bm->setAlphaType(kOpaque_SkAlphaType);
   245         }
   246     }
   248     return SUCCEEDED(hr);
   249 }
   251 /////////////////////////////////////////////////////////////////////////
   253 extern SkImageDecoder* image_decoder_from_stream(SkStreamRewindable*);
   255 SkImageDecoder* SkImageDecoder::Factory(SkStreamRewindable* stream) {
   256     SkImageDecoder* decoder = image_decoder_from_stream(stream);
   257     if (NULL == decoder) {
   258         // If no image decoder specific to the stream exists, use SkImageDecoder_WIC.
   259         return SkNEW(SkImageDecoder_WIC);
   260     } else {
   261         return decoder;
   262     }
   263 }
   265 /////////////////////////////////////////////////////////////////////////
   267 SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) {
   268     return NULL;
   269 }
   271 /////////////////////////////////////////////////////////////////////////
   273 class SkImageEncoder_WIC : public SkImageEncoder {
   274 public:
   275     SkImageEncoder_WIC(Type t) : fType(t) {}
   277 protected:
   278     virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality);
   280 private:
   281     Type fType;
   282 };
   284 bool SkImageEncoder_WIC::onEncode(SkWStream* stream
   285                                 , const SkBitmap& bitmapOrig
   286                                 , int quality)
   287 {
   288     GUID type;
   289     switch (fType) {
   290         case kBMP_Type:
   291             type = GUID_ContainerFormatBmp;
   292             break;
   293         case kICO_Type:
   294             type = GUID_ContainerFormatIco;
   295             break;
   296         case kJPEG_Type:
   297             type = GUID_ContainerFormatJpeg;
   298             break;
   299         case kPNG_Type:
   300             type = GUID_ContainerFormatPng;
   301             break;
   302         default:
   303             return false;
   304     }
   306     //Convert to 8888 if needed.
   307     const SkBitmap* bitmap;
   308     SkBitmap bitmapCopy;
   309     if (kPMColor_SkColorType == bitmapOrig.colorType() && bitmapOrig.isOpaque()) {
   310         bitmap = &bitmapOrig;
   311     } else {
   312         if (!bitmapOrig.copyTo(&bitmapCopy, kPMColor_SkColorType)) {
   313             return false;
   314         }
   315         bitmap = &bitmapCopy;
   316     }
   318     // We cannot use PBGRA so we need to unpremultiply ourselves
   319     if (!bitmap->isOpaque()) {
   320         SkAutoLockPixels alp(*bitmap);
   322         uint8_t* pixels = reinterpret_cast<uint8_t*>(bitmap->getPixels());
   323         for (int y = 0; y < bitmap->height(); ++y) {
   324             for (int x = 0; x < bitmap->width(); ++x) {
   325                 uint8_t* bytes = pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel();
   327                 SkPMColor* src = reinterpret_cast<SkPMColor*>(bytes);
   328                 SkColor* dst = reinterpret_cast<SkColor*>(bytes);
   330                 *dst = SkUnPreMultiply::PMColorToColor(*src);
   331             }
   332         }
   333     }
   335     //Initialize COM.
   336     SkAutoCoInitialize scopedCo;
   337     if (!scopedCo.succeeded()) {
   338         return false;
   339     }
   341     HRESULT hr = S_OK;
   343     //Create Windows Imaging Component ImagingFactory.
   344     SkTScopedComPtr<IWICImagingFactory> piImagingFactory;
   345     if (SUCCEEDED(hr)) {
   346         hr = CoCreateInstance(
   347             CLSID_WICImagingFactory
   348             , NULL
   349             , CLSCTX_INPROC_SERVER
   350             , IID_PPV_ARGS(&piImagingFactory)
   351         );
   352     }
   354     //Convert the SkWStream to an IStream.
   355     SkTScopedComPtr<IStream> piStream;
   356     if (SUCCEEDED(hr)) {
   357         hr = SkWIStream::CreateFromSkWStream(stream, &piStream);
   358     }
   360     //Create an encode of the appropriate type.
   361     SkTScopedComPtr<IWICBitmapEncoder> piEncoder;
   362     if (SUCCEEDED(hr)) {
   363         hr = piImagingFactory->CreateEncoder(type, NULL, &piEncoder);
   364     }
   366     if (SUCCEEDED(hr)) {
   367         hr = piEncoder->Initialize(piStream.get(), WICBitmapEncoderNoCache);
   368     }
   370     //Create a the frame.
   371     SkTScopedComPtr<IWICBitmapFrameEncode> piBitmapFrameEncode;
   372     SkTScopedComPtr<IPropertyBag2> piPropertybag;
   373     if (SUCCEEDED(hr)) {
   374         hr = piEncoder->CreateNewFrame(&piBitmapFrameEncode, &piPropertybag);
   375     }
   377     if (SUCCEEDED(hr)) {
   378         PROPBAG2 name = { 0 };
   379         name.dwType = PROPBAG2_TYPE_DATA;
   380         name.vt = VT_R4;
   381         name.pstrName = L"ImageQuality";
   383         VARIANT value;
   384         VariantInit(&value);
   385         value.vt = VT_R4;
   386         value.fltVal = (FLOAT)(quality / 100.0);
   388         //Ignore result code.
   389         //  This returns E_FAIL if the named property is not in the bag.
   390         //TODO(bungeman) enumerate the properties,
   391         //  write and set hr iff property exists.
   392         piPropertybag->Write(1, &name, &value);
   393     }
   394     if (SUCCEEDED(hr)) {
   395         hr = piBitmapFrameEncode->Initialize(piPropertybag.get());
   396     }
   398     //Set the size of the frame.
   399     const UINT width = bitmap->width();
   400     const UINT height = bitmap->height();
   401     if (SUCCEEDED(hr)) {
   402         hr = piBitmapFrameEncode->SetSize(width, height);
   403     }
   405     //Set the pixel format of the frame.
   406     const WICPixelFormatGUID formatDesired = GUID_WICPixelFormat32bppBGRA;
   407     WICPixelFormatGUID formatGUID = formatDesired;
   408     if (SUCCEEDED(hr)) {
   409         hr = piBitmapFrameEncode->SetPixelFormat(&formatGUID);
   410     }
   411     if (SUCCEEDED(hr)) {
   412         //Be sure the image format is the one requested.
   413         hr = IsEqualGUID(formatGUID, formatDesired) ? S_OK : E_FAIL;
   414     }
   416     //Write the pixels into the frame.
   417     if (SUCCEEDED(hr)) {
   418         SkAutoLockPixels alp(*bitmap);
   419         const UINT stride = (UINT) bitmap->rowBytes();
   420         hr = piBitmapFrameEncode->WritePixels(
   421             height
   422             , stride
   423             , stride * height
   424             , reinterpret_cast<BYTE*>(bitmap->getPixels()));
   425     }
   427     if (SUCCEEDED(hr)) {
   428         hr = piBitmapFrameEncode->Commit();
   429     }
   431     if (SUCCEEDED(hr)) {
   432         hr = piEncoder->Commit();
   433     }
   435     return SUCCEEDED(hr);
   436 }
   438 ///////////////////////////////////////////////////////////////////////////////
   440 static SkImageEncoder* sk_imageencoder_wic_factory(SkImageEncoder::Type t) {
   441     switch (t) {
   442         case SkImageEncoder::kBMP_Type:
   443         case SkImageEncoder::kICO_Type:
   444         case SkImageEncoder::kJPEG_Type:
   445         case SkImageEncoder::kPNG_Type:
   446             break;
   447         default:
   448             return NULL;
   449     }
   450     return SkNEW_ARGS(SkImageEncoder_WIC, (t));
   451 }
   453 static SkImageEncoder_EncodeReg gEReg(sk_imageencoder_wic_factory);
   455 static SkImageDecoder::Format get_format_wic(SkStreamRewindable* stream) {
   456     SkImageDecoder::Format format;
   457     SkImageDecoder_WIC codec;
   458     if (!codec.decodeStream(stream, NULL, SkImageDecoder_WIC::kDecodeFormat_WICMode, &format)) {
   459         format = SkImageDecoder::kUnknown_Format;
   460     }
   461     return format;
   462 }
   464 static SkImageDecoder_FormatReg gFormatReg(get_format_wic);

mercurial