blob: e8d7d3038a1860dfda00ee875bd078a1972a8ea7 [file] [log] [blame]
msarettedd2dcf2016-01-14 13:12:26 -08001/*
2 * Copyright 2015 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
Mike Reed43798692017-10-17 18:04:32 +00008#include "SkAutoPixmapStorage.h"
msarettedd2dcf2016-01-14 13:12:26 -08009#include "SkCodecImageGenerator.h"
Mike Reed185130c2017-02-15 15:14:16 -050010#include "SkMakeUnique.h"
Mike Reed43798692017-10-17 18:04:32 +000011#include "SkPixmapPriv.h"
12
13#define kMirrorX SkPixmapPriv::kMirrorX
14#define kMirrorY SkPixmapPriv::kMirrorY
15#define kSwapXY SkPixmapPriv::kSwapXY
16
17const uint8_t gOrientationFlags[] = {
18 0, // kTopLeft_Origin
19 kMirrorX, // kTopRight_Origin
20 kMirrorX | kMirrorY, // kBottomRight_Origin
21 kMirrorY, // kBottomLeft_Origin
22 kSwapXY, // kLeftTop_Origin
23 kMirrorX | kSwapXY, // kRightTop_Origin
24 kMirrorX | kMirrorY | kSwapXY, // kRightBottom_Origin
25 kMirrorY | kSwapXY, // kLeftBottom_Origin
26};
27
28SkPixmapPriv::OrientFlags SkPixmapPriv::OriginToOrient(SkCodec::Origin o) {
29 unsigned io = static_cast<int>(o) - 1;
30 SkASSERT(io < SK_ARRAY_COUNT(gOrientationFlags));
31 return static_cast<SkPixmapPriv::OrientFlags>(gOrientationFlags[io]);
32}
33
34static bool should_swap_width_height(SkCodec::Origin o) {
35 return SkToBool(SkPixmapPriv::OriginToOrient(o) & kSwapXY);
36}
37
38static SkImageInfo swap_width_height(SkImageInfo info) {
39 return info.makeWH(info.height(), info.width());
40}
41
42///////////////////////////////////////////////////////////////////////////////////////////////////
msarettedd2dcf2016-01-14 13:12:26 -080043
Mike Reed185130c2017-02-15 15:14:16 -050044std::unique_ptr<SkImageGenerator> SkCodecImageGenerator::MakeFromEncodedCodec(sk_sp<SkData> data) {
Mike Reedede7bac2017-07-23 15:30:02 -040045 auto codec = SkCodec::MakeFromData(data);
msarettedd2dcf2016-01-14 13:12:26 -080046 if (nullptr == codec) {
47 return nullptr;
48 }
49
Mike Reedede7bac2017-07-23 15:30:02 -040050 return std::unique_ptr<SkImageGenerator>(new SkCodecImageGenerator(std::move(codec), data));
msarettedd2dcf2016-01-14 13:12:26 -080051}
52
Mike Reed43798692017-10-17 18:04:32 +000053static SkImageInfo adjust_info(SkCodec* codec) {
54 SkImageInfo info = codec->getInfo();
brianosman03707122016-04-21 08:48:18 -070055 if (kUnpremul_SkAlphaType == info.alphaType()) {
Mike Reed43798692017-10-17 18:04:32 +000056 info = info.makeAlphaType(kPremul_SkAlphaType);
herb4d1061c2016-04-15 12:57:42 -070057 }
Mike Reed43798692017-10-17 18:04:32 +000058 if (should_swap_width_height(codec->getOrigin())) {
59 info = swap_width_height(info);
60 }
61 return info;
msarettb714fb02016-01-22 14:46:42 -080062}
63
Mike Reedede7bac2017-07-23 15:30:02 -040064SkCodecImageGenerator::SkCodecImageGenerator(std::unique_ptr<SkCodec> codec, sk_sp<SkData> data)
Mike Reed43798692017-10-17 18:04:32 +000065 : INHERITED(adjust_info(codec.get()))
Mike Reedede7bac2017-07-23 15:30:02 -040066 , fCodec(std::move(codec))
reed42943c82016-09-12 12:01:44 -070067 , fData(std::move(data))
msarettedd2dcf2016-01-14 13:12:26 -080068{}
69
Brian Osman2feb7962017-04-25 16:41:47 -040070SkData* SkCodecImageGenerator::onRefEncodedData() {
msarettedd2dcf2016-01-14 13:12:26 -080071 return SkRef(fData.get());
72}
73
Mike Reed43798692017-10-17 18:04:32 +000074bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& requestInfo, void* requestPixels,
75 size_t requestRowBytes, const Options& opts) {
76 const SkCodec::Origin origin = fCodec->getOrigin();
77 const SkPixmap request(requestInfo, requestPixels, requestRowBytes);
78 const SkPixmap* codecMap = &request;
79 SkAutoPixmapStorage storage; // used if we have to post-orient the output from the codec
80
81 if (origin != SkCodec::kTopLeft_Origin) {
82 SkImageInfo info = requestInfo;
83 if (should_swap_width_height(origin)) {
84 info = swap_width_height(info);
85 }
86 // need a tmp buffer to receive the pixels, so we can post-orient them
87 if (!storage.tryAlloc(info)) {
88 return false;
89 }
90 codecMap = &storage;
91 }
92
Matt Sarettd531ca02017-03-24 16:31:19 -040093 SkCodec::Options codecOpts;
94 codecOpts.fPremulBehavior = opts.fBehavior;
Mike Reed43798692017-10-17 18:04:32 +000095 SkCodec::Result result = fCodec->getPixels(*codecMap, &codecOpts);
msarettedd2dcf2016-01-14 13:12:26 -080096 switch (result) {
97 case SkCodec::kSuccess:
Mike Reed43798692017-10-17 18:04:32 +000098 if (codecMap != &request) {
99 return SkPixmapPriv::Orient(request, *codecMap,
100 SkPixmapPriv::OriginToOrient(origin));
101 }
102 // fall through
msarettedd2dcf2016-01-14 13:12:26 -0800103 case SkCodec::kIncompleteInput:
Leon Scroggins III674a1842017-07-06 12:26:09 -0400104 case SkCodec::kErrorInInput:
msarettedd2dcf2016-01-14 13:12:26 -0800105 return true;
106 default:
107 return false;
108 }
109}
110
msarett4984c3c2016-03-10 05:44:43 -0800111bool SkCodecImageGenerator::onQueryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const
112{
113 return fCodec->queryYUV8(sizeInfo, colorSpace);
114}
msarettb714fb02016-01-22 14:46:42 -0800115
msarett4984c3c2016-03-10 05:44:43 -0800116bool SkCodecImageGenerator::onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) {
msarettb714fb02016-01-22 14:46:42 -0800117 SkCodec::Result result = fCodec->getYUV8Planes(sizeInfo, planes);
msarettb714fb02016-01-22 14:46:42 -0800118
119 switch (result) {
120 case SkCodec::kSuccess:
121 case SkCodec::kIncompleteInput:
Leon Scroggins III674a1842017-07-06 12:26:09 -0400122 case SkCodec::kErrorInInput:
msarettb714fb02016-01-22 14:46:42 -0800123 return true;
124 default:
125 return false;
126 }
msarettedd2dcf2016-01-14 13:12:26 -0800127}