aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmake/CMakeLists.txt4
-rw-r--r--dm/DM.cpp6
-rw-r--r--dm/DMSrcSink.cpp23
-rw-r--r--gyp/ports.gyp8
-rw-r--r--public.bzl6
-rw-r--r--src/ports/SkImageGeneratorWIC.cpp175
-rw-r--r--src/ports/SkImageGeneratorWIC.h63
-rw-r--r--tools/dm_flags.json44
-rwxr-xr-xtools/dm_flags.py14
9 files changed, 337 insertions, 6 deletions
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index d71415996c..9fc4ea5a42 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -109,6 +109,10 @@ if (NOT APPLE)
remove_srcs(../src/ports/SkImageGeneratorCG.cpp)
endif()
+if (NOT WIN32)
+ remove_srcs(../src/ports/SkImageGeneratorWIC.cpp)
+endif()
+
if (WIN32)
if(SKIA_GDI)
remove_srcs(../src/ports/SkFontMgr_win_dw_factory.cpp)
diff --git a/dm/DM.cpp b/dm/DM.cpp
index 13024633ab..9b3a42f48b 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -605,6 +605,12 @@ static void push_codec_srcs(Path path) {
{
push_image_gen_src(path, ImageGenSrc::kPlatform_Mode, alphaType, false);
}
+#elif defined(SK_BUILD_FOR_WIN)
+ if (kWEBP_SkEncodedFormat != codec->getEncodedFormat() &&
+ kWBMP_SkEncodedFormat != codec->getEncodedFormat())
+ {
+ push_image_gen_src(path, ImageGenSrc::kPlatform_Mode, alphaType, false);
+ }
#endif
}
}
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index b27ed8b51f..b8ed96b5e4 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -15,6 +15,7 @@
#include "SkError.h"
#include "SkImageGenerator.h"
#include "SkImageGeneratorCG.h"
+#include "SkImageGeneratorWIC.h"
#include "SkMallocPixelRef.h"
#include "SkMultiPictureDraw.h"
#include "SkNullCanvas.h"
@@ -32,6 +33,10 @@
#include "SkSwizzler.h"
#include <functional>
+#if defined(SK_BUILD_FOR_WIN)
+ #include "SkAutoCoInitialize.h"
+#endif
+
#ifdef SK_MOJO
#include "SkMojo.mojom.h"
#endif
@@ -791,6 +796,14 @@ Error ImageGenSrc::draw(SkCanvas* canvas) const {
return SkStringPrintf("Couldn't read %s.", fPath.c_str());
}
+#if defined(SK_BUILD_FOR_WIN)
+ // Initialize COM in order to test with WIC.
+ SkAutoCoInitialize com;
+ if (!com.succeeded()) {
+ return "Could not initialize COM.";
+ }
+#endif
+
SkAutoTDelete<SkImageGenerator> gen(nullptr);
switch (fMode) {
case kCodec_Mode:
@@ -799,14 +812,18 @@ Error ImageGenSrc::draw(SkCanvas* canvas) const {
return "Could not create codec image generator.";
}
break;
+ case kPlatform_Mode: {
#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
- case kPlatform_Mode:
gen.reset(SkImageGeneratorCG::NewFromEncodedCG(encoded));
+#elif defined(SK_BUILD_FOR_WIN)
+ gen.reset(SkImageGeneratorWIC::NewFromEncodedWIC(encoded));
+#endif
+
if (!gen) {
- return "Could not create CG image generator.";
+ return "Could not create platform image generator.";
}
break;
-#endif
+ }
default:
SkASSERT(false);
return "Invalid image generator mode";
diff --git a/gyp/ports.gyp b/gyp/ports.gyp
index db72625b94..ddc9ead96e 100644
--- a/gyp/ports.gyp
+++ b/gyp/ports.gyp
@@ -178,6 +178,9 @@
'../src/ports/SkTime_Unix.cpp',
'../src/ports/SkTLS_pthread.cpp',
],
+ 'sources': [
+ '../src/ports/SkImageGeneratorWIC.cpp',
+ ],
'conditions': [
# when we build for win, we only want one of these default files
[ 'skia_gdi', {
@@ -186,6 +189,11 @@
'sources/': [['include', '../src/ports/SkFontMgr_win_dw_factory.cpp']],
}],
],
+ 'link_settings': {
+ 'libraries': [
+ '-lwindowscodecs.lib',
+ ],
+ },
}, { # else !win
'sources!': [
'../src/ports/SkDebug_win.cpp',
diff --git a/public.bzl b/public.bzl
index 72a27b6cac..df3049fdcd 100644
--- a/public.bzl
+++ b/public.bzl
@@ -150,6 +150,7 @@ BASE_SRCS_UNIX = struct(
"src/opts/SkBlitMask_opts_none.cpp",
"src/opts/SkBlitRow_opts_none.cpp",
"src/ports/*CG*",
+ "src/ports/*WIC*",
"src/ports/*android*",
"src/ports/*chromium*",
"src/ports/*mac*",
@@ -162,7 +163,6 @@ BASE_SRCS_UNIX = struct(
"src/ports/SkFontMgr_empty_factory.cpp",
"src/ports/SkFontMgr_fontconfig.cpp",
"src/ports/SkFontMgr_fontconfig_factory.cpp",
- "src/ports/SkImageDecoder_WIC.cpp",
"src/ports/SkImageDecoder_empty.cpp",
"src/ports/SkImageGenerator_none.cpp",
"src/ports/SkTLS_none.cpp",
@@ -196,6 +196,7 @@ BASE_SRCS_ANDROID = struct(
"src/opts/SkBlitRow_opts_none.cpp",
"src/ports/*CG*",
"src/ports/*FontConfig*",
+ "src/ports/*WIC*",
"src/ports/*chromium*",
"src/ports/*fontconfig*",
"src/ports/*mac*",
@@ -208,7 +209,6 @@ BASE_SRCS_ANDROID = struct(
"src/ports/SkFontMgr_custom_directory_factory.cpp",
"src/ports/SkFontMgr_custom_embedded_factory.cpp",
"src/ports/SkFontMgr_empty_factory.cpp",
- "src/ports/SkImageDecoder_WIC.cpp",
"src/ports/SkImageDecoder_empty.cpp",
"src/ports/SkImageGenerator_none.cpp",
"src/ports/SkTLS_none.cpp",
@@ -251,6 +251,7 @@ BASE_SRCS_IOS = struct(
"src/ports/*CG*",
"src/ports/*FontConfig*",
"src/ports/*FreeType*",
+ "src/ports/*WIC*",
"src/ports/*android*",
"src/ports/*chromium*",
"src/ports/*fontconfig*",
@@ -263,7 +264,6 @@ BASE_SRCS_IOS = struct(
"src/ports/SkFontMgr_custom_directory_factory.cpp",
"src/ports/SkFontMgr_custom_embedded_factory.cpp",
"src/ports/SkFontMgr_empty_factory.cpp",
- "src/ports/SkImageDecoder_WIC.cpp",
"src/ports/SkImageGenerator_none.cpp",
"src/ports/SkTLS_none.cpp",
],
diff --git a/src/ports/SkImageGeneratorWIC.cpp b/src/ports/SkImageGeneratorWIC.cpp
new file mode 100644
index 0000000000..f22cb5a7af
--- /dev/null
+++ b/src/ports/SkImageGeneratorWIC.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkImageGeneratorWIC.h"
+#include "SkIStream.h"
+#include "SkStream.h"
+
+// All Windows SDKs back to XPSP2 export the CLSID_WICImagingFactory symbol.
+// In the Windows8 SDK the CLSID_WICImagingFactory symbol is still exported
+// but CLSID_WICImagingFactory is then #defined to CLSID_WICImagingFactory2.
+// Undo this #define if it has been done so that we link against the symbols
+// we intended to link against on all SDKs.
+#if defined(CLSID_WICImagingFactory)
+ #undef CLSID_WICImagingFactory
+#endif
+
+SkImageGenerator* SkImageGeneratorWIC::NewFromEncodedWIC(SkData* data) {
+ // Create Windows Imaging Component ImagingFactory.
+ SkTScopedComPtr<IWICImagingFactory> imagingFactory;
+ HRESULT hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER,
+ IID_PPV_ARGS(&imagingFactory));
+ if (FAILED(hr)) {
+ return nullptr;
+ }
+
+ // Create an IStream.
+ SkTScopedComPtr<IStream> iStream;
+ // Note that iStream will take ownership of the new memory stream because
+ // we set |deleteOnRelease| to true.
+ hr = SkIStream::CreateFromSkStream(new SkMemoryStream(data), true, &iStream);
+ if (FAILED(hr)) {
+ return nullptr;
+ }
+
+ // Create the decoder from the stream.
+ SkTScopedComPtr<IWICBitmapDecoder> decoder;
+ hr = imagingFactory->CreateDecoderFromStream(iStream.get(), nullptr,
+ WICDecodeMetadataCacheOnDemand, &decoder);
+ if (FAILED(hr)) {
+ return nullptr;
+ }
+
+ // Select the first frame from the decoder.
+ SkTScopedComPtr<IWICBitmapFrameDecode> imageFrame;
+ hr = decoder->GetFrame(0, &imageFrame);
+ if (FAILED(hr)) {
+ return nullptr;
+ }
+
+ // Treat the frame as an image source.
+ SkTScopedComPtr<IWICBitmapSource> imageSource;
+ hr = imageFrame->QueryInterface(IID_PPV_ARGS(&imageSource));
+ if (FAILED(hr)) {
+ return nullptr;
+ }
+
+ // Get the size of the image.
+ UINT width;
+ UINT height;
+ hr = imageSource->GetSize(&width, &height);
+ if (FAILED(hr)) {
+ return nullptr;
+ }
+
+ // Get the encoded pixel format.
+ WICPixelFormatGUID format;
+ hr = imageSource->GetPixelFormat(&format);
+ if (FAILED(hr)) {
+ return nullptr;
+ }
+
+ // Recommend kOpaque if the image is opaque and kPremul otherwise.
+ // FIXME: We are stuck recommending kPremul for all indexed formats
+ // (Ex: GUID_WICPixelFormat8bppIndexed) because we don't have
+ // a way to check if the image has alpha.
+ SkAlphaType alphaType = kPremul_SkAlphaType;
+
+ if (GUID_WICPixelFormat16bppBGR555 == format ||
+ GUID_WICPixelFormat16bppBGR565 == format ||
+ GUID_WICPixelFormat32bppBGR101010 == format ||
+ GUID_WICPixelFormatBlackWhite == format ||
+ GUID_WICPixelFormat2bppGray == format ||
+ GUID_WICPixelFormat4bppGray == format ||
+ GUID_WICPixelFormat8bppGray == format ||
+ GUID_WICPixelFormat16bppGray == format ||
+ GUID_WICPixelFormat16bppGrayFixedPoint == format ||
+ GUID_WICPixelFormat16bppGrayHalf == format ||
+ GUID_WICPixelFormat32bppGrayFloat == format ||
+ GUID_WICPixelFormat32bppGrayFixedPoint == format ||
+ GUID_WICPixelFormat32bppRGBE == format ||
+ GUID_WICPixelFormat24bppRGB == format ||
+ GUID_WICPixelFormat24bppBGR == format ||
+ GUID_WICPixelFormat32bppBGR == format ||
+ GUID_WICPixelFormat48bppRGB == format ||
+ GUID_WICPixelFormat48bppBGR == format ||
+ GUID_WICPixelFormat48bppRGBFixedPoint == format ||
+ GUID_WICPixelFormat48bppBGRFixedPoint == format ||
+ GUID_WICPixelFormat48bppRGBHalf == format ||
+ GUID_WICPixelFormat64bppRGBFixedPoint == format ||
+ GUID_WICPixelFormat64bppRGBHalf == format ||
+ GUID_WICPixelFormat96bppRGBFixedPoint == format ||
+ GUID_WICPixelFormat128bppRGBFloat == format ||
+ GUID_WICPixelFormat128bppRGBFixedPoint == format ||
+ GUID_WICPixelFormat32bppRGB == format ||
+ GUID_WICPixelFormat64bppRGB == format ||
+ GUID_WICPixelFormat96bppRGBFloat == format ||
+ GUID_WICPixelFormat32bppCMYK == format ||
+ GUID_WICPixelFormat64bppCMYK == format ||
+ GUID_WICPixelFormat8bppY == format ||
+ GUID_WICPixelFormat8bppCb == format ||
+ GUID_WICPixelFormat8bppCr == format ||
+ GUID_WICPixelFormat16bppCbCr == format)
+ {
+ alphaType = kOpaque_SkAlphaType;
+ }
+
+ // FIXME: If we change the implementation to handle swizzling ourselves,
+ // we can support more output formats.
+ SkImageInfo info = SkImageInfo::MakeN32(width, height, alphaType);
+ return new SkImageGeneratorWIC(info, imagingFactory.release(), imageSource.release(), data);
+}
+
+SkImageGeneratorWIC::SkImageGeneratorWIC(const SkImageInfo& info,
+ IWICImagingFactory* imagingFactory, IWICBitmapSource* imageSource, SkData* data)
+ : INHERITED(info)
+ , fImagingFactory(imagingFactory)
+ , fImageSource(imageSource)
+ , fData(SkRef(data))
+{}
+
+SkData* SkImageGeneratorWIC::onRefEncodedData(SK_REFENCODEDDATA_CTXPARAM) {
+ return SkRef(fData.get());
+}
+
+bool SkImageGeneratorWIC::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
+ SkPMColor ctable[], int* ctableCount) {
+ if (kN32_SkColorType != info.colorType()) {
+ return false;
+ }
+
+ // Create a format converter.
+ SkTScopedComPtr<IWICFormatConverter> formatConverter;
+ HRESULT hr = fImagingFactory->CreateFormatConverter(&formatConverter);
+ if (FAILED(hr)) {
+ return false;
+ }
+
+ GUID format = GUID_WICPixelFormat32bppPBGRA;
+ if (kUnpremul_SkAlphaType == info.alphaType()) {
+ format = GUID_WICPixelFormat32bppBGRA;
+ }
+
+ hr = formatConverter->Initialize(fImageSource.get(), format, WICBitmapDitherTypeNone, nullptr,
+ 0.0, WICBitmapPaletteTypeCustom);
+ if (FAILED(hr)) {
+ return false;
+ }
+
+ // Treat the format converter as an image source.
+ SkTScopedComPtr<IWICBitmapSource> formatConverterSrc;
+ hr = formatConverter->QueryInterface(IID_PPV_ARGS(&formatConverterSrc));
+ if (FAILED(hr)) {
+ return false;
+ }
+
+ // Set the destination pixels.
+ hr = formatConverterSrc->CopyPixels(nullptr, (UINT) rowBytes, (UINT) rowBytes * info.height(),
+ (BYTE*) pixels);
+
+ return SUCCEEDED(hr);
+}
diff --git a/src/ports/SkImageGeneratorWIC.h b/src/ports/SkImageGeneratorWIC.h
new file mode 100644
index 0000000000..1366333350
--- /dev/null
+++ b/src/ports/SkImageGeneratorWIC.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkTypes.h"
+
+#if defined(SK_BUILD_FOR_WIN)
+
+#include "SkData.h"
+#include "SkImageGenerator.h"
+#include "SkTemplates.h"
+#include "SkTScopedComPtr.h"
+
+#include <wincodec.h>
+
+/*
+ * Any Windows program that uses COM must initialize the COM library by calling
+ * the CoInitializeEx function. In addition, each thread that uses a COM
+ * interface must make a separate call to this function.
+ *
+ * For every successful call to CoInitializeEx, the thread must call
+ * CoUninitialize before it exits.
+ *
+ * SkImageGeneratorWIC requires the COM library and leaves it to the client to
+ * initialize COM for their application.
+ *
+ * For more information on initializing COM, please see:
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/ff485844.aspx
+ */
+class SkImageGeneratorWIC : public SkImageGenerator {
+public:
+ /*
+ * Refs the data if an image generator can be returned. Otherwise does
+ * not affect the data.
+ */
+ static SkImageGenerator* NewFromEncodedWIC(SkData* data);
+
+protected:
+ SkData* onRefEncodedData(SK_REFENCODEDDATA_CTXPARAM) override;
+
+ bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[],
+ int* ctableCount) override;
+
+private:
+ /*
+ * Takes ownership of the imagingFactory
+ * Takes ownership of the imageSource
+ * Refs the data
+ */
+ SkImageGeneratorWIC(const SkImageInfo& info, IWICImagingFactory* imagingFactory,
+ IWICBitmapSource* imageSource, SkData* data);
+
+ SkTScopedComPtr<IWICImagingFactory> fImagingFactory;
+ SkTScopedComPtr<IWICBitmapSource> fImageSource;
+ SkAutoTUnref<SkData> fData;
+
+ typedef SkImageGenerator INHERITED;
+};
+
+#endif // SK_BUILD_FOR_WIN
diff --git a/tools/dm_flags.json b/tools/dm_flags.json
index c2006cd3a7..d8744f357c 100644
--- a/tools/dm_flags.json
+++ b/tools/dm_flags.json
@@ -3293,6 +3293,50 @@
"image",
"_",
"interlaced3.png",
+ "_",
+ "image",
+ "gen_platf",
+ "rle8-height-negative.bmp",
+ "_",
+ "image",
+ "gen_platf",
+ "rle4-height-negative.bmp",
+ "_",
+ "image",
+ "gen_platf",
+ "pal8os2v2.bmp",
+ "_",
+ "image",
+ "gen_platf",
+ "pal8os2v2-16.bmp",
+ "_",
+ "image",
+ "gen_platf",
+ "rgba32abf.bmp",
+ "_",
+ "image",
+ "gen_platf",
+ "rgb24prof.bmp",
+ "_",
+ "image",
+ "gen_platf",
+ "rgb24lprof.bmp",
+ "_",
+ "image",
+ "gen_platf",
+ "8bpp-pixeldata-cropped.bmp",
+ "_",
+ "image",
+ "gen_platf",
+ "4bpp-pixeldata-cropped.bmp",
+ "_",
+ "image",
+ "gen_platf",
+ "32bpp-pixeldata-cropped.bmp",
+ "_",
+ "image",
+ "gen_platf",
+ "24bpp-pixeldata-cropped.bmp",
"serialize-8888",
"gm",
"_",
diff --git a/tools/dm_flags.py b/tools/dm_flags.py
index 2e3ba7fd86..8addd08b0e 100755
--- a/tools/dm_flags.py
+++ b/tools/dm_flags.py
@@ -127,6 +127,20 @@ def get_args(bot):
# It's probably using uninitialized memory
blacklist.extend('_ image gen_platf frame_larger_than_image.gif'.split(' '))
+ # WIC fails on questionable bmps
+ if 'Win' in bot:
+ blacklist.extend('_ image gen_platf rle8-height-negative.bmp'.split(' '))
+ blacklist.extend('_ image gen_platf rle4-height-negative.bmp'.split(' '))
+ blacklist.extend('_ image gen_platf pal8os2v2.bmp'.split(' '))
+ blacklist.extend('_ image gen_platf pal8os2v2-16.bmp'.split(' '))
+ blacklist.extend('_ image gen_platf rgba32abf.bmp'.split(' '))
+ blacklist.extend('_ image gen_platf rgb24prof.bmp'.split(' '))
+ blacklist.extend('_ image gen_platf rgb24lprof.bmp'.split(' '))
+ blacklist.extend('_ image gen_platf 8bpp-pixeldata-cropped.bmp'.split(' '))
+ blacklist.extend('_ image gen_platf 4bpp-pixeldata-cropped.bmp'.split(' '))
+ blacklist.extend('_ image gen_platf 32bpp-pixeldata-cropped.bmp'.split(' '))
+ blacklist.extend('_ image gen_platf 24bpp-pixeldata-cropped.bmp'.split(' '))
+
# skia:4095
for test in ['not_native32_bitmap_config',
'bleed_image',