aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ports/SkImageEncoder_WIC.cpp
diff options
context:
space:
mode:
authorGravatar msarett <msarett@google.com>2016-03-25 08:58:55 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-03-25 08:58:55 -0700
commitc1d0312b227328bee7240d1df4ceee55cf6e1858 (patch)
tree97e1e19854530f9481bbac3fb59e54075083d779 /src/ports/SkImageEncoder_WIC.cpp
parent587ea71a522cd05601b401d17ad207c01f0ee0d6 (diff)
Rename encoders to Sk*ImageEncoder
BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1836493002 CQ_EXTRA_TRYBOTS=client.skia.compile:Build-Ubuntu-GCC-x86_64-Release-CMake-Trybot,Build-Mac-Clang-x86_64-Release-CMake-Trybot Review URL: https://codereview.chromium.org/1836493002
Diffstat (limited to 'src/ports/SkImageEncoder_WIC.cpp')
-rw-r--r--src/ports/SkImageEncoder_WIC.cpp246
1 files changed, 246 insertions, 0 deletions
diff --git a/src/ports/SkImageEncoder_WIC.cpp b/src/ports/SkImageEncoder_WIC.cpp
new file mode 100644
index 0000000000..43068fc8f6
--- /dev/null
+++ b/src/ports/SkImageEncoder_WIC.cpp
@@ -0,0 +1,246 @@
+
+/*
+ * Copyright 2011 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_WIN32)
+
+// Workaround for:
+// http://connect.microsoft.com/VisualStudio/feedback/details/621653/
+// http://crbug.com/225822
+// In VS2010 both intsafe.h and stdint.h define the following without guards.
+// SkTypes brought in windows.h and stdint.h and the following defines are
+// not used by this file. However, they may be re-introduced by wincodec.h.
+#undef INT8_MIN
+#undef INT16_MIN
+#undef INT32_MIN
+#undef INT64_MIN
+#undef INT8_MAX
+#undef UINT8_MAX
+#undef INT16_MAX
+#undef UINT16_MAX
+#undef INT32_MAX
+#undef UINT32_MAX
+#undef INT64_MAX
+#undef UINT64_MAX
+
+#include <wincodec.h>
+#include "SkAutoCoInitialize.h"
+#include "SkImageEncoder.h"
+#include "SkIStream.h"
+#include "SkMovie.h"
+#include "SkStream.h"
+#include "SkTScopedComPtr.h"
+#include "SkUnPreMultiply.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
+
+/////////////////////////////////////////////////////////////////////////
+
+SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) {
+ return nullptr;
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+class SkImageEncoder_WIC : public SkImageEncoder {
+public:
+ SkImageEncoder_WIC(Type t) : fType(t) {}
+
+ // DO NOT USE this constructor. This exists only so SkForceLinking can
+ // link the WIC image encoder.
+ SkImageEncoder_WIC() {}
+
+protected:
+ virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality);
+
+private:
+ Type fType;
+};
+
+bool SkImageEncoder_WIC::onEncode(SkWStream* stream
+ , const SkBitmap& bitmapOrig
+ , int quality)
+{
+ GUID type;
+ switch (fType) {
+ case kBMP_Type:
+ type = GUID_ContainerFormatBmp;
+ break;
+ case kICO_Type:
+ type = GUID_ContainerFormatIco;
+ break;
+ case kJPEG_Type:
+ type = GUID_ContainerFormatJpeg;
+ break;
+ case kPNG_Type:
+ type = GUID_ContainerFormatPng;
+ break;
+ default:
+ return false;
+ }
+
+ //Convert to 8888 if needed.
+ const SkBitmap* bitmap;
+ SkBitmap bitmapCopy;
+ if (kN32_SkColorType == bitmapOrig.colorType() && bitmapOrig.isOpaque()) {
+ bitmap = &bitmapOrig;
+ } else {
+ if (!bitmapOrig.copyTo(&bitmapCopy, kN32_SkColorType)) {
+ return false;
+ }
+ bitmap = &bitmapCopy;
+ }
+
+ // We cannot use PBGRA so we need to unpremultiply ourselves
+ if (!bitmap->isOpaque()) {
+ SkAutoLockPixels alp(*bitmap);
+
+ uint8_t* pixels = reinterpret_cast<uint8_t*>(bitmap->getPixels());
+ for (int y = 0; y < bitmap->height(); ++y) {
+ for (int x = 0; x < bitmap->width(); ++x) {
+ uint8_t* bytes = pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel();
+
+ SkPMColor* src = reinterpret_cast<SkPMColor*>(bytes);
+ SkColor* dst = reinterpret_cast<SkColor*>(bytes);
+
+ *dst = SkUnPreMultiply::PMColorToColor(*src);
+ }
+ }
+ }
+
+ //Initialize COM.
+ SkAutoCoInitialize scopedCo;
+ if (!scopedCo.succeeded()) {
+ return false;
+ }
+
+ HRESULT hr = S_OK;
+
+ //Create Windows Imaging Component ImagingFactory.
+ SkTScopedComPtr<IWICImagingFactory> piImagingFactory;
+ if (SUCCEEDED(hr)) {
+ hr = CoCreateInstance(
+ CLSID_WICImagingFactory
+ , nullptr
+ , CLSCTX_INPROC_SERVER
+ , IID_PPV_ARGS(&piImagingFactory)
+ );
+ }
+
+ //Convert the SkWStream to an IStream.
+ SkTScopedComPtr<IStream> piStream;
+ if (SUCCEEDED(hr)) {
+ hr = SkWIStream::CreateFromSkWStream(stream, &piStream);
+ }
+
+ //Create an encode of the appropriate type.
+ SkTScopedComPtr<IWICBitmapEncoder> piEncoder;
+ if (SUCCEEDED(hr)) {
+ hr = piImagingFactory->CreateEncoder(type, nullptr, &piEncoder);
+ }
+
+ if (SUCCEEDED(hr)) {
+ hr = piEncoder->Initialize(piStream.get(), WICBitmapEncoderNoCache);
+ }
+
+ //Create a the frame.
+ SkTScopedComPtr<IWICBitmapFrameEncode> piBitmapFrameEncode;
+ SkTScopedComPtr<IPropertyBag2> piPropertybag;
+ if (SUCCEEDED(hr)) {
+ hr = piEncoder->CreateNewFrame(&piBitmapFrameEncode, &piPropertybag);
+ }
+
+ if (SUCCEEDED(hr)) {
+ PROPBAG2 name = { 0 };
+ name.dwType = PROPBAG2_TYPE_DATA;
+ name.vt = VT_R4;
+ name.pstrName = L"ImageQuality";
+
+ VARIANT value;
+ VariantInit(&value);
+ value.vt = VT_R4;
+ value.fltVal = (FLOAT)(quality / 100.0);
+
+ //Ignore result code.
+ // This returns E_FAIL if the named property is not in the bag.
+ //TODO(bungeman) enumerate the properties,
+ // write and set hr iff property exists.
+ piPropertybag->Write(1, &name, &value);
+ }
+ if (SUCCEEDED(hr)) {
+ hr = piBitmapFrameEncode->Initialize(piPropertybag.get());
+ }
+
+ //Set the size of the frame.
+ const UINT width = bitmap->width();
+ const UINT height = bitmap->height();
+ if (SUCCEEDED(hr)) {
+ hr = piBitmapFrameEncode->SetSize(width, height);
+ }
+
+ //Set the pixel format of the frame. If native encoded format cannot match BGRA,
+ //it will choose the closest pixel format that it supports.
+ const WICPixelFormatGUID formatDesired = GUID_WICPixelFormat32bppBGRA;
+ WICPixelFormatGUID formatGUID = formatDesired;
+ if (SUCCEEDED(hr)) {
+ hr = piBitmapFrameEncode->SetPixelFormat(&formatGUID);
+ }
+ if (SUCCEEDED(hr)) {
+ //Be sure the image format is the one requested.
+ hr = IsEqualGUID(formatGUID, formatDesired) ? S_OK : E_FAIL;
+ }
+
+ //Write the pixels into the frame.
+ if (SUCCEEDED(hr)) {
+ SkAutoLockPixels alp(*bitmap);
+ const UINT stride = (UINT) bitmap->rowBytes();
+ hr = piBitmapFrameEncode->WritePixels(
+ height
+ , stride
+ , stride * height
+ , reinterpret_cast<BYTE*>(bitmap->getPixels()));
+ }
+
+ if (SUCCEEDED(hr)) {
+ hr = piBitmapFrameEncode->Commit();
+ }
+
+ if (SUCCEEDED(hr)) {
+ hr = piEncoder->Commit();
+ }
+
+ return SUCCEEDED(hr);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static SkImageEncoder* sk_imageencoder_wic_factory(SkImageEncoder::Type t) {
+ switch (t) {
+ case SkImageEncoder::kBMP_Type:
+ case SkImageEncoder::kICO_Type:
+ case SkImageEncoder::kPNG_Type:
+ break;
+ default:
+ return nullptr;
+ }
+ return new SkImageEncoder_WIC(t);
+}
+
+static SkImageEncoder_EncodeReg gEReg(sk_imageencoder_wic_factory);
+
+DEFINE_ENCODER_CREATOR(ImageEncoder_WIC);
+
+#endif // defined(SK_BUILD_FOR_WIN32)