xref: /aosp_15_r20/external/skia/src/codec/SkCodecImageGenerator.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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