aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Leon Scroggins III <scroggo@google.com>2017-10-30 09:07:53 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-11-03 15:29:34 +0000
commit0cbc10f94e2b350761e64b225c97390269f41479 (patch)
treea3dd274a32583b289af7fb930ce44a6eec001599
parent60aaeb2b551d5e3e90baacac315e899e26f758f1 (diff)
Make SkImageGeneratorCG apply encoded origin
SkImageGeneratorCG: - Detect the origin and apply it to the output - Deprecate NewFromEncodedCG and add MakeFromEncodedCG SkCodecImageGenerator: - Move code elsewhere for sharing - Apply origin for incomplete decodes SkPixmap.cpp/SkPixmapPriv.h: - Now has the shared code for generators to apply origin DMSrcSink.cpp: - Call MakeFromEncodedCG SkCGUtils.h: - Add a version of SkCopyPixelsFromCGImage that takes an SkPixmap Bug: skia:7138 Bug: skia:3834 Change-Id: Ic6dbc76360c6a84913b67373582f328d3946d637 Reviewed-on: https://skia-review.googlesource.com/63740 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Leon Scroggins <scroggo@google.com>
-rw-r--r--dm/DMSrcSink.cpp2
-rw-r--r--include/utils/mac/SkCGUtils.h4
-rw-r--r--src/codec/SkCodecImageGenerator.cpp82
-rw-r--r--src/core/SkPixmap.cpp29
-rw-r--r--src/core/SkPixmapPriv.h36
-rw-r--r--src/ports/SkImageGeneratorCG.cpp61
-rw-r--r--src/ports/SkImageGeneratorCG.h10
7 files changed, 136 insertions, 88 deletions
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 6af90c3a47..fc535dcd59 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -942,7 +942,7 @@ Error ImageGenSrc::draw(SkCanvas* canvas) const {
break;
case kPlatform_Mode: {
#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
- gen.reset(SkImageGeneratorCG::NewFromEncodedCG(encoded.get()));
+ gen = SkImageGeneratorCG::MakeFromEncodedCG(encoded);
#elif defined(SK_BUILD_FOR_WIN)
gen.reset(SkImageGeneratorWIC::NewFromEncodedWIC(encoded.get()));
#endif
diff --git a/include/utils/mac/SkCGUtils.h b/include/utils/mac/SkCGUtils.h
index 2dcbb965b4..06995c3ec1 100644
--- a/include/utils/mac/SkCGUtils.h
+++ b/include/utils/mac/SkCGUtils.h
@@ -11,6 +11,7 @@
#include "SkSize.h"
#include "SkImageInfo.h"
#include "SkImage.h"
+#include "SkPixmap.h"
#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
@@ -46,6 +47,9 @@ SK_API sk_sp<SkImage> SkMakeImageFromCGImage(CGImageRef);
*/
SK_API bool SkCopyPixelsFromCGImage(const SkImageInfo& info, size_t rowBytes, void* dstPixels,
CGImageRef src);
+static inline bool SkCopyPixelsFromCGImage(const SkPixmap& dst, CGImageRef src) {
+ return SkCopyPixelsFromCGImage(dst.info(), dst.rowBytes(), dst.writable_addr(), src);
+}
/**
* Create an imageref from the specified bitmap using the specified colorspace.
diff --git a/src/codec/SkCodecImageGenerator.cpp b/src/codec/SkCodecImageGenerator.cpp
index 741c8e393d..3f03b2f03e 100644
--- a/src/codec/SkCodecImageGenerator.cpp
+++ b/src/codec/SkCodecImageGenerator.cpp
@@ -5,42 +5,10 @@
* found in the LICENSE file.
*/
-#include "SkAutoPixmapStorage.h"
#include "SkCodecImageGenerator.h"
#include "SkMakeUnique.h"
#include "SkPixmapPriv.h"
-#define kMirrorX SkPixmapPriv::kMirrorX
-#define kMirrorY SkPixmapPriv::kMirrorY
-#define kSwapXY SkPixmapPriv::kSwapXY
-
-const uint8_t gOrientationFlags[] = {
- 0, // kTopLeft_SkEncodedOrigin
- kMirrorX, // kTopRight_SkEncodedOrigin
- kMirrorX | kMirrorY, // kBottomRight_SkEncodedOrigin
- kMirrorY, // kBottomLeft_SkEncodedOrigin
- kSwapXY, // kLeftTop_SkEncodedOrigin
- kMirrorX | kSwapXY, // kRightTop_SkEncodedOrigin
- kMirrorX | kMirrorY | kSwapXY, // kRightBottom_SkEncodedOrigin
- kMirrorY | kSwapXY, // kLeftBottom_SkEncodedOrigin
-};
-
-SkPixmapPriv::OrientFlags SkPixmapPriv::OriginToOrient(SkEncodedOrigin o) {
- unsigned io = static_cast<int>(o) - 1;
- SkASSERT(io < SK_ARRAY_COUNT(gOrientationFlags));
- return static_cast<SkPixmapPriv::OrientFlags>(gOrientationFlags[io]);
-}
-
-static bool should_swap_width_height(SkEncodedOrigin o) {
- return SkToBool(SkPixmapPriv::OriginToOrient(o) & kSwapXY);
-}
-
-static SkImageInfo swap_width_height(SkImageInfo info) {
- return info.makeWH(info.height(), info.width());
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
std::unique_ptr<SkImageGenerator> SkCodecImageGenerator::MakeFromEncodedCodec(sk_sp<SkData> data) {
auto codec = SkCodec::MakeFromData(data);
if (nullptr == codec) {
@@ -55,8 +23,8 @@ static SkImageInfo adjust_info(SkCodec* codec) {
if (kUnpremul_SkAlphaType == info.alphaType()) {
info = info.makeAlphaType(kPremul_SkAlphaType);
}
- if (should_swap_width_height(codec->getOrigin())) {
- info = swap_width_height(info);
+ if (SkPixmapPriv::ShouldSwapWidthHeight(codec->getOrigin())) {
+ info = SkPixmapPriv::SwapWidthHeight(info);
}
return info;
}
@@ -73,39 +41,23 @@ SkData* SkCodecImageGenerator::onRefEncodedData() {
bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& requestInfo, void* requestPixels,
size_t requestRowBytes, const Options& opts) {
- const auto origin = fCodec->getOrigin();
- const SkPixmap request(requestInfo, requestPixels, requestRowBytes);
- const SkPixmap* codecMap = &request;
- SkAutoPixmapStorage storage; // used if we have to post-orient the output from the codec
-
- if (origin != kTopLeft_SkEncodedOrigin) {
- SkImageInfo info = requestInfo;
- if (should_swap_width_height(origin)) {
- info = swap_width_height(info);
+ SkPixmap dst(requestInfo, requestPixels, requestRowBytes);
+
+ auto decode = [this, &opts](const SkPixmap& pm) {
+ SkCodec::Options codecOpts;
+ codecOpts.fPremulBehavior = opts.fBehavior;
+ SkCodec::Result result = fCodec->getPixels(pm, &codecOpts);
+ switch (result) {
+ case SkCodec::kSuccess:
+ case SkCodec::kIncompleteInput:
+ case SkCodec::kErrorInInput:
+ return true;
+ default:
+ return false;
}
- // need a tmp buffer to receive the pixels, so we can post-orient them
- if (!storage.tryAlloc(info)) {
- return false;
- }
- codecMap = &storage;
- }
+ };
- SkCodec::Options codecOpts;
- codecOpts.fPremulBehavior = opts.fBehavior;
- SkCodec::Result result = fCodec->getPixels(*codecMap, &codecOpts);
- switch (result) {
- case SkCodec::kSuccess:
- if (codecMap != &request) {
- return SkPixmapPriv::Orient(request, *codecMap,
- SkPixmapPriv::OriginToOrient(origin));
- }
- // fall through
- case SkCodec::kIncompleteInput:
- case SkCodec::kErrorInInput:
- return true;
- default:
- return false;
- }
+ return SkPixmapPriv::Orient(dst, fCodec->getOrigin(), decode);
}
bool SkCodecImageGenerator::onQueryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const
diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp
index 7e394b468f..bd6436e72a 100644
--- a/src/core/SkPixmap.cpp
+++ b/src/core/SkPixmap.cpp
@@ -446,3 +446,32 @@ bool SkPixmapPriv::Orient(const SkPixmap& dst, const SkPixmap& src, OrientFlags
return draw_orientation(dst, src, flags);
}
+#define kMirrorX SkPixmapPriv::kMirrorX
+#define kMirrorY SkPixmapPriv::kMirrorY
+#define kSwapXY SkPixmapPriv::kSwapXY
+
+static constexpr uint8_t gOrientationFlags[] = {
+ 0, // kTopLeft_SkEncodedOrigin
+ kMirrorX, // kTopRight_SkEncodedOrigin
+ kMirrorX | kMirrorY, // kBottomRight_SkEncodedOrigin
+ kMirrorY, // kBottomLeft_SkEncodedOrigin
+ kSwapXY, // kLeftTop_SkEncodedOrigin
+ kMirrorX | kSwapXY, // kRightTop_SkEncodedOrigin
+ kMirrorX | kMirrorY | kSwapXY, // kRightBottom_SkEncodedOrigin
+ kMirrorY | kSwapXY, // kLeftBottom_SkEncodedOrigin
+};
+
+SkPixmapPriv::OrientFlags SkPixmapPriv::OriginToOrient(SkEncodedOrigin o) {
+ unsigned io = static_cast<int>(o) - 1;
+ SkASSERT(io < SK_ARRAY_COUNT(gOrientationFlags));
+ return static_cast<SkPixmapPriv::OrientFlags>(gOrientationFlags[io]);
+}
+
+bool SkPixmapPriv::ShouldSwapWidthHeight(SkEncodedOrigin o) {
+ return SkToBool(OriginToOrient(o) & kSwapXY);
+}
+
+SkImageInfo SkPixmapPriv::SwapWidthHeight(const SkImageInfo& info) {
+ return info.makeWH(info.height(), info.width());
+}
+
diff --git a/src/core/SkPixmapPriv.h b/src/core/SkPixmapPriv.h
index 1d677fdc46..9941862676 100644
--- a/src/core/SkPixmapPriv.h
+++ b/src/core/SkPixmapPriv.h
@@ -10,6 +10,7 @@
#include "SkPixmap.h"
#include "SkEncodedOrigin.h"
+#include "SkAutoPixmapStorage.h"
class SkPixmapPriv {
public:
@@ -27,6 +28,41 @@ public:
* by the flags. If the inputs are invalid, this returns false and no copy is made.
*/
static bool Orient(const SkPixmap& dst, const SkPixmap& src, OrientFlags);
+
+ static bool ShouldSwapWidthHeight(SkEncodedOrigin o);
+ static SkImageInfo SwapWidthHeight(const SkImageInfo& info);
+
+ /**
+ * Decode an image and then copy into dst, applying origin.
+ *
+ * @param dst SkPixmap to write the final image, after
+ * applying the origin.
+ * @param origin SkEncodedOrigin to apply to the raw pixels.
+ * @param decode Function for decoding into a pixmap without
+ * applying the origin.
+ */
+ static bool Orient(const SkPixmap& dst, SkEncodedOrigin origin,
+ std::function<bool(const SkPixmap&)> decode) {
+ SkAutoPixmapStorage storage;
+ const SkPixmap* tmp = &dst;
+ if (origin != kTopLeft_SkEncodedOrigin) {
+ auto info = dst.info();
+ if (ShouldSwapWidthHeight(origin)) {
+ info = SwapWidthHeight(info);
+ }
+ if (!storage.tryAlloc(info)) {
+ return false;
+ }
+ tmp = &storage;
+ }
+ if (!decode(*tmp)) {
+ return false;
+ }
+ if (tmp != &dst) {
+ return Orient(dst, *tmp, OriginToOrient(origin));
+ }
+ return true;
+ }
};
#endif
diff --git a/src/ports/SkImageGeneratorCG.cpp b/src/ports/SkImageGeneratorCG.cpp
index a2fe6a40ef..2d2c3d3bd5 100644
--- a/src/ports/SkImageGeneratorCG.cpp
+++ b/src/ports/SkImageGeneratorCG.cpp
@@ -6,6 +6,7 @@
*/
#include "SkImageGeneratorCG.h"
+#include "SkPixmapPriv.h"
#ifdef SK_BUILD_FOR_MAC
#include <ApplicationServices/ApplicationServices.h>
@@ -28,8 +29,14 @@ static CGImageSourceRef data_to_CGImageSrc(SkData* data) {
return imageSrc;
}
+#ifdef SK_LEGACY_NEW_FROM_ENCODED_CG
SkImageGenerator* SkImageGeneratorCG::NewFromEncodedCG(SkData* data) {
- CGImageSourceRef imageSrc = data_to_CGImageSrc(data);
+ return MakeFromEncodedCG(sk_ref_sp(data)).release();
+}
+#endif
+
+std::unique_ptr<SkImageGenerator> SkImageGeneratorCG::MakeFromEncodedCG(sk_sp<SkData> data) {
+ CGImageSourceRef imageSrc = data_to_CGImageSrc(data.get());
if (!imageSrc) {
return nullptr;
}
@@ -50,8 +57,6 @@ SkImageGenerator* SkImageGeneratorCG::NewFromEncodedCG(SkData* data) {
if (nullptr == widthRef || nullptr == heightRef) {
return nullptr;
}
- bool hasAlpha = (bool) (CFDictionaryGetValue(properties,
- kCGImagePropertyHasAlpha));
int width, height;
if (!CFNumberGetValue(widthRef, kCFNumberIntType, &width) ||
@@ -59,20 +64,37 @@ SkImageGenerator* SkImageGeneratorCG::NewFromEncodedCG(SkData* data) {
return nullptr;
}
+ bool hasAlpha = (bool) (CFDictionaryGetValue(properties,
+ kCGImagePropertyHasAlpha));
SkAlphaType alphaType = hasAlpha ? kPremul_SkAlphaType : kOpaque_SkAlphaType;
SkImageInfo info = SkImageInfo::MakeS32(width, height, alphaType);
+ auto origin = kDefault_SkEncodedOrigin;
+ auto orientationRef = (CFNumberRef) (CFDictionaryGetValue(properties,
+ kCGImagePropertyOrientation));
+ int originInt;
+ if (orientationRef && CFNumberGetValue(orientationRef, kCFNumberIntType, &originInt)) {
+ origin = (SkEncodedOrigin) originInt;
+ }
+
+ if (SkPixmapPriv::ShouldSwapWidthHeight(origin)) {
+ info = SkPixmapPriv::SwapWidthHeight(info);
+ }
+
// FIXME: We have the opportunity to extract color space information here,
// though I think it makes sense to wait until we understand how
// we want to communicate it to the generator.
- return new SkImageGeneratorCG(info, autoImageSrc.release(), data);
+ return std::unique_ptr<SkImageGenerator>(new SkImageGeneratorCG(info, autoImageSrc.release(),
+ std::move(data), origin));
}
-SkImageGeneratorCG::SkImageGeneratorCG(const SkImageInfo& info, const void* imageSrc, SkData* data)
+SkImageGeneratorCG::SkImageGeneratorCG(const SkImageInfo& info, const void* imageSrc,
+ sk_sp<SkData> data, SkEncodedOrigin origin)
: INHERITED(info)
, fImageSrc(imageSrc)
- , fData(SkRef(data))
+ , fData(std::move(data))
+ , fOrigin(origin)
{}
SkData* SkImageGeneratorCG::onRefEncodedData() {
@@ -105,18 +127,17 @@ bool SkImageGeneratorCG::onGetPixels(const SkImageInfo& info, void* pixels, size
}
SkAutoTCallVProc<CGImage, CGImageRelease> autoImage(image);
- // FIXME: Using this function (as opposed to swizzling ourselves) greatly
- // restricts the color and alpha types that we support. If we
- // swizzle ourselves, we can add support for:
- // kUnpremul_SkAlphaType
- // 16-bit per component RGBA
- // kGray_8_SkColorType
- // kIndex_8_SkColorType
- // Additionally, it would be interesting to compare the performance
- // of SkSwizzler with CG's built in swizzler.
- if (!SkCopyPixelsFromCGImage(info, rowBytes, pixels, image)) {
- return false;
- }
-
- return true;
+ SkPixmap dst(info, pixels, rowBytes);
+ auto decode = [&image](const SkPixmap& pm) {
+ // FIXME: Using SkCopyPixelsFromCGImage (as opposed to swizzling
+ // ourselves) greatly restricts the color and alpha types that we
+ // support. If we swizzle ourselves, we can add support for:
+ // kUnpremul_SkAlphaType
+ // 16-bit per component RGBA
+ // kGray_8_SkColorType
+ // Additionally, it would be interesting to compare the performance
+ // of SkSwizzler with CG's built in swizzler.
+ return SkCopyPixelsFromCGImage(pm, image);
+ };
+ return SkPixmapPriv::Orient(dst, fOrigin, decode);
}
diff --git a/src/ports/SkImageGeneratorCG.h b/src/ports/SkImageGeneratorCG.h
index 65300a6de2..58aac4f01a 100644
--- a/src/ports/SkImageGeneratorCG.h
+++ b/src/ports/SkImageGeneratorCG.h
@@ -10,16 +10,21 @@
#include "SkCGUtils.h"
#include "SkData.h"
+#include "SkEncodedOrigin.h"
#include "SkImageGenerator.h"
#include "SkTemplates.h"
class SkImageGeneratorCG : public SkImageGenerator {
public:
+#ifdef SK_LEGACY_NEW_FROM_ENCODED_CG
/*
* Refs the data if an image generator can be returned. Otherwise does
* not affect the data.
*/
static SkImageGenerator* NewFromEncodedCG(SkData* data);
+#endif
+
+ static std::unique_ptr<SkImageGenerator> MakeFromEncodedCG(sk_sp<SkData>);
protected:
SkData* onRefEncodedData() override;
@@ -30,12 +35,13 @@ protected:
private:
/*
* Takes ownership of the imageSrc
- * Refs the data
*/
- SkImageGeneratorCG(const SkImageInfo& info, const void* imageSrc, SkData* data);
+ SkImageGeneratorCG(const SkImageInfo& info, const void* imageSrc, sk_sp<SkData> data,
+ SkEncodedOrigin origin);
SkAutoTCallVProc<const void, CFRelease> fImageSrc;
sk_sp<SkData> fData;
+ const SkEncodedOrigin fOrigin;
typedef SkImageGenerator INHERITED;
};