4 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 #include <glib/gstdio.h>
24 #include <magick/api.h>
26 #include "mm_util_private.h"
27 #include "mm_util_magick.h"
30 static bool __mm_util_check_rotation(mm_util_rotate_type_e rotation);
31 static void __mm_util_magick_fatal_error_handler(const ExceptionType excep, const char *reason, const char *message) MAGICK_FUNC_NORETURN;
33 static void __mm_util_magick_log_method(const ExceptionType excep, const char *message)
35 /* To exclude time, user time and pid */
36 unsigned int start_idx = 31;
38 if ((message == NULL) || (strlen(message) < start_idx)) {
42 if (excep >= ErrorException)
43 mm_util_error("[GM][Ex:%3u] %s", excep, message + start_idx);
44 else if (excep >= WarningException)
45 mm_util_warn("[GM][Ex:%3u] %s", excep, message + start_idx);
47 mm_util_debug("[GM][Ex:%3u] %s", excep, message + start_idx);
50 static void __mm_util_magick_error_handler(const ExceptionType excep, const char *reason, const char *message)
52 if (excep >= ErrorException)
53 mm_util_error("[GM][Ex:%3u][Rs:%s] %s", excep, reason, message);
55 mm_util_warn("[GM][Ex:%3u][Rs:%s] %s", excep, reason, message);
58 static void __mm_util_magick_fatal_error_handler(const ExceptionType excep, const char *reason, const char *message)
60 if (excep >= ErrorException)
61 mm_util_error("[GM][Ex:%3u][Rs:%s] %s", excep, reason, message);
63 mm_util_warn("[GM][Ex:%3u][Rs:%s] %s", excep, reason, message);
68 static void __mm_util_init(ExceptionInfo *exception)
70 InitializeMagick(NULL);
71 if (exception != NULL)
72 GetExceptionInfo(exception);
74 /* set LogEventMask to show like "all" or "warning, error" */
75 /* <LogEventMask List>
76 * "none", "information", "warning", "error", "fatalerror", "configure", "annotate",
77 * "render", "transform", "locale", "coder", "x11", "cache", "blob", "deprecate",
78 * "user", "resource", "temporaryfile", "exception", "option", "all"
80 #if (GMAGICK_DEBUG == 1)
81 SetLogEventMask("all");
83 SetLogEventMask("warning, error, fatalerror, exception, coder");
85 SetLogMethod(__mm_util_magick_log_method);
86 SetErrorHandler(__mm_util_magick_error_handler);
87 SetFatalErrorHandler(__mm_util_magick_fatal_error_handler);
88 SetWarningHandler(__mm_util_magick_error_handler);
91 static void __mm_util_finalize(Image *image_1, Image *image_2, ExceptionInfo *exception)
94 DestroyImageList(image_1);
95 DestroyImageList(image_2);
97 if (exception != NULL)
98 DestroyExceptionInfo(exception);
103 static const char * __mm_util_get_map(mm_util_color_format_e format)
107 case MM_UTIL_COLOR_RGB24:
109 case MM_UTIL_COLOR_ARGB:
111 case MM_UTIL_COLOR_BGRA:
113 case MM_UTIL_COLOR_RGBA:
116 mm_util_error("Not supported format. [%d]", format);
121 static int __mm_util_constitute_image(mm_util_image_h handle, Image **image)
123 int ret = MM_UTIL_ERROR_NONE;
124 mm_image_info_s *_handle = (mm_image_info_s*)handle;
125 const char *map = NULL;
126 Image *_image = NULL;
127 ExceptionInfo exception;
131 mm_util_retvm_if(!handle, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid handle");
132 mm_util_retvm_if(!image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image");
134 map = __mm_util_get_map(_handle->color);
135 mm_util_retvm_if(!map, MM_UTIL_ERROR_INVALID_PARAMETER, "fail to get map");
137 GetExceptionInfo(&exception);
139 /* Read image from buffer */
140 _image = ConstituteImage(_handle->width, _handle->height, map, CharPixel, _handle->data, &exception);
144 mm_util_error("Error: Getting Image failed.");
145 if (exception.severity != UndefinedException)
146 CatchException(&exception);
147 ret = MM_UTIL_ERROR_INVALID_OPERATION;
150 DestroyExceptionInfo(&exception);
157 static int __mm_util_rotate_image(Image *image, mm_util_rotate_type_e rotation, Image **rotated_image)
159 int ret = MM_UTIL_ERROR_NONE;
160 Image *_processed_image = NULL;
161 ExceptionInfo exception;
165 mm_util_retvm_if(!image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image");
166 mm_util_retvm_if(!__mm_util_check_rotation(rotation), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid rotation [%d]", rotation);
167 mm_util_retvm_if(!rotated_image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid rotated_image");
169 GetExceptionInfo(&exception);
172 case MM_UTIL_ROTATE_0:
173 case MM_UTIL_ROTATE_90:
174 case MM_UTIL_ROTATE_180:
175 case MM_UTIL_ROTATE_270:
177 RotateImage(const Image *image,const double degrees, ExceptionInfo *exception)
178 degrees: Specifies the number of degrees to rotate the image.
179 degrees is rotation multiplied by 90.
181 _processed_image = RotateImage(image, (rotation * 90), &exception);
183 case MM_UTIL_ROTATE_FLIP_HORZ:
184 _processed_image = FlopImage(image, &exception);
186 case MM_UTIL_ROTATE_FLIP_VERT:
187 _processed_image = FlipImage(image, &exception);
190 mm_util_error("Invalid rotation. [%d]", rotation);
194 if (_processed_image) {
195 *rotated_image = _processed_image;
197 mm_util_error("Error: Image processing failed.");
198 if (exception.severity != UndefinedException)
199 CatchException(&exception);
200 ret = MM_UTIL_ERROR_INVALID_OPERATION;
203 DestroyExceptionInfo(&exception);
210 static int __mm_util_resize_image(Image *image, unsigned int width, unsigned int height, Image **resized_image)
212 int ret = MM_UTIL_ERROR_NONE;
213 Image *_processed_image = NULL;
214 Image *_sampled_image = NULL;
215 ExceptionInfo exception;
216 unsigned long check_factor = 3;
217 unsigned long sample_factor = 2;
221 mm_util_retvm_if(!image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image");
222 mm_util_retvm_if(width == 0 || height == 0, MM_UTIL_ERROR_INVALID_PARAMETER,
223 "invalid request[%u * %u]", width, height);
224 mm_util_retvm_if((image->columns < width) || (image->rows < height), MM_UTIL_ERROR_INVALID_PARAMETER,
225 "request[%u * %u] is larger than image [%lu * %lu]", width, height, image->columns, image->rows);
226 mm_util_retvm_if(!resized_image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid resized_image");
228 GetExceptionInfo(&exception);
230 if ((image->columns > width * check_factor) && (image->rows > height * check_factor)) {
231 _sampled_image = SampleImage(image, width * sample_factor, height * sample_factor, &exception);
232 if (_sampled_image == (Image *) NULL)
233 mm_util_error("Error: Sampling Image failed.");
236 if (_sampled_image != NULL)
237 _processed_image = ScaleImage(_sampled_image, width, height, &exception);
239 _processed_image = ScaleImage(image, width, height, &exception);
241 if (_processed_image) {
242 *resized_image = _processed_image;
244 mm_util_error("Error: Resizing Image failed.");
245 if (exception.severity != UndefinedException)
246 CatchException(&exception);
247 ret = MM_UTIL_ERROR_INVALID_OPERATION;
250 DestroyImageList(_sampled_image);
252 DestroyExceptionInfo(&exception);
259 static Image * __mm_util_read_image(ImageInfo *image_info)
261 Image *_image = NULL;
262 ExceptionInfo exception;
266 mm_util_retvm_if(!image_info, NULL, "invalid image_info");
268 GetExceptionInfo(&exception);
270 AddDefinition(image_info, "jpeg", "dct-method", "FASTEST", &exception);
271 AddDefinition(image_info, "jpeg", "block-smoothing", "FALSE", &exception);
272 AddDefinition(image_info, "jpeg", "fancy-upsampling", "FALSE", &exception);
274 _image = ReadImage(image_info, &exception);
276 mm_util_error("Error: Reading Image failed.");
277 if (exception.severity != UndefinedException)
278 CatchException(&exception);
281 DestroyExceptionInfo(&exception);
288 static int __mm_util_read_image_from_file(const char *path, Image **image)
290 ImageInfo *_image_info = NULL;
291 Image *_image = NULL;
295 mm_util_retvm_if(!MMUTIL_STRING_VALID(path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid path");
296 mm_util_retvm_if(!image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image");
298 _image_info = CloneImageInfo(0);
299 mm_util_retvm_if(!_image_info, MM_UTIL_ERROR_INVALID_OPERATION, "Error: CloneImageInfo failed.");
300 g_strlcpy(_image_info->filename, path, sizeof(_image_info->filename));
302 _image = __mm_util_read_image(_image_info);
303 DestroyImageInfo(_image_info);
305 mm_util_error("Error: __mm_util_read_image failed.");
306 return MM_UTIL_ERROR_INVALID_OPERATION;
312 return MM_UTIL_ERROR_NONE;
315 static int __mm_util_read_image_from_buffer(const void *buf, size_t buf_size, Image **image)
317 ImageInfo *_image_info = NULL;
318 Image *_image = NULL;
322 mm_util_retvm_if(!buf, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid buf");
323 mm_util_retvm_if(buf_size == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid buf_size");
324 mm_util_retvm_if(!image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image");
326 _image_info = CloneImageInfo(0);
327 mm_util_retvm_if(!_image_info, MM_UTIL_ERROR_INVALID_OPERATION, "Error: CloneImageInfo failed.");
328 _image_info->blob = (void *)buf;
329 _image_info->length = buf_size;
331 _image = __mm_util_read_image(_image_info);
332 DestroyImageInfo(_image_info);
334 mm_util_error("Error: __mm_util_read_image failed.");
335 return MM_UTIL_ERROR_INVALID_OPERATION;
341 return MM_UTIL_ERROR_NONE;
344 static int __mm_util_write_image_to_file(Image *image, mm_util_enc_opt_t *option, const char *out_path)
346 int ret = MM_UTIL_ERROR_NONE;
347 ImageInfo *_image_info = NULL;
348 ExceptionInfo exception;
352 mm_util_retvm_if(!image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image");
353 mm_util_retvm_if(!MMUTIL_STRING_VALID(out_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid out_path");
355 if (g_strlcpy(image->filename, out_path, sizeof(image->filename)) >= MaxTextExtent) {
356 mm_util_error("Error: truncation occurred");
357 return MM_UTIL_ERROR_INVALID_OPERATION;
360 GetExceptionInfo(&exception);
362 _image_info = CloneImageInfo(0);
363 mm_util_retvm_if(!_image_info, MM_UTIL_ERROR_INVALID_OPERATION, "Error: CloneImageInfo failed.");
365 DeleteImageProfile(image, "EXIF");
366 DeleteImageProfile(image, "8BIM");
367 DeleteImageProfile(image, "ICM");
368 DeleteImageProfile(image, "IPTC");
369 DeleteImageProfile(image, "XMP");
372 switch (option->codec) {
374 AddDefinition(_image_info, "jpeg", "dct-method", "FASTEST", &exception);
375 AddDefinition(_image_info, "jpeg", "optimize-coding", "FALSE", &exception);
379 mm_util_sec_debug("PNG compression: %d", option->compression);
380 _image_info->quality = option->compression * 10;
384 mm_util_sec_debug("WEBP lossless: %s", (option->lossless ? "TRUE" : "FALSE"));
385 AddDefinition(_image_info, "webp", "lossless", (option->lossless ? "TRUE" : "FALSE"), &exception);
396 mm_util_error("invalid codec [%d]", option->codec);
401 if (WriteImage(_image_info, image) == MagickFalse) {
402 mm_util_error("Error: Writing Image failed.");
403 if (exception.severity != UndefinedException)
404 CatchException(&exception);
406 ret = MM_UTIL_ERROR_INVALID_OPERATION;
409 DestroyImageInfo(_image_info);
410 DestroyExceptionInfo(&exception);
417 static int __mm_util_dispatch_image(Image *image, mm_util_color_format_e format, mm_util_image_h *dispatched_image)
419 int ret = MM_UTIL_ERROR_NONE;
420 ExceptionInfo exception;
421 size_t pixels_size = 0;
423 unsigned int width = 0;
424 unsigned int height = 0;
425 const char *map = NULL;
429 mm_util_retvm_if(!image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image");
431 map = __mm_util_get_map(format);
432 mm_util_retvm_if(!map, MM_UTIL_ERROR_INVALID_PARAMETER, "fail to get map");
434 GetExceptionInfo(&exception);
436 width = image->columns;
437 height = image->rows;
439 pixels_size = sizeof(unsigned char) * strlen(map) * width * height;
440 pixels = MagickMalloc(pixels_size);
443 mm_util_error("Error: MagickMalloc failed.");
444 ret = MM_UTIL_ERROR_OUT_OF_MEMORY;
448 ret = DispatchImage(image, 0, 0, width, height, map, CharPixel, pixels, &exception);
449 if (ret == MagickFail) {
450 mm_util_error("Failed to Dispatch Image into dst buffer");
451 if (exception.severity != UndefinedException)
452 CatchException(&exception);
455 ret = MM_UTIL_ERROR_INVALID_OPERATION;
459 ret = mm_image_create_image(width, height, format, pixels, pixels_size, dispatched_image);
460 if (ret != MM_UTIL_ERROR_NONE)
461 mm_util_error("Error: mm_image_create_image failed.");
467 DestroyExceptionInfo(&exception);
474 static bool __mm_util_check_rotation(mm_util_rotate_type_e rotation)
477 case MM_UTIL_ROTATE_0:
478 case MM_UTIL_ROTATE_90:
479 case MM_UTIL_ROTATE_180:
480 case MM_UTIL_ROTATE_270:
481 case MM_UTIL_ROTATE_FLIP_HORZ:
482 case MM_UTIL_ROTATE_FLIP_VERT:
489 static int __mm_util_make_tmp_file(mm_util_img_codec_type type, char **path)
492 const char *template = NULL;
493 GError *error = NULL;
495 /* GraphicsMagick determine image codec from file extension */
498 template = "XXXXXX.gif";
501 template = "XXXXXX.png";
504 template = "XXXXXX.jpg";
507 template = "XXXXXX.bmp";
510 template = "XXXXXX.webp";
513 mm_util_error("invalid type [%u]", type);
514 return MM_UTIL_ERROR_INVALID_PARAMETER;
517 fd = g_file_open_tmp(template, path, &error);
519 mm_util_sec_debug("g_file_open_tmp error [%s]", (error ? error->message : "none"));
521 return MM_UTIL_ERROR_INVALID_OPERATION;
524 mm_util_sec_debug("g_file_open_tmp [%s]", *path);
528 return MM_UTIL_ERROR_NONE;
531 int mm_util_rotate_B_B(mm_util_image_h src_handle, mm_util_rotate_type_e rotation, mm_util_image_h *dst_handle)
533 int ret = MM_UTIL_ERROR_NONE;
534 mm_image_info_s *_src_handle = (mm_image_info_s*)src_handle;
535 Image *_image = NULL;
536 Image *_processed_image = NULL;
537 ExceptionInfo exception;
539 mm_util_debug("rotation [%d]", rotation);
541 __mm_util_init(&exception);
543 ret = __mm_util_constitute_image(src_handle, &_image);
544 if (ret != MM_UTIL_ERROR_NONE) {
545 mm_util_error("Error: __mm_util_constitute_image failed.");
549 ret = __mm_util_rotate_image(_image, rotation, &_processed_image);
550 if (ret != MM_UTIL_ERROR_NONE) {
551 mm_util_error("Error: __mm_util_rotate_image failed.");
555 ret = __mm_util_dispatch_image(_processed_image, _src_handle->color, dst_handle);
559 __mm_util_finalize(_image, _processed_image, &exception);
566 int mm_util_rotate_B_P(mm_util_image_h src_handle, mm_util_rotate_type_e rotation, const char *dst_path)
568 int ret = MM_UTIL_ERROR_NONE;
569 Image *_image = NULL;
570 Image *_processed_image = NULL;
571 ExceptionInfo exception;
573 mm_util_sec_debug("rotation [%d] dst_path [%s]", rotation, dst_path);
575 __mm_util_init(&exception);
577 ret = __mm_util_constitute_image(src_handle, &_image);
578 if (ret != MM_UTIL_ERROR_NONE) {
579 mm_util_error("Error: __mm_util_constitute_image failed.");
583 ret = __mm_util_rotate_image(_image, rotation, &_processed_image);
584 if (ret != MM_UTIL_ERROR_NONE) {
585 mm_util_error("Error: __mm_util_rotate_image failed.");
589 ret = __mm_util_write_image_to_file(_processed_image, NULL, dst_path);
593 __mm_util_finalize(_image, _processed_image, &exception);
600 int mm_util_rotate_P_B(const char *src_path, mm_util_rotate_type_e rotation, mm_util_color_format_e req_format, mm_util_image_h *dst_handle)
602 int ret = MM_UTIL_ERROR_NONE;
603 Image *_image = NULL;
604 Image *_processed_image = NULL;
605 ExceptionInfo exception;
607 mm_util_sec_debug("src_path [%s] rotation [%d] req_format [%d]", src_path, rotation, req_format);
609 __mm_util_init(&exception);
611 ret = __mm_util_read_image_from_file(src_path, &_image);
612 if (ret != MM_UTIL_ERROR_NONE) {
613 mm_util_error("Error: __mm_util_read_image_from_file failed.");
617 ret = __mm_util_rotate_image(_image, rotation, &_processed_image);
618 if (ret != MM_UTIL_ERROR_NONE) {
619 mm_util_error("Error: __mm_util_rotate_image failed.");
623 ret = __mm_util_dispatch_image(_processed_image, req_format, dst_handle);
627 __mm_util_finalize(_image, _processed_image, &exception);
635 int mm_util_rotate_P_P(const char *src_path, mm_util_rotate_type_e rotation, const char *dst_path)
637 int ret = MM_UTIL_ERROR_NONE;
638 Image *_image = NULL;
639 Image *_processed_image = NULL;
640 ExceptionInfo exception;
642 __mm_util_init(&exception);
644 ret = __mm_util_read_image_from_file(src_path, &_image);
645 if (ret != MM_UTIL_ERROR_NONE) {
646 mm_util_error("Error: __mm_util_read_image_from_file failed.");
650 ret = __mm_util_rotate_image(_image, rotation, &_processed_image);
651 if (ret != MM_UTIL_ERROR_NONE) {
652 mm_util_error("Error: __mm_util_rotate_image failed.");
656 ret = __mm_util_write_image_to_file(_processed_image, NULL, dst_path);
660 __mm_util_finalize(_image, _processed_image, &exception);
667 int mm_util_resize_B_B(mm_util_image_h src_handle, unsigned int req_width, unsigned int req_height, mm_util_image_h *dst_handle)
669 int ret = MM_UTIL_ERROR_NONE;
670 mm_image_info_s *_src_handle = (mm_image_info_s*)src_handle;
671 Image *_image = NULL;
672 Image *_processed_image = NULL;
673 ExceptionInfo exception;
675 mm_util_debug("req_width [%u] req_height [%u]", req_width, req_height);
677 __mm_util_init(&exception);
679 ret = __mm_util_constitute_image(src_handle, &_image);
680 if (ret != MM_UTIL_ERROR_NONE) {
681 mm_util_error("Error: __mm_util_constitute_image failed.");
685 ret = __mm_util_resize_image(_image, req_width, req_height, &_processed_image);
686 if (ret != MM_UTIL_ERROR_NONE) {
687 mm_util_error("Error: __mm_util_resize_image failed.");
691 ret = __mm_util_dispatch_image(_processed_image, _src_handle->color, dst_handle);
695 __mm_util_finalize(_image, _processed_image, &exception);
702 int mm_util_resize_B_P(mm_util_image_h src_handle, unsigned int req_width, unsigned int req_height, const char *dst_path)
704 int ret = MM_UTIL_ERROR_NONE;
705 Image *_image = NULL;
706 Image *_processed_image = NULL;
707 ExceptionInfo exception;
709 mm_util_sec_debug("req_width [%u] req_height [%u] dst_path [%s]", req_width, req_height, dst_path);
711 __mm_util_init(&exception);
713 ret = __mm_util_constitute_image(src_handle, &_image);
714 if (ret != MM_UTIL_ERROR_NONE) {
715 mm_util_error("Error: __mm_util_constitute_image failed.");
719 ret = __mm_util_resize_image(_image, req_width, req_height, &_processed_image);
720 if (ret != MM_UTIL_ERROR_NONE) {
721 mm_util_error("Error: __mm_util_resize_image failed.");
725 ret = __mm_util_write_image_to_file(_processed_image, NULL, dst_path);
729 __mm_util_finalize(_image, _processed_image, &exception);
736 int mm_util_resize_P_B(const char *src_path, unsigned int req_width, unsigned int req_height, mm_util_color_format_e req_format, mm_util_image_h *dst_handle)
738 int ret = MM_UTIL_ERROR_NONE;
739 Image *_image = NULL;
740 Image *_processed_image = NULL;
741 ExceptionInfo exception;
743 mm_util_sec_debug("src_path [%s] req_width [%u] req_height [%u]", src_path, req_width, req_height);
745 __mm_util_init(&exception);
747 ret = __mm_util_read_image_from_file(src_path, &_image);
748 if (ret != MM_UTIL_ERROR_NONE) {
749 mm_util_error("Error: __mm_util_read_image_from_file failed.");
753 ret = __mm_util_resize_image(_image, req_width, req_height, &_processed_image);
754 if (ret != MM_UTIL_ERROR_NONE) {
755 mm_util_error("Error: __mm_util_resize_image failed.");
759 ret = __mm_util_dispatch_image(_processed_image, req_format, dst_handle);
763 __mm_util_finalize(_image, _processed_image, &exception);
770 int mm_util_resize_P_P(const char *src_path, unsigned int req_width, unsigned int req_height, const char *dst_path)
772 int ret = MM_UTIL_ERROR_NONE;
773 Image *_image = NULL;
774 Image *_processed_image = NULL;
775 ExceptionInfo exception;
777 mm_util_sec_debug("src_path [%s] req_width [%u] req_height [%u] dst_path [%s]", src_path, req_width, req_height, dst_path);
779 __mm_util_init(&exception);
781 ret = __mm_util_read_image_from_file(src_path, &_image);
782 if (ret != MM_UTIL_ERROR_NONE) {
783 mm_util_error("Error: __mm_util_read_image_from_file failed.");
787 ret = __mm_util_resize_image(_image, req_width, req_height, &_processed_image);
788 if (ret != MM_UTIL_ERROR_NONE) {
789 mm_util_error("Error: __mm_util_resize_image failed.");
793 ret = __mm_util_write_image_to_file(_processed_image, NULL, dst_path);
797 __mm_util_finalize(_image, _processed_image, &exception);
804 int mm_util_convert_B_B(mm_util_image_h src_handle, mm_util_color_format_e req_format, mm_util_image_h *dst_handle)
806 int ret = MM_UTIL_ERROR_NONE;
807 mm_image_info_s *_src_handle = (mm_image_info_s*)src_handle;
808 Image *_image = NULL;
809 ExceptionInfo exception;
811 mm_util_debug("input format [%d] req_format [%d]", _src_handle->color, req_format);
813 __mm_util_init(&exception);
815 ret = __mm_util_constitute_image(src_handle, &_image);
816 if (ret != MM_UTIL_ERROR_NONE) {
817 mm_util_error("Error: __mm_util_constitute_image failed.");
821 ret = __mm_util_dispatch_image(_image, req_format, dst_handle);
825 __mm_util_finalize(_image, NULL, &exception);
832 int mm_util_decode_image_from_file(const char *path, mm_util_color_format_e format, mm_util_image_h *decoded_image)
834 int ret = MM_UTIL_ERROR_NONE;
835 Image *_image = NULL;
837 mm_util_sec_debug("path [%s] format [%d]", path, format);
839 __mm_util_init(NULL);
841 ret = __mm_util_read_image_from_file(path, &_image);
842 if (ret != MM_UTIL_ERROR_NONE) {
843 mm_util_error("Error: __mm_util_read_image_from_file failed.");
847 ret = __mm_util_dispatch_image(_image, format, decoded_image);
851 __mm_util_finalize(_image, NULL, NULL);
858 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)
860 int ret = MM_UTIL_ERROR_NONE;
861 Image *_image = NULL;
863 mm_util_sec_debug("path [%p] buf_size [%zu] format [%d]", buf, buf_size, format);
865 __mm_util_init(NULL);
867 ret = __mm_util_read_image_from_buffer(buf, buf_size, &_image);
868 if (ret != MM_UTIL_ERROR_NONE) {
869 mm_util_error("Error: __mm_util_read_image_from_buffer failed.");
873 ret = __mm_util_dispatch_image(_image, format, decoded_image);
877 __mm_util_finalize(_image, NULL, NULL);
884 int mm_util_encode_image_to_file(mm_util_image_h decoded_image, mm_util_enc_opt_h opt, const char *path)
886 int ret = MM_UTIL_ERROR_NONE;
887 Image *_image = NULL;
888 mm_util_image_h converted_image = NULL, source = NULL;
889 mm_util_enc_opt_t *_opt = (mm_util_enc_opt_t *)opt;
891 mm_util_retvm_if(!_opt, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid opt");
893 mm_util_sec_debug("path [%s]", path);
895 if (_opt->codec == IMG_CODEC_BMP) {
897 GraphicsMagick doesn't support alpha overlay(compression method:BI_ALPHABITFIELDS) for bmp.
898 Officially BMP format supports alpha overlay since BMP4(version 4), but GraphicsMagick
899 support BMP, BMP2(v2) and BMP3(v3) except BMP4.
900 So decoded_image should be converted to RGB888(RGB24) which has not alpha overlay.
901 ps. BMP4 image does not guarantee backward compatibility. BMP4 is not visible on old devices.
902 For the reasons, BMP4 is used in certain cases of windows OS, not widely used in general cases.
905 if (((mm_image_info_s *)decoded_image)->color == MM_UTIL_COLOR_RGBA) {
906 ret = mm_util_convert_B_B(decoded_image, MM_UTIL_COLOR_RGB24, &converted_image);
907 if (ret != MM_UTIL_ERROR_NONE) {
908 mm_util_error("Error: mm_util_convert_B_B failed.");
914 source = (converted_image) ? converted_image : decoded_image;
916 __mm_util_init(NULL);
918 ret = __mm_util_constitute_image(source, &_image);
919 if (ret != MM_UTIL_ERROR_NONE) {
920 mm_util_error("Error: __mm_util_constitute_image failed.");
924 ret = __mm_util_write_image_to_file(_image, _opt, path);
928 __mm_util_finalize(_image, NULL, NULL);
930 mm_image_destroy_image(converted_image);
937 int mm_util_encode_image_to_buffer(mm_util_image_h decoded_image, mm_util_enc_opt_h opt, void **buf, size_t *buf_size)
939 int ret = MM_UTIL_ERROR_NONE;
940 char *tmp_file = NULL;
942 mm_util_retvm_if(!opt, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid opt");
944 ret = __mm_util_make_tmp_file(((mm_util_enc_opt_t *)opt)->codec, &tmp_file);
945 mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "Error: __mm_util_make_tmp_file failed.");
947 ret = mm_util_encode_image_to_file(decoded_image, opt, tmp_file);
948 if (ret != MM_UTIL_ERROR_NONE) {
949 mm_util_error("Error: mm_util_encode_image_P failed.");
953 ret = mm_util_file_read(tmp_file, buf, buf_size);
954 if (ret != MM_UTIL_ERROR_NONE)
955 mm_util_error("Error: mm_util_file_read failed.");
959 if (g_remove(tmp_file) != 0)
960 mm_util_sec_debug("Temporary file was not removed [%s]", tmp_file);
968 int mm_util_resize_and_rotate_P_P(const char *src_path, unsigned int req_width, unsigned int req_height, const char *dst_path)
970 int ret = MM_UTIL_ERROR_NONE;
971 Image *_image = NULL;
972 Image *_resized_image = NULL;
973 Image *_rotated_image = NULL;
974 Image *_write_image = NULL;
975 ExceptionInfo exception;
976 mm_util_rotate_type_e rotation = MM_UTIL_ROTATE_0;
978 mm_util_sec_debug("src_path [%s] req_width [%u] req_height [%u] dst_path [%s]", src_path, req_width, req_height, dst_path);
980 __mm_util_init(&exception);
982 ret = __mm_util_read_image_from_file(src_path, &_image);
983 if (ret != MM_UTIL_ERROR_NONE) {
984 mm_util_error("Error: __mm_util_read_image_from_file failed.");
988 ret = __mm_util_resize_image(_image, req_width, req_height, &_resized_image);
989 DestroyImageList(_image);
991 if (ret != MM_UTIL_ERROR_NONE) {
992 mm_util_error("Error: __mm_util_resize_image failed.");
996 switch(_resized_image->orientation) {
997 case TopRightOrientation:
998 case RightTopOrientation:
999 rotation = MM_UTIL_ROTATE_90;
1001 case BottomRightOrientation:
1002 case RightBottomOrientation:
1003 rotation = MM_UTIL_ROTATE_180;
1005 case BottomLeftOrientation:
1006 case LeftBottomOrientation:
1007 rotation = MM_UTIL_ROTATE_270;
1009 case TopLeftOrientation:
1010 case LeftTopOrientation:
1013 mm_util_warn("Not supported orientation %d. so apply MM_UTIL_ROTATE_0", _resized_image->orientation);
1017 if (rotation != MM_UTIL_ROTATE_0) {
1018 ret = __mm_util_rotate_image(_resized_image, rotation, &_rotated_image);
1019 if (ret != MM_UTIL_ERROR_NONE) {
1020 mm_util_error("Error: __mm_util_rotate_image failed.");
1025 _write_image = (_rotated_image) ? _rotated_image : _resized_image;
1027 /* problem. a thumbnail of grayscale image is invisible
1028 add converting grayscale image into rgb(jpeg) or true color(png)
1029 the rgb(jpeg) and true-color(png) are default(else case) value.
1031 if (IsGrayImage(_write_image, &exception)) {
1032 mm_util_info("IsGrayImage, convert image into rgb(jpeg)/true-color(png).");
1033 _write_image->is_grayscale = MagickFalse;
1036 ret = __mm_util_write_image_to_file(_write_image, NULL, dst_path);
1040 __mm_util_finalize(_resized_image, _rotated_image, &exception);