Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bbef27bc authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Replace setAlphaFlags with setUnpremultipliedRequired"

parents 5477bb44 1ade46d2
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -241,7 +241,7 @@ static jobject ImageDecoder_nDecodeBitmap(JNIEnv* env, jobject /*clazz*/, jlong
        doThrowISE(env, "Could not scale to target size!");
        return nullptr;
    }
    if (requireUnpremul && !decoder->setOutAlphaType(kUnpremul_SkAlphaType)) {
    if (requireUnpremul && !decoder->setUnpremultipliedRequired(true)) {
        doThrowISE(env, "Cannot scale unpremultiplied pixels!");
        return nullptr;
    }
@@ -301,11 +301,15 @@ static jobject ImageDecoder_nDecodeBitmap(JNIEnv* env, jobject /*clazz*/, jlong
        }
    }

    SkBitmap bm;
    SkImageInfo bitmapInfo = decoder->getOutputInfo();
    if (decoder->opaque()) {
        bitmapInfo = bitmapInfo.makeAlphaType(kOpaque_SkAlphaType);
    }
    if (asAlphaMask && colorType == kGray_8_SkColorType) {
        bitmapInfo = bitmapInfo.makeColorType(kAlpha_8_SkColorType);
    }

    SkBitmap bm;
    if (!bm.setInfo(bitmapInfo)) {
        doThrowIOE(env, "Failed to setInfo properly");
        return nullptr;
+18 −29
Original line number Diff line number Diff line
@@ -30,19 +30,25 @@ ImageDecoder::ImageDecoder(std::unique_ptr<SkAndroidCodec> codec, sk_sp<SkPngChu
    , mTargetSize(mCodec->getInfo().dimensions())
    , mDecodeSize(mTargetSize)
    , mOutColorType(mCodec->computeOutputColorType(kN32_SkColorType))
    , mOutAlphaType(mCodec->getInfo().isOpaque() ?
                    kOpaque_SkAlphaType : kPremul_SkAlphaType)
    , mUnpremultipliedRequired(false)
    , mOutColorSpace(mCodec->getInfo().refColorSpace())
    , mSampleSize(1)
{
}

SkAlphaType ImageDecoder::getOutAlphaType() const {
    // While an SkBitmap may want to use kOpaque_SkAlphaType for a performance
    // optimization, this class just outputs raw pixels. Using either
    // premultiplication choice has no effect on decoding an opaque encoded image.
    return mUnpremultipliedRequired ? kUnpremul_SkAlphaType : kPremul_SkAlphaType;
}

bool ImageDecoder::setTargetSize(int width, int height) {
    if (width <= 0 || height <= 0) {
        return false;
    }

    auto info = SkImageInfo::Make(width, height, mOutColorType, mOutAlphaType);
    auto info = SkImageInfo::Make(width, height, mOutColorType, getOutAlphaType());
    size_t rowBytes = info.minRowBytes();
    if (rowBytes == 0) {
        // This would have overflowed.
@@ -63,7 +69,7 @@ bool ImageDecoder::setTargetSize(int width, int height) {
    SkISize targetSize = { width, height }, decodeSize = targetSize;
    int sampleSize = mCodec->computeSampleSize(&decodeSize);

    if (decodeSize != targetSize && mOutAlphaType == kUnpremul_SkAlphaType
    if (decodeSize != targetSize && mUnpremultipliedRequired
            && !mCodec->getInfo().isOpaque()) {
        return false;
    }
@@ -119,29 +125,11 @@ bool ImageDecoder::setOutColorType(SkColorType colorType) {
    return true;
}

bool ImageDecoder::setOutAlphaType(SkAlphaType alpha) {
    switch (alpha) {
        case kOpaque_SkAlphaType:
            return opaque();
        case kPremul_SkAlphaType:
            if (opaque()) {
                // Opaque can be treated as premul.
                return true;
            }
            break;
        case kUnpremul_SkAlphaType:
            if (opaque()) {
                // Opaque can be treated as unpremul.
                return true;
            }
            if (mDecodeSize != mTargetSize) {
                return false;
            }
            break;
        default:
bool ImageDecoder::setUnpremultipliedRequired(bool required) {
    if (required && !opaque() && mDecodeSize != mTargetSize) {
        return false;
    }
    mOutAlphaType = alpha;
    mUnpremultipliedRequired = required;
    return true;
}

@@ -151,11 +139,11 @@ void ImageDecoder::setOutColorSpace(sk_sp<SkColorSpace> colorSpace) {

SkImageInfo ImageDecoder::getOutputInfo() const {
    SkISize size = mCropRect ? mCropRect->size() : mTargetSize;
    return SkImageInfo::Make(size, mOutColorType, mOutAlphaType, mOutColorSpace);
    return SkImageInfo::Make(size, mOutColorType, getOutAlphaType(), mOutColorSpace);
}

bool ImageDecoder::opaque() const {
    return mOutAlphaType == kOpaque_SkAlphaType;
    return mCodec->getInfo().alphaType() == kOpaque_SkAlphaType;
}

bool ImageDecoder::gray() const {
@@ -165,7 +153,8 @@ bool ImageDecoder::gray() const {
SkCodec::Result ImageDecoder::decode(void* pixels, size_t rowBytes) {
    void* decodePixels = pixels;
    size_t decodeRowBytes = rowBytes;
    auto decodeInfo = SkImageInfo::Make(mDecodeSize, mOutColorType, mOutAlphaType, mOutColorSpace);
    auto decodeInfo = SkImageInfo::Make(mDecodeSize, mOutColorType, getOutAlphaType(),
                                        mOutColorSpace);
    // Used if we need a temporary before scaling or subsetting.
    // FIXME: Use scanline decoding on only a couple lines to save memory. b/70709380.
    SkBitmap tmp;
+4 −4
Original line number Diff line number Diff line
@@ -41,14 +41,12 @@ public:

    bool setOutColorType(SkColorType outColorType);

    bool setOutAlphaType(SkAlphaType outAlphaType);
    bool setUnpremultipliedRequired(bool unpremultipliedRequired);

    void setOutColorSpace(sk_sp<SkColorSpace> cs);

    // The size is the final size after scaling and cropping.
    SkImageInfo getOutputInfo() const;
    SkColorType getOutColorType() const { return mOutColorType; }
    SkAlphaType getOutAlphaType() const { return mOutAlphaType; }

    bool opaque() const;
    bool gray() const;
@@ -59,13 +57,15 @@ private:
    SkISize mTargetSize;
    SkISize mDecodeSize;
    SkColorType mOutColorType;
    SkAlphaType mOutAlphaType;
    bool mUnpremultipliedRequired;
    sk_sp<SkColorSpace> mOutColorSpace;
    int mSampleSize;
    std::optional<SkIRect> mCropRect;

    ImageDecoder(const ImageDecoder&) = delete;
    ImageDecoder& operator=(const ImageDecoder&) = delete;

    SkAlphaType getOutAlphaType() const;
};

} // namespace android
+3 −17
Original line number Diff line number Diff line
@@ -241,26 +241,12 @@ int AImageDecoderHeaderInfo_getAlphaFlags(const AImageDecoderHeaderInfo* info) {
    }
}

SkAlphaType toAlphaType(int androidBitmapFlags) {
    switch (androidBitmapFlags) {
        case ANDROID_BITMAP_FLAGS_ALPHA_PREMUL:
            return kPremul_SkAlphaType;
        case ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL:
            return kUnpremul_SkAlphaType;
        case ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE:
            return kOpaque_SkAlphaType;
        default:
            return kUnknown_SkAlphaType;
    }
}

int AImageDecoder_setAlphaFlags(AImageDecoder* decoder, int alphaFlag) {
    if (!decoder || alphaFlag < ANDROID_BITMAP_FLAGS_ALPHA_PREMUL
            || alphaFlag > ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL) {
int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* decoder, bool required) {
    if (!decoder) {
        return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
    }

    return toDecoder(decoder)->setOutAlphaType(toAlphaType(alphaFlag))
    return toDecoder(decoder)->setUnpremultipliedRequired(required)
            ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
}

+17 −17
Original line number Diff line number Diff line
LIBJNIGRAPHICS {
  global:
    AImageDecoder_createFromAAsset;
    AImageDecoder_createFromFd;
    AImageDecoder_createFromBuffer;
    AImageDecoder_delete;
    AImageDecoder_setAndroidBitmapFormat;
    AImageDecoder_setAlphaFlags;
    AImageDecoder_getHeaderInfo;
    AImageDecoder_getMinimumStride;
    AImageDecoder_decodeImage;
    AImageDecoder_setTargetSize;
    AImageDecoder_setCrop;
    AImageDecoderHeaderInfo_getWidth;
    AImageDecoderHeaderInfo_getHeight;
    AImageDecoderHeaderInfo_getMimeType;
    AImageDecoderHeaderInfo_getAlphaFlags;
    AImageDecoderHeaderInfo_isAnimated;
    AImageDecoderHeaderInfo_getAndroidBitmapFormat;
    AImageDecoder_createFromAAsset; # introduced=30
    AImageDecoder_createFromFd; # introduced=30
    AImageDecoder_createFromBuffer; # introduced=30
    AImageDecoder_delete; # introduced=30
    AImageDecoder_setAndroidBitmapFormat; # introduced=30
    AImageDecoder_setUnpremultipliedRequired; # introduced=30
    AImageDecoder_getHeaderInfo; # introduced=30
    AImageDecoder_getMinimumStride; # introduced=30
    AImageDecoder_decodeImage; # introduced=30
    AImageDecoder_setTargetSize; # introduced=30
    AImageDecoder_setCrop; # introduced=30
    AImageDecoderHeaderInfo_getWidth; # introduced=30
    AImageDecoderHeaderInfo_getHeight; # introduced=30
    AImageDecoderHeaderInfo_getMimeType; # introduced=30
    AImageDecoderHeaderInfo_getAlphaFlags; # introduced=30
    AImageDecoderHeaderInfo_isAnimated; # introduced=30
    AImageDecoderHeaderInfo_getAndroidBitmapFormat; # introduced=30
    AndroidBitmap_getInfo;
    AndroidBitmap_getDataSpace;
    AndroidBitmap_lockPixels;