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

Commit 0621313f authored by Leon Scroggins III's avatar Leon Scroggins III
Browse files

Implement FrameInfo methods on AImageDecoder

Bug: 160984428
Test: If47d475233f6b9973abf68029b63a610ff47cdae

- AImageDecoder_getFrameInfo
- AImageDecoderFrameInfo_create
- AImageDecoderFrameInfo_delete
- AImageDecoderFrameInfo_getDuration
- AImageDecoderFrameInfo_getFrameRect
- AImageDecoderFrameInfo_getDisposeOp
- AImageDecoderFrameInfo_getBlendOp
- AImageDecoderFrameInfo_hasAlphaWithinBounds

These allow querying for information specific to a single frame in an
encoded image.

Change-Id: I6ce5665e9c25aed23f99ce88290e520d68fcb60e
parent b26aebc3
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -282,6 +282,35 @@ bool ImageDecoder::advanceFrame() {
    return true;
}

SkCodec::FrameInfo ImageDecoder::getCurrentFrameInfo() {
    LOG_ALWAYS_FATAL_IF(finished());

    auto dims = mCodec->codec()->dimensions();
    SkCodec::FrameInfo info;
    if (!mCodec->codec()->getFrameInfo(mOptions.fFrameIndex, &info)) {
        // SkCodec may return false for a non-animated image. Provide defaults.
        info.fRequiredFrame = SkCodec::kNoFrame;
        info.fDuration = 0;
        info.fFullyReceived = true;
        info.fAlphaType = mCodec->codec()->getInfo().alphaType();
        info.fHasAlphaWithinBounds = info.fAlphaType != kOpaque_SkAlphaType;
        info.fDisposalMethod = SkCodecAnimation::DisposalMethod::kKeep;
        info.fBlend = SkCodecAnimation::Blend::kSrc;
        info.fFrameRect = SkIRect::MakeSize(dims);
    }

    if (auto origin = mCodec->codec()->getOrigin(); origin != kDefault_SkEncodedOrigin) {
        if (SkEncodedOriginSwapsWidthHeight(origin)) {
            dims = swapped(dims);
        }
        auto matrix = SkEncodedOriginToMatrix(origin, dims.width(), dims.height());
        auto rect = SkRect::Make(info.fFrameRect);
        LOG_ALWAYS_FATAL_IF(!matrix.mapRect(&rect));
        rect.roundIn(&info.fFrameRect);
    }
    return info;
}

bool ImageDecoder::finished() const {
    return mOptions.fFrameIndex >= mCodec->codec()->getFrameCount();
}
+2 −0
Original line number Diff line number Diff line
@@ -71,6 +71,8 @@ public:
    bool isAnimated();
    int currentFrame() const;

    SkCodec::FrameInfo getCurrentFrameInfo();

private:
    // State machine for keeping track of how to handle RestorePrevious (RP)
    // frames in decode().
+75 −0
Original line number Diff line number Diff line
@@ -429,3 +429,78 @@ int AImageDecoder_rewind(AImageDecoder* decoder) {
    return imageDecoder->rewind() ? ANDROID_IMAGE_DECODER_SUCCESS
                                  : ANDROID_IMAGE_DECODER_SEEK_ERROR;
}

AImageDecoderFrameInfo* AImageDecoderFrameInfo_create() {
    return reinterpret_cast<AImageDecoderFrameInfo*>(new SkCodec::FrameInfo);
}

static SkCodec::FrameInfo* toFrameInfo(AImageDecoderFrameInfo* info) {
    return reinterpret_cast<SkCodec::FrameInfo*>(info);
}

static const SkCodec::FrameInfo* toFrameInfo(const AImageDecoderFrameInfo* info) {
    return reinterpret_cast<const SkCodec::FrameInfo*>(info);
}

void AImageDecoderFrameInfo_delete(AImageDecoderFrameInfo* info) {
    delete toFrameInfo(info);
}

int AImageDecoder_getFrameInfo(AImageDecoder* decoder,
        AImageDecoderFrameInfo* info) {
    if (!decoder || !info) {
        return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
    }

    auto* imageDecoder = toDecoder(decoder);
    if (imageDecoder->finished()) {
        return ANDROID_IMAGE_DECODER_FINISHED;
    }

    *toFrameInfo(info) = imageDecoder->getCurrentFrameInfo();
    return ANDROID_IMAGE_DECODER_SUCCESS;
}

int64_t AImageDecoderFrameInfo_getDuration(const AImageDecoderFrameInfo* info) {
    if (!info) return 0;

    return toFrameInfo(info)->fDuration * 1'000'000;
}

ARect AImageDecoderFrameInfo_getFrameRect(const AImageDecoderFrameInfo* info) {
    if (!info) {
        return { 0, 0, 0, 0};
    }

    const SkIRect& r = toFrameInfo(info)->fFrameRect;
    return { r.left(), r.top(), r.right(), r.bottom() };
}

bool AImageDecoderFrameInfo_hasAlphaWithinBounds(const AImageDecoderFrameInfo* info) {
    if (!info) return false;

    return toFrameInfo(info)->fHasAlphaWithinBounds;
}

int32_t AImageDecoderFrameInfo_getDisposeOp(const AImageDecoderFrameInfo* info) {
    if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;

    static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kKeep)
                  == ANDROID_IMAGE_DECODER_DISPOSE_OP_NONE);
    static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kRestoreBGColor)
                  == ANDROID_IMAGE_DECODER_DISPOSE_OP_BACKGROUND);
    static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kRestorePrevious)
                  == ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS);
    return static_cast<int>(toFrameInfo(info)->fDisposalMethod);
}

int32_t AImageDecoderFrameInfo_getBlendOp(const AImageDecoderFrameInfo* info) {
    if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;

    switch (toFrameInfo(info)->fBlend) {
        case SkCodecAnimation::Blend::kSrc:
            return ANDROID_IMAGE_DECODER_BLEND_OP_SRC;
        case SkCodecAnimation::Blend::kSrcOver:
            return ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER;
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -17,12 +17,20 @@ LIBJNIGRAPHICS {
    AImageDecoder_getRepeatCount; # introduced=31
    AImageDecoder_advanceFrame; # introduced=31
    AImageDecoder_rewind; # introduced=31
    AImageDecoder_getFrameInfo; # introduced = 31
    AImageDecoderHeaderInfo_getWidth; # introduced=30
    AImageDecoderHeaderInfo_getHeight; # introduced=30
    AImageDecoderHeaderInfo_getMimeType; # introduced=30
    AImageDecoderHeaderInfo_getAlphaFlags; # introduced=30
    AImageDecoderHeaderInfo_getAndroidBitmapFormat; # introduced=30
    AImageDecoderHeaderInfo_getDataSpace; # introduced=30
    AImageDecoderFrameInfo_create; # introduced = 31
    AImageDecoderFrameInfo_delete; # introduced = 31
    AImageDecoderFrameInfo_getDuration; # introduced = 31
    AImageDecoderFrameInfo_getFrameRect; # introduced = 31
    AImageDecoderFrameInfo_hasAlphaWithinBounds; # introduced = 31
    AImageDecoderFrameInfo_getDisposeOp; # introduced = 31
    AImageDecoderFrameInfo_getBlendOp; # introduced = 31
    AndroidBitmap_getInfo;
    AndroidBitmap_getDataSpace;
    AndroidBitmap_lockPixels;