1 /*
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 
8 #include "include/core/SkYUVAIndex.h"
9 #include "src/codec/SkCodecImageGenerator.h"
10 #include "src/core/SkMakeUnique.h"
11 #include "src/core/SkPixmapPriv.h"
12 
MakeFromEncodedCodec(sk_sp<SkData> data)13 std::unique_ptr<SkImageGenerator> SkCodecImageGenerator::MakeFromEncodedCodec(sk_sp<SkData> data) {
14     auto codec = SkCodec::MakeFromData(data);
15     if (nullptr == codec) {
16         return nullptr;
17     }
18 
19     return std::unique_ptr<SkImageGenerator>(new SkCodecImageGenerator(std::move(codec), data));
20 }
21 
22 std::unique_ptr<SkImageGenerator>
MakeFromCodec(std::unique_ptr<SkCodec> codec)23 SkCodecImageGenerator::MakeFromCodec(std::unique_ptr<SkCodec> codec) {
24     return codec
25         ? std::unique_ptr<SkImageGenerator>(new SkCodecImageGenerator(std::move(codec), nullptr))
26         : nullptr;
27 }
28 
adjust_info(SkCodec * codec)29 static SkImageInfo adjust_info(SkCodec* codec) {
30     SkImageInfo info = codec->getInfo();
31     if (kUnpremul_SkAlphaType == info.alphaType()) {
32         info = info.makeAlphaType(kPremul_SkAlphaType);
33     }
34     if (SkPixmapPriv::ShouldSwapWidthHeight(codec->getOrigin())) {
35         info = SkPixmapPriv::SwapWidthHeight(info);
36     }
37     return info;
38 }
39 
SkCodecImageGenerator(std::unique_ptr<SkCodec> codec,sk_sp<SkData> data)40 SkCodecImageGenerator::SkCodecImageGenerator(std::unique_ptr<SkCodec> codec, sk_sp<SkData> data)
41     : INHERITED(adjust_info(codec.get()))
42     , fCodec(std::move(codec))
43     , fData(std::move(data))
44 {}
45 
onRefEncodedData()46 sk_sp<SkData> SkCodecImageGenerator::onRefEncodedData() {
47     return fData;
48 }
49 
onGetPixels(const SkImageInfo & requestInfo,void * requestPixels,size_t requestRowBytes,const Options &)50 bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& requestInfo, void* requestPixels,
51                                         size_t requestRowBytes, const Options&) {
52     SkPixmap dst(requestInfo, requestPixels, requestRowBytes);
53 
54     auto decode = [this](const SkPixmap& pm) {
55         SkCodec::Result result = fCodec->getPixels(pm);
56         switch (result) {
57             case SkCodec::kSuccess:
58             case SkCodec::kIncompleteInput:
59             case SkCodec::kErrorInInput:
60                 return true;
61             default:
62                 return false;
63         }
64     };
65 
66     return SkPixmapPriv::Orient(dst, fCodec->getOrigin(), decode);
67 }
68 
onQueryYUVA8(SkYUVASizeInfo * sizeInfo,SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],SkYUVColorSpace * colorSpace) const69 bool SkCodecImageGenerator::onQueryYUVA8(SkYUVASizeInfo* sizeInfo,
70                                          SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
71                                          SkYUVColorSpace* colorSpace) const {
72     // This image generator always returns 3 separate non-interleaved planes
73     yuvaIndices[SkYUVAIndex::kY_Index].fIndex = 0;
74     yuvaIndices[SkYUVAIndex::kY_Index].fChannel = SkColorChannel::kR;
75     yuvaIndices[SkYUVAIndex::kU_Index].fIndex = 1;
76     yuvaIndices[SkYUVAIndex::kU_Index].fChannel = SkColorChannel::kR;
77     yuvaIndices[SkYUVAIndex::kV_Index].fIndex = 2;
78     yuvaIndices[SkYUVAIndex::kV_Index].fChannel = SkColorChannel::kR;
79     yuvaIndices[SkYUVAIndex::kA_Index].fIndex = -1;
80     yuvaIndices[SkYUVAIndex::kA_Index].fChannel = SkColorChannel::kR;
81 
82     return fCodec->queryYUV8(sizeInfo, colorSpace);
83 }
84 
onGetYUVA8Planes(const SkYUVASizeInfo & sizeInfo,const SkYUVAIndex indices[SkYUVAIndex::kIndexCount],void * planes[])85 bool SkCodecImageGenerator::onGetYUVA8Planes(const SkYUVASizeInfo& sizeInfo,
86                                              const SkYUVAIndex indices[SkYUVAIndex::kIndexCount],
87                                              void* planes[]) {
88     SkCodec::Result result = fCodec->getYUV8Planes(sizeInfo, planes);
89     // TODO: check indices
90 
91     switch (result) {
92         case SkCodec::kSuccess:
93         case SkCodec::kIncompleteInput:
94         case SkCodec::kErrorInInput:
95             return true;
96         default:
97             return false;
98     }
99 }
100