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 #include "src/codec/SkCodecImageGenerator.h"
8
9 #include "include/codec/SkEncodedOrigin.h"
10 #include "include/codec/SkPixmapUtils.h"
11 #include "include/core/SkAlphaType.h"
12 #include "include/core/SkData.h"
13 #include "include/core/SkImageInfo.h"
14 #include "include/core/SkPixmap.h"
15 #include "include/core/SkStream.h"
16 #include "include/core/SkTypes.h"
17 #include "src/codec/SkPixmapUtilsPriv.h"
18
19 #include <utility>
20
MakeFromEncodedCodec(sk_sp<SkData> data,std::optional<SkAlphaType> at)21 std::unique_ptr<SkImageGenerator> SkCodecImageGenerator::MakeFromEncodedCodec(
22 sk_sp<SkData> data, std::optional<SkAlphaType> at) {
23 auto codec = SkCodec::MakeFromData(data);
24 if (codec == nullptr) {
25 return nullptr;
26 }
27
28 return std::unique_ptr<SkImageGenerator>(new SkCodecImageGenerator(std::move(codec), at));
29 }
30
MakeFromCodec(std::unique_ptr<SkCodec> codec,std::optional<SkAlphaType> at)31 std::unique_ptr<SkImageGenerator> SkCodecImageGenerator::MakeFromCodec(
32 std::unique_ptr<SkCodec> codec, std::optional<SkAlphaType> at) {
33 return codec ? std::unique_ptr<SkImageGenerator>(
34 new SkCodecImageGenerator(std::move(codec), at))
35 : nullptr;
36 }
37
adjust_info(SkCodec * codec,std::optional<SkAlphaType> at)38 static SkImageInfo adjust_info(SkCodec* codec, std::optional<SkAlphaType> at) {
39 SkASSERT(at != kOpaque_SkAlphaType);
40 SkImageInfo info = codec->getInfo();
41 if (at.has_value()) {
42 // If a specific alpha type was requested, use that.
43 info = info.makeAlphaType(*at);
44 } else if (kUnpremul_SkAlphaType == info.alphaType()) {
45 // Otherwise, prefer premul over unpremul (this produces better filtering in general)
46 info = info.makeAlphaType(kPremul_SkAlphaType);
47 }
48 if (SkEncodedOriginSwapsWidthHeight(codec->getOrigin())) {
49 info = SkPixmapUtils::SwapWidthHeight(info);
50 }
51 return info;
52 }
53
SkCodecImageGenerator(std::unique_ptr<SkCodec> codec,std::optional<SkAlphaType> at)54 SkCodecImageGenerator::SkCodecImageGenerator(std::unique_ptr<SkCodec> codec,
55 std::optional<SkAlphaType> at)
56 : SkImageGenerator(adjust_info(codec.get(), at)), fCodec(std::move(codec)) {}
57
onRefEncodedData()58 sk_sp<SkData> SkCodecImageGenerator::onRefEncodedData() {
59 SkASSERT(fCodec);
60 if (!fCachedData) {
61 std::unique_ptr<SkStream> stream = fCodec->getEncodedData();
62 fCachedData = stream->getData();
63 if (!fCachedData) {
64 // stream should already be a copy of the underlying stream.
65 fCachedData = SkData::MakeFromStream(stream.get(), stream->getLength());
66 }
67 }
68 return fCachedData;
69 }
70
getPixels(const SkImageInfo & info,void * pixels,size_t rowBytes,const SkCodec::Options * options)71 bool SkCodecImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const SkCodec::Options* options) {
72 SkPixmap dst(info, pixels, rowBytes);
73
74 auto decode = [this, options](const SkPixmap& pm) {
75 SkCodec::Result result = fCodec->getPixels(pm, options);
76 switch (result) {
77 case SkCodec::kSuccess:
78 case SkCodec::kIncompleteInput:
79 case SkCodec::kErrorInInput:
80 return true;
81 default:
82 return false;
83 }
84 };
85
86 return SkPixmapUtils::Orient(dst, fCodec->getOrigin(), decode);
87 }
88
onGetPixels(const SkImageInfo & requestInfo,void * requestPixels,size_t requestRowBytes,const Options & options)89 bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& requestInfo, void* requestPixels,
90 size_t requestRowBytes, const Options& options) {
91 return this->getPixels(requestInfo, requestPixels, requestRowBytes, nullptr);
92 }
93
onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes & supportedDataTypes,SkYUVAPixmapInfo * yuvaPixmapInfo) const94 bool SkCodecImageGenerator::onQueryYUVAInfo(
95 const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes,
96 SkYUVAPixmapInfo* yuvaPixmapInfo) const {
97 return fCodec->queryYUVAInfo(supportedDataTypes, yuvaPixmapInfo);
98 }
99
onGetYUVAPlanes(const SkYUVAPixmaps & yuvaPixmaps)100 bool SkCodecImageGenerator::onGetYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps) {
101 switch (fCodec->getYUVAPlanes(yuvaPixmaps)) {
102 case SkCodec::kSuccess:
103 case SkCodec::kIncompleteInput:
104 case SkCodec::kErrorInInput:
105 return true;
106 default:
107 return false;
108 }
109 }
110
getScaledDimensions(float desiredScale) const111 SkISize SkCodecImageGenerator::getScaledDimensions(float desiredScale) const {
112 SkISize size = fCodec->getScaledDimensions(desiredScale);
113 if (SkEncodedOriginSwapsWidthHeight(fCodec->getOrigin())) {
114 std::swap(size.fWidth, size.fHeight);
115 }
116 return size;
117 }
118