1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2020 Google LLC 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkImageGenerator.h" 9cb93a386Sopenharmony_ci#include "include/core/SkImageInfo.h" 10cb93a386Sopenharmony_ci#include "include/ports/SkImageGeneratorNDK.h" 11cb93a386Sopenharmony_ci#include "src/ports/SkNDKConversions.h" 12cb93a386Sopenharmony_ci 13cb93a386Sopenharmony_ci#include <android/bitmap.h> 14cb93a386Sopenharmony_ci#include <android/data_space.h> 15cb93a386Sopenharmony_ci#include <android/imagedecoder.h> 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_cinamespace { 18cb93a386Sopenharmony_ciclass ImageGeneratorNDK : public SkImageGenerator { 19cb93a386Sopenharmony_cipublic: 20cb93a386Sopenharmony_ci ImageGeneratorNDK(const SkImageInfo&, sk_sp<SkData>, AImageDecoder*); 21cb93a386Sopenharmony_ci ~ImageGeneratorNDK() override; 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_ciprotected: 24cb93a386Sopenharmony_ci sk_sp<SkData> onRefEncodedData() override; 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ci bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, 27cb93a386Sopenharmony_ci const Options& opts) override; 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ciprivate: 30cb93a386Sopenharmony_ci sk_sp<SkData> fData; 31cb93a386Sopenharmony_ci AImageDecoder* fDecoder; 32cb93a386Sopenharmony_ci // Setting the ADataSpace is sticky - it is set for all future decodes 33cb93a386Sopenharmony_ci // until it is set again. But as of R there is no way to reset it to 34cb93a386Sopenharmony_ci // ADATASPACE_UNKNOWN to skip color correction. If the client requests 35cb93a386Sopenharmony_ci // skipping correction after having set it to something else, we need 36cb93a386Sopenharmony_ci // to recreate the AImageDecoder. 37cb93a386Sopenharmony_ci bool fPreviouslySetADataSpace; 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci using INHERITED = SkImageGenerator; 40cb93a386Sopenharmony_ci}; 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_ci} // anonymous namespace 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_cistatic bool ok(int result) { 45cb93a386Sopenharmony_ci return result == ANDROID_IMAGE_DECODER_SUCCESS; 46cb93a386Sopenharmony_ci} 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_cistatic bool set_android_bitmap_format(AImageDecoder* decoder, SkColorType colorType) { 49cb93a386Sopenharmony_ci auto format = SkNDKConversions::toAndroidBitmapFormat(colorType); 50cb93a386Sopenharmony_ci return ok(AImageDecoder_setAndroidBitmapFormat(decoder, format)); 51cb93a386Sopenharmony_ci} 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_cistatic SkColorType colorType(AImageDecoder* decoder, const AImageDecoderHeaderInfo* headerInfo) { 54cb93a386Sopenharmony_ci // AImageDecoder never defaults to gray, but allows setting it if the image is 8 bit gray. 55cb93a386Sopenharmony_ci if (set_android_bitmap_format(decoder, kGray_8_SkColorType)) { 56cb93a386Sopenharmony_ci return kGray_8_SkColorType; 57cb93a386Sopenharmony_ci } 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_ci auto format = static_cast<AndroidBitmapFormat>( 60cb93a386Sopenharmony_ci AImageDecoderHeaderInfo_getAndroidBitmapFormat(headerInfo)); 61cb93a386Sopenharmony_ci return SkNDKConversions::toColorType(format); 62cb93a386Sopenharmony_ci} 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_cistatic sk_sp<SkColorSpace> get_default_colorSpace(const AImageDecoderHeaderInfo* headerInfo) { 65cb93a386Sopenharmony_ci auto dataSpace = static_cast<ADataSpace>(AImageDecoderHeaderInfo_getDataSpace(headerInfo)); 66cb93a386Sopenharmony_ci if (auto cs = SkNDKConversions::toColorSpace(dataSpace)) { 67cb93a386Sopenharmony_ci return cs; 68cb93a386Sopenharmony_ci } 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_ci return SkColorSpace::MakeSRGB(); 71cb93a386Sopenharmony_ci} 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_cistd::unique_ptr<SkImageGenerator> SkImageGeneratorNDK::MakeFromEncodedNDK(sk_sp<SkData> data) { 74cb93a386Sopenharmony_ci if (!data) return nullptr; 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci AImageDecoder* rawDecoder; 77cb93a386Sopenharmony_ci if (!ok(AImageDecoder_createFromBuffer(data->data(), data->size(), &rawDecoder))) { 78cb93a386Sopenharmony_ci return nullptr; 79cb93a386Sopenharmony_ci } 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci const AImageDecoderHeaderInfo* headerInfo = AImageDecoder_getHeaderInfo(rawDecoder); 82cb93a386Sopenharmony_ci int32_t width = AImageDecoderHeaderInfo_getWidth(headerInfo); 83cb93a386Sopenharmony_ci int32_t height = AImageDecoderHeaderInfo_getHeight(headerInfo); 84cb93a386Sopenharmony_ci SkColorType ct = colorType(rawDecoder, headerInfo); 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_ci // Although the encoded data stores unpremultiplied pixels, AImageDecoder defaults to premul 87cb93a386Sopenharmony_ci // (if the image may have alpha). 88cb93a386Sopenharmony_ci SkAlphaType at = AImageDecoderHeaderInfo_getAlphaFlags(headerInfo) 89cb93a386Sopenharmony_ci == ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE ? kOpaque_SkAlphaType : kPremul_SkAlphaType; 90cb93a386Sopenharmony_ci auto imageInfo = SkImageInfo::Make(width, height, ct, at, get_default_colorSpace(headerInfo)); 91cb93a386Sopenharmony_ci return std::unique_ptr<SkImageGenerator>( 92cb93a386Sopenharmony_ci new ImageGeneratorNDK(imageInfo, std::move(data), rawDecoder)); 93cb93a386Sopenharmony_ci} 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ciImageGeneratorNDK::ImageGeneratorNDK(const SkImageInfo& info, sk_sp<SkData> data, 96cb93a386Sopenharmony_ci AImageDecoder* decoder) 97cb93a386Sopenharmony_ci : INHERITED(info) 98cb93a386Sopenharmony_ci , fData(std::move(data)) 99cb93a386Sopenharmony_ci , fDecoder(decoder) 100cb93a386Sopenharmony_ci , fPreviouslySetADataSpace(false) 101cb93a386Sopenharmony_ci{ 102cb93a386Sopenharmony_ci SkASSERT(fDecoder); 103cb93a386Sopenharmony_ci} 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ciImageGeneratorNDK::~ImageGeneratorNDK() { 106cb93a386Sopenharmony_ci AImageDecoder_delete(fDecoder); 107cb93a386Sopenharmony_ci} 108cb93a386Sopenharmony_ci 109cb93a386Sopenharmony_cistatic bool set_target_size(AImageDecoder* decoder, const SkISize& size, const SkISize targetSize) { 110cb93a386Sopenharmony_ci if (size != targetSize) { 111cb93a386Sopenharmony_ci // AImageDecoder will scale to arbitrary sizes. Only support a size if it's supported by the 112cb93a386Sopenharmony_ci // underlying library. 113cb93a386Sopenharmony_ci const AImageDecoderHeaderInfo* headerInfo = AImageDecoder_getHeaderInfo(decoder); 114cb93a386Sopenharmony_ci const char* mimeType = AImageDecoderHeaderInfo_getMimeType(headerInfo); 115cb93a386Sopenharmony_ci if (0 == strcmp(mimeType, "image/jpeg")) { 116cb93a386Sopenharmony_ci bool supported = false; 117cb93a386Sopenharmony_ci for (int sampleSize : { 2, 4, 8 }) { 118cb93a386Sopenharmony_ci int32_t width; 119cb93a386Sopenharmony_ci int32_t height; 120cb93a386Sopenharmony_ci if (ok(AImageDecoder_computeSampledSize(decoder, sampleSize, &width, &height)) 121cb93a386Sopenharmony_ci && targetSize == SkISize::Make(width, height)) { 122cb93a386Sopenharmony_ci supported = true; 123cb93a386Sopenharmony_ci break; 124cb93a386Sopenharmony_ci } 125cb93a386Sopenharmony_ci } 126cb93a386Sopenharmony_ci if (!supported) return false; 127cb93a386Sopenharmony_ci } else if (0 == strcmp(mimeType, "image/webp")) { 128cb93a386Sopenharmony_ci // libwebp supports arbitrary downscaling. 129cb93a386Sopenharmony_ci if (targetSize.width() > size.width() || targetSize.height() > size.height()) { 130cb93a386Sopenharmony_ci return false; 131cb93a386Sopenharmony_ci } 132cb93a386Sopenharmony_ci } else { 133cb93a386Sopenharmony_ci return false; 134cb93a386Sopenharmony_ci } 135cb93a386Sopenharmony_ci } 136cb93a386Sopenharmony_ci return ok(AImageDecoder_setTargetSize(decoder, targetSize.width(), targetSize.height())); 137cb93a386Sopenharmony_ci} 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_cibool ImageGeneratorNDK::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, 140cb93a386Sopenharmony_ci const Options& opts) { 141cb93a386Sopenharmony_ci if (auto* cs = info.colorSpace()) { 142cb93a386Sopenharmony_ci if (!ok(AImageDecoder_setDataSpace(fDecoder, SkNDKConversions::toDataSpace(cs)))) { 143cb93a386Sopenharmony_ci return false; 144cb93a386Sopenharmony_ci } 145cb93a386Sopenharmony_ci fPreviouslySetADataSpace = true; 146cb93a386Sopenharmony_ci } else { 147cb93a386Sopenharmony_ci // If the requested SkColorSpace is null, the client wants the "raw" colors, without color 148cb93a386Sopenharmony_ci // space transformations applied. (This is primarily useful for a client that wants to do 149cb93a386Sopenharmony_ci // their own color transformations.) This is AImageDecoder's default, but if a previous call 150cb93a386Sopenharmony_ci // set an ADataSpace, AImageDecoder is no longer using its default, so we need to set it 151cb93a386Sopenharmony_ci // back. 152cb93a386Sopenharmony_ci if (fPreviouslySetADataSpace) { 153cb93a386Sopenharmony_ci // AImageDecoderHeaderInfo_getDataSpace always returns the same value for the same 154cb93a386Sopenharmony_ci // image, regardless of prior calls to AImageDecoder_setDataSpace. Check if it's 155cb93a386Sopenharmony_ci // ADATASPACE_UNKNOWN, which needs to be handled specially. 156cb93a386Sopenharmony_ci const AImageDecoderHeaderInfo* headerInfo = AImageDecoder_getHeaderInfo(fDecoder); 157cb93a386Sopenharmony_ci const auto defaultDataSpace = AImageDecoderHeaderInfo_getDataSpace(headerInfo); 158cb93a386Sopenharmony_ci if (defaultDataSpace == ADATASPACE_UNKNOWN) { 159cb93a386Sopenharmony_ci // As of R, there's no way to reset AImageDecoder to ADATASPACE_UNKNOWN, so 160cb93a386Sopenharmony_ci // create a new one. 161cb93a386Sopenharmony_ci AImageDecoder* decoder; 162cb93a386Sopenharmony_ci if (!ok(AImageDecoder_createFromBuffer(fData->data(), fData->size(), &decoder))) { 163cb93a386Sopenharmony_ci return false; 164cb93a386Sopenharmony_ci } 165cb93a386Sopenharmony_ci AImageDecoder_delete(fDecoder); 166cb93a386Sopenharmony_ci fDecoder = decoder; 167cb93a386Sopenharmony_ci } else { 168cb93a386Sopenharmony_ci if (!ok(AImageDecoder_setDataSpace(fDecoder, defaultDataSpace))) { 169cb93a386Sopenharmony_ci return false; 170cb93a386Sopenharmony_ci } 171cb93a386Sopenharmony_ci } 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_ci // Whether by recreating AImageDecoder or calling AImageDecoder_setDataSpace, the 174cb93a386Sopenharmony_ci // AImageDecoder is back to its default, so if the next call has a null SkColorSpace, it 175cb93a386Sopenharmony_ci // does not need to reset it again. 176cb93a386Sopenharmony_ci fPreviouslySetADataSpace = false; 177cb93a386Sopenharmony_ci } 178cb93a386Sopenharmony_ci } 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_ci if (!set_android_bitmap_format(fDecoder, info.colorType())) { 181cb93a386Sopenharmony_ci return false; 182cb93a386Sopenharmony_ci } 183cb93a386Sopenharmony_ci 184cb93a386Sopenharmony_ci switch (info.alphaType()) { 185cb93a386Sopenharmony_ci case kUnknown_SkAlphaType: 186cb93a386Sopenharmony_ci return false; 187cb93a386Sopenharmony_ci case kOpaque_SkAlphaType: 188cb93a386Sopenharmony_ci if (this->getInfo().alphaType() != kOpaque_SkAlphaType) { 189cb93a386Sopenharmony_ci return false; 190cb93a386Sopenharmony_ci } 191cb93a386Sopenharmony_ci break; 192cb93a386Sopenharmony_ci case kUnpremul_SkAlphaType: 193cb93a386Sopenharmony_ci if (!ok(AImageDecoder_setUnpremultipliedRequired(fDecoder, true))) { 194cb93a386Sopenharmony_ci return false; 195cb93a386Sopenharmony_ci } 196cb93a386Sopenharmony_ci break; 197cb93a386Sopenharmony_ci case kPremul_SkAlphaType: 198cb93a386Sopenharmony_ci break; 199cb93a386Sopenharmony_ci } 200cb93a386Sopenharmony_ci 201cb93a386Sopenharmony_ci if (!set_target_size(fDecoder, getInfo().dimensions(), info.dimensions())) { 202cb93a386Sopenharmony_ci return false; 203cb93a386Sopenharmony_ci } 204cb93a386Sopenharmony_ci 205cb93a386Sopenharmony_ci auto byteSize = info.computeByteSize(rowBytes); 206cb93a386Sopenharmony_ci switch (AImageDecoder_decodeImage(fDecoder, pixels, rowBytes, byteSize)) { 207cb93a386Sopenharmony_ci case ANDROID_IMAGE_DECODER_INCOMPLETE: 208cb93a386Sopenharmony_ci // The image was partially decoded, but the input was truncated. The client may be 209cb93a386Sopenharmony_ci // happy with the partial image. 210cb93a386Sopenharmony_ci case ANDROID_IMAGE_DECODER_ERROR: 211cb93a386Sopenharmony_ci // Similarly, the image was partially decoded, but the input had an error. The client 212cb93a386Sopenharmony_ci // may be happy with the partial image. 213cb93a386Sopenharmony_ci case ANDROID_IMAGE_DECODER_SUCCESS: 214cb93a386Sopenharmony_ci return true; 215cb93a386Sopenharmony_ci default: 216cb93a386Sopenharmony_ci return false; 217cb93a386Sopenharmony_ci } 218cb93a386Sopenharmony_ci} 219cb93a386Sopenharmony_ci 220cb93a386Sopenharmony_cisk_sp<SkData> ImageGeneratorNDK::onRefEncodedData() { 221cb93a386Sopenharmony_ci return fData; 222cb93a386Sopenharmony_ci} 223