diff --git a/app/src/main/java/com/hippo/ehviewer/preference/VersionPreference.kt b/app/src/main/java/com/hippo/ehviewer/preference/VersionPreference.kt index f44161f38..f2b0aeed3 100644 --- a/app/src/main/java/com/hippo/ehviewer/preference/VersionPreference.kt +++ b/app/src/main/java/com/hippo/ehviewer/preference/VersionPreference.kt @@ -44,7 +44,6 @@ class VersionPreference @JvmOverloads constructor( val info = NativeLibInfo().addLib(Native.getlibarchiveVersion()) .addLib("lzma(xz-utils)", Native.getliblzmaVersion()) .addLib("zlib", Native.getzlibVersion()) - .addLib("libjpeg-turbo", Native.getlibjpeg_turboVersion()) .addLib(Native.getnettleVersion()) builder.setMessage(info.getMessage()) } diff --git a/native/src/main/java/com/hippo/Native.java b/native/src/main/java/com/hippo/Native.java index 45d7ede81..96ee1fce5 100644 --- a/native/src/main/java/com/hippo/Native.java +++ b/native/src/main/java/com/hippo/Native.java @@ -28,8 +28,6 @@ public class Native { public static native String getliblzmaVersion(); - public static native String getlibjpeg_turboVersion(); - public static native String getzlibVersion(); public static native String getnettleVersion(); diff --git a/native/src/main/jni/image/CMakeLists.txt b/native/src/main/jni/image/CMakeLists.txt index 3eae3fd8b..e86a1a52c 100644 --- a/native/src/main/jni/image/CMakeLists.txt +++ b/native/src/main/jni/image/CMakeLists.txt @@ -16,6 +16,3 @@ cmake_minimum_required(VERSION 3.4.1) add_subdirectory(image) add_subdirectory(stream) -add_subdirectory(libjpeg-turbo) -add_subdirectory(libpng) -add_subdirectory(giflib) diff --git a/native/src/main/jni/image/image/CMakeLists.txt b/native/src/main/jni/image/image/CMakeLists.txt index ddadef903..5d7f1a887 100644 --- a/native/src/main/jni/image/image/CMakeLists.txt +++ b/native/src/main/jni/image/image/CMakeLists.txt @@ -19,9 +19,6 @@ set(IMAGE_SOURCES image.c image_utils.c image_plain.c - image_jpeg.c - image_png.c - image_gif.c filter/clahe.c filter/gray.c java_wrapper.c @@ -34,9 +31,6 @@ set(IMAGE_LIBRARIES jnigraphics GLESv2 stream - jpeg - png - gif ) add_library(image STATIC ${IMAGE_SOURCES}) diff --git a/native/src/main/jni/image/image/image.c b/native/src/main/jni/image/image/image.c index a0966e42f..4e65db58f 100644 --- a/native/src/main/jni/image/image/image.c +++ b/native/src/main/jni/image/image/image.c @@ -18,424 +18,97 @@ // Created by Hippo on 12/27/2015. // +#include +#include + #include "image.h" #include "image_plain.h" -#include "image_jpeg.h" -#include "image_png.h" -#include "image_gif.h" #include "filter/clahe.h" #include "filter/gray.h" #include "../log.h" -static int get_format(JNIEnv* env, InputStream* stream) -{ - unsigned char temp[2]; - int read = read_input_stream(env, stream, temp, 0, 2); - - if (read == 2) { -#ifdef IMAGE_SUPPORT_JPEG - if (temp[0] == IMAGE_JPEG_MAGIC_NUMBER_0 && temp[1] == IMAGE_JPEG_MAGIC_NUMBER_1) { - return IMAGE_FORMAT_JPEG; - } -#endif -#ifdef IMAGE_SUPPORT_PNG - if (temp[0] == IMAGE_PNG_MAGIC_NUMBER_0 && temp[1] == IMAGE_PNG_MAGIC_NUMBER_1) { - return IMAGE_FORMAT_PNG; - } -#endif -#ifdef IMAGE_SUPPORT_GIF - if (temp[0] == IMAGE_GIF_MAGIC_NUMBER_0 && temp[1] == IMAGE_GIF_MAGIC_NUMBER_1) { - return IMAGE_FORMAT_GIF; - } -#endif - LOGE(MSG("Can't recognize the two magic number: %d, %d"), temp[0], temp[1]); - } else { - LOGE(MSG("Can't read two magic number from stream")); - } - - return IMAGE_FORMAT_UNKNOWN; -} - void* decode(JNIEnv* env, InputStream* stream, bool partially, int* format) { - unsigned char magic_numbers[2]; - PatchHeadInputStream* patch_head_input_stream; - - *format = get_format(env, stream); - - switch (*format) { -#ifdef IMAGE_SUPPORT_JPEG - case IMAGE_FORMAT_JPEG: - magic_numbers[0] = IMAGE_JPEG_MAGIC_NUMBER_0; - magic_numbers[1] = IMAGE_JPEG_MAGIC_NUMBER_1; - break; -#endif -#ifdef IMAGE_SUPPORT_PNG - case IMAGE_FORMAT_PNG: - magic_numbers[0] = IMAGE_PNG_MAGIC_NUMBER_0; - magic_numbers[1] = IMAGE_PNG_MAGIC_NUMBER_1; - break; -#endif -#ifdef IMAGE_SUPPORT_GIF - case IMAGE_FORMAT_GIF: - magic_numbers[0] = IMAGE_GIF_MAGIC_NUMBER_0; - magic_numbers[1] = IMAGE_GIF_MAGIC_NUMBER_1; - break; -#endif - default: - LOGE(MSG("Can't detect format %d"), *format); - destroy_input_stream(env, &stream); - return NULL; - } - - patch_head_input_stream = create_patch_head_input_stream(stream, magic_numbers, 2); - if (patch_head_input_stream == NULL){ - WTF_OM; + AImageDecoder *decoder; + size_t len = 1024 * 1024 * 4; + void* buffer = calloc(len, sizeof(char)); + len = read_input_stream(env, stream, buffer, 0, len); + AImageDecoder_createFromBuffer(buffer, len, &decoder); + free(buffer); + AImageDecoderHeaderInfo *headerInfo = AImageDecoder_getHeaderInfo(decoder); + IMAGE *image = malloc(sizeof(IMAGE)); + image->height = AImageDecoderHeaderInfo_getHeight(headerInfo); + image->width = AImageDecoderHeaderInfo_getWidth(headerInfo); + ssize_t bufferLen = 1024 * 1024 * 64; + image->buffer = malloc(bufferLen); + AImageDecoder_decodeImage(decoder, image->buffer, AImageDecoder_getMinimumStride(decoder), bufferLen); + AImageDecoder_delete(decoder); destroy_input_stream(env, &stream); - return NULL; - } - - switch (*format) { -#ifdef IMAGE_SUPPORT_JPEG - case IMAGE_FORMAT_JPEG: - return JPEG_decode(env, patch_head_input_stream, partially); -#endif -#ifdef IMAGE_SUPPORT_PNG - case IMAGE_FORMAT_PNG: - return PNG_decode(env, patch_head_input_stream, partially); -#endif -#ifdef IMAGE_SUPPORT_GIF - case IMAGE_FORMAT_GIF: - return GIF_decode(env, patch_head_input_stream, partially); -#endif - default: - LOGE(MSG("Can't detect format %d"), *format); - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - return NULL; - } + *format = IMAGE_FORMAT_JPEG; + return image; } void* create(unsigned int width, unsigned int height, const void* data) { -#ifdef IMAGE_SUPPORT_PLAIN - return PLAIN_create(width, height, data); -#else - return NULL; -#endif + return PLAIN_create(width, height, data); } bool complete(JNIEnv* env, void* image, int format) { - switch (format) { -#ifdef IMAGE_SUPPORT_PLAIN - case IMAGE_FORMAT_PLAIN: - return PLAIN_complete((PLAIN*) image); -#endif -#ifdef IMAGE_SUPPORT_JPEG - case IMAGE_FORMAT_JPEG: - return JPEG_complete((JPEG*) image); -#endif -#ifdef IMAGE_SUPPORT_PNG - case IMAGE_FORMAT_PNG: - return PNG_complete(env, (PNG*) image); -#endif -#ifdef IMAGE_SUPPORT_GIF - case IMAGE_FORMAT_GIF: - return GIF_complete(env, (GIF*) image); -#endif - default: - LOGE(MSG("Can't detect format %d"), format); - return false; - } + return true; } bool is_completed(void* image, int format) { - switch (format) { -#ifdef IMAGE_SUPPORT_PLAIN - case IMAGE_FORMAT_PLAIN: - return PLAIN_is_completed((PLAIN*) image); -#endif -#ifdef IMAGE_SUPPORT_JPEG - case IMAGE_FORMAT_JPEG: - return JPEG_is_completed((JPEG*) image); -#endif -#ifdef IMAGE_SUPPORT_PNG - case IMAGE_FORMAT_PNG: - return PNG_is_completed((PNG*) image); -#endif -#ifdef IMAGE_SUPPORT_GIF - case IMAGE_FORMAT_GIF: - return GIF_is_completed((GIF*) image); -#endif - default: - LOGE(MSG("Can't detect format %d"), format); - return false; - } + return true; } int get_width(void* image, int format) { - switch (format) { -#ifdef IMAGE_SUPPORT_PLAIN - case IMAGE_FORMAT_PLAIN: - return PLAIN_get_width((PLAIN*) image); -#endif -#ifdef IMAGE_SUPPORT_JPEG - case IMAGE_FORMAT_JPEG: - return JPEG_get_width((JPEG*) image); -#endif -#ifdef IMAGE_SUPPORT_PNG - case IMAGE_FORMAT_PNG: - return PNG_get_width((PNG*) image); -#endif -#ifdef IMAGE_SUPPORT_GIF - case IMAGE_FORMAT_GIF: - return GIF_get_width((GIF*) image); -#endif - default: - LOGE(MSG("Can't detect format %d"), format); - return -1; - } + return ((IMAGE*)image)->width; } int get_height(void* image, int format) { - switch (format) { -#ifdef IMAGE_SUPPORT_PLAIN - case IMAGE_FORMAT_PLAIN: - return PLAIN_get_height((PLAIN*) image); -#endif -#ifdef IMAGE_SUPPORT_JPEG - case IMAGE_FORMAT_JPEG: - return JPEG_get_height((JPEG*) image); -#endif -#ifdef IMAGE_SUPPORT_PNG - case IMAGE_FORMAT_PNG: - return PNG_get_height((PNG*) image); -#endif -#ifdef IMAGE_SUPPORT_GIF - case IMAGE_FORMAT_GIF: - return GIF_get_height((GIF*) image); -#endif - default: - LOGE(MSG("Can't detect format %d"), format); - return -1; - } + return ((IMAGE*)image)->height; } int get_byte_count(void* image, int format) { - switch (format) { -#ifdef IMAGE_SUPPORT_PLAIN - case IMAGE_FORMAT_PLAIN: - return PLAIN_get_byte_count((PLAIN*) image); -#endif -#ifdef IMAGE_SUPPORT_JPEG - case IMAGE_FORMAT_JPEG: - return JPEG_get_byte_count((JPEG*) image); -#endif -#ifdef IMAGE_SUPPORT_PNG - case IMAGE_FORMAT_PNG: - return PNG_get_byte_count((PNG*) image); -#endif -#ifdef IMAGE_SUPPORT_GIF - case IMAGE_FORMAT_GIF: - return GIF_get_byte_count((GIF*) image); -#endif - default: - LOGE(MSG("Can't detect format %d"), format); - return -1; - } + return ((IMAGE*)image)->width * ((IMAGE*)image)->height * 4; } void render(void* image, int format, int src_x, int src_y, void* dst, int dst_w, int dst_h, int dst_x, int dst_y, int width, int height, bool fill_blank, int default_color) { - switch (format) { -#ifdef IMAGE_SUPPORT_PLAIN - case IMAGE_FORMAT_PLAIN: - PLAIN_render((PLAIN*) image, src_x, src_y, - dst, dst_w, dst_h, dst_x, dst_y, - width, height, fill_blank, default_color); - break; -#endif -#ifdef IMAGE_SUPPORT_JPEG - case IMAGE_FORMAT_JPEG: - JPEG_render((JPEG*) image, src_x, src_y, - dst, dst_w, dst_h, dst_x, dst_y, - width, height, fill_blank, default_color); - break; -#endif -#ifdef IMAGE_SUPPORT_PNG - case IMAGE_FORMAT_PNG: - PNG_render((PNG*) image, src_x, src_y, - dst, dst_w, dst_h, dst_x, dst_y, - width, height, fill_blank, default_color); - break; -#endif -#ifdef IMAGE_SUPPORT_GIF - case IMAGE_FORMAT_GIF: - GIF_render((GIF*) image, src_x, src_y, - dst, dst_w, dst_h, dst_x, dst_y, - width, height, fill_blank, default_color); - break; -#endif - default: - LOGE(MSG("Can't detect format %d"), format); - break; - } + PLAIN_render((IMAGE *) image, src_x, src_y, dst, dst_w, dst_h, dst_x, dst_y, width, height, fill_blank, default_color); } void advance(void* image, int format) { - switch (format) { -#ifdef IMAGE_SUPPORT_PLAIN - case IMAGE_FORMAT_PLAIN: - PLAIN_advance((PLAIN*) image); - break; -#endif -#ifdef IMAGE_SUPPORT_JPEG - case IMAGE_FORMAT_JPEG: - JPEG_advance((JPEG*) image); - break; -#endif -#ifdef IMAGE_SUPPORT_PNG - case IMAGE_FORMAT_PNG: - PNG_advance((PNG*) image); - break; -#endif -#ifdef IMAGE_SUPPORT_GIF - case IMAGE_FORMAT_GIF: - GIF_advance((GIF*) image); - break; -#endif - default: - LOGE(MSG("Can't detect format %d"), format); - } } int get_delay(void* image, int format) { - switch (format) { -#ifdef IMAGE_SUPPORT_PLAIN - case IMAGE_FORMAT_PLAIN: - return PLAIN_get_delay((PLAIN*) image); -#endif -#ifdef IMAGE_SUPPORT_JPEG - case IMAGE_FORMAT_JPEG: - return JPEG_get_delay((JPEG*) image); -#endif -#ifdef IMAGE_SUPPORT_PNG - case IMAGE_FORMAT_PNG: - return PNG_get_delay((PNG*) image); -#endif -#ifdef IMAGE_SUPPORT_GIF - case IMAGE_FORMAT_GIF: - return GIF_get_delay((GIF*) image); -#endif - default: - LOGE(MSG("Can't detect format %d"), format); - return false; - } + return 0; } int get_frame_count(void* image, int format) { - switch (format) { -#ifdef IMAGE_SUPPORT_PLAIN - case IMAGE_FORMAT_PLAIN: - return PLAIN_get_frame_count((PLAIN*) image); -#endif -#ifdef IMAGE_SUPPORT_JPEG - case IMAGE_FORMAT_JPEG: - return JPEG_get_frame_count((JPEG*) image); -#endif -#ifdef IMAGE_SUPPORT_PNG - case IMAGE_FORMAT_PNG: - return PNG_get_frame_count((PNG*) image); -#endif -#ifdef IMAGE_SUPPORT_GIF - case IMAGE_FORMAT_GIF: - return GIF_get_frame_count((GIF*) image); -#endif - default: - LOGE(MSG("Can't detect format %d"), format); - return false; - } + return 1; } bool is_opaque(void* image, int format) { - switch (format) { -#ifdef IMAGE_SUPPORT_PLAIN - case IMAGE_FORMAT_PLAIN: - return PLAIN_is_opaque((PLAIN*) image); -#endif -#ifdef IMAGE_SUPPORT_JPEG - case IMAGE_FORMAT_JPEG: - return JPEG_is_opaque((JPEG*) image); -#endif -#ifdef IMAGE_SUPPORT_PNG - case IMAGE_FORMAT_PNG: - return PNG_is_opaque((PNG*) image); -#endif -#ifdef IMAGE_SUPPORT_GIF - case IMAGE_FORMAT_GIF: - return GIF_is_opaque((GIF*) image); -#endif - default: - LOGE(MSG("Can't detect format %d"), format); - return false; - } + return false; } static void get_image_data(void* image, int format, void** pixel, int* width, int* height) { - switch (format) { -#ifdef IMAGE_SUPPORT_PLAIN - case IMAGE_FORMAT_PLAIN: { PLAIN* plain = (PLAIN*) image; *pixel = PLAIN_get_pixels(plain); *width = PLAIN_get_width(plain); *height = PLAIN_get_height(plain); - break; - } -#endif -#ifdef IMAGE_SUPPORT_JPEG - case IMAGE_FORMAT_JPEG: { - JPEG* jpeg = (JPEG*) image; - *pixel = JPEG_get_pixels(jpeg); - *width = JPEG_get_width(jpeg); - *height = JPEG_get_height(jpeg); - break; - } -#endif -#ifdef IMAGE_SUPPORT_PNG - case IMAGE_FORMAT_PNG: { - PNG* png = (PNG*) image; - *pixel = PNG_get_pixels(png); - *width = PNG_get_width(png); - *height = PNG_get_height(png); - break; - } -#endif -#ifdef IMAGE_SUPPORT_GIF - case IMAGE_FORMAT_GIF: { - GIF* gif = (GIF*) image; - *pixel = GIF_get_pixels(gif); - *width = GIF_get_width(gif); - *height = GIF_get_height(gif); - break; - } -#endif - default: - *pixel = NULL; - *width = 0; - *height = 0; - break; - } } bool is_gray(void* image, int format, int error) @@ -470,30 +143,7 @@ void clahe(void* image, int format, bool to_gray) void recycle(JNIEnv *env, void* image, int format) { - switch (format) { -#ifdef IMAGE_SUPPORT_PLAIN - case IMAGE_FORMAT_PLAIN: - PLAIN_recycle((PLAIN*) image); - break; -#endif -#ifdef IMAGE_SUPPORT_JPEG - case IMAGE_FORMAT_JPEG: - JPEG_recycle((JPEG*) image); - break; -#endif -#ifdef IMAGE_SUPPORT_PNG - case IMAGE_FORMAT_PNG: - PNG_recycle(env, (PNG*) image); - break; -#endif -#ifdef IMAGE_SUPPORT_GIF - case IMAGE_FORMAT_GIF: - GIF_recycle(env, (GIF*) image); - break; -#endif - default: - LOGE(MSG("Can't detect format %d"), format); - } + PLAIN_recycle((PLAIN*) image); } int get_supported_formats(int *formats) @@ -513,20 +163,5 @@ int get_supported_formats(int *formats) const char *get_decoder_description(int format) { - switch (format) { -#ifdef IMAGE_SUPPORT_JPEG - case IMAGE_FORMAT_JPEG: - return IMAGE_JPEG_DECODER_DESCRIPTION; -#endif -#ifdef IMAGE_SUPPORT_PNG - case IMAGE_FORMAT_PNG: - return IMAGE_PNG_DECODER_DESCRIPTION; -#endif -#ifdef IMAGE_SUPPORT_GIF - case IMAGE_FORMAT_GIF: - return IMAGE_GIF_DECODER_DESCRIPTION; -#endif - default: - return NULL; - } + return NULL; } diff --git a/native/src/main/jni/image/image/image.h b/native/src/main/jni/image/image/image.h index 2721d1476..54dcf32b8 100644 --- a/native/src/main/jni/image/image/image.h +++ b/native/src/main/jni/image/image/image.h @@ -42,6 +42,13 @@ #define IMAGE_MAX_SUPPORTED_FORMAT_COUNT 3 +typedef struct +{ + unsigned int width; + unsigned int height; + void* buffer; +} IMAGE; + void* decode(JNIEnv* env, InputStream* stream, bool partially, int* format); void* create(unsigned int width, unsigned int height, const void* data); bool complete(JNIEnv* env, void* image, int format); diff --git a/native/src/main/jni/image/image/image_gif.c b/native/src/main/jni/image/image/image_gif.c deleted file mode 100644 index ebaea6369..000000000 --- a/native/src/main/jni/image/image/image_gif.c +++ /dev/null @@ -1,558 +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. - */ - -// -// Created by Hippo on 12/27/2015. -// - -#include "config.h" -#ifdef IMAGE_SUPPORT_GIF - -#include -#include - -#include "image_gif.h" -#include "image_utils.h" -#include "java_wrapper.h" -#include "../log.h" -#include "../utils.h" - -static int error_code = 0; - -typedef struct { - unsigned char red; - unsigned char green; - unsigned char blue; - unsigned char alpha; -} RGBA; - -static int custom_read_fun(GifFileType* gif, GifByteType* bytes, int size) { - bool attach; - int read; - PatchHeadInputStream* patch_head_input_stream = gif->UserData; - JNIEnv *env = obtain_env(&attach); - - if (env == NULL) { - LOGE(MSG("Can't get JNIEnv")); - return 0; - } - - read = read_patch_head_input_stream(env, patch_head_input_stream, bytes, 0, (size_t) size); - - if (attach) { - release_env(); - } - - return read; -} - -static void generate_prepare(GIF_FRAME_INFO* frame_info_array, int count) -{ - int disposal = 0xff; - int i; - - for (i = 0; i < count; i++){ - GIF_FRAME_INFO* frame_info = frame_info_array + i; - - switch (disposal) { - case DISPOSAL_UNSPECIFIED: - case DISPOSE_DO_NOT: - frame_info->prepare = IMAGE_GIF_PREPARE_NONE; - break; - case DISPOSE_BACKGROUND: - frame_info->prepare = IMAGE_GIF_PREPARE_BACKGROUND; - break; - case DISPOSE_PREVIOUS: - frame_info->prepare = IMAGE_GIF_PREPARE_USE_BACKUP; - break; - default: - frame_info->prepare = IMAGE_GIF_PREPARE_BACKGROUND; - break; - } - - disposal = frame_info->disposal; - } -} - -static void read_gcb(GifFileType* gif_file, int index, GIF_FRAME_INFO* frame_info) -{ - GraphicsControlBlock gcb; - if (DGifSavedExtensionToGCB(gif_file, index, &gcb) == GIF_OK) { - frame_info->tran = gcb.TransparentColor; - frame_info->delay = gcb.DelayTime * 10; - frame_info->disposal = gcb.DisposalMode; - frame_info->prepare = IMAGE_GIF_PREPARE_UNKNOWN; - } else { - frame_info->tran = -1; - frame_info->delay = 0; - frame_info->disposal = DISPOSE_DO_NOT; - frame_info->prepare = IMAGE_GIF_PREPARE_UNKNOWN; - } -} - -static void fix_gif_file(GifFileType* gif_file) { - if (gif_file->ImageCount == 0) { - return; - } - - SavedImage last_image = gif_file->SavedImages[gif_file->ImageCount - 1]; - // If RasterBits is NULL, discard this frame - if (last_image.RasterBits == NULL) { - gif_file->ImageCount--; - // Free last image - if (last_image.ImageDesc.ColorMap != NULL) { - GifFreeMapObject(last_image.ImageDesc.ColorMap); - last_image.ImageDesc.ColorMap = NULL; - } - GifFreeExtensions(&last_image.ExtensionBlockCount, &last_image.ExtensionBlocks); - } -} - -void* GIF_decode(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream, bool partially) -{ - GIF* gif = NULL; - GifFileType* gif_file = NULL; - void* buffer = NULL; - void*shown_buffer = NULL; - GIF_FRAME_INFO* frame_info_array = NULL; - int i; - - gif = (GIF*) malloc(sizeof(GIF)); - if (gif == NULL) { - WTF_OM; - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - return NULL; - } - - // Open - gif_file = DGifOpen(patch_head_input_stream, &custom_read_fun, &error_code); - if (gif_file == NULL) { - WTF_OM; - free(gif); - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - return NULL; - } - - // Buffer - buffer = malloc(gif_file->SWidth * gif_file->SHeight * sizeof(RGBA)); - shown_buffer = malloc(gif_file->SWidth * gif_file->SHeight * sizeof(RGBA)); - if (buffer == NULL || shown_buffer == NULL) { - WTF_OM; - free(buffer); - free(shown_buffer); - DGifCloseFile(gif_file, &error_code); - free(gif); - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - return NULL; - } - - if (partially) { - // Glance - if (DGifGlance(gif_file) != GIF_OK) { - LOGE(MSG("GIF error code %d"), error_code); - DGifCloseFile(gif_file, &error_code); - free(buffer); - free(gif); - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - return NULL; - } - - // Frame info - frame_info_array = (GIF_FRAME_INFO*) malloc(sizeof(GIF_FRAME_INFO)); - if (frame_info_array == NULL) { - WTF_OM; - DGifCloseFile(gif_file, &error_code); - free(buffer); - free(gif); - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - return NULL; - } - - // Read gcb - read_gcb(gif_file, 0, frame_info_array); - - gif->partially = true; - gif->patch_head_input_stream = patch_head_input_stream; - } else { - // Slurp - if (DGifSlurp(gif_file) == GIF_ERROR) { - fix_gif_file(gif_file); - } - if (gif_file->ImageCount <= 0) { - LOGE(MSG("No frame")); - DGifCloseFile(gif_file, &error_code); - free(buffer); - free(gif); - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - return NULL; - } - - // Frame info - frame_info_array = (GIF_FRAME_INFO*) malloc(gif_file->ImageCount * sizeof(GIF_FRAME_INFO)); - if (frame_info_array == NULL) { - WTF_OM; - DGifCloseFile(gif_file, &error_code); - free(buffer); - free(gif); - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - return NULL; - } - - // Read gcb - for (i = 0; i < gif_file->ImageCount; i++) { - read_gcb(gif_file, i, frame_info_array + i); - } - - // Generate prepare - generate_prepare(frame_info_array, gif_file->ImageCount); - - // Close input stream - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - - gif->partially = false; - gif->patch_head_input_stream = NULL; - } - - gif->gif_file = gif_file; - gif->frame_info_array = frame_info_array; - gif->buffer = buffer; - gif->buffer_index = -1; - gif->backup = NULL; - gif->shown_buffer = shown_buffer; - - GIF_advance(gif); - - return gif; -} - -bool GIF_complete(JNIEnv* env, GIF* gif) -{ - int i; - - if (!gif->partially) { - return true; - } - - if (gif->gif_file == NULL || gif->patch_head_input_stream == NULL) { - LOGE(MSG("Some stuff is NULL")); - return false; - } - - if (DGifSlurp(gif->gif_file) == GIF_ERROR) { - fix_gif_file(gif->gif_file); - } - - // Close input stream - close_patch_head_input_stream(env, gif->patch_head_input_stream); - destroy_patch_head_input_stream(env, &gif->patch_head_input_stream); - gif->patch_head_input_stream = NULL; - - gif->partially = false; - - gif->frame_info_array = (GIF_FRAME_INFO*) realloc(gif->frame_info_array, - gif->gif_file->ImageCount * sizeof(GIF_FRAME_INFO)); - if (gif->frame_info_array == NULL) { - WTF_OM; - return false; - } - - // Read gcb - for (i = 0; i < gif->gif_file->ImageCount; i++) { - read_gcb(gif->gif_file, i, gif->frame_info_array + i); - } - - // Generate prepare - generate_prepare(gif->frame_info_array, gif->gif_file->ImageCount); - - return true; -} - -bool GIF_is_completed(GIF* gif) -{ - return !gif->partially; -} - -void* GIF_get_pixels(GIF* gif) -{ - if (!gif->partially && GIF_get_frame_count(gif) == 1) { - return gif->buffer; - } else { - return NULL; - } -} - -int GIF_get_width(GIF* gif) -{ - return gif->gif_file->SWidth; -} - -int GIF_get_height(GIF* gif) -{ - return gif->gif_file->SHeight; -} - -int GIF_get_byte_count(GIF* gif) -{ - int i; - SavedImage saved_image; - int size = 0; - // Add buffer size - if (gif->buffer != NULL) { - size += gif->gif_file->SWidth * gif->gif_file->SHeight * 4; - } - // Add backup size - if (gif->backup != NULL) { - size += gif->gif_file->SWidth * gif->gif_file->SHeight * 4; - } - // Add shown buffer size - if (gif->shown_buffer != NULL) { - size += gif->gif_file->SWidth * gif->gif_file->SHeight * 4; - } - // Add frames size - if (gif->gif_file->SavedImages != NULL) { - for (i = 0; i < gif->gif_file->ImageCount; i++) { - saved_image = gif->gif_file->SavedImages[i]; - if (saved_image.RasterBits != NULL) { - size += saved_image.ImageDesc.Width * saved_image.ImageDesc.Height * 1; - } - } - } - return size; -} - -void GIF_render(GIF* gif, int src_x, int src_y, - void* dst, int dst_w, int dst_h, int dst_x, int dst_y, - int width, int height, bool fill_blank, int default_color) -{ - copy_pixels(gif->shown_buffer, gif->gif_file->SWidth, gif->gif_file->SHeight, src_x, src_y, - dst, dst_w, dst_h, dst_x, dst_y, - width, height, fill_blank, default_color); -} - -static void backup(GIF* gif) -{ - if (gif->backup == NULL) { - gif->backup = (unsigned char*) malloc((size_t) (gif->gif_file->SWidth * gif->gif_file->SHeight * 4)); - if (gif->backup == NULL) { - WTF_OM; - return; - } - } - memcpy(gif->backup, gif->buffer, (size_t) (gif->gif_file->SWidth * gif->gif_file->SHeight * 4)); -} - -static void restore(GIF* gif) -{ - if (gif->backup == NULL) { - LOGE(MSG("Backup is NULL")); - } else { - memcpy(gif->buffer, gif->backup, (size_t) (gif->gif_file->SWidth * gif->gif_file->SHeight * 4)); - } -} - -static void switch_buffer_backup(GIF* gif) -{ - unsigned char* temp; - - if (gif->backup == NULL) { - backup(gif); - } else { - temp = gif->buffer; - gif->buffer = gif->backup; - gif->backup = temp; - } -} - -static void clear(RGBA* pixels, int num, RGBA color) { - RGBA* ptr = pixels; - int i; - for (i = 0; i < num; i++) { - *(ptr++) = color; - } -} - -static bool get_color_from_table(const ColorMapObject* cmap, int index, - RGBA* color) { - if (cmap == NULL || index < 0 || index >= cmap->ColorCount) { - return false; - } else { - GifColorType gct = cmap->Colors[index]; - color->red = gct.Red; - color->green = gct.Green; - color->blue = gct.Blue; - color->alpha = 0xff; - return true; - } -} - -static void clear_bg(GifFileType* gif_file, void* pixels) -{ - RGBA color; - if (!get_color_from_table(gif_file->SColorMap, gif_file->SBackGroundColor, &color)) { - color.red = 0x00; - color.green = 0x00; - color.blue = 0x00; - color.alpha = 0x00; - } - clear(pixels, gif_file->SWidth * gif_file->SHeight, color); -} - -static void copy_line(GifByteType* src, RGBA* dst, - const ColorMapObject* cmap, int tran, int len) -{ - for (; len > 0; len--, src++, dst++) { - int index = *src; - if (tran == -1 || index != tran) { - get_color_from_table(cmap, index, dst); - } - } -} - -static void blend(GifFileType* gif_file, int index, void* pixels, int tran) -{ - int width = gif_file->SWidth; - int height = gif_file->SHeight; - SavedImage cur = gif_file->SavedImages[index]; - GifImageDesc desc = cur.ImageDesc; - int copy_width = MIN(width - desc.Left, desc.Width); - int copy_height = MIN(height - desc.Top, desc.Height); - ColorMapObject *cmap = desc.ColorMap; - GifByteType* src = cur.RasterBits; - RGBA* dst = pixels; - GifByteType* src_ptr; - RGBA* dst_ptr; - size_t len; - int i; - - if (cmap == NULL) { - cmap = gif_file->SColorMap; - } - if (cmap != NULL) { - for (i = 0; i < copy_height; i++) { - src_ptr = src + (i * desc.Width); - dst_ptr = dst + ((desc.Top + i) * width + desc.Left); - len = (size_t) copy_width; - copy_line(src_ptr, dst_ptr, cmap, tran, len); - } - } else { - LOGW(MSG("Can't find color map")); - } -} - -void GIF_advance(GIF* gif) -{ - int index; - GIF_FRAME_INFO frame_info; - - index = (gif->buffer_index + 1) % gif->gif_file->ImageCount; - if (index != 0 && gif->partially) { - LOGE(MSG("The png is only decoded partially. Only the first frame can be shown.")); - return; - } - - if (gif->frame_info_array == NULL) { - frame_info.tran = -1; - frame_info.disposal = DISPOSE_DO_NOT; - frame_info.delay = 0; - frame_info.prepare = IMAGE_GIF_PREPARE_BACKGROUND; - } else { - memcpy(&frame_info, gif->frame_info_array + index, sizeof(GIF_FRAME_INFO)); - } - - if (frame_info.disposal == DISPOSE_PREVIOUS && frame_info.prepare == IMAGE_GIF_PREPARE_USE_BACKUP) { - switch_buffer_backup(gif); - } else { - // Backup - if (frame_info.disposal == DISPOSE_PREVIOUS) { - backup(gif); - } - - // Prepare - switch (frame_info.prepare) { - case IMAGE_GIF_PREPARE_NONE: - // Do nothing - break; - default: - case IMAGE_GIF_PREPARE_BACKGROUND: - // Set bg - clear_bg(gif->gif_file, gif->buffer); - break; - case IMAGE_GIF_PREPARE_USE_BACKUP: - restore(gif); - break; - } - } - - blend(gif->gif_file, index, gif->buffer, frame_info.tran); - - // Copy to shown buffer - memcpy(gif->shown_buffer, gif->buffer, (size_t) (gif->gif_file->SWidth * gif->gif_file->SHeight * 4)); - - gif->buffer_index = index; -} - -int GIF_get_delay(GIF* gif) -{ - if (gif->frame_info_array == NULL) { - return 0; - } else { - return gif->frame_info_array[gif->buffer_index].delay; - } -} - -int GIF_get_frame_count(GIF* gif) -{ - return gif->gif_file->ImageCount; -} - -bool GIF_is_opaque(GIF* gif) -{ - return gif->frame_info_array->tran < 0; -} - -void GIF_recycle(JNIEnv* env, GIF* gif) -{ - DGifCloseFile(gif->gif_file, &error_code); - gif->gif_file = NULL; - - free(gif->frame_info_array); - gif->frame_info_array = NULL; - - free(gif->buffer); - gif->buffer = NULL; - - free(gif->backup); - gif->backup = NULL; - - free(gif->shown_buffer); - gif->shown_buffer = NULL; - - if (gif->patch_head_input_stream != NULL) { - close_patch_head_input_stream(env, gif->patch_head_input_stream); - destroy_patch_head_input_stream(env, &gif->patch_head_input_stream); - gif->patch_head_input_stream = NULL; - } -} - -#endif // IMAGE_SUPPORT_GIF diff --git a/native/src/main/jni/image/image/image_gif.h b/native/src/main/jni/image/image/image_gif.h deleted file mode 100644 index c2d28e3eb..000000000 --- a/native/src/main/jni/image/image/image_gif.h +++ /dev/null @@ -1,84 +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. - */ - -// -// Created by Hippo on 12/27/2015. -// - -#ifndef IMAGE_IMAGE_GIF_H -#define IMAGE_IMAGE_GIF_H - -#include "config.h" -#ifdef IMAGE_SUPPORT_GIF - -#include - -#include "patch_head_input_stream.h" -#include "gif_lib.h" -#include "../utils.h" - -#define IMAGE_GIF_DECODER_DESCRIPTION ("giflib " MAKESTRING(STRINGIZE, GIFLIB_MAJOR) "." \ - MAKESTRING(STRINGIZE, GIFLIB_MINOR) "." \ - MAKESTRING(STRINGIZE, GIFLIB_RELEASE)) - -#define IMAGE_GIF_MAGIC_NUMBER_0 0x47 -#define IMAGE_GIF_MAGIC_NUMBER_1 0x49 - -#define IMAGE_GIF_PREPARE_UNKNOWN 0x00 -#define IMAGE_GIF_PREPARE_NONE 0x01 -#define IMAGE_GIF_PREPARE_BACKGROUND 0x02 -#define IMAGE_GIF_PREPARE_USE_BACKUP 0x03 - -typedef struct -{ - int tran; - int disposal; - int delay; - int prepare; -} GIF_FRAME_INFO; - -typedef struct -{ - GifFileType* gif_file; - GIF_FRAME_INFO* frame_info_array; - void* buffer; - int buffer_index; - void* backup; - bool partially; - // Use extra buffer to avoid blink - void* shown_buffer; - PatchHeadInputStream* patch_head_input_stream; -} GIF; - -void* GIF_decode(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream, bool partially); -bool GIF_complete(JNIEnv* env, GIF* gif); -bool GIF_is_completed(GIF* gif); -void* GIF_get_pixels(GIF* gif); -int GIF_get_width(GIF* gif); -int GIF_get_height(GIF* gif); -int GIF_get_byte_count(GIF* gif); -void GIF_render(GIF* gif, int src_x, int src_y, - void* dst, int dst_w, int dst_h, int dst_x, int dst_y, - int width, int height, bool fill_blank, int default_color); -void GIF_advance(GIF* gif); -int GIF_get_delay(GIF* gif); -int GIF_get_frame_count(GIF* gif); -bool GIF_is_opaque(GIF* gif); -void GIF_recycle(JNIEnv* env, GIF* gif); - -#endif // IMAGE_SUPPORT_GIF - -#endif // IMAGE_IMAGE_GIF_H diff --git a/native/src/main/jni/image/image/image_jpeg.c b/native/src/main/jni/image/image/image_jpeg.c deleted file mode 100644 index c04a80675..000000000 --- a/native/src/main/jni/image/image/image_jpeg.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2016 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. - */ - -// -// Created by Hippo on 1/3/2016. -// - -#include "config.h" -#ifdef IMAGE_SUPPORT_JPEG - -#include -#include - -#include "image_jpeg.h" -#include "image_utils.h" -#include "java_wrapper.h" -#include "../log.h" - -struct my_error_mgr { - struct jpeg_error_mgr pub; - jmp_buf setjmp_buffer; -}; - -typedef struct my_error_mgr * my_error_ptr; - -static char emsg[JMSG_LENGTH_MAX]; - -static void my_error_exit(j_common_ptr cinfo) -{ - my_error_ptr myerr = (my_error_ptr) cinfo->err; - (*cinfo->err->format_message)(cinfo, emsg); - longjmp(myerr->setjmp_buffer, 1); -} - -static size_t custom_read(void * custom_stuff, unsigned char * buffer, size_t size) -{ - bool attach; - size_t read; - PatchHeadInputStream* patch_head_input_stream = custom_stuff; - JNIEnv *env = obtain_env(&attach); - - if (env == NULL) { - LOGE(MSG("Can't get JNIEnv")); - return 0; - } - - read = read_patch_head_input_stream(env, patch_head_input_stream, buffer, 0, size); - - if (attach) { - release_env(); - } - - return read; -} - -void* JPEG_decode(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream, bool partially) -{ - JPEG* jpeg = NULL; - struct jpeg_decompress_struct cinfo; - struct my_error_mgr jerr; - unsigned char* buffer = NULL; - size_t stride; - unsigned char* line_buffer_array[3]; - int read_lines; - - jpeg = (JPEG*) malloc(sizeof(JPEG)); - if (jpeg == NULL) { - WTF_OM; - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - return NULL; - } - - // Init - cinfo.err = jpeg_std_error(&jerr.pub); - jerr.pub.error_exit = my_error_exit; - if (setjmp(jerr.setjmp_buffer)) { - LOGE(MSG("%s"), emsg); - free(jpeg); - free(buffer); - jpeg_destroy_decompress(&cinfo); - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - return NULL; - } - jpeg_create_decompress(&cinfo); - jpeg_custom_src(&cinfo, &custom_read, patch_head_input_stream); - jpeg_read_header(&cinfo, TRUE); - - // Start decompress - cinfo.out_color_space = JCS_EXT_RGBA; - jpeg_start_decompress(&cinfo); - - stride = cinfo.output_components * cinfo.output_width; - buffer = malloc(stride * cinfo.output_height); - if (buffer == NULL) { - free(jpeg); - jpeg_destroy_decompress(&cinfo); - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - return NULL; - } - - // Copy buffer - line_buffer_array[0] = buffer; - line_buffer_array[1] = line_buffer_array[0] + stride; - line_buffer_array[2] = line_buffer_array[1] + stride; - while (cinfo.output_scanline < cinfo.output_height) { - read_lines = jpeg_read_scanlines(&cinfo, line_buffer_array, 3); - line_buffer_array[0] += stride * read_lines; - line_buffer_array[1] = line_buffer_array[0] + stride; - line_buffer_array[2] = line_buffer_array[1] + stride; - } - - // Finish decompress - jpeg_finish_decompress(&cinfo); - jpeg_destroy_decompress(&cinfo); - - // Close stream - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - - // Fill jpeg - jpeg->width = cinfo.output_width; - jpeg->height = cinfo.output_height; - jpeg->buffer = buffer; - - return jpeg; -} - -bool JPEG_complete(JPEG* jpeg) -{ - return true; -} - -bool JPEG_is_completed(JPEG* jpeg) -{ - return true; -} - -void* JPEG_get_pixels(JPEG* jpeg) -{ - return jpeg->buffer; -} - -int JPEG_get_width(JPEG* jpeg) -{ - return jpeg->width; -} - -int JPEG_get_height(JPEG* jpeg) -{ - return jpeg->height; -} - -int JPEG_get_byte_count(JPEG* jpeg) -{ - return jpeg->width * jpeg->height * 4; -} - -void JPEG_render(JPEG* jpeg, int src_x, int src_y, - void* dst, int dst_w, int dst_h, int dst_x, int dst_y, - int width, int height, bool fill_blank, int default_color) -{ - copy_pixels(jpeg->buffer, jpeg->width, jpeg->height, src_x, src_y, - dst, dst_w, dst_h, dst_x, dst_y, - width, height, fill_blank, default_color); -} - -void JPEG_advance(JPEG* jpeg) -{ -} - -int JPEG_get_delay(JPEG* jpeg) -{ - return 0; -} - -int JPEG_get_frame_count(JPEG* jpeg) -{ - return 1; -} - -bool JPEG_is_opaque(JPEG* jpeg) -{ - return true; -} - -void JPEG_recycle(JPEG* jpeg) -{ - free(jpeg->buffer); - jpeg->buffer = NULL; - - free(jpeg); -} - -#endif // IMAGE_SUPPORT_JPEG diff --git a/native/src/main/jni/image/image/image_jpeg.h b/native/src/main/jni/image/image/image_jpeg.h deleted file mode 100644 index e2a79d8e9..000000000 --- a/native/src/main/jni/image/image/image_jpeg.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2016 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. - */ - -// -// Created by Hippo on 1/3/2016. -// - -#ifndef IMAGE_IMAGE_JPEG_H -#define IMAGE_IMAGE_JPEG_H - -#include "config.h" -#ifdef IMAGE_SUPPORT_JPEG - -#include -#include - -#include "jpeglib.h" -#include "patch_head_input_stream.h" -#include "../utils.h" - -#define IMAGE_JPEG_DECODER_DESCRIPTION ("libjpeg-turbo " MAKESTRING(STRINGIZE, LIBJPEG_TURBO_VERSION)) - -#define IMAGE_JPEG_MAGIC_NUMBER_0 0xFF -#define IMAGE_JPEG_MAGIC_NUMBER_1 0xD8 - -typedef struct -{ - unsigned int width; - unsigned int height; - void* buffer; -} JPEG; - -void* JPEG_decode(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream, bool partially); -bool JPEG_complete(JPEG* jpeg); -bool JPEG_is_completed(JPEG* jpeg); -void* JPEG_get_pixels(JPEG* jpeg); -int JPEG_get_width(JPEG* jpeg); -int JPEG_get_height(JPEG* jpeg); -int JPEG_get_byte_count(JPEG* jpeg); -void JPEG_render(JPEG* jpeg, int src_x, int src_y, - void* dst, int dst_w, int dst_h, int dst_x, int dst_y, - int width, int height, bool fill_blank, int default_color); -void JPEG_advance(JPEG* jpeg); -int JPEG_get_delay(JPEG* jpeg); -int JPEG_get_frame_count(JPEG* jpeg); -bool JPEG_is_opaque(JPEG* jpeg); -void JPEG_recycle(JPEG* jpeg); - -#endif // IMAGE_SUPPORT_JPEG - -#endif // IMAGE_IMAGE_JPEG_H diff --git a/native/src/main/jni/image/image/image_plain.h b/native/src/main/jni/image/image/image_plain.h index 6aed105e6..77edd5148 100644 --- a/native/src/main/jni/image/image/image_plain.h +++ b/native/src/main/jni/image/image/image_plain.h @@ -28,12 +28,9 @@ #include "patch_head_input_stream.h" -typedef struct -{ - unsigned int width; - unsigned int height; - void* buffer; -} PLAIN; +#include "image.h" + +typedef IMAGE PLAIN; void* PLAIN_create(unsigned int width, unsigned int height, const void* data); bool PLAIN_complete(PLAIN* plain); diff --git a/native/src/main/jni/image/image/image_png.c b/native/src/main/jni/image/image/image_png.c deleted file mode 100644 index 4a46e9718..000000000 --- a/native/src/main/jni/image/image/image_png.c +++ /dev/null @@ -1,642 +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. - */ - -// -// Created by Hippo on 12/27/2015. -// - -#include "config.h" -#ifdef IMAGE_SUPPORT_PNG - -#include -#include - -#include "../log.h" -#include "../utils.h" -#include "image_png.h" -#include "image_utils.h" -#include "java_wrapper.h" - -static void user_read_fn(png_structp png_ptr, - png_bytep data, png_size_t length) -{ - bool attach; - PatchHeadInputStream* patch_head_input_stream = png_get_io_ptr(png_ptr); - JNIEnv *env = obtain_env(&attach); - - if (env == NULL) { - LOGE(MSG("Can't get JNIEnv")); - } - - read_patch_head_input_stream(env, patch_head_input_stream, data, 0, length); - - if (attach) { - release_env(); - } -} - -static void user_error_fn(png_structp png_ptr, - png_const_charp error_msg) -{ - LOGE(MSG("%s"), error_msg); -} - -static void user_warn_fn(png_structp png_ptr, - png_const_charp error_msg) -{ - LOGW(MSG("%s"), error_msg); -} - -static void free_frame_info_array(PNG_FRAME_INFO* frame_info_array, unsigned int count) -{ - int i; - - if (frame_info_array == NULL) { - return; - } - - for (i = 0; i < count; i++) { - PNG_FRAME_INFO* frame_info = frame_info_array + i; - free(frame_info->buffer); - frame_info->buffer = NULL; - } - free(frame_info_array); -} - -static bool read_image(png_structp png_ptr, unsigned char* buffer, unsigned int width, unsigned int height) -{ - int i; - unsigned char** line_buffer_ptr_array = (unsigned char**) malloc(height * sizeof(unsigned char*)); - if (line_buffer_ptr_array == NULL) { - WTF_OM; - return false; - } - for (i = 0; i < height; i++) { - line_buffer_ptr_array[i] = buffer + (width * i * 4); - } - png_read_image(png_ptr, line_buffer_ptr_array); - free(line_buffer_ptr_array); - return true; -} - -static void read_frame(png_structp png_ptr, png_infop info_ptr, PNG_FRAME_INFO* frame_info) -{ - unsigned int width; - unsigned int height; - unsigned int offset_x; - unsigned int offset_y; - unsigned short delay_num; - unsigned short delay_den; - unsigned char dop; - unsigned char bop; - unsigned int delay; - unsigned char* buffer = NULL; - - png_read_frame_head(png_ptr, info_ptr); - png_get_next_frame_fcTL(png_ptr, info_ptr, &width, &height, &offset_x, &offset_y, &delay_num, &delay_den, &dop, &bop); - - delay = 1000u * delay_num / delay_den; - - frame_info->width = width; - frame_info->height = height; - frame_info->offset_x = offset_x; - frame_info->offset_y = offset_y; - frame_info->delay = delay; - frame_info->dop = dop; - frame_info->bop = bop; - frame_info->pop = IMAGE_PNG_PREPARE_UNKNOWN; - - buffer = (unsigned char*) malloc(width * height * 4); - if (buffer == NULL) { - frame_info->buffer = NULL; - return; - } - - read_image(png_ptr, buffer, width, height); - frame_info->buffer = buffer; -} - -static void generate_pop(PNG_FRAME_INFO* frame_info_array, int count) -{ - unsigned char dop = 0xff; - int i; - - for (i = 0; i < count; i++){ - PNG_FRAME_INFO* frame_info = frame_info_array + i; - - switch (dop) { - case PNG_DISPOSE_OP_NONE: - frame_info->pop = IMAGE_PNG_PREPARE_NONE; - break; - case PNG_DISPOSE_OP_BACKGROUND: - frame_info->pop = IMAGE_PNG_PREPARE_BACKGROUND; - break; - case PNG_DISPOSE_OP_PREVIOUS: - frame_info->pop = IMAGE_PNG_PREPARE_USE_BACKUP; - break; - default: - frame_info->pop = IMAGE_PNG_PREPARE_BACKGROUND; - break; - } - - dop = frame_info->dop; - } -} - -void* PNG_decode(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream, bool partially) -{ - PNG *png = NULL; - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; - bool apng; - unsigned int width; - unsigned int height; - int color_type; - int bit_depth; - bool is_opaque; - unsigned char* buffer = NULL; - unsigned int frame_count = 0; - bool hide_first_frame = false; - PNG_FRAME_INFO* frame_info_array = NULL; - int i; - - png = (PNG *) malloc(sizeof(PNG)); - if (png == NULL) { - WTF_OM; - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - return NULL; - } - - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, &user_error_fn, &user_warn_fn); - if (png_ptr == NULL) { - free(png); - png = NULL; - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - return NULL; - } - - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == NULL) { - png_destroy_read_struct(&png_ptr, NULL, NULL); - free(png); - png = NULL; - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - return NULL; - } - - if (setjmp(png_jmpbuf(png_ptr))) { - LOGE(MSG("Error in png decode")); - free_frame_info_array(frame_info_array, frame_count); - frame_info_array = NULL; - free(buffer); - buffer = NULL; - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - free(png); - png = NULL; - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - return NULL; - } - - // Set custom read function - png_set_read_fn(png_ptr, patch_head_input_stream, &user_read_fn); - - // Get png info - png_read_info(png_ptr, info_ptr); - - // Check apng - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL)) { - apng = true; - } else { - apng = false; - } - - // PNG info - width = png_get_image_width(png_ptr, info_ptr); - height = png_get_image_height(png_ptr, info_ptr); - color_type = png_get_color_type(png_ptr, info_ptr); - bit_depth = png_get_bit_depth(png_ptr, info_ptr); - - // Create buffer - buffer = (unsigned char*) malloc(width * height * 4); - if (buffer == NULL) { - WTF_OM; - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - free(png); - png = NULL; - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - return NULL; - } - - if (apng) { - // Get frame count - frame_count = png_get_num_frames(png_ptr, info_ptr); - hide_first_frame = png_get_first_frame_is_hidden(png_ptr, info_ptr); - if (hide_first_frame) { - frame_count--; - } - - // Create frame info array - frame_info_array = (PNG_FRAME_INFO*) calloc(frame_count, sizeof(PNG_FRAME_INFO)); - if (frame_info_array == NULL) { - WTF_OM; - free(buffer); - buffer = NULL; - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - free(png); - png = NULL; - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - return NULL; - } - } - - // Configure to ARGB - png_set_expand(png_ptr); - if (bit_depth == 16) { - png_set_scale_16(png_ptr); - } - if (color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { - png_set_gray_to_rgb(png_ptr); - } - if (!(color_type & PNG_COLOR_MASK_ALPHA)) { - is_opaque = true; - png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER); - } else { - is_opaque = false; - } - - if (apng) { - if (hide_first_frame) { - // Skip first frame - read_image(png_ptr, buffer, width, height); - } - - // Read first frame - read_frame(png_ptr, info_ptr, frame_info_array); - // Fix dop - if (frame_info_array->dop == PNG_DISPOSE_OP_PREVIOUS) { - frame_info_array->dop = PNG_DISPOSE_OP_BACKGROUND; - } - - if (!partially || frame_count == 1) { - // Read all frame - for (i = 1; i < frame_count; read_frame(png_ptr, info_ptr, frame_info_array + i++)); - - // Generate pop - generate_pop(frame_info_array, frame_count); - - // End read - png_read_end(png_ptr, info_ptr); - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - - // Close input stream - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - - png->partially = false; - png->png_ptr = NULL; - png->info_ptr = NULL; - png->patch_head_input_stream = NULL; - } else { - png->partially = true; - png->png_ptr = png_ptr; - png->info_ptr = info_ptr; - png->patch_head_input_stream = patch_head_input_stream; - } - - // Fill PNG - png->width = width; - png->height = height; - png->is_opaque = is_opaque; - png->buffer = buffer; - png->apng = true; - png->buffer_index = -1; - png->frame_info_array = frame_info_array; - png->frame_count = frame_count; - png->backup = NULL; - - // Render first frame - PNG_advance(png); - } else { - read_image(png_ptr, buffer, width, height); - - // End read - png_read_end(png_ptr, info_ptr); - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - - // Close input stream - close_patch_head_input_stream(env, patch_head_input_stream); - destroy_patch_head_input_stream(env, &patch_head_input_stream); - - // Fill PNG - png->width = width; - png->height = height; - png->buffer = buffer; - png->apng = false; - png->buffer_index = 0; - png->frame_info_array = NULL; - png->frame_count = 0; - png->backup = NULL; - png->partially = false; - png->png_ptr = NULL; - png->info_ptr = NULL; - png->patch_head_input_stream = NULL; - } - - return png; -} - -bool PNG_complete(JNIEnv *env, PNG* png) -{ - int i; - - if (!png->partially) { - return true; - } - - if (png->png_ptr == NULL || png->info_ptr == NULL || png->patch_head_input_stream == NULL) { - LOGE(MSG("Some stuff is NULL")); - return false; - } - - // Read left frames - for (i = 1; i < png->frame_count; read_frame(png->png_ptr, png->info_ptr, png->frame_info_array + i++)); - - // Generate pop - generate_pop(png->frame_info_array, png->frame_count); - - // End read - png_read_end(png->png_ptr, png->info_ptr); - png_destroy_read_struct(&png->png_ptr, &png->info_ptr, NULL); - - // Close input stream - close_patch_head_input_stream(env, png->patch_head_input_stream); - destroy_patch_head_input_stream(env, &png->patch_head_input_stream); - - // Clean up - png->partially = false; - png->png_ptr = NULL; - png->info_ptr = NULL; - png->patch_head_input_stream = NULL; - - return true; -} - -bool PNG_is_completed(PNG* png) -{ - return !png->partially; -} - -void* PNG_get_pixels(PNG* png) -{ - if (!png->partially && PNG_get_frame_count(png) == 1) { - return png->buffer; - } else { - return NULL; - } -} - -int PNG_get_width(PNG* png) -{ - return png->width; -} - -int PNG_get_height(PNG* png) -{ - return png->height; -} - -int PNG_get_byte_count(PNG* png) -{ - int i; - PNG_FRAME_INFO* frame_info; - int size = 0; - // Add buffer size - if (png->buffer != NULL) { - size += png->width * png->height * 4; - } - // Add backup size - if (png->backup != NULL) { - size += png->width * png->height * 4; - } - // Add frames size - if (png->frame_info_array != NULL) { - for (i = 0; i < png->frame_count; i++) { - frame_info = png->frame_info_array + i; - // Add frame buffer size - if (frame_info->buffer != NULL) { - size += frame_info->width * frame_info->height * 4; - } - } - } - return size; -} - -void PNG_render(PNG* png, int src_x, int src_y, - void* dst, int dst_w, int dst_h, int dst_x, int dst_y, - int width, int height, bool fill_blank, int default_color) -{ - copy_pixels(png->buffer, png->width, png->height, src_x, src_y, - dst, dst_w, dst_h, dst_x, dst_y, - width, height, fill_blank, default_color); -} - -static void backup(PNG* png) -{ - if (png->backup == NULL) { - png->backup = (unsigned char*) malloc(png->width * png->height * 4); - if (png->backup == NULL) { - WTF_OM; - return; - } - } - memcpy(png->backup, png->buffer, png->width * png->height * 4); -} - -static void restore(PNG* png) -{ - if (png->backup == NULL) { - LOGE(MSG("Backup is NULL")); - } else { - memcpy(png->buffer, png->backup, png->width * png->height * 4); - } -} - -static void switch_buffer_backup(PNG* png) -{ - unsigned char* temp; - - if (png->backup == NULL) { - backup(png); - } else { - temp = png->buffer; - png->buffer = png->backup; - png->backup = temp; - } -} - -static void blend_over(unsigned char* dp, const unsigned char* sp, size_t len) -{ - unsigned int i; - int u, v, al; - - for (i = 0; i < len; i += 4, sp += 4, dp += 4) { - if (sp[3] == 255) { - memcpy(dp, sp, 4); - } else if (sp[3] != 0) { - if (dp[3] != 0) { - u = sp[3] * 255; - v = (255 - sp[3]) * dp[3]; - al = u + v; - dp[0] = (unsigned char) ((sp[0] * u + dp[0] * v) / al); - dp[1] = (unsigned char) ((sp[1] * u + dp[1] * v) / al); - dp[2] = (unsigned char) ((sp[2] * u + dp[2] * v) / al); - dp[3] = (unsigned char) (al / 255); - } else { - memcpy(dp, sp, 4); - } - } - } -} - -static void blend(unsigned char* src, int src_width, int src_height, int offset_x, int offset_y, - unsigned char* dst, int dst_width, int dst_height, bool blend_op_over) -{ - int i; - unsigned char* src_ptr; - unsigned char* dst_ptr; - size_t len; - int copy_width = MIN(dst_width - offset_x, src_width); - int copy_height = MIN(dst_height - offset_y, src_height); - - for (i = 0; i < copy_height; i++) { - src_ptr = src + (i * src_width * 4); - dst_ptr = dst + (((offset_y + i) * dst_width + offset_x) * 4); - len = (size_t) (copy_width * 4); - - if (blend_op_over) { - blend_over(dst_ptr, src_ptr, len); - } else { - memcpy(dst_ptr, src_ptr, len); - } - } -} - -void PNG_advance(PNG* png) -{ - int index; - - if (!png->apng) { - LOGW(MSG("It is not apng, no need to advance")); - return; - } - - index = (png->buffer_index + 1) % png->frame_count; - if (index != 0 && png->partially) { - LOGE(MSG("The png is only decoded partially. Only the first frame can be shown.")); - return; - } - - PNG_FRAME_INFO* frame_info = png->frame_info_array + index; - - if (frame_info->dop == PNG_DISPOSE_OP_PREVIOUS && frame_info->pop == IMAGE_PNG_PREPARE_USE_BACKUP) { - switch_buffer_backup(png); - } else { - // Backup - if (frame_info->dop == PNG_DISPOSE_OP_PREVIOUS) { - backup(png); - } - - // Prepare - switch (frame_info->pop) { - case IMAGE_PNG_PREPARE_NONE: - // Do nothing - break; - default: - case IMAGE_PNG_PREPARE_BACKGROUND: - // Set transparent - memset(png->buffer, '\0', png->width * png->height * 4); - break; - case IMAGE_PNG_PREPARE_USE_BACKUP: - restore(png); - break; - } - } - - blend(frame_info->buffer, frame_info->width, frame_info->height, frame_info->offset_x, frame_info->offset_y, - png->buffer, png->width, png->height, frame_info->bop == PNG_BLEND_OP_OVER); - - png->buffer_index = index; -} - -int PNG_get_delay(PNG* png) -{ - if (png->apng) { - return png->frame_info_array[png->buffer_index].delay; - } else { - return 0; - } -} - -int PNG_get_frame_count(PNG* png) -{ - if (png->apng) { - return png->frame_count; - } else { - return 1; - } -} - -bool PNG_is_opaque(PNG* png) -{ - return png->is_opaque; -} - -void PNG_recycle(JNIEnv *env, PNG* png) -{ - if (png == NULL) { - return; - } - - free(png->buffer); - png->buffer = NULL; - - free_frame_info_array(png->frame_info_array, png->frame_count); - png->frame_info_array = NULL; - - free(png->backup); - png->backup = NULL; - - if (png->png_ptr != NULL && png->info_ptr != NULL) { - png_destroy_read_struct(&png->png_ptr, &png->info_ptr, NULL); - } - png->png_ptr = NULL; - png->info_ptr = NULL; - - if (png->patch_head_input_stream != NULL) { - close_patch_head_input_stream(env, png->patch_head_input_stream); - destroy_patch_head_input_stream(env, &png->patch_head_input_stream); - png->patch_head_input_stream = NULL; - } -} - -#endif // IMAGE_SUPPORT_PNG diff --git a/native/src/main/jni/image/image/image_png.h b/native/src/main/jni/image/image/image_png.h deleted file mode 100644 index 02642c230..000000000 --- a/native/src/main/jni/image/image/image_png.h +++ /dev/null @@ -1,89 +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. - */ - -// -// Created by Hippo on 12/27/2015. -// - -#ifndef IMAGE_IMAGE_PNG_H -#define IMAGE_IMAGE_PNG_H - -#include "config.h" -#ifdef IMAGE_SUPPORT_PNG - -#include - -#include "png.h" -#include "patch_head_input_stream.h" - -#define IMAGE_PNG_DECODER_DESCRIPTION ("libpng " PNG_LIBPNG_VER_STRING) - -#define IMAGE_PNG_MAGIC_NUMBER_0 0x89 -#define IMAGE_PNG_MAGIC_NUMBER_1 0x50 - -#define IMAGE_PNG_PREPARE_UNKNOWN 0x00 -#define IMAGE_PNG_PREPARE_NONE 0x01 -#define IMAGE_PNG_PREPARE_BACKGROUND 0x02 -#define IMAGE_PNG_PREPARE_USE_BACKUP 0x03 - -typedef struct { - unsigned char* buffer; - unsigned int width; - unsigned int height; - unsigned int offset_x; - unsigned int offset_y; - unsigned int delay; // ms - unsigned char dop; - unsigned char bop; - unsigned char pop; -} PNG_FRAME_INFO; - -typedef struct -{ - unsigned int width; - unsigned int height; - bool is_opaque; - unsigned char* buffer; - bool apng; - int buffer_index; - PNG_FRAME_INFO* frame_info_array; - unsigned int frame_count; - unsigned char* backup; - bool partially; - png_structp png_ptr; - png_infop info_ptr; - PatchHeadInputStream* patch_head_input_stream; -} PNG; - -void* PNG_decode(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream, bool partially); -bool PNG_complete(JNIEnv* env, PNG* png); -bool PNG_is_completed(PNG* png); -void* PNG_get_pixels(PNG* png); -int PNG_get_width(PNG* png); -int PNG_get_height(PNG* png); -int PNG_get_byte_count(PNG* png); -void PNG_render(PNG* png, int src_x, int src_y, - void* dst, int dst_w, int dst_h, int dst_x, int dst_y, - int width, int height, bool fill_blank, int default_color); -void PNG_advance(PNG* png); -int PNG_get_delay(PNG* png); -int PNG_get_frame_count(PNG* png); -bool PNG_is_opaque(PNG* png); -void PNG_recycle(JNIEnv* env, PNG* png); - -#endif // IMAGE_SUPPORT_PNG - -#endif // IMAGE_IMAGE_PNG_H diff --git a/native/src/main/jni/main.c b/native/src/main/jni/main.c index 3b45993e6..ab5a342bf 100644 --- a/native/src/main/jni/main.c +++ b/native/src/main/jni/main.c @@ -21,7 +21,6 @@ #include #include #include -#include "image/libjpeg-turbo/jconfigint.h" #include #include "java_wrapper.h" @@ -50,11 +49,6 @@ Java_com_hippo_Native_getliblzmaVersion(JNIEnv *env, jclass clazz) { return (*env)->NewStringUTF(env, lzma_version_string()); } -JNIEXPORT jstring JNICALL -Java_com_hippo_Native_getlibjpeg_1turboVersion(JNIEnv *env, jclass clazz) { - return (*env)->NewStringUTF(env, VERSION); -} - JNIEXPORT jstring JNICALL Java_com_hippo_Native_getzlibVersion(JNIEnv *env, jclass clazz) { return (*env)->NewStringUTF(env, ZLIB_VERSION);