SkImageGeneratorWIC.cpp 7.2 KB

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