Implement AImageDecoder _advanceFrame and _rewind
Bug: 160984428
Test: Iae7d274b69999c471fd5610c6ef4d148cca81bec
Disallow AImageDecoder_set* methods after the first frame, since
changing the settings would interfere with blending and caching for
kRestorePrevious frames.
Add a cache (and a state machine) for handling kRestorePrevious frames.
Follow-on to Ib93b0ced09fa3cca4a6681745406355c48158fae - support using
a matrix for unpremul + orientation (the orientation was previously
handled by a matrix internally in SkAndroidCodec).
Change-Id: I7c32ede013fa83f1fe95c35778c33278ca6fe6a3
diff --git a/native/graphics/jni/imagedecoder.cpp b/native/graphics/jni/imagedecoder.cpp
index 4aeebe4..971ba37 100644
--- a/native/graphics/jni/imagedecoder.cpp
+++ b/native/graphics/jni/imagedecoder.cpp
@@ -173,7 +173,13 @@
|| format > ANDROID_BITMAP_FORMAT_RGBA_F16) {
return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
}
- return toDecoder(decoder)->setOutColorType(getColorType((AndroidBitmapFormat) format))
+
+ auto* imageDecoder = toDecoder(decoder);
+ if (imageDecoder->currentFrame() != 0) {
+ return ANDROID_IMAGE_DECODER_INVALID_STATE;
+ }
+
+ return imageDecoder->setOutColorType(getColorType((AndroidBitmapFormat) format))
? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
}
@@ -185,6 +191,10 @@
}
ImageDecoder* imageDecoder = toDecoder(decoder);
+ if (imageDecoder->currentFrame() != 0) {
+ return ANDROID_IMAGE_DECODER_INVALID_STATE;
+ }
+
imageDecoder->setOutColorSpace(std::move(cs));
return ANDROID_IMAGE_DECODER_SUCCESS;
}
@@ -279,7 +289,12 @@
return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
}
- return toDecoder(decoder)->setUnpremultipliedRequired(required)
+ auto* imageDecoder = toDecoder(decoder);
+ if (imageDecoder->currentFrame() != 0) {
+ return ANDROID_IMAGE_DECODER_INVALID_STATE;
+ }
+
+ return imageDecoder->setUnpremultipliedRequired(required)
? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
}
@@ -288,7 +303,12 @@
return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
}
- return toDecoder(decoder)->setTargetSize(width, height)
+ auto* imageDecoder = toDecoder(decoder);
+ if (imageDecoder->currentFrame() != 0) {
+ return ANDROID_IMAGE_DECODER_INVALID_STATE;
+ }
+
+ return imageDecoder->setTargetSize(width, height)
? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_SCALE;
}
@@ -309,10 +329,15 @@
return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
}
+ auto* imageDecoder = toDecoder(decoder);
+ if (imageDecoder->currentFrame() != 0) {
+ return ANDROID_IMAGE_DECODER_INVALID_STATE;
+ }
+
SkIRect cropIRect;
cropIRect.setLTRB(crop.left, crop.top, crop.right, crop.bottom);
SkIRect* cropPtr = cropIRect == SkIRect::MakeEmpty() ? nullptr : &cropIRect;
- return toDecoder(decoder)->setCropRect(cropPtr)
+ return imageDecoder->setCropRect(cropPtr)
? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_BAD_PARAMETER;
}
@@ -341,6 +366,10 @@
return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
}
+ if (imageDecoder->finished()) {
+ return ANDROID_IMAGE_DECODER_FINISHED;
+ }
+
return ResultToErrorCode(imageDecoder->decode(pixels, stride));
}
@@ -352,7 +381,7 @@
if (!decoder) return false;
ImageDecoder* imageDecoder = toDecoder(decoder);
- return imageDecoder->mCodec->codec()->getFrameCount() > 1;
+ return imageDecoder->isAnimated();
}
int32_t AImageDecoder_getRepeatCount(AImageDecoder* decoder) {
@@ -369,3 +398,34 @@
}
return count;
}
+
+int AImageDecoder_advanceFrame(AImageDecoder* decoder) {
+ if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
+
+ ImageDecoder* imageDecoder = toDecoder(decoder);
+ if (!imageDecoder->isAnimated()) {
+ return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
+ }
+
+ if (imageDecoder->advanceFrame()) {
+ return ANDROID_IMAGE_DECODER_SUCCESS;
+ }
+
+ if (imageDecoder->finished()) {
+ return ANDROID_IMAGE_DECODER_FINISHED;
+ }
+
+ return ANDROID_IMAGE_DECODER_INCOMPLETE;
+}
+
+int AImageDecoder_rewind(AImageDecoder* decoder) {
+ if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
+
+ ImageDecoder* imageDecoder = toDecoder(decoder);
+ if (!imageDecoder->isAnimated()) {
+ return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
+ }
+
+ return imageDecoder->rewind() ? ANDROID_IMAGE_DECODER_SUCCESS
+ : ANDROID_IMAGE_DECODER_SEEK_ERROR;
+}