aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/codec
diff options
context:
space:
mode:
Diffstat (limited to 'src/codec')
-rw-r--r--src/codec/SkCodecImageGenerator.cpp74
1 files changed, 66 insertions, 8 deletions
diff --git a/src/codec/SkCodecImageGenerator.cpp b/src/codec/SkCodecImageGenerator.cpp
index e6ca2122ea..e8d7d3038a 100644
--- a/src/codec/SkCodecImageGenerator.cpp
+++ b/src/codec/SkCodecImageGenerator.cpp
@@ -5,8 +5,41 @@
* 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_Origin
+ kMirrorX, // kTopRight_Origin
+ kMirrorX | kMirrorY, // kBottomRight_Origin
+ kMirrorY, // kBottomLeft_Origin
+ kSwapXY, // kLeftTop_Origin
+ kMirrorX | kSwapXY, // kRightTop_Origin
+ kMirrorX | kMirrorY | kSwapXY, // kRightBottom_Origin
+ kMirrorY | kSwapXY, // kLeftBottom_Origin
+};
+
+SkPixmapPriv::OrientFlags SkPixmapPriv::OriginToOrient(SkCodec::Origin 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(SkCodec::Origin 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);
@@ -17,16 +50,19 @@ std::unique_ptr<SkImageGenerator> SkCodecImageGenerator::MakeFromEncodedCodec(sk
return std::unique_ptr<SkImageGenerator>(new SkCodecImageGenerator(std::move(codec), data));
}
-static SkImageInfo adjust_info(const SkImageInfo& info) {
- SkImageInfo newInfo = info;
+static SkImageInfo adjust_info(SkCodec* codec) {
+ SkImageInfo info = codec->getInfo();
if (kUnpremul_SkAlphaType == info.alphaType()) {
- newInfo = newInfo.makeAlphaType(kPremul_SkAlphaType);
+ info = info.makeAlphaType(kPremul_SkAlphaType);
}
- return newInfo;
+ if (should_swap_width_height(codec->getOrigin())) {
+ info = swap_width_height(info);
+ }
+ return info;
}
SkCodecImageGenerator::SkCodecImageGenerator(std::unique_ptr<SkCodec> codec, sk_sp<SkData> data)
- : INHERITED(adjust_info(codec->getInfo()))
+ : INHERITED(adjust_info(codec.get()))
, fCodec(std::move(codec))
, fData(std::move(data))
{}
@@ -35,13 +71,35 @@ SkData* SkCodecImageGenerator::onRefEncodedData() {
return SkRef(fData.get());
}
-bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
- const Options& opts) {
+bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& requestInfo, void* requestPixels,
+ size_t requestRowBytes, const Options& opts) {
+ const SkCodec::Origin 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 != SkCodec::kTopLeft_Origin) {
+ SkImageInfo info = requestInfo;
+ if (should_swap_width_height(origin)) {
+ info = swap_width_height(info);
+ }
+ // 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(info, pixels, rowBytes, &codecOpts);
+ 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;