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
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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().
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user