diff --git a/app/src/main/java/com/hippo/glview/image/ImageTexture.java b/app/src/main/java/com/hippo/glview/image/ImageTexture.java index cd2a79232..d98d459c9 100644 --- a/app/src/main/java/com/hippo/glview/image/ImageTexture.java +++ b/app/src/main/java/com/hippo/glview/image/ImageTexture.java @@ -239,7 +239,7 @@ public class ImageTexture implements Texture, Animatable { } boolean end = mReleased.get() || mImage.isImageRecycled() || mNeedRelease.get() || - (mImage.isCompleted() && mImage.getFrameCount() <= 1) || mRunning.get(); + (mImage.isCompleted() && mImage.getFormat() == 0) || mRunning.get(); synchronized (mImage) { mImageBusy = false; @@ -609,13 +609,11 @@ public class ImageTexture implements Texture, Animatable { sPVLock.v(); } - int frameCount = mImage.getFrameCount(); - synchronized (mImage) { // Release image mImageBusy = false; // Check need release, frameCount <= 1 - if (mNeedRelease.get() || frameCount <= 1) { + if (mNeedRelease.get() || mImage.getFormat() == 0) { mAnimateRunnable = null; return; } diff --git a/app/src/main/java/com/hippo/glview/image/ImageWrapper.java b/app/src/main/java/com/hippo/glview/image/ImageWrapper.java index 99093406b..e16498ddc 100644 --- a/app/src/main/java/com/hippo/glview/image/ImageWrapper.java +++ b/app/src/main/java/com/hippo/glview/image/ImageWrapper.java @@ -168,13 +168,6 @@ public class ImageWrapper { return mImage.getDelay(); } - /** - * @see Image#getFrameCount() - */ - public int getFrameCount() { - return mImage.getFrameCount(); - } - /** * @see Image#isOpaque() */ diff --git a/native/src/main/java/com/hippo/image/Image.java b/native/src/main/java/com/hippo/image/Image.java index ccf34e34b..0ead00b8d 100644 --- a/native/src/main/java/com/hippo/image/Image.java +++ b/native/src/main/java/com/hippo/image/Image.java @@ -216,14 +216,6 @@ public final class Image { return delay <= 10 ? 100 : delay; } - /** - * Return frame count. 1 for non-animation image - */ - public int getFrameCount() { - checkRecycled(); - return nativeFrameCount(mNativePtr, mFormat); - } - /** * Return is the image opaque */ diff --git a/native/src/main/java/com/hippo/image/ImageBitmap.java b/native/src/main/java/com/hippo/image/ImageBitmap.java index 509807b1d..b76b79cbf 100644 --- a/native/src/main/java/com/hippo/image/ImageBitmap.java +++ b/native/src/main/java/com/hippo/image/ImageBitmap.java @@ -46,7 +46,6 @@ public final class ImageBitmap implements Animatable, Runnable { private final int mFormat; private final boolean mIsOpaque; private final int mByteCount; - private final int mFrameCount; private final Set> mCallbackSet = new LinkedHashSet<>(); @Nullable private Image mImage; @@ -62,9 +61,8 @@ public final class ImageBitmap implements Animatable, Runnable { mFormat = image.getFormat(); mIsOpaque = image.isOpaque(); mByteCount = image.getByteCount(); - mFrameCount = image.getFrameCount(); - if (mFrameCount > 1) { + if (mFormat == 1) { // For animated image, save image object mImage = image; } else { @@ -78,7 +76,6 @@ public final class ImageBitmap implements Animatable, Runnable { mBitmap = bitmap; mIsOpaque = !bitmap.hasAlpha(); mByteCount = bitmap.getRowBytes() * bitmap.getHeight(); - mFrameCount = 1; } /** @@ -238,13 +235,6 @@ public final class ImageBitmap implements Animatable, Runnable { return mImage != null; } - /** - * Return image frame count - */ - public int getFrameCount() { - return mFrameCount; - } - /** * Draw image to canvas */ diff --git a/native/src/main/jni/image/image.c b/native/src/main/jni/image/image.c index bec244c5f..fa80396e7 100644 --- a/native/src/main/jni/image/image.c +++ b/native/src/main/jni/image/image.c @@ -19,6 +19,7 @@ // #include +#include #include #include @@ -29,44 +30,48 @@ #include "filter/gray.h" #include "log.h" -void* decode(JNIEnv* env, int fd, bool partially, int* format) +void decodeCommon(IMAGE * image) { + AImageDecoder *decoder = image->decoder; + AImageDecoder_setDataSpace(decoder, ADATASPACE_SRGB); + AImageDecoder_setAndroidBitmapFormat(decoder, ANDROID_BITMAP_FORMAT_RGBA_8888); + const AImageDecoderHeaderInfo *headerInfo = AImageDecoder_getHeaderInfo(decoder); + image->height = AImageDecoderHeaderInfo_getHeight(headerInfo); + image->width = AImageDecoderHeaderInfo_getWidth(headerInfo); + image->stride = AImageDecoder_getMinimumStride(decoder); + image->bufferLen = image->height * image->stride; + image->buffer = malloc(image->bufferLen); + if (image->isAnimated) { + image->frameInfo = AImageDecoderFrameInfo_create(); + AImageDecoder_getFrameInfo(decoder, image->frameInfo); + } + AImageDecoder_decodeImage(decoder, image->buffer, image->stride, image->bufferLen); +} + +IMAGE * createFromFd(JNIEnv* env, int fd, bool partially, int* format) { AImageDecoder *decoder; int r = AImageDecoder_createFromFd(fd, &decoder); LOGD("%s%d", "Create ImageDecoder with ret ", r); if (r) return NULL; - *format = AImageDecoder_isAnimated(decoder); - const AImageDecoderHeaderInfo *headerInfo = AImageDecoder_getHeaderInfo(decoder); - size_t stride = AImageDecoder_getMinimumStride(decoder); IMAGE *image = calloc(1, sizeof(IMAGE)); - image->height = AImageDecoderHeaderInfo_getHeight(headerInfo); - image->width = AImageDecoderHeaderInfo_getWidth(headerInfo); + image->isAnimated = *format = AImageDecoder_isAnimated(decoder); image->decoder = decoder; - image->bufferLen = image->height * stride; - image->buffer = malloc(image->bufferLen); - AImageDecoder_decodeImage(decoder, image->buffer, stride, image->bufferLen); + decodeCommon(image); return image; } -void* decodeAddr(JNIEnv* env, void* addr, long size, bool partially, int* format) -{ +IMAGE * createFromAddr(JNIEnv* env, void* addr, long size, bool partially, int* format) { AImageDecoder *decoder; int r = AImageDecoder_createFromBuffer((const void *) addr, size, &decoder); LOGD("%s%d", "Create ImageDecoder with ret ", r); if (r) return NULL; - *format = AImageDecoder_isAnimated(decoder); - const AImageDecoderHeaderInfo *headerInfo = AImageDecoder_getHeaderInfo(decoder); - size_t stride = AImageDecoder_getMinimumStride(decoder); IMAGE *image = calloc(1, sizeof(IMAGE)); - image->height = AImageDecoderHeaderInfo_getHeight(headerInfo); - image->width = AImageDecoderHeaderInfo_getWidth(headerInfo); + image->isAnimated = *format = AImageDecoder_isAnimated(decoder); image->decoder = decoder; - image->bufferLen = image->height * stride; - image->buffer = malloc(image->bufferLen); image->srcBuffer = addr; - AImageDecoder_decodeImage(decoder, image->buffer, stride, image->bufferLen); + decodeCommon(image); return image; } @@ -111,6 +116,10 @@ void advance(IMAGE * image, int format) { if (format) { AImageDecoder_advanceFrame(image->decoder); + if (AImageDecoder_decodeImage(image->decoder, image->buffer, image->stride, image->bufferLen) == ANDROID_IMAGE_DECODER_FINISHED) { + AImageDecoder_rewind(image->decoder); + AImageDecoder_decodeImage(image->decoder, image->buffer, image->stride, image->bufferLen); + } } } @@ -119,11 +128,6 @@ int get_delay(IMAGE * image, int format) return 0; } -int get_frame_count(IMAGE * image, int format) -{ - return 1; -} - bool is_opaque(IMAGE * image, int format) { return false; diff --git a/native/src/main/jni/image/image.h b/native/src/main/jni/image/image.h index a98a60eb4..53cf7ec1c 100644 --- a/native/src/main/jni/image/image.h +++ b/native/src/main/jni/image/image.h @@ -33,10 +33,13 @@ typedef struct int bufferLen; AImageDecoder* decoder; void* srcBuffer; + size_t stride; + bool isAnimated; + AImageDecoderFrameInfo *frameInfo; } IMAGE; -void* decode(JNIEnv* env, int fd, bool partially, int* format); -void* decodeAddr(JNIEnv* env, void* addr, long size, bool partially, int* format); +IMAGE * createFromFd(JNIEnv* env, int fd, bool partially, int* format); +IMAGE * createFromAddr(JNIEnv* env, void* addr, long size, bool partially, int* format); void* create(int32_t width, int32_t height, const void* data); bool complete(JNIEnv* env, IMAGE * image, int format); bool is_completed(IMAGE * image, int format); @@ -48,7 +51,6 @@ void render(IMAGE * image, int format, int src_x, int src_y, int width, int height, bool fill_blank, int default_color); void advance(IMAGE * image, int format); int get_delay(IMAGE * image, int format); -int get_frame_count(IMAGE * image, int format); bool is_opaque(IMAGE * image, int format); bool is_gray(IMAGE * image, int format, int error); void clahe(IMAGE * image, int format, bool to_gray); diff --git a/native/src/main/jni/image/java_wrapper.c b/native/src/main/jni/image/java_wrapper.c index 8bd5c3847..4c4859c2d 100644 --- a/native/src/main/jni/image/java_wrapper.c +++ b/native/src/main/jni/image/java_wrapper.c @@ -89,7 +89,7 @@ Java_com_hippo_image_Image_nativeDecodeFdInt(JNIEnv* env, void* image; jobject image_object; - image = decode(env, fd, partially, &format); + image = createFromFd(env, fd, partially, &format); if (image == NULL) { return NULL; } @@ -232,13 +232,6 @@ Java_com_hippo_image_Image_nativeGetDelay(JNIEnv* env, return (jint) get_delay((void*) (intptr_t) ptr, format); } -JNIEXPORT jint JNICALL -Java_com_hippo_image_Image_nativeFrameCount(JNIEnv* env, - jclass clazz, jlong ptr, jint format) -{ - return (jint) get_frame_count((void*) (intptr_t) ptr, format); -} - JNIEXPORT jboolean JNICALL Java_com_hippo_image_Image_nativeIsOpaque(JNIEnv* env, jclass clazz, jlong ptr, jint format) @@ -296,7 +289,7 @@ Java_com_hippo_image_Image_nativeDecodeAddr(JNIEnv *env, jclass clazz, jlong add jobject image_object; Memarea *memarea = (Memarea*)addr; - image = decodeAddr(env, memarea->buffer, memarea->size, partially, &format); + image = createFromAddr(env, memarea->buffer, memarea->size, partially, &format); free(memarea); if (image == NULL) { return NULL;