Home | History | Annotate | Download | only in ports
      1 /*
      2  * Copyright 2016 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkImageGeneratorWIC.h"
      9 #include "SkIStream.h"
     10 #include "SkStream.h"
     11 
     12 // All Windows SDKs back to XPSP2 export the CLSID_WICImagingFactory symbol.
     13 // In the Windows8 SDK the CLSID_WICImagingFactory symbol is still exported
     14 // but CLSID_WICImagingFactory is then #defined to CLSID_WICImagingFactory2.
     15 // Undo this #define if it has been done so that we link against the symbols
     16 // we intended to link against on all SDKs.
     17 #if defined(CLSID_WICImagingFactory)
     18     #undef CLSID_WICImagingFactory
     19 #endif
     20 
     21 SkImageGenerator* SkImageGeneratorWIC::NewFromEncodedWIC(SkData* data) {
     22     // Create Windows Imaging Component ImagingFactory.
     23     SkTScopedComPtr<IWICImagingFactory> imagingFactory;
     24     HRESULT hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER,
     25             IID_PPV_ARGS(&imagingFactory));
     26     if (FAILED(hr)) {
     27         return nullptr;
     28     }
     29 
     30     // Create an IStream.
     31     SkTScopedComPtr<IStream> iStream;
     32     // Note that iStream will take ownership of the new memory stream because
     33     // we set |deleteOnRelease| to true.
     34     hr = SkIStream::CreateFromSkStream(new SkMemoryStream(sk_ref_sp(data)), true, &iStream);
     35     if (FAILED(hr)) {
     36         return nullptr;
     37     }
     38 
     39     // Create the decoder from the stream.
     40     SkTScopedComPtr<IWICBitmapDecoder> decoder;
     41     hr = imagingFactory->CreateDecoderFromStream(iStream.get(), nullptr,
     42             WICDecodeMetadataCacheOnDemand, &decoder);
     43     if (FAILED(hr)) {
     44         return nullptr;
     45     }
     46 
     47     // Select the first frame from the decoder.
     48     SkTScopedComPtr<IWICBitmapFrameDecode> imageFrame;
     49     hr = decoder->GetFrame(0, &imageFrame);
     50     if (FAILED(hr)) {
     51         return nullptr;
     52     }
     53 
     54     // Treat the frame as an image source.
     55     SkTScopedComPtr<IWICBitmapSource> imageSource;
     56     hr = imageFrame->QueryInterface(IID_PPV_ARGS(&imageSource));
     57     if (FAILED(hr)) {
     58         return nullptr;
     59     }
     60 
     61     // Get the size of the image.
     62     UINT width;
     63     UINT height;
     64     hr = imageSource->GetSize(&width, &height);
     65     if (FAILED(hr)) {
     66         return nullptr;
     67     }
     68 
     69     // Get the encoded pixel format.
     70     WICPixelFormatGUID format;
     71     hr = imageSource->GetPixelFormat(&format);
     72     if (FAILED(hr)) {
     73         return nullptr;
     74     }
     75 
     76     // Recommend kOpaque if the image is opaque and kPremul otherwise.
     77     // FIXME: We are stuck recommending kPremul for all indexed formats
     78     //        (Ex: GUID_WICPixelFormat8bppIndexed) because we don't have
     79     //        a way to check if the image has alpha.
     80     SkAlphaType alphaType = kPremul_SkAlphaType;
     81 
     82     if (GUID_WICPixelFormat16bppBGR555 == format ||
     83         GUID_WICPixelFormat16bppBGR565 == format ||
     84         GUID_WICPixelFormat32bppBGR101010 == format ||
     85         GUID_WICPixelFormatBlackWhite == format ||
     86         GUID_WICPixelFormat2bppGray == format ||
     87         GUID_WICPixelFormat4bppGray == format ||
     88         GUID_WICPixelFormat8bppGray == format ||
     89         GUID_WICPixelFormat16bppGray == format ||
     90         GUID_WICPixelFormat16bppGrayFixedPoint == format ||
     91         GUID_WICPixelFormat16bppGrayHalf == format ||
     92         GUID_WICPixelFormat32bppGrayFloat == format ||
     93         GUID_WICPixelFormat32bppGrayFixedPoint == format ||
     94         GUID_WICPixelFormat32bppRGBE == format ||
     95         GUID_WICPixelFormat24bppRGB == format ||
     96         GUID_WICPixelFormat24bppBGR == format ||
     97         GUID_WICPixelFormat32bppBGR == format ||
     98         GUID_WICPixelFormat48bppRGB == format ||
     99         GUID_WICPixelFormat48bppBGR == format ||
    100         GUID_WICPixelFormat48bppRGBFixedPoint == format ||
    101         GUID_WICPixelFormat48bppBGRFixedPoint == format ||
    102         GUID_WICPixelFormat48bppRGBHalf == format ||
    103         GUID_WICPixelFormat64bppRGBFixedPoint == format ||
    104         GUID_WICPixelFormat64bppRGBHalf == format ||
    105         GUID_WICPixelFormat96bppRGBFixedPoint == format ||
    106         GUID_WICPixelFormat128bppRGBFloat == format ||
    107         GUID_WICPixelFormat128bppRGBFixedPoint == format ||
    108         GUID_WICPixelFormat32bppRGB == format ||
    109         GUID_WICPixelFormat64bppRGB == format ||
    110         GUID_WICPixelFormat96bppRGBFloat == format ||
    111         GUID_WICPixelFormat32bppCMYK == format ||
    112         GUID_WICPixelFormat64bppCMYK == format ||
    113         GUID_WICPixelFormat8bppY == format ||
    114         GUID_WICPixelFormat8bppCb == format ||
    115         GUID_WICPixelFormat8bppCr == format ||
    116         GUID_WICPixelFormat16bppCbCr == format)
    117     {
    118         alphaType = kOpaque_SkAlphaType;
    119     }
    120 
    121     // FIXME: If we change the implementation to handle swizzling ourselves,
    122     //        we can support more output formats.
    123     SkImageInfo info = SkImageInfo::MakeS32(width, height, alphaType);
    124     return new SkImageGeneratorWIC(info, imagingFactory.release(), imageSource.release(), data);
    125 }
    126 
    127 SkImageGeneratorWIC::SkImageGeneratorWIC(const SkImageInfo& info,
    128         IWICImagingFactory* imagingFactory, IWICBitmapSource* imageSource, SkData* data)
    129     : INHERITED(info)
    130     , fImagingFactory(imagingFactory)
    131     , fImageSource(imageSource)
    132     , fData(SkRef(data))
    133 {}
    134 
    135 SkData* SkImageGeneratorWIC::onRefEncodedData() {
    136     return SkRef(fData.get());
    137 }
    138 
    139 bool SkImageGeneratorWIC::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
    140         const Options&) {
    141     if (kN32_SkColorType != info.colorType()) {
    142         return false;
    143     }
    144 
    145     // Create a format converter.
    146     SkTScopedComPtr<IWICFormatConverter> formatConverter;
    147     HRESULT hr = fImagingFactory->CreateFormatConverter(&formatConverter);
    148     if (FAILED(hr)) {
    149         return false;
    150     }
    151 
    152     GUID format = GUID_WICPixelFormat32bppPBGRA;
    153     if (kUnpremul_SkAlphaType == info.alphaType()) {
    154         format = GUID_WICPixelFormat32bppBGRA;
    155     }
    156 
    157     hr = formatConverter->Initialize(fImageSource.get(), format, WICBitmapDitherTypeNone, nullptr,
    158             0.0, WICBitmapPaletteTypeCustom);
    159     if (FAILED(hr)) {
    160         return false;
    161     }
    162 
    163     // Treat the format converter as an image source.
    164     SkTScopedComPtr<IWICBitmapSource> formatConverterSrc;
    165     hr = formatConverter->QueryInterface(IID_PPV_ARGS(&formatConverterSrc));
    166     if (FAILED(hr)) {
    167         return false;
    168     }
    169 
    170     // Set the destination pixels.
    171     hr = formatConverterSrc->CopyPixels(nullptr, (UINT) rowBytes, (UINT) rowBytes * info.height(),
    172             (BYTE*) pixels);
    173 
    174     return SUCCEEDED(hr);
    175 }
    176