diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp index d34117b76f..6db8f262e6 100644 --- a/dm/DMSrcSink.cpp +++ b/dm/DMSrcSink.cpp @@ -161,7 +161,7 @@ Error BRDSrc::draw(SkCanvas* canvas) const { case kFullImage_Mode: { SkBitmap bitmap; if (!brd->decodeRegion(&bitmap, nullptr, SkIRect::MakeXYWH(0, 0, width, height), - fSampleSize, colorType, false)) { + fSampleSize, colorType, false, SkColorSpace::MakeSRGB())) { return "Cannot decode (full) region."; } alpha8_to_gray8(&bitmap); @@ -215,7 +215,8 @@ Error BRDSrc::draw(SkCanvas* canvas) const { const uint32_t decodeHeight = subsetHeight + unscaledBorder * 2; SkBitmap bitmap; if (!brd->decodeRegion(&bitmap, nullptr, SkIRect::MakeXYWH(decodeLeft, - decodeTop, decodeWidth, decodeHeight), fSampleSize, colorType, false)) { + decodeTop, decodeWidth, decodeHeight), fSampleSize, colorType, false, + SkColorSpace::MakeSRGB())) { return "Cannot decode region."; } diff --git a/include/android/SkBitmapRegionDecoder.h b/include/android/SkBitmapRegionDecoder.h index 660aa0aefc..841bf8d415 100644 --- a/include/android/SkBitmapRegionDecoder.h +++ b/include/android/SkBitmapRegionDecoder.h @@ -55,11 +55,14 @@ public: * if this color type is unsupported. * @param requireUnpremul If the image is not opaque, we will use this to determine the * alpha type to use. + * @param prefColorSpace If non-null and supported, this is the color space that we will + * decode into. Otherwise, we will choose a default. * */ virtual bool decodeRegion(SkBitmap* bitmap, SkBRDAllocator* allocator, const SkIRect& desiredSubset, int sampleSize, - SkColorType colorType, bool requireUnpremul) = 0; + SkColorType colorType, bool requireUnpremul, + sk_sp prefColorSpace = nullptr) = 0; /* * @param Requested destination color type * @return true if we support the requested color type and false otherwise diff --git a/include/codec/SkAndroidCodec.h b/include/codec/SkAndroidCodec.h index 8e9ad4e2d3..87d514dfff 100644 --- a/include/codec/SkAndroidCodec.h +++ b/include/codec/SkAndroidCodec.h @@ -76,11 +76,17 @@ public: SkAlphaType computeOutputAlphaType(bool requestedUnpremul); /** - * @param outputColorType Color type that the client will decode to + * @param outputColorType Color type that the client will decode to. + * @param prefColorSpace Preferred color space to decode to. + * This may not return |prefColorSpace| for a couple reasons. + * (1) Android Principles: 565 must be sRGB, F16 must be + * linear sRGB, transfer function must be parametric. + * (2) Codec Limitations: F16 requires a linear color space. * * Returns the appropriate color space to decode to. */ - sk_sp computeOutputColorSpace(SkColorType outputColorType); + sk_sp computeOutputColorSpace(SkColorType outputColorType, + sk_sp prefColorSpace = nullptr); /** * Returns the dimensions of the scaled output image, for an input diff --git a/src/android/SkBitmapRegionCodec.cpp b/src/android/SkBitmapRegionCodec.cpp index ffe7ea81f8..7ce9d26b4d 100644 --- a/src/android/SkBitmapRegionCodec.cpp +++ b/src/android/SkBitmapRegionCodec.cpp @@ -18,7 +18,7 @@ SkBitmapRegionCodec::SkBitmapRegionCodec(SkAndroidCodec* codec) bool SkBitmapRegionCodec::decodeRegion(SkBitmap* bitmap, SkBRDAllocator* allocator, const SkIRect& desiredSubset, int sampleSize, SkColorType prefColorType, - bool requireUnpremul) { + bool requireUnpremul, sk_sp prefColorSpace) { // Fix the input sampleSize if necessary. if (sampleSize < 1) { @@ -52,7 +52,8 @@ bool SkBitmapRegionCodec::decodeRegion(SkBitmap* bitmap, SkBRDAllocator* allocat // Create the image info for the decode SkColorType dstColorType = fCodec->computeOutputColorType(prefColorType); SkAlphaType dstAlphaType = fCodec->computeOutputAlphaType(requireUnpremul); - sk_sp dstColorSpace = fCodec->computeOutputColorSpace(dstColorType); + sk_sp dstColorSpace = fCodec->computeOutputColorSpace(dstColorType, + prefColorSpace); SkImageInfo decodeInfo = SkImageInfo::Make(scaledSize.width(), scaledSize.height(), dstColorType, dstAlphaType, dstColorSpace); diff --git a/src/android/SkBitmapRegionCodec.h b/src/android/SkBitmapRegionCodec.h index b3b0637432..baaecc937a 100644 --- a/src/android/SkBitmapRegionCodec.h +++ b/src/android/SkBitmapRegionCodec.h @@ -25,7 +25,8 @@ public: bool decodeRegion(SkBitmap* bitmap, SkBRDAllocator* allocator, const SkIRect& desiredSubset, int sampleSize, - SkColorType colorType, bool requireUnpremul) override; + SkColorType colorType, bool requireUnpremul, + sk_sp prefColorSpace) override; bool conversionSupported(SkColorType colorType) override; diff --git a/src/codec/SkAndroidCodec.cpp b/src/codec/SkAndroidCodec.cpp index 6e1f4b853e..96ad72a259 100644 --- a/src/codec/SkAndroidCodec.cpp +++ b/src/codec/SkAndroidCodec.cpp @@ -169,13 +169,19 @@ SkAlphaType SkAndroidCodec::computeOutputAlphaType(bool requestedUnpremul) { return requestedUnpremul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType; } -sk_sp SkAndroidCodec::computeOutputColorSpace(SkColorType outputColorType) { +sk_sp SkAndroidCodec::computeOutputColorSpace(SkColorType outputColorType, + sk_sp prefColorSpace) { switch (outputColorType) { case kRGBA_8888_SkColorType: case kBGRA_8888_SkColorType: case kIndex_8_SkColorType: { - SkColorSpace* encodedSpace = fCodec->getInfo().colorSpace(); + // If |prefColorSpace| is supported, choose it. SkColorSpaceTransferFn fn; + if (prefColorSpace && prefColorSpace->isNumericalTransferFn(&fn)) { + return prefColorSpace; + } + + SkColorSpace* encodedSpace = fCodec->getInfo().colorSpace(); if (encodedSpace->isNumericalTransferFn(&fn)) { // Leave the pixels in the encoded color space. Color space conversion // will be handled after decode time. @@ -190,8 +196,10 @@ sk_sp SkAndroidCodec::computeOutputColorSpace(SkColorType outputCo return SkColorSpace::MakeSRGB(); } case kRGBA_F16_SkColorType: + // Note that |prefColorSpace| is ignored, F16 is always linear sRGB. return SkColorSpace::MakeSRGBLinear(); case kRGB_565_SkColorType: + // Note that |prefColorSpace| is ignored, 565 is always sRGB. return SkColorSpace::MakeSRGB(); default: // Color correction not supported for kGray.