Use fprintf intead of g_print, printf in testsuite
[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  * Contact: YoungHun Kim <yh8004.kim@samsung.com>
7  *
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21
22 #include <limits.h>
23 #include <dlfcn.h>
24 #include <glib.h>
25 #include "mm_util_private.h"
26 #include "mm_util_imgp.h"
27 #include "mm_util_imgp_internal.h"
28
29 #define GEN_MASK(x) ((1<<(x))-1)
30 #define ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) & ~GEN_MASK(x))
31 #define DIV_ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) >> (x))
32
33 typedef bool(*IMGPInfoFunc) (imgp_info_s *, const unsigned char *, unsigned char **, imgp_type_e);
34
35 static int __check_valid_picture_size(unsigned int width, unsigned int height)
36 {
37         if ((size_t)((width + 128) * (height + 128)) < (size_t)(INT_MAX/4))
38                 return MM_UTIL_ERROR_NONE;
39
40         return MM_UTIL_ERROR_INVALID_PARAMETER;
41 }
42
43 static bool __mm_gst_can_resize_format(mm_util_color_format_e color_format)
44 {
45         mm_util_debug("color_format [%d]", color_format);
46
47         switch (color_format) {
48         case MM_UTIL_COLOR_YUV420:
49         case MM_UTIL_COLOR_YUV422:
50         case MM_UTIL_COLOR_I420:
51         case MM_UTIL_COLOR_UYVY:
52         case MM_UTIL_COLOR_YUYV:
53         case MM_UTIL_COLOR_RGB16:
54         case MM_UTIL_COLOR_RGB24:
55         case MM_UTIL_COLOR_ARGB:
56         case MM_UTIL_COLOR_BGRA:
57         case MM_UTIL_COLOR_RGBA:
58         case MM_UTIL_COLOR_BGRX:
59                 return true;
60         default:
61                 mm_util_error("Not supported format");  //only not support NV12
62                 return false;
63         }
64 }
65
66 static bool __mm_gst_can_rotate_format(mm_util_color_format_e color_format)
67 {
68         mm_util_debug("color_format [%d]", color_format);
69
70         switch (color_format) {
71         case MM_UTIL_COLOR_YUV420:
72         case MM_UTIL_COLOR_I420:
73         case MM_UTIL_COLOR_RGB24:
74         case MM_UTIL_COLOR_ARGB:
75         case MM_UTIL_COLOR_BGRA:
76         case MM_UTIL_COLOR_RGBA:
77                 return true;
78         default:
79                 mm_util_error("Not supported format");
80                 return false;
81         }
82 }
83
84 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)
85 {
86         unsigned char x_chroma_shift = 0;
87         unsigned char y_chroma_shift = 0;
88         size_t w2, h2, stride, stride2;
89         size_t size, size2;
90         size_t _width = (size_t)width;
91         size_t _height = (size_t)height;
92
93         mm_util_fenter();
94
95         mm_util_retvm_if(imgsize == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid imgsize");
96         mm_util_retvm_if(!IS_VALID_COLOR(format), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid format(%u)", format);
97         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);
98
99         switch (format) {
100         case MM_UTIL_COLOR_I420:
101         case MM_UTIL_COLOR_YUV420:
102                 x_chroma_shift = 1;
103                 y_chroma_shift = 1;
104                 stride = MM_UTIL_ROUND_UP_4(_width);
105                 h2 = ROUND_UP_X(_height, x_chroma_shift);
106                 size = stride * h2;
107                 w2 = DIV_ROUND_UP_X(_width, x_chroma_shift);
108                 stride2 = MM_UTIL_ROUND_UP_4(w2);
109                 h2 = DIV_ROUND_UP_X(_height, y_chroma_shift);
110                 size2 = stride2 * h2;
111                 *imgsize = size + 2 * size2;
112                 break;
113         case MM_UTIL_COLOR_YUV422:
114         case MM_UTIL_COLOR_YUYV:
115         case MM_UTIL_COLOR_UYVY:
116         case MM_UTIL_COLOR_NV16:
117         case MM_UTIL_COLOR_NV61:
118                 stride = MM_UTIL_ROUND_UP_4(_width) * 2;
119                 size = stride * _height;
120                 *imgsize = size;
121                 break;
122
123         case MM_UTIL_COLOR_RGB16:
124                 stride = 2 * (is_crop ? _width : MM_UTIL_ROUND_UP_4(_width));
125                 size = stride * _height;
126                 *imgsize = size;
127                 break;
128
129         case MM_UTIL_COLOR_RGB24:
130                 stride = 3 * (is_crop ? _width : MM_UTIL_ROUND_UP_4(_width));
131                 size = stride * _height;
132                 *imgsize = size;
133                 break;
134
135         case MM_UTIL_COLOR_ARGB:
136         case MM_UTIL_COLOR_BGRA:
137         case MM_UTIL_COLOR_RGBA:
138         case MM_UTIL_COLOR_BGRX:
139                 stride = _width * 4;
140                 size = stride * _height;
141                 *imgsize = size;
142                 break;
143
144         case MM_UTIL_COLOR_NV12:
145         case MM_UTIL_COLOR_NV12_TILED:
146         case MM_UTIL_COLOR_NV21:
147                 x_chroma_shift = 1;
148                 y_chroma_shift = 1;
149                 stride = MM_UTIL_ROUND_UP_4(_width);
150                 h2 = ROUND_UP_X(_height, y_chroma_shift);
151                 size = stride * h2;
152                 w2 = 2 * DIV_ROUND_UP_X(_width, x_chroma_shift);
153                 stride2 = MM_UTIL_ROUND_UP_4(w2);
154                 h2 = DIV_ROUND_UP_X(_height, y_chroma_shift);
155                 size2 = stride2 * h2;
156                 *imgsize = size + size2;
157                 break;
158
159         default:
160                 mm_util_error("Not supported format [%u]", format);
161                 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
162         }
163
164         mm_util_debug("format: %u, *imgsize: %zu", format, *imgsize);
165
166         return MM_UTIL_ERROR_NONE;
167 }
168
169 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)
170 {
171         int ret = MM_UTIL_ERROR_NONE;
172
173         mm_util_retvm_if(_imgp_info_s == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid _imgp_info_s");
174
175         _imgp_info_s->src_format = src_format;
176         _imgp_info_s->src_width = src_width;
177         _imgp_info_s->src_height = src_height;
178
179         _imgp_info_s->dst_format = dst_format;
180         _imgp_info_s->dst_width = dst_width;
181         _imgp_info_s->dst_height = dst_height;
182         _imgp_info_s->buffer_size = 0;
183         _imgp_info_s->angle = angle;
184
185         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);
186
187         return ret;
188 }
189
190 static void __mm_util_imgp_finalize(void *module, imgp_info_s *_imgp_info_s)
191 {
192         if (module)
193                 dlclose(module);
194
195         g_free(_imgp_info_s);
196 }
197
198 static void __mm_util_crop_rgb32(const unsigned char *src, unsigned int src_width, unsigned int src_height,
199 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
200 {
201         unsigned int idx = 0;
202         unsigned long src_bytesperline = (unsigned long)src_width * 4;
203         unsigned long dst_bytesperline = (unsigned long)crop_dest_width * 4;
204
205         src += crop_start_y * src_bytesperline + 4 * crop_start_x;
206
207         for (idx = 0; idx < crop_dest_height; idx++) {
208                 memcpy(dst, src, dst_bytesperline);
209                 src += src_bytesperline;
210                 dst += dst_bytesperline;
211         }
212 }
213
214 static void __mm_util_crop_rgb24(const unsigned char *src, unsigned int src_width, unsigned int src_height,
215 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
216 {
217         unsigned int idx = 0;
218         unsigned long src_bytesperline = (unsigned long)src_width * 3;
219         unsigned long dst_bytesperline = (unsigned long)crop_dest_width * 3;
220
221         src += crop_start_y * src_bytesperline + 3 * crop_start_x;
222
223         for (idx = 0; idx < crop_dest_height; idx++) {
224                 memcpy(dst, src, dst_bytesperline);
225                 src += src_bytesperline;
226                 dst += dst_bytesperline;
227         }
228 }
229
230 static void __mm_util_crop_rgb16(const unsigned char *src, unsigned int src_width, unsigned int src_height,
231 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
232 {
233         unsigned int idx = 0;
234         unsigned long src_bytesperline = (unsigned long)src_width * 2;
235         unsigned long dst_bytesperline = (unsigned long)crop_dest_width * 2;
236
237         src += crop_start_y * src_bytesperline + 2 * crop_start_x;
238
239         for (idx = 0; idx < crop_dest_height; idx++) {
240                 memcpy(dst, src, dst_bytesperline);
241                 src += src_bytesperline;
242                 dst += dst_bytesperline;
243         }
244 }
245
246 static void __mm_util_crop_yuv420(const unsigned char *src, unsigned int src_width, unsigned int src_height,
247 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
248 {
249         unsigned int idx = 0;
250         unsigned int start_x = crop_start_x;
251         unsigned int start_y = crop_start_y;
252
253         const unsigned char *_src = src + start_y * src_width + start_x;
254
255         /* Y */
256         for (idx = 0; idx < crop_dest_height; idx++) {
257                 memcpy(dst, _src, crop_dest_width);
258                 _src += src_width;
259                 dst += crop_dest_width;
260         }
261
262         /* U */
263         _src = src + src_height * src_width + (start_y / 2) * src_width / 2 + start_x / 2;
264         for (idx = 0; idx < crop_dest_height / 2; idx++) {
265                 memcpy(dst, _src, crop_dest_width / 2);
266                 _src += src_width / 2;
267                 dst += crop_dest_width / 2;
268         }
269
270         /* V */
271         _src = src + src_height * src_width * 5 / 4 + (start_y / 2) * src_width / 2 + start_x / 2;
272         for (idx = 0; idx < crop_dest_height / 2; idx++) {
273                 memcpy(dst, _src, crop_dest_width / 2);
274                 _src += src_width / 2;
275                 dst += crop_dest_width / 2;
276         }
277 }
278
279 static IMGPInfoFunc __mm_util_initialize(void **module)
280 {
281         void *_module = NULL;
282         IMGPInfoFunc _func = NULL;
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 }
627
628 int mm_util_get_image_size(mm_util_color_format_e format, unsigned int width, unsigned int height, size_t *imgsize)
629 {
630         return __mm_util_get_image_size(format, width, height, false, imgsize);
631 }