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;
349 mm_util_img_codec_type codec = IMG_CODEC_JPEG;
353 mm_util_retvm_if(!image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image");
354 mm_util_retvm_if(!MMUTIL_STRING_VALID(out_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid out_path");
356 if (g_strlcpy(image->filename, out_path, sizeof(image->filename)) >= MaxTextExtent) {
357 mm_util_error("Error: truncation occurred");
358 return MM_UTIL_ERROR_INVALID_OPERATION;
361 GetExceptionInfo(&exception);
363 _image_info = CloneImageInfo(0);
364 mm_util_retvm_if(!_image_info, MM_UTIL_ERROR_INVALID_OPERATION, "Error: CloneImageInfo failed.");
366 DeleteImageProfile(image, "EXIF");
367 DeleteImageProfile(image, "8BIM");
368 DeleteImageProfile(image, "ICM");
369 DeleteImageProfile(image, "IPTC");
370 DeleteImageProfile(image, "XMP");
373 codec = option->codec;
377 AddDefinition(_image_info, "jpeg", "dct-method", "FASTEST", &exception);
378 AddDefinition(_image_info, "jpeg", "optimize-coding", "FALSE", &exception);
382 mm_util_sec_debug("PNG compression: %d", option->compression);
383 _image_info->quality = option->compression * 10;
387 mm_util_sec_debug("WEBP lossless: %s", (option->lossless ? "TRUE" : "FALSE"));
388 AddDefinition(_image_info, "webp", "lossless", (option->lossless ? "TRUE" : "FALSE"), &exception);
399 mm_util_error("invalid codec [%d]", codec);
403 if (WriteImage (_image_info, image) == MagickFalse) {
404 mm_util_error("Error: Writing Image failed.");
405 if (exception.severity != UndefinedException)
406 CatchException(&exception);
408 ret = MM_UTIL_ERROR_INVALID_OPERATION;
411 DestroyImageInfo(_image_info);
412 DestroyExceptionInfo(&exception);
419 static int __mm_util_dispatch_image(Image *image, mm_util_color_format_e format, mm_util_image_h *dispatched_image)
421 int ret = MM_UTIL_ERROR_NONE;
422 ExceptionInfo exception;
423 size_t pixels_size = 0;
425 unsigned int width = 0;
426 unsigned int height = 0;
427 const char *map = NULL;
431 mm_util_retvm_if(!image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image");
433 map = __mm_util_get_map(format);
434 mm_util_retvm_if(!map, MM_UTIL_ERROR_INVALID_PARAMETER, "fail to get map");
436 GetExceptionInfo(&exception);
438 width = image->columns;
439 height = image->rows;
441 pixels_size = sizeof(unsigned char) * strlen(map) * width * height;
442 pixels = MagickMalloc(pixels_size);
445 mm_util_error("Error: MagickMalloc failed.");
446 ret = MM_UTIL_ERROR_OUT_OF_MEMORY;
450 ret = DispatchImage(image, 0, 0, width, height, map, CharPixel, pixels, &exception);
451 if (ret == MagickFail) {
452 mm_util_error("Failed to Dispatch Image into dst buffer");
453 if (exception.severity != UndefinedException)
454 CatchException(&exception);
457 ret = MM_UTIL_ERROR_INVALID_OPERATION;
461 ret = mm_image_create_image(width, height, format, pixels, pixels_size, dispatched_image);
462 if (ret != MM_UTIL_ERROR_NONE)
463 mm_util_error("Error: mm_image_create_image failed.");
469 DestroyExceptionInfo(&exception);
476 static bool __mm_util_check_rotation(mm_util_rotate_type_e rotation)
479 case MM_UTIL_ROTATE_0:
480 case MM_UTIL_ROTATE_90:
481 case MM_UTIL_ROTATE_180:
482 case MM_UTIL_ROTATE_270:
483 case MM_UTIL_ROTATE_FLIP_HORZ:
484 case MM_UTIL_ROTATE_FLIP_VERT:
491 static int __mm_util_make_tmp_file(mm_util_img_codec_type type, char **path)
494 const char *template = NULL;
495 GError *error = NULL;
497 /* GraphicsMagick determine image codec from file extension */
500 template = "XXXXXX.gif";
503 template = "XXXXXX.png";
506 template = "XXXXXX.jpg";
509 template = "XXXXXX.bmp";
512 template = "XXXXXX.webp";
515 mm_util_error("invalid type [%u]", type);
516 return MM_UTIL_ERROR_INVALID_PARAMETER;
519 fd = g_file_open_tmp(template, path, &error);
521 mm_util_sec_debug("g_file_open_tmp error [%s]", (error ? error->message : "none"));
523 return MM_UTIL_ERROR_INVALID_OPERATION;
526 mm_util_sec_debug("g_file_open_tmp [%s]", *path);
530 return MM_UTIL_ERROR_NONE;
533 int mm_util_rotate_B_B(mm_util_image_h src_handle, mm_util_rotate_type_e rotation, mm_util_image_h *dst_handle)
535 int ret = MM_UTIL_ERROR_NONE;
536 mm_image_info_s *_src_handle = (mm_image_info_s*)src_handle;
537 Image *_image = NULL;
538 Image *_processed_image = NULL;
539 ExceptionInfo exception;
541 mm_util_debug("rotation [%d]", rotation);
543 __mm_util_init(&exception);
545 ret = __mm_util_constitute_image(src_handle, &_image);
546 if (ret != MM_UTIL_ERROR_NONE) {
547 mm_util_error("Error: __mm_util_constitute_image failed.");
551 ret = __mm_util_rotate_image(_image, rotation, &_processed_image);
552 if (ret != MM_UTIL_ERROR_NONE) {
553 mm_util_error("Error: __mm_util_rotate_image failed.");
557 ret = __mm_util_dispatch_image(_processed_image, _src_handle->color, dst_handle);
561 __mm_util_finalize(_image, _processed_image, &exception);
568 int mm_util_rotate_B_P(mm_util_image_h src_handle, mm_util_rotate_type_e rotation, const char *dst_path)
570 int ret = MM_UTIL_ERROR_NONE;
571 Image *_image = NULL;
572 Image *_processed_image = NULL;
573 ExceptionInfo exception;
575 mm_util_sec_debug("rotation [%d] dst_path [%s]", rotation, dst_path);
577 __mm_util_init(&exception);
579 ret = __mm_util_constitute_image(src_handle, &_image);
580 if (ret != MM_UTIL_ERROR_NONE) {
581 mm_util_error("Error: __mm_util_constitute_image failed.");
585 ret = __mm_util_rotate_image(_image, rotation, &_processed_image);
586 if (ret != MM_UTIL_ERROR_NONE) {
587 mm_util_error("Error: __mm_util_rotate_image failed.");
591 ret = __mm_util_write_image_to_file(_processed_image, NULL, dst_path);
595 __mm_util_finalize(_image, _processed_image, &exception);
602 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)
604 int ret = MM_UTIL_ERROR_NONE;
605 Image *_image = NULL;
606 Image *_processed_image = NULL;
607 ExceptionInfo exception;
609 mm_util_sec_debug("src_path [%s] rotation [%d] req_format [%d]", src_path, rotation, req_format);
611 __mm_util_init(&exception);
613 ret = __mm_util_read_image_from_file(src_path, &_image);
614 if (ret != MM_UTIL_ERROR_NONE) {
615 mm_util_error("Error: __mm_util_read_image_from_file failed.");
619 ret = __mm_util_rotate_image(_image, rotation, &_processed_image);
620 if (ret != MM_UTIL_ERROR_NONE) {
621 mm_util_error("Error: __mm_util_rotate_image failed.");
625 ret = __mm_util_dispatch_image(_processed_image, req_format, dst_handle);
629 __mm_util_finalize(_image, _processed_image, &exception);
637 int mm_util_rotate_P_P(const char *src_path, mm_util_rotate_type_e rotation, const char *dst_path)
639 int ret = MM_UTIL_ERROR_NONE;
640 Image *_image = NULL;
641 Image *_processed_image = NULL;
642 ExceptionInfo exception;
644 __mm_util_init(&exception);
646 ret = __mm_util_read_image_from_file(src_path, &_image);
647 if (ret != MM_UTIL_ERROR_NONE) {
648 mm_util_error("Error: __mm_util_read_image_from_file failed.");
652 ret = __mm_util_rotate_image(_image, rotation, &_processed_image);
653 if (ret != MM_UTIL_ERROR_NONE) {
654 mm_util_error("Error: __mm_util_rotate_image failed.");
658 ret = __mm_util_write_image_to_file(_processed_image, NULL, dst_path);
662 __mm_util_finalize(_image, _processed_image, &exception);
669 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)
671 int ret = MM_UTIL_ERROR_NONE;
672 mm_image_info_s *_src_handle = (mm_image_info_s*)src_handle;
673 Image *_image = NULL;
674 Image *_processed_image = NULL;
675 ExceptionInfo exception;
677 mm_util_debug("req_width [%u] req_height [%u]", req_width, req_height);
679 __mm_util_init(&exception);
681 ret = __mm_util_constitute_image(src_handle, &_image);
682 if (ret != MM_UTIL_ERROR_NONE) {
683 mm_util_error("Error: __mm_util_constitute_image failed.");
687 ret = __mm_util_resize_image(_image, req_width, req_height, &_processed_image);
688 if (ret != MM_UTIL_ERROR_NONE) {
689 mm_util_error("Error: __mm_util_resize_image failed.");
693 ret = __mm_util_dispatch_image(_processed_image, _src_handle->color, dst_handle);
697 __mm_util_finalize(_image, _processed_image, &exception);
704 int mm_util_resize_B_P(mm_util_image_h src_handle, unsigned int req_width, unsigned int req_height, const char *dst_path)
706 int ret = MM_UTIL_ERROR_NONE;
707 Image *_image = NULL;
708 Image *_processed_image = NULL;
709 ExceptionInfo exception;
711 mm_util_sec_debug("req_width [%u] req_height [%u] dst_path [%s]", req_width, req_height, dst_path);
713 __mm_util_init(&exception);
715 ret = __mm_util_constitute_image(src_handle, &_image);
716 if (ret != MM_UTIL_ERROR_NONE) {
717 mm_util_error("Error: __mm_util_constitute_image failed.");
721 ret = __mm_util_resize_image(_image, req_width, req_height, &_processed_image);
722 if (ret != MM_UTIL_ERROR_NONE) {
723 mm_util_error("Error: __mm_util_resize_image failed.");
727 ret = __mm_util_write_image_to_file(_processed_image, NULL, dst_path);
731 __mm_util_finalize(_image, _processed_image, &exception);
738 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)
740 int ret = MM_UTIL_ERROR_NONE;
741 Image *_image = NULL;
742 Image *_processed_image = NULL;
743 ExceptionInfo exception;
745 mm_util_sec_debug("src_path [%s] req_width [%u] req_height [%u]", src_path, req_width, req_height);
747 __mm_util_init(&exception);
749 ret = __mm_util_read_image_from_file(src_path, &_image);
750 if (ret != MM_UTIL_ERROR_NONE) {
751 mm_util_error("Error: __mm_util_read_image_from_file failed.");
755 ret = __mm_util_resize_image(_image, req_width, req_height, &_processed_image);
756 if (ret != MM_UTIL_ERROR_NONE) {
757 mm_util_error("Error: __mm_util_resize_image failed.");
761 ret = __mm_util_dispatch_image(_processed_image, req_format, dst_handle);
765 __mm_util_finalize(_image, _processed_image, &exception);
772 int mm_util_resize_P_P(const char *src_path, unsigned int req_width, unsigned int req_height, const char *dst_path)
774 int ret = MM_UTIL_ERROR_NONE;
775 Image *_image = NULL;
776 Image *_processed_image = NULL;
777 ExceptionInfo exception;
779 mm_util_sec_debug("src_path [%s] req_width [%u] req_height [%u] dst_path [%s]", src_path, req_width, req_height, dst_path);
781 __mm_util_init(&exception);
783 ret = __mm_util_read_image_from_file(src_path, &_image);
784 if (ret != MM_UTIL_ERROR_NONE) {
785 mm_util_error("Error: __mm_util_read_image_from_file failed.");
789 ret = __mm_util_resize_image(_image, req_width, req_height, &_processed_image);
790 if (ret != MM_UTIL_ERROR_NONE) {
791 mm_util_error("Error: __mm_util_resize_image failed.");
795 ret = __mm_util_write_image_to_file(_processed_image, NULL, dst_path);
799 __mm_util_finalize(_image, _processed_image, &exception);
806 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)
808 int ret = MM_UTIL_ERROR_NONE;
809 mm_image_info_s *_src_handle = (mm_image_info_s*)src_handle;
810 Image *_image = NULL;
811 ExceptionInfo exception;
813 mm_util_debug("input format [%d] req_format [%d]", _src_handle->color, req_format);
815 __mm_util_init(&exception);
817 ret = __mm_util_constitute_image(src_handle, &_image);
818 if (ret != MM_UTIL_ERROR_NONE) {
819 mm_util_error("Error: __mm_util_constitute_image failed.");
823 ret = __mm_util_dispatch_image(_image, req_format, dst_handle);
827 __mm_util_finalize(_image, NULL, &exception);
834 int mm_util_decode_image_from_file(const char *path, mm_util_color_format_e format, mm_util_image_h *decoded_image)
836 int ret = MM_UTIL_ERROR_NONE;
837 Image *_image = NULL;
839 mm_util_sec_debug("path [%s] format [%d]", path, format);
841 __mm_util_init(NULL);
843 ret = __mm_util_read_image_from_file(path, &_image);
844 if (ret != MM_UTIL_ERROR_NONE) {
845 mm_util_error("Error: __mm_util_read_image_from_file failed.");
849 ret = __mm_util_dispatch_image(_image, format, decoded_image);
853 __mm_util_finalize(_image, NULL, NULL);
860 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)
862 int ret = MM_UTIL_ERROR_NONE;
863 Image *_image = NULL;
865 mm_util_sec_debug("path [%p] buf_size [%zu] format [%d]", buf, buf_size, format);
867 __mm_util_init(NULL);
869 ret = __mm_util_read_image_from_buffer(buf, buf_size, &_image);
870 if (ret != MM_UTIL_ERROR_NONE) {
871 mm_util_error("Error: __mm_util_read_image_from_buffer failed.");
875 ret = __mm_util_dispatch_image(_image, format, decoded_image);
879 __mm_util_finalize(_image, NULL, NULL);
886 int mm_util_encode_image_to_file(mm_util_image_h decoded_image, mm_util_enc_opt_h opt, const char *path)
888 int ret = MM_UTIL_ERROR_NONE;
889 Image *_image = NULL;
890 mm_util_image_h converted_image = NULL, source = NULL;
891 mm_util_enc_opt_t *_opt = (mm_util_enc_opt_t *)opt;
893 mm_util_retvm_if(!_opt, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid opt");
895 mm_util_sec_debug("path [%s]", path);
897 if (_opt->codec == IMG_CODEC_BMP) {
899 GraphicsMagick doesn't support alpha overlay(compression method:BI_ALPHABITFIELDS) for bmp.
900 Officially BMP format supports alpha overlay since BMP4(version 4), but GraphicsMagick
901 support BMP, BMP2(v2) and BMP3(v3) except BMP4.
902 So decoded_image should be converted to RGB888(RGB24) which has not alpha overlay.
903 ps. BMP4 image does not guarantee backward compatibility. BMP4 is not visible on old devices.
904 For the reasons, BMP4 is used in certain cases of windows OS, not widely used in general cases.
907 if (((mm_image_info_s *)decoded_image)->color == MM_UTIL_COLOR_RGBA) {
908 ret = mm_util_convert_B_B(decoded_image, MM_UTIL_COLOR_RGB24, &converted_image);
909 if (ret != MM_UTIL_ERROR_NONE) {
910 mm_util_error("Error: mm_util_convert_B_B failed.");
916 source = (converted_image) ? converted_image : decoded_image;
918 __mm_util_init(NULL);
920 ret = __mm_util_constitute_image(source, &_image);
921 if (ret != MM_UTIL_ERROR_NONE) {
922 mm_util_error("Error: __mm_util_constitute_image failed.");
926 ret = __mm_util_write_image_to_file(_image, _opt, path);
930 __mm_util_finalize(_image, NULL, NULL);
932 mm_image_destroy_image(converted_image);
939 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)
941 int ret = MM_UTIL_ERROR_NONE;
942 char *tmp_file = NULL;
944 mm_util_retvm_if(!opt, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid opt");
946 ret = __mm_util_make_tmp_file(((mm_util_enc_opt_t *)opt)->codec, &tmp_file);
947 mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "Error: __mm_util_make_tmp_file failed.");
949 ret = mm_util_encode_image_to_file(decoded_image, opt, tmp_file);
950 if (ret != MM_UTIL_ERROR_NONE) {
951 mm_util_error("Error: mm_util_encode_image_P failed.");
955 ret = mm_util_file_read(tmp_file, buf, buf_size);
956 if (ret != MM_UTIL_ERROR_NONE)
957 mm_util_error("Error: mm_util_file_read failed.");
961 if (g_remove(tmp_file) != 0)
962 mm_util_sec_debug("Temporary file was not removed [%s]", tmp_file);
970 int mm_util_resize_and_rotate_P_P(const char *src_path, unsigned int req_width, unsigned int req_height, const char *dst_path)
972 int ret = MM_UTIL_ERROR_NONE;
973 Image *_image = NULL;
974 Image *_resized_image = NULL;
975 Image *_rotated_image = NULL;
976 Image *_write_image = NULL;
977 ExceptionInfo exception;
978 mm_util_rotate_type_e rotation = MM_UTIL_ROTATE_0;
980 mm_util_sec_debug("src_path [%s] req_width [%u] req_height [%u] dst_path [%s]", src_path, req_width, req_height, dst_path);
982 __mm_util_init(&exception);
984 ret = __mm_util_read_image_from_file(src_path, &_image);
985 if (ret != MM_UTIL_ERROR_NONE) {
986 mm_util_error("Error: __mm_util_read_image_from_file failed.");
990 ret = __mm_util_resize_image(_image, req_width, req_height, &_resized_image);
991 DestroyImageList(_image);
993 if (ret != MM_UTIL_ERROR_NONE) {
994 mm_util_error("Error: __mm_util_resize_image failed.");
998 switch(_resized_image->orientation) {
999 case TopRightOrientation:
1000 case RightTopOrientation:
1001 rotation = MM_UTIL_ROTATE_90;
1003 case BottomRightOrientation:
1004 case RightBottomOrientation:
1005 rotation = MM_UTIL_ROTATE_180;
1007 case BottomLeftOrientation:
1008 case LeftBottomOrientation:
1009 rotation = MM_UTIL_ROTATE_270;
1011 case TopLeftOrientation:
1012 case LeftTopOrientation:
1015 mm_util_warn("Not supported orientation %d. so apply MM_UTIL_ROTATE_0", _resized_image->orientation);
1019 if (rotation != MM_UTIL_ROTATE_0) {
1020 ret = __mm_util_rotate_image(_resized_image, rotation, &_rotated_image);
1021 if (ret != MM_UTIL_ERROR_NONE) {
1022 mm_util_error("Error: __mm_util_rotate_image failed.");
1027 _write_image = (_rotated_image) ? _rotated_image : _resized_image;
1029 /* problem. a thumbnail of grayscale image is invisible
1030 add converting grayscale image into rgb(jpeg) or true color(png)
1031 the rgb(jpeg) and true-color(png) are default(else case) value.
1033 if (IsGrayImage(_write_image, &exception)) {
1034 mm_util_info("IsGrayImage, convert image into rgb(jpeg)/true-color(png).");
1035 _write_image->is_grayscale = MagickFalse;
1038 ret = __mm_util_write_image_to_file(_write_image, NULL, dst_path);
1042 __mm_util_finalize(_resized_image, _rotated_image, &exception);