Replace BMP encoder from libbmp to GraphicsMagick 13/228413/14
authorjiyong.min <jiyong.min@samsung.com>
Mon, 23 Mar 2020 02:40:13 +0000 (11:40 +0900)
committerjiyong.min <jiyong.min@samsung.com>
Wed, 25 Mar 2020 04:30:26 +0000 (13:30 +0900)
  - There are two open sources that have same BMP encoder, Libbmp and
    GraphicsMagick. Libbmp is only used for encoding BMP of libmm-utility.
    The libbmp can be removed from build after replacing it.

  - Libbmp dependency
    https://github.sec.samsung.net/pages/oslim/dash/dependency_checker/tizen60_common/libbmp.svg

Change-Id: Idd38cb29d47b27be7b27be5b388319af1561c690

bmp/CMakeLists.txt
bmp/mm_util_bmp.c
magick/include/mm_util_magick.h
magick/mm_util_magick.c
packaging/libmm-utility.spec

index db25504..4cd9ce8 100644 (file)
@@ -16,7 +16,7 @@ INCLUDE_DIRECTORIES(${INC_DIR}
        ../magick/include
        )
 
-SET(dependents "dlog glib-2.0 libbmp")
+SET(dependents "dlog glib-2.0")
 
 INCLUDE(FindPkgConfig)
 pkg_check_modules(${fw_name} REQUIRED ${dependents})
index 7a35fbf..70175e3 100644 (file)
  */
 
 #include <stdlib.h>
-#include <bmpfile.h>
-#include <mm_util_magick.h>
 
 #include "mm_util_bmp.h"
-#include "mm_util_private.h"
+#include "mm_util_magick.h"
 
-#define BYTES_PER_PIXEL 4
-
-/* encodes color image to bmp image */
-static int __write_bmp(mm_util_image_h decoded, const char *file_path, void **buffer, size_t *src_size)
-{
-       mm_image_info_s *_decoded = (mm_image_info_s *)decoded;
-       bmpfile_t *bmp;
-       rgb_pixel_t pixel = { 0, 0, 0, 0 };
-       uint16_t row, col;
-       uint8_t *image;
-
-       mm_util_retvm_if(!decoded, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image src");
-       mm_util_retvm_if(!MMUTIL_STRING_VALID(file_path) && (!buffer || !src_size), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid parameter");
-       mm_util_retvm_if(_decoded->color != MM_UTIL_COLOR_RGBA, MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported color [%d]", _decoded->color);
-
-       mm_util_fenter();
-
-       /* header of bmp image is create at 'bmp' */
-       if ((bmp = bmp_create(_decoded->width, _decoded->height, BYTES_PER_PIXEL * 8)) == NULL) {
-               mm_util_error("Invalid depth value.");
-               return MM_UTIL_ERROR_INVALID_OPERATION;
-       }
-
-       /* pixcels of bmp image is stored at 'bmp' */
-       image = (uint8_t *) _decoded->data;
-       for (row = 0; row != _decoded->height; row++) {
-               for (col = 0; col != _decoded->width; col++) {
-                       size_t z = (row * _decoded->width + col) * BYTES_PER_PIXEL;
-                       pixel.red = image[z];
-                       pixel.green = image[z + 1];
-                       pixel.blue = image[z + 2];
-                       bmp_set_pixel(bmp, col, row, pixel);
-               }
-       }
-
-       /* write 'bmp' to file or buffer */
-       if (MMUTIL_STRING_VALID(file_path)) {
-               mm_util_sec_debug("Save to file [%s]", file_path);
-               if (!bmp_save(bmp, file_path)) {
-                       mm_util_error("Saving bmp was failed.");
-                       bmp_destroy(bmp);
-                       return MM_UTIL_ERROR_INVALID_OPERATION;
-               }
-       } else {
-               mm_util_sec_debug("Save to buffer");
-               if (!bmp_save2(bmp, buffer, src_size)) {
-                       mm_util_error("Saving bmp was failed.");
-                       bmp_destroy(bmp);
-                       MMUTIL_SAFE_FREE(*buffer);
-                       *src_size = 0;
-                       return MM_UTIL_ERROR_INVALID_OPERATION;
-               }
-       }
-
-       bmp_destroy(bmp);
-
-       mm_util_fleave();
-
-       return MM_UTIL_ERROR_NONE;
-}
 
 int mm_util_decode_from_bmp_file(const char *file_path, mm_util_image_h *decoded)
 {
@@ -99,15 +37,10 @@ int mm_util_decode_from_bmp_memory(void *memory, const size_t src_size, mm_util_
 
 int mm_util_encode_bmp_to_file(mm_util_image_h decoded, const char *file_path)
 {
-       mm_util_retvm_if(!MMUTIL_STRING_VALID(file_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid file_path");
-
-       return __write_bmp(decoded, file_path, NULL, NULL);
+       return mm_util_encode_image_to_file(decoded, file_path);
 }
 
 int mm_util_encode_bmp_to_memory(mm_util_image_h decoded, void **buffer, size_t *size)
 {
-       mm_util_retvm_if(!buffer, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid buffer");
-       mm_util_retvm_if(!size, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid size");
-
-       return __write_bmp(decoded, NULL, buffer, size);
+       return mm_util_encode_image_to_buffer(decoded, IMG_CODEC_BMP, buffer, size);
 }
index a956608..7f0da4b 100644 (file)
@@ -67,6 +67,8 @@ int mm_util_extract_image_info(const char *path, mm_util_img_codec_type *type, u
 
 int mm_util_decode_image_from_file(const char *path, mm_util_color_format_e format, mm_util_image_h *decoded_image);
 int mm_util_decode_image_from_buffer(const void *buf, size_t buf_size, mm_util_color_format_e format, mm_util_image_h *decoded_image);
+int mm_util_encode_image_to_file(mm_util_image_h decoded_image, const char *path);
+int mm_util_encode_image_to_buffer(mm_util_image_h decoded_image, mm_util_img_codec_type type, void **buf, size_t *buf_size);
 
 #ifdef __cplusplus
 }
index 9c07898..b16ca36 100644 (file)
  */
 
 #include <stdbool.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <unistd.h>
+
 #include <magick/api.h>
+
 #include "mm_util_private.h"
 #include "mm_util_magick.h"
 
@@ -380,6 +385,102 @@ static bool __mm_util_check_angle(mm_util_magick_rotate_type angle)
                return FALSE;
 }
 
+static int __mm_util_make_tmp_file(mm_util_img_codec_type type, char **path)
+{
+       int fd = 0;
+       const char *template = NULL;
+       GError *error = NULL;
+
+       /* GraphicsMagick determine image codec from filename suffix */
+       switch(type) {
+       case IMG_CODEC_GIF:
+               template = "XXXXXX.gif";
+               break;
+       case IMG_CODEC_PNG:
+               template = "XXXXXX.png";
+               break;
+       case IMG_CODEC_JPEG:
+               template = "XXXXXX.jpg";
+               break;
+       case IMG_CODEC_BMP:
+               template = "XXXXXX.bmp";
+               break;
+       default:
+               mm_util_error("invalid type [%u]", type);
+               return MM_UTIL_ERROR_INVALID_PARAMETER;
+       }
+
+       fd = g_file_open_tmp(template, path, &error);
+       if (fd < 0) {
+               mm_util_sec_debug("g_file_open_tmp error [%s]", error->message);
+               g_free(error);
+               return MM_UTIL_ERROR_INVALID_OPERATION;
+       }
+
+       mm_util_sec_debug("g_file_open_tmp [%s]", *path);
+
+       close(fd);
+
+       return MM_UTIL_ERROR_NONE;
+}
+
+static int __mm_util_read_tmp_file(const char *path, void **data, size_t *length)
+{
+       int ret = MM_UTIL_ERROR_NONE;
+       FILE *fp = NULL;
+       char *_data = NULL;
+       long _length = 0;
+
+       mm_util_retvm_if(!path, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid path");
+       mm_util_retvm_if(!data, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid data");
+       mm_util_retvm_if(!length, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid length");
+
+       mm_util_sec_debug("read path [%s]", path);
+
+       fp = fopen(path, "r");
+       if (!fp) {
+               mm_util_stderror("fopen failed");
+               return MM_UTIL_ERROR_INVALID_OPERATION;
+       }
+
+       if (fseek(fp, 0, SEEK_END) < 0) {
+               mm_util_stderror("fseek failed");
+               ret = MM_UTIL_ERROR_INVALID_OPERATION;
+               goto ERROR;
+       }
+
+       _length = ftell(fp);
+       if (_length < 0) {
+               mm_util_stderror("ftell failed");
+               ret = MM_UTIL_ERROR_INVALID_OPERATION;
+               goto ERROR;
+       }
+
+       rewind(fp);
+       _data = (void *)calloc(1, _length);
+       if (!_data) {
+               mm_util_stderror("calloc failed");
+               ret = MM_UTIL_ERROR_OUT_OF_MEMORY;
+               goto ERROR;
+       }
+
+       if (fread(_data, 1, _length, fp) != _length) {
+               mm_util_stderror("fread failed");
+               ret = MM_UTIL_ERROR_INVALID_OPERATION;
+               MMUTIL_SAFE_FREE(_data);
+               goto ERROR;
+       }
+
+       *data = _data;
+       *length = (size_t)_length;
+
+ERROR:
+
+       fclose(fp);
+
+       return ret;
+}
+
 int mm_util_rotate_B_B(mm_util_image_h src_handle, mm_util_magick_rotate_type angle, mm_util_image_h *dst_handle)
 {
        int ret = MM_UTIL_ERROR_NONE;
@@ -859,7 +960,7 @@ int mm_util_convert_B_B(mm_util_image_h src_handle, mm_util_color_format_e req_f
                goto ERROR;
        }
 
-       ret = mm_image_create_image(_image->columns, _image->rows, _src_handle->color, pixels, pixels_size, dst_handle);
+       ret = mm_image_create_image(_image->columns, _image->rows, req_format, pixels, pixels_size, dst_handle);
        if (ret != MM_UTIL_ERROR_NONE)
                mm_util_error("Error: mm_image_create_image failed.");
 
@@ -972,3 +1073,104 @@ ERROR:
 
        return ret;
 }
+
+int mm_util_encode_image_to_file(mm_util_image_h decoded_image, const char *path)
+{
+       int ret = MM_UTIL_ERROR_NONE;
+       char *extension = NULL;
+       char *map = NULL;
+       Image *_image = NULL;
+       mm_image_info_s *convert_image = NULL;
+       mm_util_color_format_e format;
+
+       mm_util_retvm_if(!decoded_image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid decoded_image");
+       mm_util_retvm_if(!MMUTIL_STRING_VALID(path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid path");
+
+       mm_util_sec_debug("path [%s]", path);
+
+       extension = g_strrstr(path, ".");
+       mm_util_retvm_if(!MMUTIL_STRING_VALID(extension), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid path");
+
+       if (g_ascii_strcasecmp(extension, ".bmp") == 0) {
+               /*
+                 GraphicsMagick doesn't support alpha overlay(compression method:BI_ALPHABITFIELDS) for bmp.
+                 Officialy BMP format supports alpha overlay since BMP4(version 4), but GraphicsMagick
+                 support BMP, BMP2(v2) and BMP3(v3) except BMP4.
+                 So decoded_image should be converted to RGB888(RGB24) which has not alpha overlay.
+                 ps. BMP4 image does not guarantee backward compatibility. BMP4 is not visible on old devices.
+                 For the reasons, BMP4 is used in certain cases of windows OS, not widely used in general cases.
+               */
+
+               if (((mm_image_info_s *)decoded_image)->color == MM_UTIL_COLOR_RGBA) {
+                       ret = mm_util_convert_B_B(decoded_image, MM_UTIL_COLOR_RGB24, (mm_util_image_h *)&convert_image);
+                       if (ret != MM_UTIL_ERROR_NONE) {
+                               mm_util_error("Error: mm_util_convert_B_B failed.");
+                               goto ERROR;
+                       }
+               }
+       }
+
+       format = (convert_image) ? (convert_image->color) : (((mm_image_info_s *)decoded_image)->color);
+       ret = __mm_util_get_map(format, &map);
+       if (ret != MM_UTIL_ERROR_NONE) {
+               mm_util_error("fail to get map");
+               goto ERROR;
+       }
+
+       __mm_util_init(NULL);
+
+       _image = __mm_util_constitute_image((convert_image ? convert_image : decoded_image), map);
+       if (_image == NULL) {
+               mm_util_error("Error: __mm_util_constitute_image failed.");
+               ret = MM_UTIL_ERROR_INVALID_OPERATION;
+               goto ERROR;
+       }
+
+       ret = __mm_util_write_image_to_file(_image, path);
+
+ERROR:
+
+       __mm_util_finalize(_image, NULL, NULL);
+
+       MMUTIL_SAFE_FREE(map);
+       mm_image_destroy_image((mm_util_image_h)convert_image);
+
+       mm_util_fleave();
+
+       return ret;
+}
+
+int mm_util_encode_image_to_buffer(mm_util_image_h decoded_image, mm_util_img_codec_type type, void **buf, size_t *buf_size)
+{
+       int ret = MM_UTIL_ERROR_NONE;
+       char *tmp_file = NULL;
+
+       mm_util_retvm_if(!decoded_image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid decoded_image");
+       mm_util_retvm_if(!buf, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid buf");
+       mm_util_retvm_if(buf_size == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid buf_size");
+
+       mm_util_sec_debug("type [%d]", type);
+
+       ret = __mm_util_make_tmp_file(type, &tmp_file);
+       mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "Error: __mm_util_make_tmp_file failed.");
+
+       ret = mm_util_encode_image_to_file(decoded_image, tmp_file);
+       if (ret != MM_UTIL_ERROR_NONE) {
+               mm_util_error("Error: mm_util_encode_image_P failed.");
+               goto ERROR;
+       }
+
+       ret = __mm_util_read_tmp_file(tmp_file, buf, buf_size);
+       if (ret != MM_UTIL_ERROR_NONE)
+               mm_util_error("Error: __mm_util_read_tmp_file failed.");
+
+ERROR:
+
+       if (g_remove(tmp_file) != 0)
+               mm_util_sec_debug("Temporary file was not removed [%s]", tmp_file);
+       MMUTIL_SAFE_FREE(tmp_file);
+
+       mm_util_fleave();
+
+       return ret;
+}
index 25a7757..3a6bc41 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-utility
 Summary:    Multimedia Framework Utility Library
-Version:    0.1.38
+Version:    0.1.39
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
@@ -20,7 +20,6 @@ BuildRequires:  pkgconfig(libtzplatform-config)
 BuildRequires:  pkgconfig(opencv) >= 3.4.1
 BuildRequires:  pkgconfig(libpng)
 BuildRequires:  giflib-devel
-BuildRequires:  pkgconfig(libbmp)
 BuildRequires:  pkgconfig(GraphicsMagick)
 %if 0%{?gtests:1}
 BuildRequires:  pkgconfig(gmock)