diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index 19612537a..4f24abfd8 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -44,10 +44,7 @@ SET(LIBARCHIVE_CUSTOM_LIBS "liblzma" "nettle")
# Build libarchive
add_subdirectory(libarchive)
-# Build hippo's image lib
-add_subdirectory(image)
-
# Build and link our app's native lib
-add_library(${PROJECT_NAME} SHARED main.c archive.c)
-target_include_directories(${PROJECT_NAME} PUBLIC image/image libarchive/libarchive)
-target_link_libraries(${PROJECT_NAME} image archive_static -Wl,--gc-sections)
+add_library(${PROJECT_NAME} SHARED main.c archive.c image.c)
+target_include_directories(${PROJECT_NAME} PUBLIC libarchive/libarchive)
+target_link_libraries(${PROJECT_NAME} archive_static log jnigraphics GLESv2 -Wl,--gc-sections)
diff --git a/app/src/main/cpp/image.c b/app/src/main/cpp/image.c
new file mode 100644
index 000000000..71a6aae72
--- /dev/null
+++ b/app/src/main/cpp/image.c
@@ -0,0 +1,380 @@
+/*
+ * Copyright 2022 Tarsin Norbin
+ *
+ * This file is part of EhViewer
+ *
+ * EhViewer is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * EhViewer is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * EhViewer. If not, see .
+ */
+
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+#include "image.h"
+
+#define TAG "ImageDecoder_wrapper"
+#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG ,__VA_ARGS__)
+#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG ,__VA_ARGS__)
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG ,__VA_ARGS__)
+#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG ,__VA_ARGS__)
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG ,__VA_ARGS__)
+#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, TAG ,__VA_ARGS__)
+
+#define IMAGE_TILE_MAX_SIZE (512 * 512)
+
+static void *tile_buffer = NULL;
+
+bool image_onLoad() {
+ tile_buffer = malloc(IMAGE_TILE_MAX_SIZE * 4);
+ return tile_buffer != NULL;
+}
+
+void image_onUnload() {
+ free(tile_buffer);
+ tile_buffer = NULL;
+}
+
+typedef struct {
+ AImageDecoder *decoder;
+ void *srcBuffer;
+ size_t stride;
+ int fd;
+} SOURCE;
+
+typedef struct {
+ int32_t width;
+ int32_t height;
+ void *buffer;
+ int bufferLen;
+ bool isAnimated;
+ bool alpha;
+ int delay;
+ SOURCE *src;
+} IMAGE;
+
+static void recycleSource(SOURCE *src) {
+ if (!src)
+ return;
+ AImageDecoder_delete(src->decoder);
+ free(src->srcBuffer);
+ free(src);
+}
+
+static void recycle(IMAGE *image) {
+ if (!image)
+ return;
+ recycleSource(image->src);
+ free(image->buffer);
+ free(image);
+}
+
+typedef struct Memarea {
+ void *buffer;
+ long size;
+} Memarea;
+
+bool copy_pixels(const void *src, int src_w, int src_h, int src_x, int src_y,
+ void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
+ int width, int height) {
+ int left;
+ int line;
+ size_t line_stride;
+ int src_stride;
+ int src_pos;
+ int dst_pos;
+ size_t dst_blank_length;
+
+ // Sanitize
+ if (src_x < 0) {
+ width -= src_x;
+ dst_x -= src_x;
+ src_x = 0;
+ }
+ if (dst_x < 0) {
+ width -= dst_x;
+ src_x -= dst_x;
+ dst_x = 0;
+ }
+ if (width <= 0) {
+ return false;
+ }
+ if (src_y < 0) {
+ height -= src_y;
+ dst_y -= src_y;
+ src_y = 0;
+ }
+ if (dst_y < 0) {
+ height -= dst_y;
+ src_y -= dst_y;
+ dst_y = 0;
+ }
+ if (height <= 0) {
+ return false;
+ }
+ left = src_x + width - src_w;
+ if (left > 0) {
+ width -= left;
+ }
+ left = dst_x + width - dst_w;
+ if (left > 0) {
+ width -= left;
+ }
+ if (width <= 0) {
+ return false;
+ }
+ left = src_y + height - src_h;
+ if (left > 0) {
+ height -= left;
+ }
+ left = dst_y + height - dst_h;
+ if (left > 0) {
+ height -= left;
+ }
+ if (height <= 0) {
+ return false;
+ }
+
+ // Init
+ line_stride = (size_t) (width * 4);
+ src_stride = src_w * 4;
+ src_pos = src_y * src_stride + src_x * 4;
+ dst_pos = 0;
+
+ dst_blank_length = (size_t) (dst_y * dst_w + dst_x) * 4;
+
+ // First line
+ dst_pos += (int)dst_blank_length;
+ memcpy(dst + dst_pos, src + src_pos, line_stride);
+ dst_pos += (int)line_stride;
+ src_pos += src_stride;
+
+ // Other lines
+ dst_blank_length = (size_t) ((dst_w - width) * 4);
+ for (line = 1; line < height; line++) {
+ dst_pos += (int)dst_blank_length;
+ memcpy(dst + dst_pos, src + src_pos, line_stride);
+ dst_pos += (int)line_stride;
+ src_pos += src_stride;
+ }
+
+ return true;
+}
+
+void decodeCommon(IMAGE *image, SOURCE *src) {
+ image->src = src;
+ AImageDecoder *decoder = src->decoder;
+ image->isAnimated = AImageDecoder_isAnimated(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->alpha =
+ AImageDecoderHeaderInfo_getAlphaFlags(headerInfo) == ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
+ src->stride = AImageDecoder_getMinimumStride(decoder);
+ image->bufferLen = (int) (image->height * src->stride);
+ image->buffer = malloc(image->bufferLen);
+ if (image->isAnimated) {
+ AImageDecoder_setInternallyHandleDisposePrevious(decoder, false);
+ AImageDecoderFrameInfo *frameInfo = AImageDecoderFrameInfo_create();
+ AImageDecoder_getFrameInfo(decoder, frameInfo);
+ image->delay = (int) AImageDecoderFrameInfo_getDuration(frameInfo) / 1000000;
+ AImageDecoderFrameInfo_delete(frameInfo);
+ }
+ AImageDecoder_decodeImage(decoder, image->buffer, src->stride, image->bufferLen);
+ if (!image->isAnimated) {
+ recycleSource(image->src);
+ image->src = NULL;
+ }
+}
+
+IMAGE *createFromFd(int fd) {
+ AImageDecoder *decoder = NULL;
+ if (AImageDecoder_createFromFd(fd, &decoder) != ANDROID_IMAGE_DECODER_SUCCESS)
+ return NULL;
+ IMAGE *image = calloc(1, sizeof(IMAGE));
+ SOURCE *src = calloc(1, sizeof(SOURCE));
+ src->decoder = decoder;
+ src->fd = fd;
+ decodeCommon(image, src);
+ return image;
+}
+
+IMAGE *createFromAddr(void *addr, long size) {
+ AImageDecoder *decoder;
+ AImageDecoder_createFromBuffer((const void *) addr, size, &decoder);
+ IMAGE *image = calloc(1, sizeof(IMAGE));
+ SOURCE *src = calloc(1, sizeof(SOURCE));
+ src->decoder = decoder;
+ src->srcBuffer = addr;
+ decodeCommon(image, src);
+ return image;
+}
+
+IMAGE *create(int32_t width, int32_t height, const void *data) {
+ IMAGE *plain = calloc(1, sizeof(IMAGE));
+ void *buffer = NULL;
+ size_t length = width * height * 4;
+
+ buffer = malloc(length);
+ memcpy(buffer, data, length);
+
+ // plain->isAnimated = false; this is unnecessary since we use calloc
+ plain->width = width;
+ plain->height = height;
+ plain->buffer = buffer;
+ plain->bufferLen = (int) length;
+
+ return plain;
+}
+
+void render(IMAGE *image, int src_x, int src_y,
+ void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
+ int width, int height) {
+ copy_pixels(image->buffer, image->width, image->height, src_x, src_y, dst, dst_w, dst_h, dst_x,
+ dst_y, width, height);
+}
+
+void advance(IMAGE *image) {
+ if (image->isAnimated) {
+ AImageDecoder_advanceFrame(image->src->decoder);
+ if (AImageDecoder_decodeImage(image->src->decoder, image->buffer, image->src->stride,
+ image->bufferLen) == ANDROID_IMAGE_DECODER_FINISHED) {
+ AImageDecoder_rewind(image->src->decoder);
+ AImageDecoder_decodeImage(image->src->decoder, image->buffer, image->src->stride,
+ image->bufferLen);
+ }
+ }
+}
+
+static int jniGetFDFromFileDescriptor(JNIEnv *env, jobject fileDescriptor) {
+ jint fd = -1;
+ jclass fdClass = (*env)->FindClass(env, "java/io/FileDescriptor");
+
+ if (fdClass != NULL) {
+ jfieldID fdClassDescriptorFieldID = (*env)->GetFieldID(env, fdClass, "descriptor", "I");
+ if (fdClassDescriptorFieldID != NULL && fileDescriptor != NULL) {
+ fd = (*env)->GetIntField(env, fileDescriptor, fdClassDescriptorFieldID);
+ }
+ }
+
+ return fd;
+}
+
+JNIEXPORT jlong JNICALL
+Java_com_hippo_image_Image_nativeDecodeFdInt(JNIEnv *env, jclass clazz, jint fd) {
+ IMAGE *image = createFromFd(fd);
+ return (jlong) image;
+}
+
+JNIEXPORT jlong JNICALL
+Java_com_hippo_image_Image_nativeDecode(JNIEnv *env, jclass clazz, jobject fd) {
+ return Java_com_hippo_image_Image_nativeDecodeFdInt(env, clazz,
+ jniGetFDFromFileDescriptor(env, fd));
+}
+
+JNIEXPORT jlong JNICALL
+Java_com_hippo_image_Image_nativeCreate(JNIEnv *env, jclass clazz, jobject bitmap) {
+ AndroidBitmapInfo info;
+ void *pixels = NULL;
+ void *image = NULL;
+
+ AndroidBitmap_getInfo(env, bitmap, &info);
+ AndroidBitmap_lockPixels(env, bitmap, &pixels);
+
+ image = create((int)info.width, (int)info.height, pixels);
+ AndroidBitmap_unlockPixels(env, bitmap);
+ return (jlong) image;
+}
+
+JNIEXPORT void JNICALL
+Java_com_hippo_image_Image_nativeRender(JNIEnv *env, jclass clazz, jlong ptr, jint src_x,
+ jint src_y, jobject dst, jint dst_x, jint dst_y, jint width,
+ jint height) {
+ AndroidBitmapInfo info;
+ void *pixels = NULL;
+
+ AndroidBitmap_getInfo(env, dst, &info);
+ AndroidBitmap_lockPixels(env, dst, &pixels);
+
+ render((IMAGE *) ptr, src_x, src_y, pixels, (int)info.width, (int)info.height, dst_x, dst_y, width,
+ height);
+
+ AndroidBitmap_unlockPixels(env, dst);
+}
+
+JNIEXPORT void JNICALL
+Java_com_hippo_image_Image_nativeTexImage(JNIEnv *env, jclass clazz, jlong ptr, jboolean init,
+ jint src_x, jint src_y, jint width, jint height) {
+ if (width * height > IMAGE_TILE_MAX_SIZE)
+ return;
+
+ render((IMAGE *) ptr, src_x, src_y, tile_buffer, width, height, 0, 0, width, height);
+
+ if (init) {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ tile_buffer);
+ } else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
+ tile_buffer);
+ }
+}
+
+JNIEXPORT void JNICALL
+Java_com_hippo_image_Image_nativeAdvance(JNIEnv *env, jclass clazz, jlong ptr) {
+ advance((IMAGE *) ptr);
+}
+
+JNIEXPORT jint JNICALL
+Java_com_hippo_image_Image_nativeGetDelay(JNIEnv *env, jclass clazz, jlong ptr) {
+ return ((IMAGE *) ptr)->delay;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_com_hippo_image_Image_nativeIsOpaque(JNIEnv *env, jclass clazz, jlong ptr) {
+ return ((IMAGE *) ptr)->alpha;
+}
+
+JNIEXPORT void JNICALL
+Java_com_hippo_image_Image_nativeRecycle(JNIEnv *env, jclass clazz, jlong ptr) {
+ recycle((IMAGE *) ptr);
+}
+
+JNIEXPORT jlong JNICALL
+Java_com_hippo_image_Image_nativeDecodeAddr(JNIEnv *env, jclass clazz, jlong addr) {
+ Memarea *memarea = (Memarea *) addr;
+ IMAGE *image = createFromAddr(memarea->buffer, memarea->size);
+ free(memarea);
+ return (jlong) image;
+}
+
+JNIEXPORT jint JNICALL
+Java_com_hippo_image_Image_nativeGetFormat(JNIEnv *env, jclass clazz, jlong native_ptr) {
+ return ((IMAGE *) native_ptr)->isAnimated;
+}
+
+JNIEXPORT jint JNICALL
+Java_com_hippo_image_Image_nativeGetWidth(JNIEnv *env, jclass clazz, jlong native_ptr) {
+ return ((IMAGE *) native_ptr)->width;
+}
+
+JNIEXPORT jint JNICALL
+Java_com_hippo_image_Image_nativeGetHeight(JNIEnv *env, jclass clazz, jlong native_ptr) {
+ return ((IMAGE *) native_ptr)->height;
+}
diff --git a/app/src/main/cpp/image/java_wrapper.h b/app/src/main/cpp/image.h
similarity index 79%
rename from app/src/main/cpp/image/java_wrapper.h
rename to app/src/main/cpp/image.h
index a8b7a267f..fe5dcc63a 100644
--- a/app/src/main/cpp/image/java_wrapper.h
+++ b/app/src/main/cpp/image.h
@@ -17,20 +17,13 @@
* EhViewer. If not, see .
*/
-#ifndef IMAGE_JAVA_WRAPPER_H
-#define IMAGE_JAVA_WRAPPER_H
+#ifndef IMAGE_IMAGE_H
+#define IMAGE_IMAGE_H
#include
-#define IMAGE_TILE_MAX_SIZE (512 * 512)
-
-typedef struct Memarea {
- void *buffer;
- long size;
-} Memarea;
-
bool image_onLoad();
void image_onUnload();
-#endif /* IMAGE_JAVA_WRAPPER_H */
+#endif /* IMAGE_IMAGE_H */
diff --git a/app/src/main/cpp/image/CMakeLists.txt b/app/src/main/cpp/image/CMakeLists.txt
deleted file mode 100644
index 4adce6dc6..000000000
--- a/app/src/main/cpp/image/CMakeLists.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2018 Hippo Seven
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-cmake_minimum_required(VERSION 3.4.1)
-project(image C)
-
-set(IMAGE_SOURCES
- image.c
- image_utils.c
- java_wrapper.c
- )
-set(IMAGE_INCLUDES
- ${CMAKE_CURRENT_SOURCE_DIR}
- )
-set(IMAGE_LIBRARIES
- log
- jnigraphics
- GLESv2
- )
-
-add_library(image STATIC ${IMAGE_SOURCES})
-target_include_directories(image PRIVATE ${IMAGE_INCLUDES})
-target_link_libraries(image PRIVATE ${IMAGE_LIBRARIES})
\ No newline at end of file
diff --git a/app/src/main/cpp/image/image.c b/app/src/main/cpp/image/image.c
deleted file mode 100644
index 219560b46..000000000
--- a/app/src/main/cpp/image/image.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2022 Tarsin Norbin
- *
- * This file is part of EhViewer
- *
- * EhViewer is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * EhViewer is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * EhViewer. If not, see .
- */
-
-#include
-#include
-#include
-
-#include "image.h"
-#include "image_utils.h"
-
-void decodeCommon(IMAGE *image, SOURCE *src) {
- image->src = src;
- AImageDecoder *decoder = src->decoder;
- image->isAnimated = AImageDecoder_isAnimated(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->alpha =
- AImageDecoderHeaderInfo_getAlphaFlags(headerInfo) == ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
- src->stride = AImageDecoder_getMinimumStride(decoder);
- image->bufferLen = (int) (image->height * src->stride);
- image->buffer = malloc(image->bufferLen);
- if (image->isAnimated) {
- AImageDecoder_setInternallyHandleDisposePrevious(decoder, false);
- AImageDecoderFrameInfo *frameInfo = AImageDecoderFrameInfo_create();
- AImageDecoder_getFrameInfo(decoder, frameInfo);
- image->delay = (int) AImageDecoderFrameInfo_getDuration(frameInfo) / 1000000;
- AImageDecoderFrameInfo_delete(frameInfo);
- }
- AImageDecoder_decodeImage(decoder, image->buffer, src->stride, image->bufferLen);
- if (!image->isAnimated) {
- recycleSource(image->src);
- image->src = NULL;
- }
-}
-
-IMAGE *createFromFd(int fd) {
- AImageDecoder *decoder = NULL;
- if (AImageDecoder_createFromFd(fd, &decoder) != ANDROID_IMAGE_DECODER_SUCCESS)
- return NULL;
- IMAGE *image = calloc(1, sizeof(IMAGE));
- SOURCE *src = calloc(1, sizeof(SOURCE));
- src->decoder = decoder;
- src->fd = fd;
- decodeCommon(image, src);
- return image;
-}
-
-IMAGE *createFromAddr(void *addr, long size) {
- AImageDecoder *decoder;
- AImageDecoder_createFromBuffer((const void *) addr, size, &decoder);
- IMAGE *image = calloc(1, sizeof(IMAGE));
- SOURCE *src = calloc(1, sizeof(SOURCE));
- src->decoder = decoder;
- src->srcBuffer = addr;
- decodeCommon(image, src);
- return image;
-}
-
-IMAGE *create(int32_t width, int32_t height, const void *data) {
- IMAGE *plain = calloc(1, sizeof(IMAGE));
- void *buffer = NULL;
- size_t length = width * height * 4;
-
- buffer = malloc(length);
- memcpy(buffer, data, length);
-
- // plain->isAnimated = false; this is unnecessary since we use calloc
- plain->width = width;
- plain->height = height;
- plain->buffer = buffer;
- plain->bufferLen = (int) length;
-
- return plain;
-}
-
-void render(IMAGE *image, int src_x, int src_y,
- void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
- int width, int height) {
- copy_pixels(image->buffer, image->width, image->height, src_x, src_y, dst, dst_w, dst_h, dst_x,
- dst_y, width, height);
-}
-
-void advance(IMAGE *image) {
- if (image->isAnimated) {
- AImageDecoder_advanceFrame(image->src->decoder);
- if (AImageDecoder_decodeImage(image->src->decoder, image->buffer, image->src->stride,
- image->bufferLen) == ANDROID_IMAGE_DECODER_FINISHED) {
- AImageDecoder_rewind(image->src->decoder);
- AImageDecoder_decodeImage(image->src->decoder, image->buffer, image->src->stride,
- image->bufferLen);
- }
- }
-}
diff --git a/app/src/main/cpp/image/image.h b/app/src/main/cpp/image/image.h
deleted file mode 100644
index 17258e360..000000000
--- a/app/src/main/cpp/image/image.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2022 Tarsin Norbin
- *
- * This file is part of EhViewer
- *
- * EhViewer is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * EhViewer is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * EhViewer. If not, see .
- */
-
-#ifndef IMAGE_IMAGE_H
-#define IMAGE_IMAGE_H
-
-#include
-#include
-
-typedef struct {
- AImageDecoder *decoder;
- void *srcBuffer;
- size_t stride;
- int fd;
-} SOURCE;
-
-typedef struct {
- int32_t width;
- int32_t height;
- void *buffer;
- int bufferLen;
- bool isAnimated;
- bool alpha;
- int delay;
- SOURCE *src;
-} IMAGE;
-
-static void recycleSource(SOURCE *src) {
- if (!src)
- return;
- AImageDecoder_delete(src->decoder);
- free(src->srcBuffer);
- free(src);
-}
-
-static void recycle(IMAGE *image) {
- if (!image)
- return;
- recycleSource(image->src);
- free(image->buffer);
- free(image);
-}
-
-IMAGE *createFromFd(int fd);
-
-IMAGE *createFromAddr(void *addr, long size);
-
-IMAGE *create(int32_t width, int32_t height, const void *data);
-
-void render(IMAGE *image, int src_x, int src_y,
- void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
- int width, int height);
-
-void advance(IMAGE *image);
-
-#endif /* IMAGE_IMAGE_H */
diff --git a/app/src/main/cpp/image/image_utils.c b/app/src/main/cpp/image/image_utils.c
deleted file mode 100644
index 7b39308be..000000000
--- a/app/src/main/cpp/image/image_utils.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2015 Hippo Seven
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "image_utils.h"
-
-#include
-#include
-
-bool copy_pixels(const void *src, int src_w, int src_h, int src_x, int src_y,
- void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
- int width, int height) {
- int left;
- int line;
- size_t line_stride;
- int src_stride;
- int src_pos;
- int dst_pos;
- size_t dst_blank_length;
-
- // Sanitize
- if (src_x < 0) {
- width -= src_x;
- dst_x -= src_x;
- src_x = 0;
- }
- if (dst_x < 0) {
- width -= dst_x;
- src_x -= dst_x;
- dst_x = 0;
- }
- if (width <= 0) {
- return false;
- }
- if (src_y < 0) {
- height -= src_y;
- dst_y -= src_y;
- src_y = 0;
- }
- if (dst_y < 0) {
- height -= dst_y;
- src_y -= dst_y;
- dst_y = 0;
- }
- if (height <= 0) {
- return false;
- }
- left = src_x + width - src_w;
- if (left > 0) {
- width -= left;
- }
- left = dst_x + width - dst_w;
- if (left > 0) {
- width -= left;
- }
- if (width <= 0) {
- return false;
- }
- left = src_y + height - src_h;
- if (left > 0) {
- height -= left;
- }
- left = dst_y + height - dst_h;
- if (left > 0) {
- height -= left;
- }
- if (height <= 0) {
- return false;
- }
-
- // Init
- line_stride = (size_t) (width * 4);
- src_stride = src_w * 4;
- src_pos = src_y * src_stride + src_x * 4;
- dst_pos = 0;
-
- dst_blank_length = (size_t) (dst_y * dst_w + dst_x) * 4;
-
- // First line
- dst_pos += dst_blank_length;
- memcpy(dst + dst_pos, src + src_pos, line_stride);
- dst_pos += line_stride;
- src_pos += src_stride;
-
- // Other lines
- dst_blank_length = (size_t) ((dst_w - width) * 4);
- for (line = 1; line < height; line++) {
- dst_pos += dst_blank_length;
- memcpy(dst + dst_pos, src + src_pos, line_stride);
- dst_pos += line_stride;
- src_pos += src_stride;
- }
-
- return true;
-}
diff --git a/app/src/main/cpp/image/image_utils.h b/app/src/main/cpp/image/image_utils.h
deleted file mode 100644
index fe4f6df76..000000000
--- a/app/src/main/cpp/image/image_utils.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2022 Tarsin Norbin
- *
- * This file is part of EhViewer
- *
- * EhViewer is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * EhViewer is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * EhViewer. If not, see .
- */
-
-#ifndef IMAGE_IMAGE_UTILS_H
-#define IMAGE_IMAGE_UTILS_H
-
-#include
-
-bool copy_pixels(const void *src, int src_w, int src_h, int src_x, int src_y,
- void *dst, int dst_w, int dst_h, int dst_x, int dst_y,
- int width, int height);
-
-#endif /* IMAGE_IMAGE_UTILS_H */
diff --git a/app/src/main/cpp/image/java_wrapper.c b/app/src/main/cpp/image/java_wrapper.c
deleted file mode 100644
index 61010dce6..000000000
--- a/app/src/main/cpp/image/java_wrapper.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright 2015 Hippo Seven
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include
-#include
-#include
-#include
-
-#include "java_wrapper.h"
-#include "image.h"
-#include "log.h"
-
-static void *tile_buffer = NULL;
-
-static int jniGetFDFromFileDescriptor(JNIEnv *env, jobject fileDescriptor) {
- jint fd = -1;
- jclass fdClass = (*env)->FindClass(env, "java/io/FileDescriptor");
-
- if (fdClass != NULL) {
- jfieldID fdClassDescriptorFieldID = (*env)->GetFieldID(env, fdClass, "descriptor", "I");
- if (fdClassDescriptorFieldID != NULL && fileDescriptor != NULL) {
- fd = (*env)->GetIntField(env, fileDescriptor, fdClassDescriptorFieldID);
- }
- }
-
- return fd;
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_hippo_image_Image_nativeDecodeFdInt(JNIEnv *env, jclass clazz, jint fd) {
- IMAGE *image = createFromFd(fd);
- return (jlong) image;
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_hippo_image_Image_nativeDecode(JNIEnv *env, jclass clazz, jobject fd) {
- return Java_com_hippo_image_Image_nativeDecodeFdInt(env, clazz,
- jniGetFDFromFileDescriptor(env, fd));
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_hippo_image_Image_nativeCreate(JNIEnv *env, jclass clazz, jobject bitmap) {
- AndroidBitmapInfo info;
- void *pixels = NULL;
- void *image = NULL;
-
- AndroidBitmap_getInfo(env, bitmap, &info);
- AndroidBitmap_lockPixels(env, bitmap, &pixels);
-
- image = create(info.width, info.height, pixels);
- AndroidBitmap_unlockPixels(env, bitmap);
- return (jlong) image;
-}
-
-JNIEXPORT void JNICALL
-Java_com_hippo_image_Image_nativeRender(JNIEnv *env, jclass clazz, jlong ptr, jint src_x,
- jint src_y, jobject dst, jint dst_x, jint dst_y, jint width,
- jint height) {
- AndroidBitmapInfo info;
- void *pixels = NULL;
-
- AndroidBitmap_getInfo(env, dst, &info);
- AndroidBitmap_lockPixels(env, dst, &pixels);
-
- render((IMAGE *) ptr, src_x, src_y, pixels, info.width, info.height, dst_x, dst_y, width,
- height);
-
- AndroidBitmap_unlockPixels(env, dst);
-}
-
-JNIEXPORT void JNICALL
-Java_com_hippo_image_Image_nativeTexImage(JNIEnv *env, jclass clazz, jlong ptr, jboolean init,
- jint src_x, jint src_y, jint width, jint height) {
- if (width * height > IMAGE_TILE_MAX_SIZE)
- return;
-
- render((IMAGE *) ptr, src_x, src_y, tile_buffer, width, height, 0, 0, width, height);
-
- if (init) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
- tile_buffer);
- } else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
- tile_buffer);
- }
-}
-
-JNIEXPORT void JNICALL
-Java_com_hippo_image_Image_nativeAdvance(JNIEnv *env, jclass clazz, jlong ptr) {
- advance((IMAGE *) ptr);
-}
-
-JNIEXPORT jint JNICALL
-Java_com_hippo_image_Image_nativeGetDelay(JNIEnv *env, jclass clazz, jlong ptr) {
- return ((IMAGE *) ptr)->delay;
-}
-
-JNIEXPORT jboolean JNICALL
-Java_com_hippo_image_Image_nativeIsOpaque(JNIEnv *env, jclass clazz, jlong ptr) {
- return ((IMAGE *) ptr)->alpha;
-}
-
-JNIEXPORT void JNICALL
-Java_com_hippo_image_Image_nativeRecycle(JNIEnv *env, jclass clazz, jlong ptr) {
- recycle((IMAGE *) ptr);
-}
-
-bool image_onLoad() {
- tile_buffer = malloc(IMAGE_TILE_MAX_SIZE * 4);
- return tile_buffer != NULL;
-}
-
-void image_onUnload() {
- free(tile_buffer);
- tile_buffer = NULL;
-}
-
-JNIEXPORT jlong JNICALL
-Java_com_hippo_image_Image_nativeDecodeAddr(JNIEnv *env, jclass clazz, jlong addr) {
- Memarea *memarea = (Memarea *) addr;
- IMAGE *image = createFromAddr(memarea->buffer, memarea->size);
- free(memarea);
- return (jlong) image;
-}
-
-JNIEXPORT jint JNICALL
-Java_com_hippo_image_Image_nativeGetFormat(JNIEnv *env, jclass clazz, jlong native_ptr) {
- return ((IMAGE *) native_ptr)->isAnimated;
-}
-
-JNIEXPORT jint JNICALL
-Java_com_hippo_image_Image_nativeGetWidth(JNIEnv *env, jclass clazz, jlong native_ptr) {
- return ((IMAGE *) native_ptr)->width;
-}
-
-JNIEXPORT jint JNICALL
-Java_com_hippo_image_Image_nativeGetHeight(JNIEnv *env, jclass clazz, jlong native_ptr) {
- return ((IMAGE *) native_ptr)->height;
-}
diff --git a/app/src/main/cpp/image/log.h b/app/src/main/cpp/image/log.h
deleted file mode 100644
index 0f52e28bb..000000000
--- a/app/src/main/cpp/image/log.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2015 Hippo Seven
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LOG_H
-#define LOG_H
-
-#include
-
-#define TAG "ImageDecoder_wrapper"
-#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG ,__VA_ARGS__)
-#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG ,__VA_ARGS__)
-#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG ,__VA_ARGS__)
-#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG ,__VA_ARGS__)
-#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG ,__VA_ARGS__)
-#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, TAG ,__VA_ARGS__)
-
-#endif /* LOG_H */
diff --git a/app/src/main/cpp/main.c b/app/src/main/cpp/main.c
index b8124f906..cc540335a 100644
--- a/app/src/main/cpp/main.c
+++ b/app/src/main/cpp/main.c
@@ -23,7 +23,7 @@
#include
#include
-#include "image/java_wrapper.h"
+#include "image.h"
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env;