Replace BMP decoder from libnsbmp to GraphicsMagick 80/227980/9
authorjiyong.min <jiyong.min@samsung.com>
Wed, 18 Mar 2020 00:53:45 +0000 (09:53 +0900)
committerjiyong.min <jiyong.min@samsung.com>
Mon, 23 Mar 2020 02:35:11 +0000 (11:35 +0900)
  - There are two open sources that have same BMP decoder, Libnsbmp and
    GraphicsMagick. Libnsbmp is only used for decoding BMP of libmm-utility.
    Libnsbmp can be removed from the build after replacing it.

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

Change-Id: I644c7ecb23724f67c1a82602aa09b71e2f8d2932

bmp/CMakeLists.txt [changed mode: 0755->0644]
bmp/mm_util_bmp.c [changed mode: 0755->0644]
magick/include/mm_util_magick.h [changed mode: 0755->0644]
magick/mm_util_magick.c
packaging/libmm-utility.spec [changed mode: 0755->0644]

old mode 100755 (executable)
new mode 100644 (file)
index abf459a..db25504
@@ -13,9 +13,10 @@ SET(INC_DIR
        )
 INCLUDE_DIRECTORIES(${INC_DIR}
        ../common/include
+       ../magick/include
        )
 
-SET(dependents "dlog glib-2.0 libbmp libnsbmp")
+SET(dependents "dlog glib-2.0 libbmp")
 
 INCLUDE(FindPkgConfig)
 pkg_check_modules(${fw_name} REQUIRED ${dependents})
@@ -38,7 +39,7 @@ SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIB_INSTALL_DIR}")
 
 aux_source_directory(. SOURCES)
 ADD_LIBRARY(${fw_name} SHARED ${SOURCES})
-TARGET_LINK_LIBRARIES(${fw_name} ${${fw_name}_LDFLAGS} mmutil_common)
+TARGET_LINK_LIBRARIES(${fw_name} ${${fw_name}_LDFLAGS} mmutil_common mmutil_magick)
 SET_TARGET_PROPERTIES(${fw_name}
        PROPERTIES
        VERSION ${VERSION}
old mode 100755 (executable)
new mode 100644 (file)
index 8288396..7a35fbf
  *
  */
 
-#include <stdio.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <glib.h>
-
-#include <libnsbmp.h>
+#include <stdlib.h>
 #include <bmpfile.h>
+#include <mm_util_magick.h>
 
 #include "mm_util_bmp.h"
 #include "mm_util_private.h"
 
 #define BYTES_PER_PIXEL 4
 
-/* for bmp_bitmap_callback_vt of nsbmp */
-void *__bitmap_create(int width, int height, unsigned int state);
-unsigned char *__bitmap_get_buffer(void *bitmap);
-size_t __bitmap_get_bpp(void *bitmap);
-void __bitmap_destroy(void *bitmap);
-
-void *__bitmap_create(int width, int height, unsigned int state)
-{
-       return calloc(width * height, BYTES_PER_PIXEL);
-}
-
-unsigned char *__bitmap_get_buffer(void *bitmap)
-{
-       return bitmap;
-}
-
-size_t __bitmap_get_bpp(void *bitmap)
-{
-       return BYTES_PER_PIXEL;
-}
-
-void __bitmap_destroy(void *bitmap)
-{
-       MMUTIL_SAFE_FREE(bitmap);
-}
-
-static gboolean __load_file(const char *path, unsigned char **data, size_t * data_size)
-{
-       FILE *fd;
-       struct stat sb;
-       void *buffer = NULL;
-       size_t size;
-       size_t n;
-
-       if (MM_UTIL_ERROR_NONE != mm_util_safe_fopen(path, "rb", &fd)) {
-               mm_util_error("mm_util_safe_fopen failed");
-               return FALSE;
-       }
-
-       if (stat(path, &sb)) {
-               mm_util_error("file stat failed");
-               mm_util_safe_fclose(fd);
-               return FALSE;
-       }
-       size = sb.st_size;
-
-       buffer = calloc(1, size);
-       if (!buffer) {
-               mm_util_error("Unable to allocate %lld bytes", (long long)size);
-               mm_util_safe_fclose(fd);
-               return FALSE;
-       }
-
-       n = fread(buffer, 1, size, fd);
-       if (n != size) {
-               mm_util_error("file read failed");
-               MMUTIL_SAFE_FREE(buffer);
-               mm_util_safe_fclose(fd);
-               return FALSE;
-       }
-
-       mm_util_safe_fclose(fd);
-       *data_size = size;
-       *data = buffer;
-
-       return TRUE;
-}
-
-static void __print_error(const char *context, bmp_result code)
-{
-       switch (code) {
-       case BMP_INSUFFICIENT_MEMORY:
-               mm_util_error("%s failed: BMP_INSUFFICIENT_MEMORY", context);
-               break;
-       case BMP_INSUFFICIENT_DATA:
-               mm_util_error("%s failed: BMP_INSUFFICIENT_DATA", context);
-               break;
-       case BMP_DATA_ERROR:
-               mm_util_error("%s failed: BMP_DATA_ERROR", context);
-               break;
-       default:
-               mm_util_error("%s failed: unknown code %i", context, code);
-               break;
-       }
-}
-
-/* decodes bmp image to color image */
-static int __read_bmp(const char *file_path, void *memory, size_t src_size, mm_util_image_h *decoded)
-{
-       bmp_bitmap_callback_vt bitmap_callbacks = {
-               __bitmap_create,
-               __bitmap_destroy,
-               __bitmap_get_buffer,
-               __bitmap_get_bpp
-       };
-       bmp_result code;
-       bmp_image bmp;
-       size_t size = 0;
-       int res = MM_UTIL_ERROR_NONE;
-       unsigned char *data = NULL;
-
-       mm_util_retvm_if(!MMUTIL_STRING_VALID(file_path) && !memory, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid bmp image");
-       mm_util_retvm_if(!decoded, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image handle");
-
-       mm_util_fenter();
-
-       if (MMUTIL_STRING_VALID(file_path)) {
-               mm_util_sec_debug("read from file [%s]", file_path);
-               if (!__load_file(file_path, &data, &size))
-                       return MM_UTIL_ERROR_INVALID_OPERATION;
-       } else {
-               mm_util_debug("read from memory");
-               data = (unsigned char *)memory;
-               size = src_size;
-       }
-
-       nsbmp_create(&bmp, &bitmap_callbacks);
-
-       code = bmp_analyse(&bmp, size, data);
-       if (code != BMP_OK) {
-               __print_error("bmp_analyse", code);
-               res = MM_UTIL_ERROR_INVALID_OPERATION;
-               goto cleanup;
-       }
-
-       code = bmp_decode(&bmp);
-
-       if ((code != BMP_OK) || (bmp.bitmap == NULL)) {
-               __print_error("bmp_decode", code);
-               /* allow partially decoded images */
-               if (code != BMP_INSUFFICIENT_DATA) {
-                       res = MM_UTIL_ERROR_INVALID_OPERATION;
-                       goto cleanup;
-               }
-       }
-
-       res = mm_image_create_image(bmp.width, bmp.height, MM_UTIL_COLOR_RGBA, bmp.bitmap, bmp.width * bmp.height * BYTES_PER_PIXEL, decoded);
-
- cleanup:
-       bmp_finalise(&bmp);
-       if (file_path)
-               MMUTIL_SAFE_FREE(data);
-
-       mm_util_fleave();
-
-       return res;
-}
-
 /* 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)
 {
@@ -216,14 +64,14 @@ static int __write_bmp(mm_util_image_h decoded, const char *file_path, void **bu
        /* 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) == false) {
+               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) == false) {
+               if (!bmp_save2(bmp, buffer, src_size)) {
                        mm_util_error("Saving bmp was failed.");
                        bmp_destroy(bmp);
                        MMUTIL_SAFE_FREE(*buffer);
@@ -241,17 +89,12 @@ static int __write_bmp(mm_util_image_h decoded, const char *file_path, void **bu
 
 int mm_util_decode_from_bmp_file(const char *file_path, mm_util_image_h *decoded)
 {
-       mm_util_retvm_if(!MMUTIL_STRING_VALID(file_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid file_path");
-
-       return __read_bmp(file_path, NULL, 0, decoded);
+       return mm_util_decode_image_from_file(file_path, MM_UTIL_COLOR_RGBA, decoded);
 }
 
 int mm_util_decode_from_bmp_memory(void *memory, const size_t src_size, mm_util_image_h *decoded)
 {
-       mm_util_retvm_if(!memory, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid bmp image");
-       mm_util_retvm_if(!src_size, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_size");
-
-       return __read_bmp(NULL, memory, src_size, decoded);
+       return mm_util_decode_image_from_buffer(memory, src_size, MM_UTIL_COLOR_RGBA, decoded);
 }
 
 int mm_util_encode_bmp_to_file(mm_util_image_h decoded, const char *file_path)
old mode 100755 (executable)
new mode 100644 (file)
index 4c54789..a956608
@@ -65,6 +65,9 @@ int mm_util_convert_B_B(mm_util_image_h src_handle, mm_util_color_format_e req_f
 
 int mm_util_extract_image_info(const char *path, mm_util_img_codec_type *type, unsigned int *width, unsigned int *height);
 
+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);
+
 #ifdef __cplusplus
 }
 #endif
index acac0cc..9c07898 100644 (file)
@@ -74,12 +74,11 @@ static void __mm_util_init(ExceptionInfo *exception)
        SetWarningHandler(__mm_util_magick_error_handler);
 }
 
-static void __mm_util_finalize(Image *image_1, Image *image_2, ImageInfo *imageInfo, ExceptionInfo *exception)
+static void __mm_util_finalize(Image *image_1, Image *image_2, ExceptionInfo *exception)
 {
 
        DestroyImage(image_1);
        DestroyImage(image_2);
-       DestroyImageInfo(imageInfo);
 
        if (exception != NULL)
                DestroyExceptionInfo(exception);
@@ -251,6 +250,44 @@ static Image * __mm_util_read_image_from_file(const char *path)
        return _image;
 }
 
+static Image * __mm_util_read_image_from_buffer(const void *buf, size_t buf_size)
+{
+       ImageInfo *_image_info = NULL;
+       Image *_image = NULL;
+       ExceptionInfo exception;
+
+       mm_util_fenter();
+
+       mm_util_retvm_if(!buf, NULL, "invalid buf");
+       mm_util_retvm_if(buf_size == 0, NULL, "invalid buf_size");
+
+       GetExceptionInfo(&exception);
+
+       _image_info = CloneImageInfo(0);
+       mm_util_retvm_if(!_image_info, NULL, "Error: CloneImageInfo failed.");
+       _image_info->blob = (void *)buf;
+       _image_info->length = buf_size;
+
+       AddDefinition(_image_info, "jpeg", "dct-method", "FASTEST", &exception);
+       AddDefinition(_image_info, "jpeg", "block-smoothing", "FALSE", &exception);
+       AddDefinition(_image_info, "jpeg", "fancy-upsampling", "FALSE", &exception);
+
+       _image = ReadImage(_image_info, &exception);
+
+       if (_image == NULL) {
+               mm_util_error("Error: Reading Image failed.");
+               if (exception.severity != UndefinedException)
+                       CatchException(&exception);
+       }
+
+       DestroyImageInfo(_image_info);
+       DestroyExceptionInfo(&exception);
+
+       mm_util_fleave();
+
+       return _image;
+}
+
 static int __mm_util_write_image_to_file(Image *image, const char *out_path)
 {
        int ret = MM_UTIL_ERROR_NONE;
@@ -361,7 +398,7 @@ int mm_util_rotate_B_B(mm_util_image_h src_handle, mm_util_magick_rotate_type an
        mm_util_debug("angle [%d]", angle);
 
        ret = __mm_util_get_map(_src_handle->color, &map);
-       mm_util_retvm_if((ret != MM_UTIL_ERROR_NONE) || (map == NULL), ret, "fail to get map");
+       mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "fail to get map");
 
        __mm_util_init(&exception);
 
@@ -394,7 +431,7 @@ int mm_util_rotate_B_B(mm_util_image_h src_handle, mm_util_magick_rotate_type an
 
 ERROR:
 
-       __mm_util_finalize(_image, _processed_image, NULL, &exception);
+       __mm_util_finalize(_image, _processed_image, &exception);
 
        MMUTIL_SAFE_FREE(map);
 
@@ -419,7 +456,7 @@ int mm_util_rotate_B_P(mm_util_image_h src_handle, mm_util_magick_rotate_type an
        mm_util_sec_debug("angle [%d] dst_path [%s]", angle, dst_path);
 
        ret = __mm_util_get_map(_src_handle->color, &map);
-       mm_util_retvm_if((ret != MM_UTIL_ERROR_NONE) || (map == NULL), ret, "fail to get map");
+       mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "fail to get map");
 
        __mm_util_init(&exception);
 
@@ -441,7 +478,7 @@ int mm_util_rotate_B_P(mm_util_image_h src_handle, mm_util_magick_rotate_type an
 
 ERROR:
 
-       __mm_util_finalize(_image, _processed_image, NULL, &exception);
+       __mm_util_finalize(_image, _processed_image, &exception);
 
        MMUTIL_SAFE_FREE(map);
 
@@ -467,7 +504,7 @@ int mm_util_rotate_P_B(const char *src_path, mm_util_magick_rotate_type angle, m
        mm_util_sec_debug("src_path [%s] angle [%d] req_format [%d]", src_path, angle, req_format);
 
        ret = __mm_util_get_map(req_format, &map);
-       mm_util_retvm_if((ret != MM_UTIL_ERROR_NONE) || (map == NULL), ret, "fail to get map");
+       mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "fail to get map");
 
        __mm_util_init(&exception);
 
@@ -500,7 +537,7 @@ int mm_util_rotate_P_B(const char *src_path, mm_util_magick_rotate_type angle, m
 
 ERROR:
 
-       __mm_util_finalize(_image, _processed_image, NULL, &exception);
+       __mm_util_finalize(_image, _processed_image, &exception);
 
        MMUTIL_SAFE_FREE(map);
 
@@ -543,7 +580,7 @@ int mm_util_rotate_P_P(const char *src_path, mm_util_magick_rotate_type angle, c
 
 ERROR:
 
-       __mm_util_finalize(_image, _processed_image, NULL, &exception);
+       __mm_util_finalize(_image, _processed_image, &exception);
 
        mm_util_fleave();
 
@@ -568,7 +605,7 @@ int mm_util_resize_B_B(mm_util_image_h src_handle, unsigned int req_width, unsig
        mm_util_debug("req_width [%u] req_height [%u]", req_width, req_height);
 
        ret = __mm_util_get_map(_src_handle->color, &map);
-       mm_util_retvm_if((ret != MM_UTIL_ERROR_NONE) || (map == NULL), ret, "fail to get map");
+       mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "fail to get map");
 
        __mm_util_init(&exception);
 
@@ -607,7 +644,7 @@ int mm_util_resize_B_B(mm_util_image_h src_handle, unsigned int req_width, unsig
 
 ERROR:
 
-       __mm_util_finalize(_image, _processed_image, NULL, &exception);
+       __mm_util_finalize(_image, _processed_image, &exception);
 
        MMUTIL_SAFE_FREE(map);
 
@@ -632,7 +669,7 @@ int mm_util_resize_B_P(mm_util_image_h src_handle, unsigned int req_width, unsig
        mm_util_sec_debug("req_width [%u] req_height [%u] dst_path [%s]", req_width, req_height, dst_path);
 
        ret = __mm_util_get_map(_src_handle->color, &map);
-       mm_util_retvm_if((ret != MM_UTIL_ERROR_NONE) || (map == NULL), ret, "fail to get map");
+       mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "fail to get map");
 
        __mm_util_init(&exception);
 
@@ -660,7 +697,7 @@ int mm_util_resize_B_P(mm_util_image_h src_handle, unsigned int req_width, unsig
 
 ERROR:
 
-       __mm_util_finalize(_image, _processed_image, NULL, &exception);
+       __mm_util_finalize(_image, _processed_image, &exception);
 
        MMUTIL_SAFE_FREE(map);
 
@@ -686,7 +723,7 @@ int mm_util_resize_P_B(const char *src_path, unsigned int req_width, unsigned in
        mm_util_sec_debug("src_path [%s] req_width [%u] req_height [%u]", src_path, req_width, req_height);
 
        ret = __mm_util_get_map(req_format, &map);
-       mm_util_retvm_if((ret != MM_UTIL_ERROR_NONE) || (map == NULL), ret, "fail to get map");
+       mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "fail to get map");
 
        __mm_util_init(&exception);
 
@@ -725,7 +762,7 @@ int mm_util_resize_P_B(const char *src_path, unsigned int req_width, unsigned in
 
 ERROR:
 
-       __mm_util_finalize(_image, _processed_image, NULL, &exception);
+       __mm_util_finalize(_image, _processed_image, &exception);
 
        MMUTIL_SAFE_FREE(map);
 
@@ -773,7 +810,7 @@ int mm_util_resize_P_P(const char *src_path, unsigned int req_width, unsigned in
 
 ERROR:
 
-       __mm_util_finalize(_image, _processed_image, NULL, &exception);
+       __mm_util_finalize(_image, _processed_image, &exception);
 
        mm_util_fleave();
 
@@ -796,7 +833,7 @@ int mm_util_convert_B_B(mm_util_image_h src_handle, mm_util_color_format_e req_f
        mm_util_debug("input format [%d] req_format [%d]", _src_handle->color, req_format);
 
        ret = __mm_util_get_map(_src_handle->color, &map);
-       mm_util_retvm_if((ret != MM_UTIL_ERROR_NONE) || (map == NULL), ret, "fail to get map");
+       mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "fail to get map");
 
        __mm_util_init(&exception);
 
@@ -830,8 +867,105 @@ int mm_util_convert_B_B(mm_util_image_h src_handle, mm_util_color_format_e req_f
 
 ERROR:
 
-       __mm_util_finalize(_image, NULL, NULL, &exception);
+       __mm_util_finalize(_image, NULL, &exception);
+
+       MMUTIL_SAFE_FREE(map);
+
+       mm_util_fleave();
+
+       return ret;
+}
+
+int mm_util_decode_image_from_file(const char *path, mm_util_color_format_e format, mm_util_image_h *decoded_image)
+{
+       int ret = MM_UTIL_ERROR_NONE;
+       char *map = NULL;
+       Image *_image = NULL;
+       size_t pixels_size = 0;
+       void *pixels = 0;
+
+       mm_util_retvm_if(!MMUTIL_STRING_VALID(path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid path");
+       mm_util_retvm_if(!decoded_image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid decoded_image");
+
+       mm_util_sec_debug("path [%s] format [%d]", path, format);
+
+       ret = __mm_util_get_map(format, &map);
+       mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "fail to get map");
+
+       __mm_util_init(NULL);
+
+       _image = __mm_util_read_image_from_file(path);
+       if (_image == NULL) {
+               mm_util_error("Error: __mm_util_read_image_from_file failed.");
+               ret = MM_UTIL_ERROR_INVALID_OPERATION;
+               goto ERROR;
+       }
+
+       pixels = __mm_util_write_image_to_buffer(_image, _image->columns, _image->rows, map, &pixels_size);
+       if (pixels == NULL) {
+               mm_util_error("Error: __mm_util_write_image_to_buffer failed.");
+               ret = MM_UTIL_ERROR_INVALID_OPERATION;
+               goto ERROR;
+       }
+
+       ret = mm_image_create_image(_image->columns, _image->rows, format, pixels, pixels_size, decoded_image);
+       if (ret != MM_UTIL_ERROR_NONE)
+               mm_util_error("Error: mm_image_create_image failed.");
+
+       MagickFree(pixels);
+
+ERROR:
+
+       __mm_util_finalize(_image, NULL, NULL);
+       MMUTIL_SAFE_FREE(map);
+
+       mm_util_fleave();
+
+       return ret;
+}
+
+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 ret = MM_UTIL_ERROR_NONE;
+       char *map = NULL;
+       Image *_image = NULL;
+       size_t pixels_size = 0;
+       void *pixels = 0;
+
+       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_retvm_if(!decoded_image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid decoded_image");
+
+       mm_util_sec_debug("path [%p] buf_size [%zu] format [%d]", buf, buf_size, format);
+
+       ret = __mm_util_get_map(format, &map);
+       mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "fail to get map");
+
+       __mm_util_init(NULL);
+
+       _image = __mm_util_read_image_from_buffer(buf, buf_size);
+       if (_image == NULL) {
+               mm_util_error("Error: __mm_util_read_image_from_file failed.");
+               ret = MM_UTIL_ERROR_INVALID_OPERATION;
+               goto ERROR;
+       }
+
+       pixels = __mm_util_write_image_to_buffer(_image, _image->columns, _image->rows, map, &pixels_size);
+       if (pixels == NULL) {
+               mm_util_error("Error: __mm_util_write_image_to_buffer failed.");
+               ret = MM_UTIL_ERROR_INVALID_OPERATION;
+               goto ERROR;
+       }
+
+       ret = mm_image_create_image(_image->columns, _image->rows, format, pixels, pixels_size, decoded_image);
+       if (ret != MM_UTIL_ERROR_NONE)
+               mm_util_error("Error: mm_image_create_image failed.");
+
+       MagickFree(pixels);
+
+ERROR:
 
+       __mm_util_finalize(_image, NULL, NULL);
        MMUTIL_SAFE_FREE(map);
 
        mm_util_fleave();
old mode 100755 (executable)
new mode 100644 (file)
index 547d3c5..25a7757
@@ -1,6 +1,6 @@
 Name:       libmm-utility
 Summary:    Multimedia Framework Utility Library
-Version:    0.1.37
+Version:    0.1.38
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
@@ -21,7 +21,6 @@ BuildRequires:  pkgconfig(opencv) >= 3.4.1
 BuildRequires:  pkgconfig(libpng)
 BuildRequires:  giflib-devel
 BuildRequires:  pkgconfig(libbmp)
-BuildRequires:  pkgconfig(libnsbmp)
 BuildRequires:  pkgconfig(GraphicsMagick)
 %if 0%{?gtests:1}
 BuildRequires:  pkgconfig(gmock)