diff options
author | jiyong.min <jiyong.min@samsung.com> | 2023-02-13 07:52:11 +0900 |
---|---|---|
committer | jiyong.min <jiyong.min@samsung.com> | 2023-02-13 15:59:56 +0900 |
commit | 53056d9ef79e1ff445a2967eefe4b2a4d6649f07 (patch) | |
tree | cb732469708daefa45a38e211c750702699ddf43 | |
parent | 0152e16389429e9d0e9b53178c20cc9442ddec5a (diff) | |
download | libmedia-thumbnail-53056d9ef79e1ff445a2967eefe4b2a4d6649f07.tar.gz libmedia-thumbnail-53056d9ef79e1ff445a2967eefe4b2a4d6649f07.tar.bz2 libmedia-thumbnail-53056d9ef79e1ff445a2967eefe4b2a4d6649f07.zip |
Add memory usage reduction for creating image thumbnail
- Please use this option for low memory limit due to memory policy.
For large-sized images, memory usage may decrease to less than 100MB,
but thumbnail quality may be slightly lowered in some cases.
- A-Gif has been changed from mmutil_magick to mmutil_gif.
- Jpeg has been added to use the downscale option.
Change-Id: Id0cff4690e4ebea10649859ee2ff678d67d850db
-rw-r--r-- | CMakeLists.txt | 8 | ||||
-rw-r--r-- | packaging/libmedia-thumbnail.spec | 9 | ||||
-rwxr-xr-x | src/media-thumbnail.c | 165 |
3 files changed, 164 insertions, 18 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d6a304..68ab48d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,8 +33,13 @@ MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/src/include ${CMAKE_SOURCE_DIR}/src/include/util ${CMAKE_SOURCE_DIR}/src/include/util ${CMAKE_SOURCE_DIR}/src/include/ipc ${CMAKE_SOURCE_DIR}/server/include ${CMAKE_SOURCE_DIR}/md5) +IF(WITH_DA_PROFILE) +INCLUDE(FindPkgConfig) + pkg_check_modules(pkgs REQUIRED glib-2.0 gthread-2.0 dlog sqlite3 mm-fileinfo aul libmedia-utils libtzplatform-config mmutil-common mmutil-gif mmutil-jpeg mmutil-magick libexif) +ELSE(WITH_DA_PROFILE) INCLUDE(FindPkgConfig) pkg_check_modules(pkgs REQUIRED glib-2.0 gthread-2.0 dlog sqlite3 mm-fileinfo aul libmedia-utils libtzplatform-config mmutil-common mmutil-magick) +ENDIF(WITH_DA_PROFILE) FOREACH(flag ${pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") @@ -57,7 +62,8 @@ ADD_DEFINITIONS("-DPACKAGE_NAME=\"${PKGNAME}\"") ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"") ADD_DEFINITIONS("-D_GNU_SOURCE") IF(WITH_DA_PROFILE) - ADD_DEFINITIONS("-DWITH_DA_PROFILE") + # Enable reduced memory solution + ADD_DEFINITIONS("-DUSE_MEMORY_USAGE_REDUCTION") ENDIF(WITH_DA_PROFILE) SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--hash-style=both") diff --git a/packaging/libmedia-thumbnail.spec b/packaging/libmedia-thumbnail.spec index 7bc4dfe..089cdd0 100644 --- a/packaging/libmedia-thumbnail.spec +++ b/packaging/libmedia-thumbnail.spec @@ -1,6 +1,6 @@ Name: libmedia-thumbnail Summary: Media thumbnail service library for multimedia applications -Version: 0.3.4 +Version: 0.3.5 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 and PD @@ -20,7 +20,12 @@ BuildRequires: pkgconfig(sqlite3) BuildRequires: pkgconfig(mmutil-common) BuildRequires: pkgconfig(mmutil-magick) %if 0%{?gtests:1} -BuildRequires: pkgconfig(gmock) +BuildRequires: pkgconfig(gmock) +%endif +%if 0%{?_with_da_profile:1} +BuildRequires: pkgconfig(mmutil-gif) +BuildRequires: pkgconfig(mmutil-jpeg) +BuildRequires: pkgconfig(libexif) %endif %description diff --git a/src/media-thumbnail.c b/src/media-thumbnail.c index b8ecdee..a99482c 100755 --- a/src/media-thumbnail.c +++ b/src/media-thumbnail.c @@ -28,11 +28,12 @@ #include "media-thumb-util.h" #include "media-thumb-internal.h" #include "media-thumb-ipc.h" - -#if defined(WITH_DA_PROFILE) -/* The maximum of resolution to be able to get thumbnail is 3000 x 2000, except for only jpeg */ -#define THUMB_MAX_ALLOWED_MEM_FOR_THUMB 6000000 +#if defined(USE_MEMORY_USAGE_REDUCTION) +#include <mm_util_gif.h> +#include <mm_util_jpeg.h> +#include <libexif/exif-data.h> #endif + #define THUMB_MAX_ALLOWED_RESOLUTION 2000 int thumbnail_request_from_db_async(unsigned int request_id, const char *origin_path, ThumbFunc func, void *user_data, uid_t uid) @@ -504,7 +505,7 @@ int create_video_thumbnail_to_buffer(const char *path, return err; } -static int __get_image_info(const char *path, unsigned int *width, unsigned int *height) +static int __get_image_info(const char *path, unsigned int *width, unsigned int *height, mm_util_img_codec_type *type) { int err = MS_MEDIA_ERR_NONE; mm_util_img_codec_type image_type = 0; @@ -519,19 +520,61 @@ static int __get_image_info(const char *path, unsigned int *width, unsigned int thumb_retvm_if(err != MS_MEDIA_ERR_NONE, MS_MEDIA_ERR_INTERNAL, "Getting image info is failed err: %d", err); thumb_retvm_if(image_type == IMG_CODEC_UNKNOWN_TYPE, MS_MEDIA_ERR_UNSUPPORTED_CONTENT, "Unsupported image codec"); -#if defined(WITH_DA_PROFILE) - if (image_w * image_h >= THUMB_MAX_ALLOWED_MEM_FOR_THUMB) { - thumb_warn("This original image is too big. w[%d] h[%d] size limit[%d]", image_w, image_h, THUMB_MAX_ALLOWED_MEM_FOR_THUMB); - return MS_MEDIA_ERR_UNSUPPORTED_CONTENT; - } -#endif + *type = image_type; *width = image_w; *height = image_h; return MS_MEDIA_ERR_NONE; } +#if defined(USE_MEMORY_USAGE_REDUCTION) +static mm_util_rotate_type_e __get_image_orientation(const char *path) +{ + ExifData *ed = NULL; + ExifEntry *entry = NULL; + short orientation = 0; + mm_util_rotate_type_e rotation = MM_UTIL_ROTATE_0; + + ed = exif_data_new_from_file(path); + thumb_retvm_if(!ed, MM_UTIL_ROTATE_0, "no exif data"); + + entry = exif_data_get_entry(ed, EXIF_TAG_ORIENTATION); + if (!entry) { + thumb_info("no orientation entry"); + exif_data_unref(ed); + return MM_UTIL_ROTATE_0; + } + + orientation = exif_get_short(entry->data, exif_data_get_byte_order(ed)); + + /* exif orientation + * 0 - not available, 1- normal, 2 - hflip, 3 - rot_180, + * 4 - vflip, 5 - tranpose, 6 - rot_90, 7 - transverse, 8 - rot_270 + */ + switch (orientation) { + case 3: + rotation = MM_UTIL_ROTATE_180; + break; + case 6: + rotation = MM_UTIL_ROTATE_90; + break; + case 8: + rotation = MM_UTIL_ROTATE_270; + break; + default: + thumb_warn("not supported orientation[%d], rotation will be 0", orientation); + rotation = MM_UTIL_ROTATE_0; + break; + }; + + exif_data_unref(ed); + thumb_info("orientation: %d, rotation: %d", orientation, rotation); + + return rotation; +} +#endif + int create_image_thumbnail_to_file(const char *path, unsigned int width, unsigned int height, const char *thumb_path, bool auto_rotate) { int err = MS_MEDIA_ERR_NONE; @@ -539,17 +582,70 @@ int create_image_thumbnail_to_file(const char *path, unsigned int width, unsigne unsigned int image_h = 0; unsigned int thumb_w = width; unsigned int thumb_h = height; + mm_util_img_codec_type image_type = 0; err = __check_parameter_validity_for_file(path, width, height, thumb_path); thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "Invalid parameter"); //Get image info - err = __get_image_info(path, &image_w, &image_h); + err = __get_image_info(path, &image_w, &image_h, &image_type); thumb_retvm_if(err != MM_UTIL_ERROR_NONE, err, "fail to __get_image_info [%d]", err); //Extract thumbnail __media_thumb_get_proper_thumb_size(image_w, image_h, &thumb_w, &thumb_h); +#if defined(USE_MEMORY_USAGE_REDUCTION) + if (image_type == IMG_CODEC_GIF) { + mm_util_image_h decode_image = NULL; + + err = mm_util_decode_from_gif_file(path, &decode_image); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_util_decode_from_gif_file failed : %d", err); + + err = mm_util_resize_B_P(decode_image, thumb_w, thumb_h, thumb_path); + mm_image_destroy_image(decode_image); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_util_resize_B_P failed : %d", err); + + return MS_MEDIA_ERR_NONE; + } else if (image_type == IMG_CODEC_JPEG) { + mm_util_image_h decode_image = NULL; + mm_util_image_h resize_image = NULL; + mm_util_jpeg_decode_downscale downscale = MM_UTIL_JPEG_DECODE_DOWNSCALE_1_1; + unsigned int thumb_size = thumb_w * thumb_h; + unsigned int image_size = image_w * image_h; + mm_util_rotate_type_e rotation = __get_image_orientation(path); + + // The downscale divide each width & height, so we should use squares 4(2*2), 16(4*4), 64(8*8). + if ((image_size >= thumb_size * 4) && (image_size < thumb_size * 16)) { + downscale = MM_UTIL_JPEG_DECODE_DOWNSCALE_1_2; + } else if ((image_size >= thumb_size * 16) && (image_size < thumb_size * 64)) { + downscale = MM_UTIL_JPEG_DECODE_DOWNSCALE_1_4; + } else if (image_size >= thumb_size * 64) { + downscale = MM_UTIL_JPEG_DECODE_DOWNSCALE_1_8; + } + + thumb_info("downscale: %d", downscale); + + err = mm_util_decode_from_jpeg_file(path, MM_UTIL_COLOR_RGB24, downscale, &decode_image); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_util_decode_from_jpeg_file failed : %d", err); + + if (auto_rotate && (rotation != MM_UTIL_ROTATE_0)) { + err = mm_util_resize_B_B(decode_image, thumb_w, thumb_h, &resize_image); + mm_image_destroy_image(decode_image); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_util_resize_B_B failed : %d", err); + + err = mm_util_rotate_B_P(resize_image, rotation, thumb_path); + mm_image_destroy_image(resize_image); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_util_rotate_B_P failed : %d", err); + } else { + err = mm_util_resize_B_P(decode_image, thumb_w, thumb_h, thumb_path); + mm_image_destroy_image(decode_image); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_util_resize_B_P failed : %d", err); + } + + return MS_MEDIA_ERR_NONE; + } +#endif + if (auto_rotate) err = mm_util_resize_and_rotate_P_P(path, thumb_w, thumb_h, thumb_path); else @@ -567,19 +663,58 @@ int create_image_thumbnail_to_buffer(const char *path, unsigned int width, unsig unsigned int thumb_w = width; unsigned int thumb_h = height; mm_util_image_h img = NULL; + mm_util_img_codec_type image_type = 0; err = __check_parameter_validity_for_buffer(path, width, height, thumb_buffer, thumb_size, thumb_width, thumb_height); thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "Invalid parameter"); //Get image info - err = __get_image_info(path, &image_w, &image_h); + err = __get_image_info(path, &image_w, &image_h, &image_type); thumb_retvm_if(err != MM_UTIL_ERROR_NONE, err, "fail to __get_image_info [%d]", err); //Extract thumbnail __media_thumb_get_proper_thumb_size(image_w, image_h, &thumb_w, &thumb_h); - err = mm_util_resize_P_B(path, thumb_w, thumb_h, MM_UTIL_COLOR_BGRA, &img); - thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_util_resize_P_B failed : %d", err); +#if defined(USE_MEMORY_USAGE_REDUCTION) + if (image_type == IMG_CODEC_GIF) { + mm_util_image_h decode_image = NULL; + + err = mm_util_decode_from_gif_file(path, &decode_image); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_util_decode_from_gif_file failed : %d", err); + + err = mm_util_resize_B_B(decode_image, thumb_w, thumb_h, &img); + mm_image_destroy_image(decode_image); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_util_resize_B_B failed : %d", err); + } else if (image_type == IMG_CODEC_JPEG) { + mm_util_image_h decode_image = NULL; + mm_util_jpeg_decode_downscale downscale = MM_UTIL_JPEG_DECODE_DOWNSCALE_1_1; + unsigned int thumb_size = thumb_w * thumb_h; + unsigned int image_size = image_w * image_h; + + // The downscale divide each width & height, so we should use squares 4(2*2), 16(4*4), 64(8*8). + if ((image_size >= thumb_size * 4) && (image_size < thumb_size * 16)) { + downscale = MM_UTIL_JPEG_DECODE_DOWNSCALE_1_2; + } else if ((image_size >= thumb_size * 16) && (image_size < thumb_size * 64)) { + downscale = MM_UTIL_JPEG_DECODE_DOWNSCALE_1_4; + } else if (image_size >= thumb_size * 64) { + downscale = MM_UTIL_JPEG_DECODE_DOWNSCALE_1_8; + } + + thumb_info("downscale: %d", downscale); + err = mm_util_decode_from_jpeg_file(path, MM_UTIL_COLOR_RGB24, downscale, &decode_image); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_util_decode_from_jpeg_file failed : %d", err); + + err = mm_util_resize_B_B(decode_image, thumb_w, thumb_h, &img); + mm_image_destroy_image(decode_image); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_util_resize_B_B failed : %d", err); + + return MS_MEDIA_ERR_NONE; + } else +#endif + { + err = mm_util_resize_P_B(path, thumb_w, thumb_h, MM_UTIL_COLOR_BGRA, &img); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_util_resize_P_B failed : %d", err); + } err = mm_image_get_image(img, thumb_width, thumb_height, NULL, thumb_buffer, thumb_size); |