diff --git a/native/src/main/java/com/hippo/Native.java b/native/src/main/java/com/hippo/Native.java index 92f8d41be..544732969 100644 --- a/native/src/main/java/com/hippo/Native.java +++ b/native/src/main/java/com/hippo/Native.java @@ -5,9 +5,14 @@ public class Native { public static void initialize() { System.loadLibrary("ehviewer"); } + public static native String getlibarchiveVersion(); + public static native String getliblzmaVersion(); + public static native String getlibzstdVersion(); + public static native String getlibjpeg_turboVersion(); + public static native String getzlibVersion(); } diff --git a/native/src/main/java/com/hippo/UriArchiveAccessor.java b/native/src/main/java/com/hippo/UriArchiveAccessor.java index 1087a8392..491bbfbef 100644 --- a/native/src/main/java/com/hippo/UriArchiveAccessor.java +++ b/native/src/main/java/com/hippo/UriArchiveAccessor.java @@ -31,6 +31,7 @@ public class UriArchiveAccessor implements Closeable { } private native int openArchive(OsReadableFile osf); + private native int extracttoOutputStream(OsReadableFile osf, int index, OutputStream os); @Override diff --git a/native/src/main/java/com/hippo/image/Image.java b/native/src/main/java/com/hippo/image/Image.java index a202894ac..8ee9a1072 100644 --- a/native/src/main/java/com/hippo/image/Image.java +++ b/native/src/main/java/com/hippo/image/Image.java @@ -55,12 +55,10 @@ public final class Image { public static final int FORMAT_GIF = 3; private static final AtomicInteger sImageCount = new AtomicInteger(); - - private long mNativePtr; private final int mFormat; private final int mWidth; private final int mHeight; - + private long mNativePtr; private Throwable mRecycleTracker; private Image(long nativePtr, int format, int width, int height) { @@ -72,6 +70,83 @@ public final class Image { sImageCount.getAndIncrement(); } + /** + * Decode image from {@code InputStream} + */ + @Nullable + public static Image decode(InputStream is, boolean partially) { + if (!(is instanceof BufferedInputStream)) { + is = new BufferedInputStream(is); + } + return nativeDecode(is, partially); + } + + /** + * Create a plain image from Bitmap + */ + @Nullable + public static Image create(Bitmap bitmap) { + return nativeCreate(bitmap); + } + + /** + * Return all un-recycled {@code Image} instance count. + * It is useful for debug. + */ + public static int getImageCount() { + return sImageCount.get(); + } + + /** + * Return all supported image formats, exclude {@link #FORMAT_PLAIN} + */ + public static int[] getSupportedImageFormats() { + return nativeGetSupportedImageFormats(); + } + + /** + * Return decoder description of the image format, + * {@code null} for invalid image format. + */ + public static String getDecoderDescription(int format) { + return nativeGetDecoderDescription(format); + } + + private static native Image nativeDecode(InputStream is, boolean partially); + + private static native Image nativeCreate(Bitmap bitmap); + + private static native int nativeGetByteCount(long nativePtr, int format); + + private static native boolean nativeComplete(long nativePtr, int format); + + private static native boolean nativeIsCompleted(long nativePtr, int format); + + private static native void nativeRender(long nativePtr, int format, + int srcX, int srcY, Bitmap dst, int dstX, int dstY, + int width, int height, boolean fillBlank, int defaultColor); + + private static native void nativeTexImage(long nativePtr, int format, + boolean init, int offsetX, int offsetY, int width, int height); + + private static native void nativeAdvance(long nativePtr, int format); + + private static native int nativeGetDelay(long nativePtr, int format); + + private static native int nativeFrameCount(long nativePtr, int format); + + private static native boolean nativeIsOpaque(long nativePtr, int format); + + private static native boolean nativeIsGray(long nativePtr, int format, int error); + + private static native void nativeClahe(long nativePtr, int format, boolean toGray); + + private static native void nativeRecycle(long nativePtr, int format); + + private static native int[] nativeGetSupportedImageFormats(); + + private static native String nativeGetDecoderDescription(int format); + /** * Return the format of the image */ @@ -218,81 +293,4 @@ public final class Image { public boolean isRecycled() { return mNativePtr == 0; } - - /** - * Decode image from {@code InputStream} - */ - @Nullable - public static Image decode(InputStream is, boolean partially) { - if (!(is instanceof BufferedInputStream)) { - is = new BufferedInputStream(is); - } - return nativeDecode(is, partially); - } - - /** - * Create a plain image from Bitmap - */ - @Nullable - public static Image create(Bitmap bitmap) { - return nativeCreate(bitmap); - } - - /** - * Return all un-recycled {@code Image} instance count. - * It is useful for debug. - */ - public static int getImageCount() { - return sImageCount.get(); - } - - /** - * Return all supported image formats, exclude {@link #FORMAT_PLAIN} - */ - public static int[] getSupportedImageFormats() { - return nativeGetSupportedImageFormats(); - } - - /** - * Return decoder description of the image format, - * {@code null} for invalid image format. - */ - public static String getDecoderDescription(int format) { - return nativeGetDecoderDescription(format); - } - - private static native Image nativeDecode(InputStream is, boolean partially); - - private static native Image nativeCreate(Bitmap bitmap); - - private static native int nativeGetByteCount(long nativePtr, int format); - - private static native boolean nativeComplete(long nativePtr, int format); - - private static native boolean nativeIsCompleted(long nativePtr, int format); - - private static native void nativeRender(long nativePtr, int format, - int srcX, int srcY, Bitmap dst, int dstX, int dstY, - int width, int height, boolean fillBlank, int defaultColor); - - private static native void nativeTexImage(long nativePtr, int format, - boolean init, int offsetX, int offsetY, int width, int height); - - private static native void nativeAdvance(long nativePtr, int format); - - private static native int nativeGetDelay(long nativePtr, int format); - - private static native int nativeFrameCount(long nativePtr, int format); - - private static native boolean nativeIsOpaque(long nativePtr, int format); - - private static native boolean nativeIsGray(long nativePtr, int format, int error); - - private static native void nativeClahe(long nativePtr, int format, boolean toGray); - - private static native void nativeRecycle(long nativePtr, int format); - - private static native int[] nativeGetSupportedImageFormats(); - - private static native String nativeGetDecoderDescription(int format); } diff --git a/native/src/main/java/com/hippo/image/ImageBitmap.java b/native/src/main/java/com/hippo/image/ImageBitmap.java index e3a1339c4..aa7601279 100644 --- a/native/src/main/java/com/hippo/image/ImageBitmap.java +++ b/native/src/main/java/com/hippo/image/ImageBitmap.java @@ -40,19 +40,18 @@ import java.util.Set; public final class ImageBitmap implements Animatable, Runnable { private static final Handler HANDLER = new Handler(Looper.getMainLooper()); - - @Nullable - private Image mImage; @NonNull private final Bitmap mBitmap; 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; private int mReferences; private int mAnimationReferences; private boolean mRunning; - private final Set> mCallbackSet = new LinkedHashSet<>(); private ImageBitmap(@NonNull Image image) throws OutOfMemoryError { int width = image.getWidth(); diff --git a/native/src/main/jni/archive.c b/native/src/main/jni/archive.c index e5d0a1b38..19ccc424f 100644 --- a/native/src/main/jni/archive.c +++ b/native/src/main/jni/archive.c @@ -30,14 +30,13 @@ typedef struct archive_inst_sc { jmethodID readID; jmethodID seekID; jmethodID skipID; - void* read_buffer; - void* output_buffer; + void *read_buffer; + void *output_buffer; jbyteArray jbr; } archive_inst; -static int filename_is_playable_file(const char* name) -{ - const char* dotptr = strrchr(name, '.'); +static int filename_is_playable_file(const char *name) { + const char *dotptr = strrchr(name, '.'); if (dotptr++) { switch (*dotptr) { case 'j': @@ -53,21 +52,19 @@ static int filename_is_playable_file(const char* name) return 0; } -static void archive_list_all_entries(struct archive_inst_sc *inst) -{ +static void archive_list_all_entries(struct archive_inst_sc *inst) { struct archive *a = inst->archive; struct archive_entry *entry; int count = 0; while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { - if(filename_is_playable_file(archive_entry_pathname(entry))) + if (filename_is_playable_file(archive_entry_pathname(entry))) count++; archive_read_data_skip(a); } inst->entry_num = count; } -ssize_t ins_read(struct archive *a, void* client_data_ptr, const void **buff) -{ +ssize_t ins_read(struct archive *a, void *client_data_ptr, const void **buff) { archive_inst *arc = client_data_ptr; int32_t r = (*arc->env)->CallIntMethod(arc->env, arc->file, arc->readID, arc->jbr); (*arc->env)->GetByteArrayRegion(arc->env, arc->jbr, 0, r, arc->read_buffer); @@ -75,31 +72,28 @@ ssize_t ins_read(struct archive *a, void* client_data_ptr, const void **buff) return r; } -int ins_close(struct archive *a, void* client_data) -{ +int ins_close(struct archive *a, void *client_data) { archive_inst *arc = client_data; JNIEnv *env = arc->env; - jmethodID rewind = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, arc->file), "rewind", "()V"); + jmethodID rewind = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, arc->file), "rewind", + "()V"); (*arc->env)->CallVoidMethod(arc->env, arc->file, rewind); return ARCHIVE_OK; } -la_int64_t ins_seek(struct archive *a, void *client_data, la_int64_t offset, int whence) -{ +la_int64_t ins_seek(struct archive *a, void *client_data, la_int64_t offset, int whence) { archive_inst *arc = client_data; jlong ret = (*arc->env)->CallLongMethod(arc->env, arc->file, arc->seekID, offset, whence); return ret; } -la_int64_t ins_skip(struct archive *a, void *client_data, la_int64_t request) -{ +la_int64_t ins_skip(struct archive *a, void *client_data, la_int64_t request) { archive_inst *arc = client_data; jlong ret = (*arc->env)->CallLongMethod(arc->env, arc->file, arc->skipID, request); return ret; } -static archive_inst *archive_create_inst(JNIEnv *env, jobject file) -{ +static archive_inst *archive_create_inst(JNIEnv *env, jobject file) { archive_inst *inst = malloc(sizeof(archive_inst)); inst->archive = archive_read_new(); archive_read_set_seek_callback(inst->archive, ins_seek); @@ -117,8 +111,7 @@ static archive_inst *archive_create_inst(JNIEnv *env, jobject file) return inst; } -static void archive_destroy_inst(archive_inst* inst) -{ +static void archive_destroy_inst(archive_inst *inst) { JNIEnv *env = inst->env; archive_read_close(inst->archive); (*env)->DeleteLocalRef(env, inst->jbr); @@ -147,17 +140,17 @@ Java_com_hippo_UriArchiveAccessor_extracttoOutputStream(JNIEnv *env, jobject thi jint index, jobject os) { int count = 0; struct archive_entry *entry; - archive_inst *arc = archive_create_inst(env, osf); + archive_inst *arc = archive_create_inst(env, osf); int32_t size; jmethodID writeID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, os), "write", "([B)V"); jmethodID flushID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, os), "flush", "()V"); archive_read_open(arc->archive, arc, NULL, ins_read, ins_close); while (archive_read_next_header(arc->archive, &entry) == ARCHIVE_OK) { - if(!filename_is_playable_file(archive_entry_pathname(entry))) + if (!filename_is_playable_file(archive_entry_pathname(entry))) continue; if (count == index) { for (;;) { - size = (int32_t)archive_read_data(arc->archive, arc->output_buffer, BLOCK_SIZE); + size = (int32_t) archive_read_data(arc->archive, arc->output_buffer, BLOCK_SIZE); if (size < 0) { return READ_DATA_ERR; } diff --git a/native/src/main/jni/main.c b/native/src/main/jni/main.c index 2a34ab182..463108a7b 100644 --- a/native/src/main/jni/main.c +++ b/native/src/main/jni/main.c @@ -7,11 +7,10 @@ #include "java_wrapper.h" -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) -{ - JNIEnv* env; +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { + JNIEnv *env; - if ((*vm)->GetEnv(vm, (void**) (&env), JNI_VERSION_1_6) != JNI_OK) { + if ((*vm)->GetEnv(vm, (void **) (&env), JNI_VERSION_1_6) != JNI_OK) { return JNI_ERR; }