Bug fix. add lock for GraphicsMagick function
[platform/core/multimedia/libmm-utility.git] / imgp / mm_util_imgp.c
1 /*
2  * libmm-utility
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20 #include <limits.h>
21 #include <dlfcn.h>
22 #include <glib.h>
23 #include "mm_util_private.h"
24 #include "mm_util_imgp.h"
25 #include "mm_util_imgp_internal.h"
26
27 #define GEN_MASK(x) ((1<<(x))-1)
28 #define ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) & ~GEN_MASK(x))
29 #define DIV_ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) >> (x))
30
31 typedef bool(*IMGPInfoFunc) (imgp_info_s *, const unsigned char *, unsigned char **, imgp_type_e);
32
33 static int __check_valid_picture_size(unsigned int width, unsigned int height)
34 {
35         if ((size_t)((width + 128) * (height + 128)) < (size_t)(INT_MAX/4))
36                 return MM_UTIL_ERROR_NONE;
37
38         return MM_UTIL_ERROR_INVALID_PARAMETER;
39 }
40
41 static bool __mm_gst_can_resize_format(mm_util_color_format_e color_format)
42 {
43         mm_util_debug("color_format [%d]", color_format);
44
45         switch (color_format) {
46         case MM_UTIL_COLOR_YUV420:
47         case MM_UTIL_COLOR_YUV422:
48         case MM_UTIL_COLOR_I420:
49         case MM_UTIL_COLOR_UYVY:
50         case MM_UTIL_COLOR_YUYV:
51         case MM_UTIL_COLOR_RGB16:
52         case MM_UTIL_COLOR_RGB24:
53         case MM_UTIL_COLOR_ARGB:
54         case MM_UTIL_COLOR_BGRA:
55         case MM_UTIL_COLOR_RGBA:
56         case MM_UTIL_COLOR_BGRX:
57                 return true;
58         default:
59                 mm_util_error("Not supported format");  //only not support NV12
60                 return false;
61         }
62 }
63
64 static bool __mm_gst_can_rotate_format(mm_util_color_format_e color_format)
65 {
66         mm_util_debug("color_format [%d]", color_format);
67
68         switch (color_format) {
69         case MM_UTIL_COLOR_YUV420:
70         case MM_UTIL_COLOR_I420:
71         case MM_UTIL_COLOR_RGB24:
72         case MM_UTIL_COLOR_ARGB:
73         case MM_UTIL_COLOR_BGRA:
74         case MM_UTIL_COLOR_RGBA:
75                 return true;
76         default:
77                 mm_util_error("Not supported format");
78                 return false;
79         }
80 }
81
82 static int __mm_util_get_image_size(mm_util_color_format_e format, unsigned int width, unsigned int height, bool is_crop, size_t *imgsize)
83 {
84         unsigned char x_chroma_shift = 0;
85         unsigned char y_chroma_shift = 0;
86         size_t w2, h2, stride, stride2;
87         size_t size, size2;
88         size_t _width = (size_t)width;
89         size_t _height = (size_t)height;
90
91         mm_util_fenter();
92
93         mm_util_retvm_if(imgsize == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid imgsize");
94         mm_util_retvm_if(!IS_VALID_COLOR(format), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid format(%u)", format);
95         mm_util_retvm_if(__check_valid_picture_size(width, height) != MM_UTIL_ERROR_NONE, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid width(%u) or height(%u)", width, height);
96
97         switch (format) {
98         case MM_UTIL_COLOR_I420:
99         case MM_UTIL_COLOR_YUV420:
100                 x_chroma_shift = 1;
101                 y_chroma_shift = 1;
102                 stride = MM_UTIL_ROUND_UP_4(_width);
103                 h2 = ROUND_UP_X(_height, x_chroma_shift);
104                 size = stride * h2;
105                 w2 = DIV_ROUND_UP_X(_width, x_chroma_shift);
106                 stride2 = MM_UTIL_ROUND_UP_4(w2);
107                 h2 = DIV_ROUND_UP_X(_height, y_chroma_shift);
108                 size2 = stride2 * h2;
109                 *imgsize = size + 2 * size2;
110                 break;
111         case MM_UTIL_COLOR_YUV422:
112         case MM_UTIL_COLOR_YUYV:
113         case MM_UTIL_COLOR_UYVY:
114         case MM_UTIL_COLOR_NV16:
115         case MM_UTIL_COLOR_NV61:
116                 stride = MM_UTIL_ROUND_UP_4(_width) * 2;
117                 size = stride * _height;
118                 *imgsize = size;
119                 break;
120
121         case MM_UTIL_COLOR_RGB16:
122                 stride = 2 * (is_crop ? _width : MM_UTIL_ROUND_UP_4(_width));
123                 size = stride * _height;
124                 *imgsize = size;
125                 break;
126
127         case MM_UTIL_COLOR_RGB24:
128                 stride = 3 * (is_crop ? _width : MM_UTIL_ROUND_UP_4(_width));
129                 size = stride * _height;
130                 *imgsize = size;
131                 break;
132
133         case MM_UTIL_COLOR_ARGB:
134         case MM_UTIL_COLOR_BGRA:
135         case MM_UTIL_COLOR_RGBA:
136         case MM_UTIL_COLOR_BGRX:
137                 stride = _width * 4;
138                 size = stride * _height;
139                 *imgsize = size;
140                 break;
141
142         case MM_UTIL_COLOR_NV12:
143         case MM_UTIL_COLOR_NV12_TILED:
144         case MM_UTIL_COLOR_NV21:
145                 x_chroma_shift = 1;
146                 y_chroma_shift = 1;
147                 stride = MM_UTIL_ROUND_UP_4(_width);
148                 h2 = ROUND_UP_X(_height, y_chroma_shift);
149                 size = stride * h2;
150                 w2 = 2 * DIV_ROUND_UP_X(_width, x_chroma_shift);
151                 stride2 = MM_UTIL_ROUND_UP_4(w2);
152                 h2 = DIV_ROUND_UP_X(_height, y_chroma_shift);
153                 size2 = stride2 * h2;
154                 *imgsize = size + size2;
155                 break;
156
157         default:
158                 mm_util_error("Not supported format [%u]", format);
159                 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
160         }
161
162         mm_util_debug("format: %u, *imgsize: %zu", format, *imgsize);
163
164         return MM_UTIL_ERROR_NONE;
165 }
166
167 static int __mm_set_imgp_info_s(imgp_info_s *_imgp_info_s, mm_util_color_format_e src_format, unsigned int src_width, unsigned int src_height, mm_util_color_format_e dst_format, unsigned int dst_width, unsigned int dst_height, mm_util_rotate_type_e angle)
168 {
169         int ret = MM_UTIL_ERROR_NONE;
170
171         mm_util_retvm_if(_imgp_info_s == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid _imgp_info_s");
172
173         _imgp_info_s->src_format = src_format;
174         _imgp_info_s->src_width = src_width;
175         _imgp_info_s->src_height = src_height;
176
177         _imgp_info_s->dst_format = dst_format;
178         _imgp_info_s->dst_width = dst_width;
179         _imgp_info_s->dst_height = dst_height;
180         _imgp_info_s->buffer_size = 0;
181         _imgp_info_s->angle = angle;
182
183         mm_util_debug("src_w[%u] src_h[%u] dst_w[%u] dst_h[%u] rotation[%d]", _imgp_info_s->src_width, _imgp_info_s->src_height, _imgp_info_s->dst_width, _imgp_info_s->dst_height, _imgp_info_s->angle);
184
185         return ret;
186 }
187
188 static void __mm_util_imgp_finalize(void *module, imgp_info_s *_imgp_info_s)
189 {
190         if (module)
191                 dlclose(module);
192
193         g_free(_imgp_info_s);
194 }
195
196 static void __mm_util_crop_rgb32(const unsigned char *src, unsigned int src_width, unsigned int src_height,
197 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
198 {
199         unsigned int idx = 0;
200         unsigned long src_bytesperline = (unsigned long)src_width * 4;
201         unsigned long dst_bytesperline = (unsigned long)crop_dest_width * 4;
202
203         src += crop_start_y * src_bytesperline + 4 * crop_start_x;
204
205         for (idx = 0; idx < crop_dest_height; idx++) {
206                 memcpy(dst, src, dst_bytesperline);
207                 src += src_bytesperline;
208                 dst += dst_bytesperline;
209         }
210 }
211
212 static void __mm_util_crop_rgb24(const unsigned char *src, unsigned int src_width, unsigned int src_height,
213 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
214 {
215         unsigned int idx = 0;
216         unsigned long src_bytesperline = (unsigned long)src_width * 3;
217         unsigned long dst_bytesperline = (unsigned long)crop_dest_width * 3;
218
219         src += crop_start_y * src_bytesperline + 3 * crop_start_x;
220
221         for (idx = 0; idx < crop_dest_height; idx++) {
222                 memcpy(dst, src, dst_bytesperline);
223                 src += src_bytesperline;
224                 dst += dst_bytesperline;
225         }
226 }
227
228 static void __mm_util_crop_rgb16(const unsigned char *src, unsigned int src_width, unsigned int src_height,
229 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
230 {
231         unsigned int idx = 0;
232         unsigned long src_bytesperline = (unsigned long)src_width * 2;
233         unsigned long dst_bytesperline = (unsigned long)crop_dest_width * 2;
234
235         src += crop_start_y * src_bytesperline + 2 * crop_start_x;
236
237         for (idx = 0; idx < crop_dest_height; idx++) {
238                 memcpy(dst, src, dst_bytesperline);
239                 src += src_bytesperline;
240                 dst += dst_bytesperline;
241         }
242 }
243
244 static void __mm_util_crop_yuv420(const unsigned char *src, unsigned int src_width, unsigned int src_height,
245 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
246 {
247         unsigned int idx = 0;
248         unsigned int start_x = crop_start_x;
249         unsigned int start_y = crop_start_y;
250
251         const unsigned char *_src = src + start_y * src_width + start_x;
252
253         /* Y */
254         for (idx = 0; idx < crop_dest_height; idx++) {
255                 memcpy(dst, _src, crop_dest_width);
256                 _src += src_width;
257                 dst += crop_dest_width;
258         }
259
260         /* U */
261         _src = src + src_height * src_width + (start_y / 2) * src_width / 2 + start_x / 2;
262         for (idx = 0; idx < crop_dest_height / 2; idx++) {
263                 memcpy(dst, _src, crop_dest_width / 2);
264                 _src += src_width / 2;
265                 dst += crop_dest_width / 2;
266         }
267
268         /* V */
269         _src = src + src_height * src_width * 5 / 4 + (start_y / 2) * src_width / 2 + start_x / 2;
270         for (idx = 0; idx < crop_dest_height / 2; idx++) {
271                 memcpy(dst, _src, crop_dest_width / 2);
272                 _src += src_width / 2;
273                 dst += crop_dest_width / 2;
274         }
275 }
276
277 static IMGPInfoFunc __mm_util_initialize(void **module)
278 {
279         void *_module = NULL;
280         IMGPInfoFunc _func = NULL;
281
282         mm_util_retvm_if(!module, NULL, "invalid module");
283
284         _module = dlopen(PATH_GSTCS_LIB, RTLD_LAZY);
285         mm_util_retvm_if(!_module, NULL, "%s module open failed", PATH_GSTCS_LIB);
286
287         _func = dlsym(_module, IMGP_FUNC_NAME);
288         if (!_func) {
289                 mm_util_error("dlsym failed: %s", dlerror());
290                 dlclose(_module);
291                 return NULL;
292         }
293
294         *module = _module;
295
296         return _func;
297 }
298
299 static bool __mm_util_check_format(mm_util_color_format_e color_format)
300 {
301         if ((color_format >= MM_UTIL_COLOR_YUV420) && (color_format <= MM_UTIL_COLOR_BGRX))
302                 return true;
303
304         return false;
305 }
306
307 int mm_util_convert_colorspace(mm_util_image_h src, mm_util_color_format_e color, mm_util_image_h *dst)
308 {
309         int ret = MM_UTIL_ERROR_NONE;
310         IMGPInfoFunc _mm_util_imgp_func = NULL;
311         void *_module = NULL;
312         unsigned char *output_buffer = NULL;
313         mm_image_info_s *_src = (mm_image_info_s *)src;
314         mm_util_image_h _convert_image = NULL;
315         imgp_info_s *_imgp_info_s = NULL;
316
317         mm_util_fenter();
318
319         mm_util_retvm_if(!IS_VALID_IMAGE(src), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid src");
320         mm_util_retvm_if(!__mm_util_check_format(color), MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "Not supported format [%d]", color);
321         mm_util_retvm_if(!dst, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid dst");
322
323         mm_util_debug("[Input] format[%d]", color);
324         mm_image_debug_image(src, "Input");
325
326         _mm_util_imgp_func = __mm_util_initialize(&_module);
327         mm_util_retvm_if(!_mm_util_imgp_func, MM_UTIL_ERROR_INVALID_OPERATION, "failed to __mm_util_initialize()");
328
329         _imgp_info_s = g_new0(imgp_info_s, 1);
330
331         ret = __mm_set_imgp_info_s(_imgp_info_s, _src->color, _src->width, _src->height, color, _src->width, _src->height, MM_UTIL_ROTATE_0);
332         if (ret != MM_UTIL_ERROR_NONE) {
333                 mm_util_error("__mm_set_imgp_info_s failed");
334                 ret = MM_UTIL_ERROR_INVALID_OPERATION;
335                 goto ERROR;
336         }
337
338         ret = _mm_util_imgp_func(_imgp_info_s, _src->data, &output_buffer, IMGP_CSC);
339         if (ret != MM_UTIL_ERROR_NONE) {
340                 mm_util_error("image processing failed");
341                 goto ERROR;
342         }
343
344         if ((_imgp_info_s->dst_width != _imgp_info_s->output_stride || _imgp_info_s->dst_height != _imgp_info_s->output_elevation)) {
345                 ret = mm_image_create_image(_imgp_info_s->output_stride, _imgp_info_s->output_elevation, color, output_buffer, _imgp_info_s->buffer_size, &_convert_image);
346                 if (ret != MM_UTIL_ERROR_NONE) {
347                         mm_util_error("mm_image_create_image failed");
348                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
349                         goto ERROR;
350                 }
351
352                 ret = mm_util_crop_image(_convert_image, 0, 0, _imgp_info_s->dst_width, _imgp_info_s->dst_height, dst);
353                 mm_image_destroy_image(_convert_image);
354                 if (ret != MM_UTIL_ERROR_NONE) {
355                         mm_util_error("mm_util_crop_image failed");
356                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
357                         goto ERROR;
358                 }
359         } else {
360                 ret = mm_image_create_image(_src->width, _src->height, color, output_buffer, _imgp_info_s->buffer_size, dst);
361                 if (ret != MM_UTIL_ERROR_NONE) {
362                         mm_util_error("mm_image_create_image failed");
363                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
364                         goto ERROR;
365                 }
366         }
367
368 ERROR:
369         /* Finalize */
370         __mm_util_imgp_finalize(_module, _imgp_info_s);
371         g_free(output_buffer);
372
373         mm_util_fleave();
374
375         return ret;
376 }
377
378 int mm_util_resize_image(mm_util_image_h src, unsigned int width, unsigned int height, mm_util_image_h *dst)
379 {
380         int ret = MM_UTIL_ERROR_NONE;
381         IMGPInfoFunc _mm_util_imgp_func = NULL;
382         void *_module = NULL;
383         unsigned char *output_buffer = NULL;
384         mm_image_info_s *_src = (mm_image_info_s *)src;
385         mm_util_image_h _resize_image = NULL;
386         imgp_info_s *_imgp_info_s = NULL;
387
388         mm_util_fenter();
389
390         mm_util_retvm_if(!IS_VALID_IMAGE(src), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid src");
391         mm_util_retvm_if(width == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid width");
392         mm_util_retvm_if(height == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid height");
393         mm_util_retvm_if(!dst, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid dst");
394
395         mm_util_debug("[Input] width[%u] height[%u]", width, height);
396         mm_image_debug_image(src, "Input");
397
398         _mm_util_imgp_func = __mm_util_initialize(&_module);
399         mm_util_retvm_if(!_mm_util_imgp_func, MM_UTIL_ERROR_INVALID_OPERATION, "failed to __mm_util_initialize()");
400
401         _imgp_info_s = g_new0(imgp_info_s, 1);
402
403         ret = __mm_set_imgp_info_s(_imgp_info_s, _src->color, _src->width, _src->height, _src->color, width, height, MM_UTIL_ROTATE_0);
404         if (ret != MM_UTIL_ERROR_NONE) {
405                 mm_util_error("__mm_set_imgp_info_s failed [%d]", ret);
406                 ret = MM_UTIL_ERROR_INVALID_OPERATION;
407                 goto ERROR;
408         }
409
410         if (!__mm_gst_can_resize_format(_imgp_info_s->src_format)) {
411                 mm_util_error("Not supported format");
412                 ret = MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
413                 goto ERROR;
414         }
415
416         ret = _mm_util_imgp_func(_imgp_info_s, _src->data, &output_buffer, IMGP_RSZ);
417         mm_util_debug("_mm_util_imgp_func, ret: %d", ret);
418         if (ret != MM_UTIL_ERROR_NONE) {
419                 mm_util_error("image processing failed");
420                 goto ERROR;
421         }
422
423         if ((_imgp_info_s->dst_width != _imgp_info_s->output_stride || _imgp_info_s->dst_height != _imgp_info_s->output_elevation)) {
424                 ret = mm_image_create_image(_imgp_info_s->output_stride, _imgp_info_s->output_elevation, _src->color, output_buffer, _imgp_info_s->buffer_size, &_resize_image);
425                 if (ret != MM_UTIL_ERROR_NONE) {
426                         mm_util_error("mm_image_create_image failed");
427                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
428                         goto ERROR;
429                 }
430
431                 ret = mm_util_crop_image(_resize_image, 0, 0, _imgp_info_s->dst_width, _imgp_info_s->dst_height, dst);
432                 mm_image_destroy_image(_resize_image);
433                 if (ret != MM_UTIL_ERROR_NONE) {
434                         mm_util_error("mm_util_crop_image failed");
435                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
436                         goto ERROR;
437                 }
438         } else {
439                 ret = mm_image_create_image(width, height, _src->color, output_buffer, _imgp_info_s->buffer_size, dst);
440                 if (ret != MM_UTIL_ERROR_NONE) {
441                         mm_util_error("mm_image_create_image failed");
442                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
443                         goto ERROR;
444                 }
445         }
446
447 ERROR:
448         /* Finalize */
449         __mm_util_imgp_finalize(_module, _imgp_info_s);
450         g_free(output_buffer);
451
452         mm_util_fleave();
453
454         return ret;
455 }
456
457 int mm_util_rotate_image(mm_util_image_h src, mm_util_rotate_type_e angle, mm_util_image_h *dst)
458 {
459         int ret = MM_UTIL_ERROR_NONE;
460         IMGPInfoFunc _mm_util_imgp_func = NULL;
461         void *_module = NULL;
462         unsigned char *output_buffer = NULL;
463         unsigned int uint_w = 0;
464         unsigned int uint_h = 0;
465         mm_image_info_s *_src = (mm_image_info_s *)src;
466         mm_util_image_h _rotate_image = NULL;
467         imgp_info_s *_imgp_info_s = NULL;
468
469         mm_util_fenter();
470
471         mm_util_retvm_if(!IS_VALID_IMAGE(src), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid src");
472         mm_util_retvm_if((angle < MM_UTIL_ROTATE_0) || (angle >= MM_UTIL_ROTATE_NUM), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid angle [%d]", angle);
473         mm_util_retvm_if(!dst, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid dst");
474
475         mm_util_debug("[Input] angle[%d]", angle);
476         mm_image_debug_image(src, "Input");
477
478         _mm_util_imgp_func = __mm_util_initialize(&_module);
479         mm_util_retvm_if(!_mm_util_imgp_func, MM_UTIL_ERROR_INVALID_OPERATION, "failed to __mm_util_initialize()");
480
481         _imgp_info_s = g_new0(imgp_info_s, 1);
482
483         if ((angle == MM_UTIL_ROTATE_90) || (angle == MM_UTIL_ROTATE_270)) {
484                 uint_w = _src->height;
485                 uint_h = _src->width;
486         } else {
487                 uint_w = _src->width;
488                 uint_h = _src->height;
489         }
490
491         ret = __mm_set_imgp_info_s(_imgp_info_s, _src->color, _src->width, _src->height, _src->color, uint_w, uint_h, angle);
492         mm_util_debug("__mm_set_imgp_info_s");
493         if (ret != MM_UTIL_ERROR_NONE) {
494                 mm_util_error("__mm_set_imgp_info_s failed");
495                 ret = MM_UTIL_ERROR_INVALID_OPERATION;
496                 goto ERROR;
497         }
498
499         if (!__mm_gst_can_rotate_format(_imgp_info_s->src_format)) {
500                 mm_util_error("Not supported format");
501                 ret = MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
502                 goto ERROR;
503         }
504
505         ret = _mm_util_imgp_func(_imgp_info_s, _src->data, &output_buffer, IMGP_ROT);
506         if (ret != MM_UTIL_ERROR_NONE) {
507                 mm_util_error("image processing failed");
508                 goto ERROR;
509         }
510
511         if ((_imgp_info_s->dst_width != _imgp_info_s->output_stride || _imgp_info_s->dst_height != _imgp_info_s->output_elevation)) {
512                 unsigned int start_x = 0;
513                 unsigned int start_y = 0;
514                 if (angle == MM_UTIL_ROTATE_90) {
515                         start_x = _imgp_info_s->output_stride - _imgp_info_s->dst_width;
516                         start_y = 0;
517                 } else if (angle == MM_UTIL_ROTATE_180) {
518                         start_x = _imgp_info_s->output_stride - _imgp_info_s->dst_width;
519                         start_y = _imgp_info_s->output_elevation - _imgp_info_s->dst_height;
520                 } else if (angle == MM_UTIL_ROTATE_270) {
521                         start_x = 0;
522                         start_y = _imgp_info_s->output_elevation - _imgp_info_s->dst_height;
523                 }
524                 ret = mm_image_create_image(_imgp_info_s->output_stride, _imgp_info_s->output_elevation, _src->color, output_buffer, _imgp_info_s->buffer_size, &_rotate_image);
525                 if (ret != MM_UTIL_ERROR_NONE) {
526                         mm_util_error("mm_image_create_image failed");
527                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
528                         goto ERROR;
529                 }
530
531                 ret = mm_util_crop_image(_rotate_image, start_x, start_y, _imgp_info_s->dst_width, _imgp_info_s->dst_height, dst);
532                 mm_image_destroy_image(_rotate_image);
533                 if (ret != MM_UTIL_ERROR_NONE) {
534                         mm_util_error("mm_util_crop_image failed");
535                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
536                         goto ERROR;
537                 }
538         } else {
539                 ret = mm_image_create_image(uint_w, uint_h, _src->color, output_buffer, _imgp_info_s->buffer_size, dst);
540                 if (ret != MM_UTIL_ERROR_NONE) {
541                         mm_util_error("mm_image_create_image failed");
542                         ret = MM_UTIL_ERROR_INVALID_OPERATION;
543                         goto ERROR;
544                 }
545         }
546
547 ERROR:
548         /* Finalize */
549         __mm_util_imgp_finalize(_module, _imgp_info_s);
550         g_free(output_buffer);
551
552         mm_util_fleave();
553
554         return ret;
555 }
556
557 int mm_util_crop_image(mm_util_image_h src, unsigned int start_x, unsigned int start_y, unsigned int width, unsigned int height, mm_util_image_h *dst)
558 {
559         int ret = MM_UTIL_ERROR_NONE;
560         mm_image_info_s *_src = (mm_image_info_s *)src;
561         unsigned int _width = width;
562         unsigned int _height = height;
563         unsigned char *_buffer = NULL;
564         size_t _buffer_size = 0;
565
566         mm_util_fenter();
567
568         mm_util_retvm_if(!IS_VALID_IMAGE(src), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid src");
569         mm_util_retvm_if((start_x + width > _src->width), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid position [%u][%u]", start_x, width);
570         mm_util_retvm_if((start_y + height > _src->height), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid position [%u][%u]", start_y, height);
571         mm_util_retvm_if(!dst, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid dst");
572
573         mm_util_debug("[Input] start_x[%u] start_y[%u] width[%u] height[%u]", start_x, start_y, width, height);
574         mm_image_debug_image(src, "Input");
575
576         if (_src->color == MM_UTIL_COLOR_I420 || _src->color == MM_UTIL_COLOR_YUV420) {
577                 if ((_width % 2) != 0) {
578                         _width = ((_width+1)>>1)<<1;
579                         mm_util_warn("width must be even. change from [%d] to [%d]", width, _width);
580                 }
581
582                 if ((_height % 2) != 0) {
583                         _height = ((_height+1)>>1)<<1;
584                         mm_util_warn("height must be even. change from [%d] to [%d]", height, _height);
585                 }
586         }
587
588         __mm_util_get_image_size(_src->color, _width, _height, true, &_buffer_size);
589         mm_util_retvm_if(!_buffer_size, MM_UTIL_ERROR_INVALID_OPERATION, "fail to get dst_buf_size");
590
591         _buffer = g_malloc0(_buffer_size);
592
593         switch (_src->color) {
594         case MM_UTIL_COLOR_RGB16: {
595                 __mm_util_crop_rgb16(_src->data, _src->width, _src->height, start_x, start_y, _width, _height, _buffer);
596                 break;
597                 }
598         case MM_UTIL_COLOR_RGB24: {
599                 __mm_util_crop_rgb24(_src->data, _src->width, _src->height, start_x, start_y, _width, _height, _buffer);
600                 break;
601                 }
602         case MM_UTIL_COLOR_ARGB:
603         case MM_UTIL_COLOR_BGRA:
604         case MM_UTIL_COLOR_RGBA:
605         case MM_UTIL_COLOR_BGRX: {
606                 __mm_util_crop_rgb32(_src->data, _src->width, _src->height, start_x, start_y, _width, _height, _buffer);
607                 break;
608                 }
609         case MM_UTIL_COLOR_I420:
610         case MM_UTIL_COLOR_YUV420: {
611                 __mm_util_crop_yuv420(_src->data, _src->width, _src->height, start_x, start_y, _width, _height, _buffer);
612                 break;
613                 }
614         default:
615                 mm_util_error("Not supported format [%d]", _src->color);
616                 g_free(_buffer);
617                 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
618         }
619
620         ret = mm_image_create_image(_width, _height, _src->color, _buffer, _buffer_size, dst);
621
622         g_free(_buffer);
623         mm_util_fleave();
624
625         return ret;
626 }