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-21 09:00:13 +0900 |
commit | d9988868a4c8e6b8b6763abbbae8981957c34970 (patch) | |
tree | 7bcfc5a69544d61780b5d3a3b4d242613d4ce3c6 | |
parent | 6678129c4289346a4eeebb5d4d96d1b34fc3f196 (diff) | |
download | libmedia-thumbnail-accepted/tizen_7.0_unified.tar.gz libmedia-thumbnail-accepted/tizen_7.0_unified.tar.bz2 libmedia-thumbnail-accepted/tizen_7.0_unified.zip |
Add memory usage reduction for creating image thumbnailaccepted/tizen/7.0/unified/20230303.030103accepted/tizen/7.0/unified/20230302.145956tizen_7.0accepted/tizen_7.0_unified
- 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
Add image size limitation for specific device
- This patch is for specific device, do not use it on other devices.
If necessary in the future, we will provide a hal-config that can be used on the others.
Change-Id: I6ee8f6fb8f03874d7c9cb31bd2b09e56af8a3a8f
Separate functions for 'USE_MEMORY_USAGE_REDUCTION'
Change-Id: I3967b917078d2cefb277a1627729005856a16ae7
Add to convert RGBA to BGRA for raw data
- In case of raw data, if it is an image,
thumbnail should be returned as BGRA colorspace.
https://docs.tizen.org/application/native/guides/multimedia/thumbnail-images/
Change-Id: I11065190336962db66f228d6d93279dd180e2e6e
-rw-r--r-- | CMakeLists.txt | 10 | ||||
-rw-r--r-- | packaging/libmedia-thumbnail.spec | 12 | ||||
-rwxr-xr-x | src/media-thumbnail.c | 211 |
3 files changed, 217 insertions, 16 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index c74eb53..41534a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,8 +26,13 @@ MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +IF(WITH_DA_PROFILE) +INCLUDE(FindPkgConfig) + pkg_check_modules(pkgs REQUIRED glib-2.0 dlog mm-fileinfo aul libmedia-utils libtzplatform-config mmutil-common mmutil-magick mmutil-gif mmutil-jpeg libexif) +ELSE(WITH_DA_PROFILE) INCLUDE(FindPkgConfig) pkg_check_modules(pkgs REQUIRED glib-2.0 dlog 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}") @@ -50,6 +55,11 @@ ADD_DEFINITIONS("-DPACKAGE_NAME=\"${PKGNAME}\"") ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"") ADD_DEFINITIONS("-D_GNU_SOURCE") +IF(WITH_DA_PROFILE) + ADD_DEFINITIONS("-DUSE_MEMORY_USAGE_REDUCTION") + ADD_DEFINITIONS("-DENABLE_IMAGE_SIZE_LIMITATION") +ENDIF(WITH_DA_PROFILE) + SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--hash-style=both") CONFIGURE_FILE(media-thumbnail.pc.in media-thumbnail.pc @ONLY) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/media-thumbnail.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) diff --git a/packaging/libmedia-thumbnail.spec b/packaging/libmedia-thumbnail.spec index c5fb01f..ec50ef8 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.4.3 +Version: 0.4.4 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 @@ -17,7 +17,12 @@ BuildRequires: pkgconfig(libtzplatform-config) 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 @@ -38,7 +43,8 @@ cp %{SOURCE1001} %{SOURCE1002} . %build -%cmake . -DBUILD_GTESTS=%{?gtests:1}%{!?gtests:0} +%cmake . -DBUILD_GTESTS=%{?gtests:1}%{!?gtests:0} \ + -DWITH_DA_PROFILE=%{?_with_da_profile:1}%{!?_with_da_profile:0} make %{?_smp_mflags} %install diff --git a/src/media-thumbnail.c b/src/media-thumbnail.c index 6b4960e..4671f82 100755 --- a/src/media-thumbnail.c +++ b/src/media-thumbnail.c @@ -25,6 +25,12 @@ #include "media-thumbnail.h" #include "media-thumbnail-debug.h" #include <aul.h> +#if defined(USE_MEMORY_USAGE_REDUCTION) +#include <mm_util_gif.h> +#include <mm_util_jpeg.h> +#include <libexif/exif-data.h> +#endif + #define MAX_THUMB_SIZE 2000 #define MIME_TYPE_TIFF "image/tiff" @@ -368,34 +374,199 @@ int create_video_thumbnail_to_buffer(const char *path, return err; } -static int __adjust_thumb_ratio(const char *path, unsigned int *width, unsigned int *height) +static int __adjust_thumb_ratio(const char *path, unsigned int *width, unsigned int *height, + unsigned int *image_w, unsigned int *image_h, mm_util_img_codec_type *image_type) { int err = MS_MEDIA_ERR_NONE; - unsigned int image_w = 0; - unsigned int image_h = 0; - mm_util_img_codec_type image_type = 0; - - err = mm_util_extract_image_info(path, &image_type, &image_w, &image_h); +#if defined(ENABLE_IMAGE_SIZE_LIMITATION) + const size_t image_size_limit[IMG_CODEC_UNKNOWN_TYPE] = { + [IMG_CODEC_JPEG] = (4096 * 4096), + [IMG_CODEC_PNG] = (3000 * 3000), + [IMG_CODEC_GIF] = (3000 * 3000), + }; +#endif + + err = mm_util_extract_image_info(path, image_type, image_w, image_h); thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_util_extract_image_info: %d", err); - thumb_retvm_if(image_type == IMG_CODEC_UNKNOWN_TYPE, MS_MEDIA_ERR_THUMB_UNSUPPORTED, "Unsupported image codec"); + thumb_retvm_if(*image_type == IMG_CODEC_UNKNOWN_TYPE, MS_MEDIA_ERR_THUMB_UNSUPPORTED, "Unsupported image codec"); + +#if defined(ENABLE_IMAGE_SIZE_LIMITATION) + if ((*image_type == IMG_CODEC_JPEG) || + (*image_type == IMG_CODEC_PNG) || + (*image_type == IMG_CODEC_GIF)) + if ((size_t)((*image_w) * (*image_h)) > image_size_limit[*image_type]) { + thumb_err("Unsupported image size [%u x %u] limit [%zu]", *image_w, *image_h, image_size_limit[*image_type]); + return MS_MEDIA_ERR_UNSUPPORTED_CONTENT; + } +#endif + __media_thumb_get_proper_thumb_size(*image_w, *image_h, width, height); + + 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; + } - __media_thumb_get_proper_thumb_size(image_w, image_h, width, height); + 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; +} + +static int __create_gif_thumbnail_to_file(const char *path, unsigned int thumb_w, unsigned int thumb_h, const char *thumb_path) +{ + int err = MS_MEDIA_ERR_NONE; + 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; } +static int __create_gif_thumbnail_to_buffer(const char *path, unsigned int thumb_w, unsigned int thumb_h, mm_util_image_h *thumbnail) +{ + int err = MS_MEDIA_ERR_NONE; + mm_util_image_h decode_image = NULL; + mm_util_image_h rgba_thumbnail = 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, &rgba_thumbnail); + 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_convert_B_B(rgba_thumbnail, MM_UTIL_COLOR_BGRA, thumbnail); + mm_image_destroy_image(rgba_thumbnail); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "mm_util_convert_B_B failed : %d", err); + + return MS_MEDIA_ERR_NONE; +} + +static int __decode_jpeg_with_downscale(const char *path, size_t image_size, size_t thumb_size, mm_util_image_h *decode_image) +{ + mm_util_jpeg_decode_downscale downscale = MM_UTIL_JPEG_DECODE_DOWNSCALE_1_1; + + // 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); + + return mm_util_decode_from_jpeg_file(path, MM_UTIL_COLOR_BGRA, downscale, decode_image); +} + +static int __create_jpeg_thumbnail_to_file(const char *path, size_t image_size, unsigned int thumb_w, unsigned int thumb_h, const char *thumb_path, bool auto_rotate) +{ + int err = MS_MEDIA_ERR_NONE; + mm_util_image_h decode_image = NULL; + mm_util_image_h resize_image = NULL; + mm_util_rotate_type_e rotation = __get_image_orientation(path); + + err = __decode_jpeg_with_downscale(path, image_size, (size_t)(thumb_w * thumb_h), &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; +} + +static int __create_jpeg_thumbnail_to_buffer(const char *path, size_t image_size, unsigned int thumb_w, unsigned int thumb_h, mm_util_image_h *thumbnail) +{ + int err = MS_MEDIA_ERR_NONE; + mm_util_image_h decode_image = NULL; + + err = __decode_jpeg_with_downscale(path, image_size, (size_t)(thumb_w * thumb_h), &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, thumbnail); + 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; +} +#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; + unsigned int image_w = 0; + 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"); - err = __adjust_thumb_ratio(path, &thumb_w, &thumb_h); + err = __adjust_thumb_ratio(path, &thumb_w, &thumb_h, &image_w, &image_h, &image_type); thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "__adjust_thumb_ratio failed"); +#if defined(USE_MEMORY_USAGE_REDUCTION) + if (image_type == IMG_CODEC_GIF) + return __create_gif_thumbnail_to_file(path, thumb_w, thumb_h, thumb_path); + else if (image_type == IMG_CODEC_JPEG) + return __create_jpeg_thumbnail_to_file(path, (size_t)(image_w * image_h), thumb_w, thumb_h, thumb_path, auto_rotate); +#endif + if (auto_rotate) err = mm_util_resize_and_rotate_P_P(path, thumb_w, thumb_h, thumb_path); else @@ -408,18 +579,32 @@ int create_image_thumbnail_to_file(const char *path, unsigned int width, unsigne int create_image_thumbnail_to_buffer(const char *path, unsigned int width, unsigned int height, unsigned char **thumb_buffer, size_t *thumb_size, unsigned int *thumb_width, unsigned int *thumb_height) { int err = MS_MEDIA_ERR_NONE; + unsigned int image_w = 0; + unsigned int image_h = 0; 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"); - err = __adjust_thumb_ratio(path, &thumb_w, &thumb_h); + err = __adjust_thumb_ratio(path, &thumb_w, &thumb_h, &image_w, &image_h, &image_type); thumb_retvm_if(err != MS_MEDIA_ERR_NONE, err, "__adjust_thumb_ratio failed"); - 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) { + err = __create_gif_thumbnail_to_buffer(path, thumb_w, thumb_h, &img); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "__create_gif_thumbnail_to_buffer failed : %d", err); + } else if (image_type == IMG_CODEC_JPEG) { + err = __create_jpeg_thumbnail_to_buffer(path, (size_t)(image_w * image_h), thumb_w, thumb_h, &img); + thumb_retvm_if(err != MM_UTIL_ERROR_NONE, MS_MEDIA_ERR_INTERNAL, "__create_jpeg_thumbnail_to_buffer failed : %d", err); + } 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); @@ -491,4 +676,4 @@ int create_thumbnail_to_file(const char *path, unsigned int width, unsigned int } return create_video_thumbnail_to_file(path, width, height, thumb_path, false); -}
\ No newline at end of file +} |