4 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: YoungHun Kim <yh8004.kim@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
24 #include <glib/gstdio.h>
27 #include <magick/api.h>
29 #include "mm_util_private.h"
30 #include "mm_util_magick.h"
32 static bool __mm_util_check_rotation(mm_util_rotate_type_e rotation);
34 static void __mm_util_magick_log_method(const ExceptionType excep, const char *message)
36 /* To exclude time, user time and pid */
37 unsigned int start_idx = 31;
39 if ((message == NULL) || (strlen(message) < start_idx)) {
43 if (excep >= ErrorException)
44 mm_util_error("[GM][Ex:%3u] %s", excep, message + start_idx);
45 else if (excep >= WarningException)
46 mm_util_warn("[GM][Ex:%3u] %s", excep, message + start_idx);
48 mm_util_debug("[GM][Ex:%3u] %s", excep, message + start_idx);
51 static void __mm_util_magick_error_handler(const ExceptionType excep, const char *reason, const char *message)
53 if (excep >= ErrorException)
54 mm_util_error("[GM][Ex:%3u][Rs:%s] %s", excep, reason, message);
56 mm_util_warn("[GM][Ex:%3u][Rs:%s] %s", excep, reason, message);
59 static void __mm_util_init(ExceptionInfo *exception)
61 InitializeMagick(NULL);
62 if (exception != NULL)
63 GetExceptionInfo(exception);
65 /* set LogEventMask to show like "all" or "warning, error" */
66 /* <LogEventMask List>
67 * "none", "information", "warning", "error", "fatalerror", "configure", "annotate",
68 * "render", "transform", "locale", "coder", "x11", "cache", "blob", "deprecate",
69 * "user", "resource", "temporaryfile", "exception", "option", "all"
71 #if (GMAGICK_DEBUG == 1)
72 SetLogEventMask("all");
74 SetLogEventMask("warning, error, fatalerror, exception");
76 SetLogMethod(__mm_util_magick_log_method);
77 SetErrorHandler(__mm_util_magick_error_handler);
78 SetFatalErrorHandler(__mm_util_magick_error_handler);
79 SetWarningHandler(__mm_util_magick_error_handler);
82 static void __mm_util_finalize(Image *image_1, Image *image_2, ExceptionInfo *exception)
85 DestroyImageList(image_1);
86 DestroyImageList(image_2);
88 if (exception != NULL)
89 DestroyExceptionInfo(exception);
94 static const char * __mm_util_get_map(mm_util_color_format_e format)
98 case MM_UTIL_COLOR_RGB24:
100 case MM_UTIL_COLOR_ARGB:
102 case MM_UTIL_COLOR_BGRA:
104 case MM_UTIL_COLOR_RGBA:
107 mm_util_error("Not supported format. [%d]", format);
112 static Image * __mm_util_constitute_image(mm_util_image_h handle)
114 mm_image_info_s *_handle = (mm_image_info_s*)handle;
115 const char *map = NULL;
116 Image *_image = NULL;
117 ExceptionInfo exception;
121 mm_util_retvm_if(!handle, NULL, "invalid handle");
123 map = __mm_util_get_map(_handle->color);
124 mm_util_retvm_if(!map, NULL, "fail to get map");
126 GetExceptionInfo(&exception);
128 /* Read image from buffer */
129 _image = ConstituteImage(_handle->width, _handle->height, map, CharPixel, _handle->data, &exception);
130 if (_image == NULL) {
131 mm_util_error("Error: Getting Image failed.");
132 if (exception.severity != UndefinedException)
133 CatchException(&exception);
136 DestroyExceptionInfo(&exception);
143 static Image * __mm_util_rotate_image(Image *image, mm_util_rotate_type_e rotation)
145 Image *_processed_image = NULL;
146 ExceptionInfo exception;
150 mm_util_retvm_if(image == NULL, NULL, "invalid image");
152 GetExceptionInfo(&exception);
155 case MM_UTIL_ROTATE_0:
156 case MM_UTIL_ROTATE_90:
157 case MM_UTIL_ROTATE_180:
158 case MM_UTIL_ROTATE_270:
160 RotateImage(const Image *image,const double degrees, ExceptionInfo *exception)
161 degrees: Specifies the number of degrees to rotate the image.
162 degrees is rotation multiplied by 90.
164 _processed_image = RotateImage(image, (rotation * 90), &exception);
166 case MM_UTIL_ROTATE_FLIP_HORZ:
167 _processed_image = FlopImage(image, &exception);
169 case MM_UTIL_ROTATE_FLIP_VERT:
170 _processed_image = FlipImage(image, &exception);
173 mm_util_error("Invalid rotation. [%d]", rotation);
177 if (_processed_image == NULL) {
178 mm_util_error("Error: Image processing failed.");
179 if (exception.severity != UndefinedException)
180 CatchException(&exception);
183 DestroyExceptionInfo(&exception);
187 return _processed_image;
190 static Image * __mm_util_resize_image(Image *image, unsigned int width, unsigned int height)
192 Image *_processed_image = NULL;
193 Image *_sampled_image = NULL;
194 ExceptionInfo exception;
195 unsigned int check_factor = 3;
196 unsigned int sample_factor = 2;
200 mm_util_retvm_if(image == NULL, NULL, "invalid image");
202 GetExceptionInfo(&exception);
204 if ((image->columns > width * check_factor) && (image->rows > height * check_factor)) {
205 _sampled_image = SampleImage(image, width * sample_factor, height * sample_factor, &exception);
206 if (_sampled_image == (Image *) NULL)
207 mm_util_error("Error: Sampling Image failed.");
210 if (_sampled_image != NULL)
211 _processed_image = ScaleImage(_sampled_image, width, height, &exception);
213 _processed_image = ScaleImage(image, width, height, &exception);
215 if (_processed_image == NULL) {
216 mm_util_error("Error: Resizing Image failed.");
217 if (exception.severity != UndefinedException)
218 CatchException(&exception);
221 DestroyImageList(_sampled_image);
223 DestroyExceptionInfo(&exception);
227 return _processed_image;
230 static Image * __mm_util_read_image_from_file(const char *path)
232 ImageInfo *_image_info = NULL;
233 Image *_image = NULL;
234 ExceptionInfo exception;
238 mm_util_retvm_if(!MMUTIL_STRING_VALID(path), NULL, "invalid path");
240 GetExceptionInfo(&exception);
242 _image_info = CloneImageInfo(0);
243 mm_util_retvm_if(!_image_info, NULL, "Error: CloneImageInfo failed.");
244 g_strlcpy(_image_info->filename, path, sizeof(_image_info->filename));
246 AddDefinition(_image_info, "jpeg", "dct-method", "FASTEST", &exception);
247 AddDefinition(_image_info, "jpeg", "block-smoothing", "FALSE", &exception);
248 AddDefinition(_image_info, "jpeg", "fancy-upsampling", "FALSE", &exception);
250 _image = ReadImage(_image_info, &exception);
252 if (_image == NULL) {
253 mm_util_error("Error: Reading Image failed.");
254 if (exception.severity != UndefinedException)
255 CatchException(&exception);
258 DestroyImageInfo(_image_info);
259 DestroyExceptionInfo(&exception);
266 static Image * __mm_util_read_image_from_buffer(const void *buf, size_t buf_size)
268 ImageInfo *_image_info = NULL;
269 Image *_image = NULL;
270 ExceptionInfo exception;
274 mm_util_retvm_if(!buf, NULL, "invalid buf");
275 mm_util_retvm_if(buf_size == 0, NULL, "invalid buf_size");
277 GetExceptionInfo(&exception);
279 _image_info = CloneImageInfo(0);
280 mm_util_retvm_if(!_image_info, NULL, "Error: CloneImageInfo failed.");
281 _image_info->blob = (void *)buf;
282 _image_info->length = buf_size;
284 AddDefinition(_image_info, "jpeg", "dct-method", "FASTEST", &exception);
285 AddDefinition(_image_info, "jpeg", "block-smoothing", "FALSE", &exception);
286 AddDefinition(_image_info, "jpeg", "fancy-upsampling", "FALSE", &exception);
288 _image = ReadImage(_image_info, &exception);
290 if (_image == NULL) {
291 mm_util_error("Error: Reading Image failed.");
292 if (exception.severity != UndefinedException)
293 CatchException(&exception);
296 DestroyImageInfo(_image_info);
297 DestroyExceptionInfo(&exception);
304 static int __mm_util_write_image_to_file(Image *image, const char *out_path)
306 int ret = MM_UTIL_ERROR_NONE;
307 ImageInfo *_image_info = NULL;
308 ExceptionInfo exception;
312 mm_util_retvm_if(image == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image");
313 mm_util_retvm_if(!MMUTIL_STRING_VALID(out_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid out_path");
315 GetExceptionInfo(&exception);
317 _image_info = CloneImageInfo(0);
318 mm_util_retvm_if(_image_info == NULL, MM_UTIL_ERROR_INVALID_OPERATION, "Error: CloneImageInfo failed.");
320 SAFE_STRLCPY(image->filename, out_path, sizeof(image->filename));
321 image->filename[MaxTextExtent-1] = '\0';
323 AddDefinition(_image_info, "jpeg", "dct-method", "FASTEST", &exception);
324 AddDefinition(_image_info, "jpeg", "optimize-coding", "FALSE", &exception);
325 DeleteImageProfile(image, "EXIF");
326 DeleteImageProfile(image, "8BIM");
327 DeleteImageProfile(image, "ICM");
328 DeleteImageProfile(image, "IPTC");
329 DeleteImageProfile(image, "XMP");
331 if (WriteImage (_image_info, image) == MagickFalse) {
332 mm_util_error("Error: Writing Image failed.");
333 if (exception.severity != UndefinedException)
334 CatchException(&exception);
336 ret = MM_UTIL_ERROR_INVALID_OPERATION;
339 DestroyImageInfo(_image_info);
340 DestroyExceptionInfo(&exception);
347 static int __mm_util_dispatch_image(Image *image, mm_util_color_format_e format, mm_util_image_h *dispatched_image)
349 int ret = MM_UTIL_ERROR_NONE;
350 ExceptionInfo exception;
351 size_t pixels_size = 0;
353 unsigned int width = 0;
354 unsigned int height = 0;
355 const char *map = NULL;
359 mm_util_retvm_if(!image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image");
361 map = __mm_util_get_map(format);
362 mm_util_retvm_if(!map, MM_UTIL_ERROR_INVALID_PARAMETER, "fail to get map");
364 GetExceptionInfo(&exception);
366 width = image->columns;
367 height = image->rows;
369 pixels_size = sizeof(unsigned char) * strlen(map) * width * height;
370 pixels = MagickMalloc(pixels_size);
372 if (pixels == NULL) {
373 mm_util_error("Error: MagickMalloc failed.");
374 ret = MM_UTIL_ERROR_OUT_OF_MEMORY;
378 ret = DispatchImage(image, 0, 0, width, height, map, CharPixel, pixels, &exception);
379 if (ret == MagickFail) {
380 mm_util_error("Failed to Dispatch Image into dst buffer");
381 if (exception.severity != UndefinedException)
382 CatchException(&exception);
385 ret = MM_UTIL_ERROR_INVALID_OPERATION;
389 ret = mm_image_create_image(width, height, format, pixels, pixels_size, dispatched_image);
390 if (ret != MM_UTIL_ERROR_NONE)
391 mm_util_error("Error: mm_image_create_image failed.");
397 DestroyExceptionInfo(&exception);
404 static bool __mm_util_check_rotation(mm_util_rotate_type_e rotation)
407 case MM_UTIL_ROTATE_0:
408 case MM_UTIL_ROTATE_90:
409 case MM_UTIL_ROTATE_180:
410 case MM_UTIL_ROTATE_270:
411 case MM_UTIL_ROTATE_FLIP_HORZ:
412 case MM_UTIL_ROTATE_FLIP_VERT:
419 static int __mm_util_make_tmp_file(mm_util_img_codec_type type, char **path)
422 const char *template = NULL;
423 GError *error = NULL;
425 /* GraphicsMagick determine image codec from file extension */
428 template = "XXXXXX.gif";
431 template = "XXXXXX.png";
434 template = "XXXXXX.jpg";
437 template = "XXXXXX.bmp";
440 mm_util_error("invalid type [%u]", type);
441 return MM_UTIL_ERROR_INVALID_PARAMETER;
444 fd = g_file_open_tmp(template, path, &error);
446 mm_util_sec_debug("g_file_open_tmp error [%s]", error->message);
448 return MM_UTIL_ERROR_INVALID_OPERATION;
451 mm_util_sec_debug("g_file_open_tmp [%s]", *path);
455 return MM_UTIL_ERROR_NONE;
458 static int __mm_util_read_tmp_file(const char *path, void **data, size_t *length)
460 int ret = MM_UTIL_ERROR_NONE;
465 mm_util_retvm_if(!path, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid path");
466 mm_util_retvm_if(!data, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid data");
467 mm_util_retvm_if(!length, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid length");
469 mm_util_sec_debug("read path [%s]", path);
471 fp = fopen(path, "r");
473 mm_util_stderror("fopen failed");
474 return MM_UTIL_ERROR_INVALID_OPERATION;
477 if (fseek(fp, 0, SEEK_END) < 0) {
478 mm_util_stderror("fseek failed");
479 ret = MM_UTIL_ERROR_INVALID_OPERATION;
485 mm_util_stderror("ftell failed");
486 ret = MM_UTIL_ERROR_INVALID_OPERATION;
491 _data = g_malloc0(_length);
493 if (fread(_data, 1, _length, fp) != _length) {
494 mm_util_stderror("fread failed");
495 ret = MM_UTIL_ERROR_INVALID_OPERATION;
501 *length = (size_t)_length;
510 int mm_util_rotate_B_B(mm_util_image_h src_handle, mm_util_rotate_type_e rotation, mm_util_image_h *dst_handle)
512 int ret = MM_UTIL_ERROR_NONE;
513 mm_image_info_s *_src_handle = (mm_image_info_s*)src_handle;
514 Image *_image = NULL;
515 Image *_processed_image = NULL;
516 ExceptionInfo exception;
518 mm_util_retvm_if(!src_handle, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_handle");
519 mm_util_retvm_if(!__mm_util_check_rotation(rotation), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid rotation [%d]", rotation);
520 mm_util_retvm_if(!dst_handle, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid dst_handle");
522 mm_util_debug("rotation [%d]", rotation);
524 __mm_util_init(&exception);
526 _image = __mm_util_constitute_image(src_handle);
527 if (_image == NULL) {
528 mm_util_error("Error: __mm_util_constitute_image failed.");
529 ret = MM_UTIL_ERROR_INVALID_OPERATION;
533 _processed_image = __mm_util_rotate_image(_image, rotation);
534 if (_processed_image == NULL) {
535 mm_util_error("Error: __mm_util_rotate_image failed.");
536 ret = MM_UTIL_ERROR_INVALID_OPERATION;
540 ret = __mm_util_dispatch_image(_processed_image, _src_handle->color, dst_handle);
544 __mm_util_finalize(_image, _processed_image, &exception);
551 int mm_util_rotate_B_P(mm_util_image_h src_handle, mm_util_rotate_type_e rotation, const char *dst_path)
553 int ret = MM_UTIL_ERROR_NONE;
554 Image *_image = NULL;
555 Image *_processed_image = NULL;
556 ExceptionInfo exception;
558 mm_util_retvm_if(!src_handle, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_handle");
559 mm_util_retvm_if(!__mm_util_check_rotation(rotation), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid rotation [%d]", rotation);
560 mm_util_retvm_if(!MMUTIL_STRING_VALID(dst_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid dst_path");
562 mm_util_sec_debug("rotation [%d] dst_path [%s]", rotation, dst_path);
564 __mm_util_init(&exception);
566 _image = __mm_util_constitute_image(src_handle);
567 if (_image == NULL) {
568 mm_util_error("Error: __mm_util_constitute_image failed.");
569 ret = MM_UTIL_ERROR_INVALID_OPERATION;
573 _processed_image = __mm_util_rotate_image(_image, rotation);
574 if (_processed_image == NULL) {
575 mm_util_error("Error: __mm_util_rotate_image failed.");
576 ret = MM_UTIL_ERROR_INVALID_OPERATION;
580 ret = __mm_util_write_image_to_file(_processed_image, dst_path);
584 __mm_util_finalize(_image, _processed_image, &exception);
591 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)
593 int ret = MM_UTIL_ERROR_NONE;
594 Image *_image = NULL;
595 Image *_processed_image = NULL;
596 ExceptionInfo exception;
598 mm_util_retvm_if(!MMUTIL_STRING_VALID(src_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_path");
599 mm_util_retvm_if(!__mm_util_check_rotation(rotation), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid rotation [%d]", rotation);
600 mm_util_retvm_if(!dst_handle, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid dst_handle");
602 mm_util_sec_debug("src_path [%s] rotation [%d] req_format [%d]", src_path, rotation, req_format);
604 __mm_util_init(&exception);
606 _image = __mm_util_read_image_from_file(src_path);
607 if (_image == NULL) {
608 mm_util_error("Error: __mm_util_read_image_from_file failed.");
609 ret = MM_UTIL_ERROR_INVALID_OPERATION;
613 _processed_image = __mm_util_rotate_image(_image, rotation);
614 if (_processed_image == NULL) {
615 mm_util_error("Error: __mm_util_rotate_image failed.");
616 ret = MM_UTIL_ERROR_INVALID_OPERATION;
620 ret = __mm_util_dispatch_image(_processed_image, req_format, dst_handle);
624 __mm_util_finalize(_image, _processed_image, &exception);
632 int mm_util_rotate_P_P(const char *src_path, mm_util_rotate_type_e rotation, const char *dst_path)
634 int ret = MM_UTIL_ERROR_NONE;
635 Image *_image = NULL;
636 Image *_processed_image = NULL;
637 ExceptionInfo exception;
639 mm_util_retvm_if(!MMUTIL_STRING_VALID(src_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_path");
640 mm_util_retvm_if(!__mm_util_check_rotation(rotation), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid rotation [%d]", rotation);
641 mm_util_retvm_if(!MMUTIL_STRING_VALID(dst_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid dst_path");
643 mm_util_sec_debug("src_path [%s] rotation [%d] dst_path [%s]", src_path, rotation, dst_path);
645 __mm_util_init(&exception);
647 _image = __mm_util_read_image_from_file(src_path);
648 if (_image == NULL) {
649 mm_util_error("Error: __mm_util_read_image_from_file failed.");
650 ret = MM_UTIL_ERROR_INVALID_OPERATION;
654 _processed_image = __mm_util_rotate_image(_image, rotation);
655 if (_processed_image == NULL) {
656 mm_util_error("Error: __mm_util_rotate_image failed.");
657 ret = MM_UTIL_ERROR_INVALID_OPERATION;
661 ret = __mm_util_write_image_to_file(_processed_image, dst_path);
665 __mm_util_finalize(_image, _processed_image, &exception);
672 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)
674 int ret = MM_UTIL_ERROR_NONE;
675 mm_image_info_s *_src_handle = (mm_image_info_s*)src_handle;
676 Image *_image = NULL;
677 Image *_processed_image = NULL;
678 ExceptionInfo exception;
680 mm_util_retvm_if(!src_handle, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_handle");
681 mm_util_retvm_if((req_width == 0) || (req_height == 0), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid size W[%d] H[%d]", req_width, req_height);
682 mm_util_retvm_if(!dst_handle, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid dst_handle");
684 mm_util_debug("req_width [%u] req_height [%u]", req_width, req_height);
686 __mm_util_init(&exception);
688 _image = __mm_util_constitute_image(src_handle);
689 if (_image == NULL) {
690 mm_util_error("Error: __mm_util_constitute_image failed.");
691 ret = MM_UTIL_ERROR_INVALID_OPERATION;
695 if ((_image->columns < req_width) || (_image->rows < req_height)) {
696 mm_util_error("Wrong Size. image [%lu * %lu], request [%u * %u]", _image->columns, _image->rows, req_width, req_height);
697 ret = MM_UTIL_ERROR_INVALID_PARAMETER;
701 _processed_image = __mm_util_resize_image(_image, req_width, req_height);
702 if (_processed_image == NULL) {
703 mm_util_error("Error: __mm_util_resize_image failed.");
704 ret = MM_UTIL_ERROR_INVALID_OPERATION;
708 ret = __mm_util_dispatch_image(_processed_image, _src_handle->color, dst_handle);
712 __mm_util_finalize(_image, _processed_image, &exception);
719 int mm_util_resize_B_P(mm_util_image_h src_handle, unsigned int req_width, unsigned int req_height, const char *dst_path)
721 int ret = MM_UTIL_ERROR_NONE;
722 Image *_image = NULL;
723 Image *_processed_image = NULL;
724 ExceptionInfo exception;
726 mm_util_retvm_if(!src_handle, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_handle");
727 mm_util_retvm_if((req_width == 0) || (req_height == 0), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid size W[%d] H[%d]", req_width, req_height);
728 mm_util_retvm_if(!MMUTIL_STRING_VALID(dst_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid dst_path");
730 mm_util_sec_debug("req_width [%u] req_height [%u] dst_path [%s]", req_width, req_height, dst_path);
732 __mm_util_init(&exception);
734 _image = __mm_util_constitute_image(src_handle);
735 if (_image == NULL) {
736 mm_util_error("Error: __mm_util_constitute_image failed.");
737 ret = MM_UTIL_ERROR_INVALID_OPERATION;
741 if ((_image->columns < req_width) || (_image->rows < req_height)) {
742 mm_util_error("Wrong Size. image [%lu * %lu], request [%u * %u]", _image->columns, _image->rows, req_width, req_height);
743 ret = MM_UTIL_ERROR_INVALID_PARAMETER;
747 _processed_image = __mm_util_resize_image(_image, req_width, req_height);
748 if (_processed_image == NULL) {
749 mm_util_error("Error: __mm_util_resize_image failed.");
750 ret = MM_UTIL_ERROR_INVALID_OPERATION;
754 ret = __mm_util_write_image_to_file(_processed_image, dst_path);
758 __mm_util_finalize(_image, _processed_image, &exception);
765 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)
767 int ret = MM_UTIL_ERROR_NONE;
768 Image *_image = NULL;
769 Image *_processed_image = NULL;
770 ExceptionInfo exception;
772 mm_util_retvm_if(!MMUTIL_STRING_VALID(src_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_path");
773 mm_util_retvm_if((req_width == 0) || (req_height == 0), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid size W[%d] H[%d]", req_width, req_height);
774 mm_util_retvm_if(!dst_handle, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid dst_handle");
776 mm_util_sec_debug("src_path [%s] req_width [%u] req_height [%u]", src_path, req_width, req_height);
778 __mm_util_init(&exception);
780 _image = __mm_util_read_image_from_file(src_path);
781 if (_image == NULL) {
782 mm_util_error("Error: __mm_util_read_image_from_file failed.");
783 ret = MM_UTIL_ERROR_INVALID_OPERATION;
787 if ((_image->columns < req_width) || (_image->rows < req_height)) {
788 mm_util_error("Wrong Size. image [%lu * %lu], request [%u * %u]", _image->columns, _image->rows, req_width, req_height);
789 ret = MM_UTIL_ERROR_INVALID_PARAMETER;
793 _processed_image = __mm_util_resize_image(_image, req_width, req_height);
794 if (_processed_image == NULL) {
795 mm_util_error("Error: __mm_util_resize_image failed.");
796 ret = MM_UTIL_ERROR_INVALID_OPERATION;
800 ret = __mm_util_dispatch_image(_processed_image, req_format, dst_handle);
804 __mm_util_finalize(_image, _processed_image, &exception);
811 int mm_util_resize_P_P(const char *src_path, unsigned int req_width, unsigned int req_height, const char *dst_path)
813 int ret = MM_UTIL_ERROR_NONE;
814 Image *_image = NULL;
815 Image *_processed_image = NULL;
816 ExceptionInfo exception;
818 mm_util_retvm_if(!MMUTIL_STRING_VALID(src_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_path");
819 mm_util_retvm_if((req_width == 0) || (req_height == 0), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid size W[%d] H[%d]", req_width, req_height);
820 mm_util_retvm_if(!MMUTIL_STRING_VALID(dst_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid dst_path");
822 mm_util_sec_debug("src_path [%s] req_width [%u] req_height [%u] dst_path [%s]", src_path, req_width, req_height, dst_path);
824 __mm_util_init(&exception);
826 _image = __mm_util_read_image_from_file(src_path);
827 if (_image == NULL) {
828 mm_util_error("Error: __mm_util_read_image_from_file failed.");
829 ret = MM_UTIL_ERROR_INVALID_OPERATION;
833 if ((_image->columns < req_width) || (_image->rows < req_height)) {
834 mm_util_error("Wrong Size. image [%lu * %lu], request [%u * %u]", _image->columns, _image->rows, req_width, req_height);
835 ret = MM_UTIL_ERROR_INVALID_PARAMETER;
839 _processed_image = __mm_util_resize_image(_image, req_width, req_height);
840 if (_processed_image == NULL) {
841 mm_util_error("Error: __mm_util_resize_image failed.");
842 ret = MM_UTIL_ERROR_INVALID_OPERATION;
846 ret = __mm_util_write_image_to_file(_processed_image, dst_path);
850 __mm_util_finalize(_image, _processed_image, &exception);
857 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)
859 int ret = MM_UTIL_ERROR_NONE;
860 mm_image_info_s *_src_handle = (mm_image_info_s*)src_handle;
861 Image *_image = NULL;
862 ExceptionInfo exception;
864 mm_util_retvm_if(!src_handle, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_handle");
865 mm_util_retvm_if(!dst_handle, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid dst_handle");
867 mm_util_debug("input format [%d] req_format [%d]", _src_handle->color, req_format);
869 __mm_util_init(&exception);
871 _image = __mm_util_constitute_image(src_handle);
872 if (_image == NULL) {
873 mm_util_error("Error: __mm_util_constitute_image failed.");
874 ret = MM_UTIL_ERROR_INVALID_OPERATION;
878 ret = __mm_util_dispatch_image(_image, req_format, dst_handle);
882 __mm_util_finalize(_image, NULL, &exception);
889 int mm_util_decode_image_from_file(const char *path, mm_util_color_format_e format, mm_util_image_h *decoded_image)
891 int ret = MM_UTIL_ERROR_NONE;
892 Image *_image = NULL;
894 mm_util_retvm_if(!MMUTIL_STRING_VALID(path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid path");
895 mm_util_retvm_if(!decoded_image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid decoded_image");
897 mm_util_sec_debug("path [%s] format [%d]", path, format);
899 __mm_util_init(NULL);
901 _image = __mm_util_read_image_from_file(path);
902 if (_image == NULL) {
903 mm_util_error("Error: __mm_util_read_image_from_file failed.");
904 ret = MM_UTIL_ERROR_INVALID_OPERATION;
908 ret = __mm_util_dispatch_image(_image, format, decoded_image);
912 __mm_util_finalize(_image, NULL, NULL);
919 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)
921 int ret = MM_UTIL_ERROR_NONE;
922 Image *_image = NULL;
924 mm_util_retvm_if(!buf, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid buf");
925 mm_util_retvm_if(buf_size == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid buf_size");
926 mm_util_retvm_if(!decoded_image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid decoded_image");
928 mm_util_sec_debug("path [%p] buf_size [%zu] format [%d]", buf, buf_size, format);
930 __mm_util_init(NULL);
932 _image = __mm_util_read_image_from_buffer(buf, buf_size);
933 if (_image == NULL) {
934 mm_util_error("Error: __mm_util_read_image_from_file failed.");
935 ret = MM_UTIL_ERROR_INVALID_OPERATION;
939 ret = __mm_util_dispatch_image(_image, format, decoded_image);
943 __mm_util_finalize(_image, NULL, NULL);
950 int mm_util_encode_image_to_file(mm_util_image_h decoded_image, const char *path)
952 int ret = MM_UTIL_ERROR_NONE;
953 char *extension = NULL;
954 Image *_image = NULL;
955 mm_util_image_h converted_image = NULL, source = NULL;
957 mm_util_retvm_if(!decoded_image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid decoded_image");
958 mm_util_retvm_if(!MMUTIL_STRING_VALID(path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid path");
960 mm_util_sec_debug("path [%s]", path);
962 extension = g_strrstr(path, ".");
963 mm_util_retvm_if(!MMUTIL_STRING_VALID(extension), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid path");
965 if (g_ascii_strcasecmp(extension, ".bmp") == 0) {
967 GraphicsMagick doesn't support alpha overlay(compression method:BI_ALPHABITFIELDS) for bmp.
968 Officialy BMP format supports alpha overlay since BMP4(version 4), but GraphicsMagick
969 support BMP, BMP2(v2) and BMP3(v3) except BMP4.
970 So decoded_image should be converted to RGB888(RGB24) which has not alpha overlay.
971 ps. BMP4 image does not guarantee backward compatibility. BMP4 is not visible on old devices.
972 For the reasons, BMP4 is used in certain cases of windows OS, not widely used in general cases.
975 if (((mm_image_info_s *)decoded_image)->color == MM_UTIL_COLOR_RGBA) {
976 ret = mm_util_convert_B_B(decoded_image, MM_UTIL_COLOR_RGB24, &converted_image);
977 if (ret != MM_UTIL_ERROR_NONE) {
978 mm_util_error("Error: mm_util_convert_B_B failed.");
984 source = (converted_image) ? converted_image : decoded_image;
986 __mm_util_init(NULL);
988 _image = __mm_util_constitute_image(source);
989 if (_image == NULL) {
990 mm_util_error("Error: __mm_util_constitute_image failed.");
991 ret = MM_UTIL_ERROR_INVALID_OPERATION;
995 ret = __mm_util_write_image_to_file(_image, path);
999 __mm_util_finalize(_image, NULL, NULL);
1001 mm_image_destroy_image(converted_image);
1008 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)
1010 int ret = MM_UTIL_ERROR_NONE;
1011 char *tmp_file = NULL;
1013 mm_util_retvm_if(!decoded_image, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid decoded_image");
1014 mm_util_retvm_if(!buf, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid buf");
1015 mm_util_retvm_if(buf_size == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid buf_size");
1017 mm_util_sec_debug("type [%d]", type);
1019 ret = __mm_util_make_tmp_file(type, &tmp_file);
1020 mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "Error: __mm_util_make_tmp_file failed.");
1022 ret = mm_util_encode_image_to_file(decoded_image, tmp_file);
1023 if (ret != MM_UTIL_ERROR_NONE) {
1024 mm_util_error("Error: mm_util_encode_image_P failed.");
1028 ret = __mm_util_read_tmp_file(tmp_file, buf, buf_size);
1029 if (ret != MM_UTIL_ERROR_NONE)
1030 mm_util_error("Error: __mm_util_read_tmp_file failed.");
1034 if (g_remove(tmp_file) != 0)
1035 mm_util_sec_debug("Temporary file was not removed [%s]", tmp_file);
1043 int mm_util_resize_and_rotate_P_P(const char *src_path, unsigned int req_width, unsigned int req_height, const char *dst_path)
1045 int ret = MM_UTIL_ERROR_NONE;
1046 Image *_image = NULL;
1047 Image *_resized_image = NULL;
1048 Image *_rotated_image = NULL;
1049 Image *_write_image = NULL;
1050 ExceptionInfo exception;
1051 mm_util_rotate_type_e rotation = MM_UTIL_ROTATE_0;
1053 mm_util_retvm_if(!MMUTIL_STRING_VALID(src_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_path");
1054 mm_util_retvm_if((req_width == 0) || (req_height == 0), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid size W[%d] H[%d]", req_width, req_height);
1055 mm_util_retvm_if(!MMUTIL_STRING_VALID(dst_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid dst_path");
1057 mm_util_sec_debug("src_path [%s] req_width [%u] req_height [%u] dst_path [%s]", src_path, req_width, req_height, dst_path);
1059 __mm_util_init(&exception);
1061 _image = __mm_util_read_image_from_file(src_path);
1062 if (_image == NULL) {
1063 mm_util_error("Error: __mm_util_read_image_from_file failed.");
1064 ret = MM_UTIL_ERROR_INVALID_OPERATION;
1068 if ((_image->columns < req_width) || (_image->rows < req_height)) {
1069 mm_util_error("Wrong Size. image [%lu * %lu], request [%u * %u]", _image->columns, _image->rows, req_width, req_height);
1070 ret = MM_UTIL_ERROR_INVALID_PARAMETER;
1074 _resized_image = __mm_util_resize_image(_image, req_width, req_height);
1075 if (_resized_image == NULL) {
1076 mm_util_error("Error: __mm_util_resize_image failed.");
1077 ret = MM_UTIL_ERROR_INVALID_OPERATION;
1081 switch(_resized_image->orientation) {
1082 case TopRightOrientation:
1083 case RightTopOrientation:
1084 rotation = MM_UTIL_ROTATE_90;
1086 case BottomRightOrientation:
1087 case RightBottomOrientation:
1088 rotation = MM_UTIL_ROTATE_180;
1090 case BottomLeftOrientation:
1091 case LeftBottomOrientation:
1092 rotation = MM_UTIL_ROTATE_270;
1094 case TopLeftOrientation:
1095 case LeftTopOrientation:
1098 mm_util_warn("Not supported orientation %d. so apply MM_UTIL_ROTATE_0", _resized_image->orientation);
1102 if (rotation != MM_UTIL_ROTATE_0) {
1103 _rotated_image = __mm_util_rotate_image(_resized_image, rotation);
1104 if (_rotated_image == NULL) {
1105 mm_util_error("Error: __mm_util_resize_image failed.");
1106 ret = MM_UTIL_ERROR_INVALID_OPERATION;
1111 _write_image = (_rotated_image) ? _rotated_image : _resized_image;
1113 /* problem. a thumbnail of grayscale image is invisible
1114 add converting grayscale image into rgb(jpeg) or true color(png)
1115 the rgb(jpeg) and true-color(png) are default(else case) value.
1117 if (IsGrayImage(_write_image, &exception)) {
1118 mm_util_info("IsGrayImage, convert image into rgb(jpeg)/true-color(png).");
1119 _write_image->is_grayscale = MagickFalse;
1122 ret = __mm_util_write_image_to_file(_write_image, dst_path);
1126 DestroyImageList(_image);
1127 __mm_util_finalize(_resized_image, _rotated_image, &exception);