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