4 * Copyright (c) 2000 - 2011 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 "mm_util_private.h"
25 #include "mm_util_imgp.h"
26 #include "mm_util_imgp_internal.h"
28 #define GEN_MASK(x) ((1<<(x))-1)
29 #define ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) & ~GEN_MASK(x))
30 #define DIV_ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) >> (x))
33 typedef gboolean(*IMGPInfoFunc) (imgp_info_s *, const unsigned char *, unsigned char **, imgp_plugin_type_e);
35 static int __check_valid_picture_size(unsigned int width, unsigned int height)
37 if ((size_t)((width + 128) * (height + 128)) < (size_t)(INT_MAX/4))
38 return MM_UTIL_ERROR_NONE;
40 return MM_UTIL_ERROR_INVALID_PARAMETER;
43 static gboolean __mm_gst_can_resize_format(mm_util_color_format_e color_format)
45 gboolean _bool = FALSE;
47 mm_util_debug("color_format [%d]", color_format);
49 switch (color_format) {
50 case MM_UTIL_COLOR_YUV420:
51 case MM_UTIL_COLOR_YUV422:
52 case MM_UTIL_COLOR_I420:
53 case MM_UTIL_COLOR_UYVY:
54 case MM_UTIL_COLOR_YUYV:
55 case MM_UTIL_COLOR_RGB16:
56 case MM_UTIL_COLOR_RGB24:
57 case MM_UTIL_COLOR_ARGB:
58 case MM_UTIL_COLOR_BGRA:
59 case MM_UTIL_COLOR_RGBA:
60 case MM_UTIL_COLOR_BGRX:
64 mm_util_error("Not supported format"); //only not support NV12
70 static gboolean __mm_gst_can_rotate_format(mm_util_color_format_e color_format)
72 gboolean _bool = FALSE;
74 mm_util_debug("color_format [%d]", color_format);
76 switch (color_format) {
77 case MM_UTIL_COLOR_YUV420:
78 case MM_UTIL_COLOR_I420:
79 case MM_UTIL_COLOR_RGB24:
80 case MM_UTIL_COLOR_ARGB:
81 case MM_UTIL_COLOR_BGRA:
82 case MM_UTIL_COLOR_RGBA:
86 mm_util_error("Not supported format");
92 static gboolean __mm_select_convert_plugin(mm_util_color_format_e src_format, mm_util_color_format_e dst_format)
94 gboolean _bool = FALSE;
96 mm_util_debug("src_format: %d, dst_format:%d", src_format, dst_format);
98 if (((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_NV12)) ||
99 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
100 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
101 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_ARGB)) ||
102 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_BGRA)) ||
103 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_RGBA)) ||
104 ((src_format == MM_UTIL_COLOR_YUV420) && (dst_format == MM_UTIL_COLOR_NV12_TILED)) ||
106 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_NV12)) ||
107 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
108 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
109 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_ARGB)) ||
110 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_BGRA)) ||
111 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_RGBA)) ||
112 ((src_format == MM_UTIL_COLOR_I420) && (dst_format == MM_UTIL_COLOR_NV12_TILED)) ||
114 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
115 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_I420)) ||
116 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
117 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
118 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_ARGB)) ||
119 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_BGRA)) ||
120 ((src_format == MM_UTIL_COLOR_NV12) && (dst_format == MM_UTIL_COLOR_RGBA)) ||
122 ((src_format == MM_UTIL_COLOR_UYVY) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
123 ((src_format == MM_UTIL_COLOR_UYVY) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
125 ((src_format == MM_UTIL_COLOR_YUYV) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
126 ((src_format == MM_UTIL_COLOR_YUYV) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
127 ((src_format == MM_UTIL_COLOR_YUYV) && (dst_format == MM_UTIL_COLOR_ARGB)) ||
128 ((src_format == MM_UTIL_COLOR_YUYV) && (dst_format == MM_UTIL_COLOR_BGRA)) ||
129 ((src_format == MM_UTIL_COLOR_YUYV) && (dst_format == MM_UTIL_COLOR_RGBA)) ||
131 ((src_format == MM_UTIL_COLOR_RGB16) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
132 ((src_format == MM_UTIL_COLOR_RGB16) && (dst_format == MM_UTIL_COLOR_I420)) ||
133 ((src_format == MM_UTIL_COLOR_RGB16) && (dst_format == MM_UTIL_COLOR_NV12)) ||
135 ((src_format == MM_UTIL_COLOR_RGB24) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
136 ((src_format == MM_UTIL_COLOR_RGB24) && (dst_format == MM_UTIL_COLOR_I420)) ||
137 ((src_format == MM_UTIL_COLOR_RGB24) && (dst_format == MM_UTIL_COLOR_NV12)) ||
139 ((src_format == MM_UTIL_COLOR_ARGB) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
140 ((src_format == MM_UTIL_COLOR_ARGB) && (dst_format == MM_UTIL_COLOR_I420)) ||
141 ((src_format == MM_UTIL_COLOR_ARGB) && (dst_format == MM_UTIL_COLOR_NV12)) ||
143 ((src_format == MM_UTIL_COLOR_BGRA) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
144 ((src_format == MM_UTIL_COLOR_BGRA) && (dst_format == MM_UTIL_COLOR_I420)) ||
145 ((src_format == MM_UTIL_COLOR_BGRA) && (dst_format == MM_UTIL_COLOR_NV12)) ||
146 ((src_format == MM_UTIL_COLOR_RGBA) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
147 ((src_format == MM_UTIL_COLOR_RGBA) && (dst_format == MM_UTIL_COLOR_I420)) ||
148 ((src_format == MM_UTIL_COLOR_RGBA) && (dst_format == MM_UTIL_COLOR_NV12)) ||
149 ((src_format == MM_UTIL_COLOR_RGBA) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
151 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_YUV420)) ||
152 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_I420)) ||
153 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_NV12)) ||
154 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_RGB16)) ||
155 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_RGB24)) ||
156 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_ARGB)) ||
157 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_BGRA)) ||
158 ((src_format == MM_UTIL_COLOR_NV12_TILED) && (dst_format == MM_UTIL_COLOR_RGBA))) {
166 static gboolean __mm_select_resize_plugin(mm_util_color_format_e _format)
168 gboolean _bool = FALSE;
170 mm_util_debug("_format: %d", _format);
172 if ((_format == MM_UTIL_COLOR_UYVY) || (_format == MM_UTIL_COLOR_YUYV) ||
173 (_format == MM_UTIL_COLOR_RGBA) || (_format == MM_UTIL_COLOR_BGRX))
181 static gboolean __mm_select_rotate_plugin(mm_util_color_format_e _format)
183 mm_util_debug("_format: %d", _format);
185 if ((_format == MM_UTIL_COLOR_YUV420) || (_format == MM_UTIL_COLOR_I420) || (_format == MM_UTIL_COLOR_NV12)
186 || (_format == MM_UTIL_COLOR_RGB24 || _format == MM_UTIL_COLOR_RGB16)) {
193 static int __mm_util_get_crop_image_size(mm_util_color_format_e format, unsigned int width, unsigned int height, size_t *imgsize)
195 int ret = MM_UTIL_ERROR_NONE;
196 unsigned char x_chroma_shift = 0;
197 unsigned char y_chroma_shift = 0;
198 unsigned int w2, h2, stride, stride2;
203 mm_util_retvm_if(imgsize == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid imgsize");
204 mm_util_retvm_if(__check_valid_picture_size(width, height) != MM_UTIL_ERROR_NONE, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid width and height");
209 case MM_UTIL_COLOR_I420:
210 case MM_UTIL_COLOR_YUV420:
213 stride = MM_UTIL_ROUND_UP_4(width);
214 h2 = ROUND_UP_X(height, x_chroma_shift);
216 w2 = DIV_ROUND_UP_X(width, x_chroma_shift);
217 stride2 = MM_UTIL_ROUND_UP_4(w2);
218 h2 = DIV_ROUND_UP_X(height, y_chroma_shift);
219 size2 = stride2 * h2;
220 *imgsize = size + 2 * size2;
222 case MM_UTIL_COLOR_YUV422:
223 case MM_UTIL_COLOR_YUYV:
224 case MM_UTIL_COLOR_UYVY:
225 case MM_UTIL_COLOR_NV16:
226 case MM_UTIL_COLOR_NV61:
227 stride = MM_UTIL_ROUND_UP_4(width) * 2;
228 size = stride * height;
232 case MM_UTIL_COLOR_RGB16:
234 size = stride * height;
238 case MM_UTIL_COLOR_RGB24:
240 size = stride * height;
244 case MM_UTIL_COLOR_ARGB:
245 case MM_UTIL_COLOR_BGRA:
246 case MM_UTIL_COLOR_RGBA:
247 case MM_UTIL_COLOR_BGRX:
249 size = stride * height;
254 case MM_UTIL_COLOR_NV12:
255 case MM_UTIL_COLOR_NV12_TILED:
258 stride = MM_UTIL_ROUND_UP_4(width);
259 h2 = ROUND_UP_X(height, y_chroma_shift);
261 w2 = 2 * DIV_ROUND_UP_X(width, x_chroma_shift);
262 stride2 = MM_UTIL_ROUND_UP_4(w2);
263 h2 = DIV_ROUND_UP_X(height, y_chroma_shift);
264 size2 = stride2 * h2;
265 *imgsize = size + size2;
269 mm_util_error("Not supported format");
270 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
273 mm_util_debug("format: %d, *imgsize: %zu", format, *imgsize);
278 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_img_rotate_type angle)
280 int ret = MM_UTIL_ERROR_NONE;
282 mm_util_retvm_if(_imgp_info_s == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid _imgp_info_s");
284 _imgp_info_s->src_format = src_format;
285 _imgp_info_s->src_width = src_width;
286 _imgp_info_s->src_height = src_height;
288 _imgp_info_s->dst_format = dst_format;
289 _imgp_info_s->dst_width = dst_width;
290 _imgp_info_s->dst_height = dst_height;
291 _imgp_info_s->buffer_size = 0;
292 _imgp_info_s->angle = angle;
294 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);
299 static GModule *__mm_util_imgp_initialize(imgp_plugin_type_e _imgp_plugin_type_e)
301 GModule *module = NULL;
304 if (_imgp_plugin_type_e == IMGP_NEON)
305 module = g_module_open(PATH_NEON_LIB, G_MODULE_BIND_LAZY);
306 else if (_imgp_plugin_type_e == IMGP_GSTCS)
307 module = g_module_open(PATH_GSTCS_LIB, G_MODULE_BIND_LAZY);
309 mm_util_retvm_if(module == NULL, NULL, "[%d] %s | %s module open failed", _imgp_plugin_type_e, PATH_NEON_LIB, PATH_GSTCS_LIB);
310 mm_util_debug("module: %p, g_module_name: %s", module, g_module_name(module));
315 static void __mm_util_imgp_finalize(GModule *module, imgp_info_s *_imgp_info_s)
318 g_module_close(module);
320 MMUTIL_SAFE_FREE(_imgp_info_s);
325 static int __mm_util_crop_rgb32(const unsigned char *src, unsigned int src_width, unsigned int src_height,
326 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
328 int ret = MM_UTIL_ERROR_NONE;
329 unsigned int idx = 0;
330 int src_bytesperline = src_width * 4;
331 int dst_bytesperline = crop_dest_width * 4;
333 src += crop_start_y * src_bytesperline + 4 * crop_start_x;
335 for (idx = 0; idx < crop_dest_height; idx++) {
336 memcpy(dst, src, dst_bytesperline);
337 src += src_bytesperline;
338 dst += dst_bytesperline;
344 static int __mm_util_crop_rgb24(const unsigned char *src, unsigned int src_width, unsigned int src_height,
345 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
347 int ret = MM_UTIL_ERROR_NONE;
348 unsigned int idx = 0;
349 unsigned long src_bytesperline = src_width * 3;
350 unsigned long dst_bytesperline = crop_dest_width * 3;
352 src += crop_start_y * src_bytesperline + 3 * crop_start_x;
354 for (idx = 0; idx < crop_dest_height; idx++) {
355 memcpy(dst, src, dst_bytesperline);
356 src += src_bytesperline;
357 dst += dst_bytesperline;
363 static int __mm_util_crop_rgb16(const unsigned char *src, unsigned int src_width, unsigned int src_height,
364 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
366 int ret = MM_UTIL_ERROR_NONE;
367 unsigned int idx = 0;
368 unsigned long src_bytesperline = src_width * 2;
369 unsigned long dst_bytesperline = crop_dest_width * 2;
371 src += crop_start_y * src_bytesperline + 2 * crop_start_x;
373 for (idx = 0; idx < crop_dest_height; idx++) {
374 memcpy(dst, src, dst_bytesperline);
375 src += src_bytesperline;
376 dst += dst_bytesperline;
382 static int __mm_util_crop_yuv420(const unsigned char *src, unsigned int src_width, unsigned int src_height,
383 unsigned int crop_start_x, unsigned int crop_start_y, unsigned int crop_dest_width, unsigned int crop_dest_height, unsigned char *dst)
385 int ret = MM_UTIL_ERROR_NONE;
386 unsigned int idx = 0;
387 unsigned int start_x = crop_start_x;
388 unsigned int start_y = crop_start_y;
390 const unsigned char *_src = src + start_y * src_width + start_x;
393 for (idx = 0; idx < crop_dest_height; idx++) {
394 memcpy(dst, _src, crop_dest_width);
396 dst += crop_dest_width;
400 _src = src + src_height * src_width + (start_y / 2) * src_width / 2 + start_x / 2;
401 for (idx = 0; idx < crop_dest_height / 2; idx++) {
402 memcpy(dst, _src, crop_dest_width / 2);
403 _src += src_width / 2;
404 dst += crop_dest_width / 2;
408 _src = src + src_height * src_width * 5 / 4 + (start_y / 2) * src_width / 2 + start_x / 2;
409 for (idx = 0; idx < crop_dest_height / 2; idx++) {
410 memcpy(dst, _src, crop_dest_width / 2);
411 _src += src_width / 2;
412 dst += crop_dest_width / 2;
418 static IMGPInfoFunc __mm_util_initialize(imgp_type_e function, mm_util_color_format_e src_format, mm_util_color_format_e dst_format, GModule **module)
420 imgp_plugin_type_e _imgp_plugin_type_e = IMGP_GSTCS;
421 GModule *_module = NULL;
422 IMGPInfoFunc _func = NULL;
424 if (function == IMGP_CSC) {
425 if (__mm_select_convert_plugin(src_format, dst_format))
426 _imgp_plugin_type_e = IMGP_NEON;
428 } else if (function == IMGP_RSZ) {
429 if (__mm_select_resize_plugin(src_format))
430 _imgp_plugin_type_e = IMGP_NEON;
432 } else if (function == IMGP_ROT) {
433 if (__mm_select_rotate_plugin(src_format))
434 _imgp_plugin_type_e = IMGP_NEON;
437 mm_util_error("invalid function : [%d]", function);
440 mm_util_debug("plugin type: %d", _imgp_plugin_type_e);
442 _module = __mm_util_imgp_initialize(_imgp_plugin_type_e);
444 if (_module == NULL) { /* when IMGP_NEON is NULL */
445 _imgp_plugin_type_e = IMGP_GSTCS;
446 mm_util_debug("You use %s module", PATH_GSTCS_LIB);
447 _module = __mm_util_imgp_initialize(_imgp_plugin_type_e);
450 mm_util_debug("mm_util_imgp_func: %p", _module);
452 if (_module == NULL) {
453 mm_util_error("invalid module");
457 g_module_symbol(_module, IMGP_FUNC_NAME, (gpointer *)&_func);
460 mm_util_error("invalid function");
461 g_module_close(_module);
470 static bool __mm_util_check_format(mm_util_color_format_e color_format)
472 if ((color_format >= MM_UTIL_COLOR_YUV420) && (color_format <= MM_UTIL_COLOR_BGRX))
478 int mm_util_convert_colorspace(mm_util_image_h src, mm_util_color_format_e color, mm_util_image_h *dst)
480 int ret = MM_UTIL_ERROR_NONE;
481 IMGPInfoFunc _mm_util_imgp_func = NULL;
482 GModule *_module = NULL;
483 unsigned char *output_buffer = NULL;
484 mm_image_info_s *_src = (mm_image_info_s *)src;
485 mm_util_image_h _convert_image = NULL;
489 mm_util_retvm_if(!IS_VALID_IMAGE(src), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid src");
490 mm_util_retvm_if(!__mm_util_check_format(color), MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "Not supported format [%d]", color);
491 mm_util_retvm_if(!dst, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid dst");
493 mm_util_debug("[Input] format[%d]", color);
494 mm_image_debug_image(src, "Input");
496 _mm_util_imgp_func = __mm_util_initialize(IMGP_CSC, _src->color, color, &_module);
497 if (_mm_util_imgp_func == NULL) {
498 mm_util_error("ERROR - __mm_util_initialize");
499 return MM_UTIL_ERROR_INVALID_OPERATION;
502 imgp_info_s *_imgp_info_s = (imgp_info_s *) calloc(1, sizeof(imgp_info_s));
503 if (_imgp_info_s == NULL) {
504 mm_util_error("ERROR - alloc handle");
505 ret = MM_UTIL_ERROR_OUT_OF_MEMORY;
509 ret = __mm_set_imgp_info_s(_imgp_info_s, _src->color, _src->width, _src->height, color, _src->width, _src->height, MM_UTIL_ROTATE_0);
510 if (ret != MM_UTIL_ERROR_NONE) {
511 mm_util_error("__mm_set_imgp_info_s failed");
512 ret = MM_UTIL_ERROR_INVALID_OPERATION;
516 ret = _mm_util_imgp_func(_imgp_info_s, _src->data, &output_buffer, IMGP_CSC);
517 if (ret != MM_UTIL_ERROR_NONE) {
518 mm_util_error("image processing failed");
522 if ((_imgp_info_s->dst_width != _imgp_info_s->output_stride || _imgp_info_s->dst_height != _imgp_info_s->output_elevation)) {
523 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);
524 if (ret != MM_UTIL_ERROR_NONE) {
525 mm_util_error("mm_image_create_image failed");
526 ret = MM_UTIL_ERROR_INVALID_OPERATION;
530 ret = mm_util_crop_image(_convert_image, 0, 0, _imgp_info_s->dst_width, _imgp_info_s->dst_height, dst);
531 mm_image_destroy_image(_convert_image);
532 if (ret != MM_UTIL_ERROR_NONE) {
533 mm_util_error("mm_util_crop_image failed");
534 ret = MM_UTIL_ERROR_INVALID_OPERATION;
538 ret = mm_image_create_image(_src->width, _src->height, color, output_buffer, _imgp_info_s->buffer_size, dst);
539 if (ret != MM_UTIL_ERROR_NONE) {
540 mm_util_error("mm_image_create_image failed");
541 ret = MM_UTIL_ERROR_INVALID_OPERATION;
548 __mm_util_imgp_finalize(_module, _imgp_info_s);
549 MMUTIL_SAFE_FREE(output_buffer);
556 int mm_util_resize_image(mm_util_image_h src, unsigned int width, unsigned int height, mm_util_image_h *dst)
558 int ret = MM_UTIL_ERROR_NONE;
559 IMGPInfoFunc _mm_util_imgp_func = NULL;
560 GModule *_module = NULL;
561 unsigned char *output_buffer = NULL;
562 mm_image_info_s *_src = (mm_image_info_s *)src;
563 mm_util_image_h _resize_image = NULL;
567 mm_util_retvm_if(!IS_VALID_IMAGE(src), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid src");
568 mm_util_retvm_if(width == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid width");
569 mm_util_retvm_if(height == 0, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid height");
570 mm_util_retvm_if(!dst, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid dst");
572 mm_util_debug("[Input] width[%u] height[%u]", width, height);
573 mm_image_debug_image(src, "Input");
575 _mm_util_imgp_func = __mm_util_initialize(IMGP_RSZ, _src->color, 0, &_module);
576 mm_util_retvm_if(_mm_util_imgp_func == NULL, MM_UTIL_ERROR_INVALID_OPERATION, "fail __mm_util_initialize");
578 imgp_info_s *_imgp_info_s = (imgp_info_s *) calloc(1, sizeof(imgp_info_s));
579 if (_imgp_info_s == NULL) {
580 mm_util_error("ERROR - alloc handle");
581 ret = MM_UTIL_ERROR_OUT_OF_MEMORY;
585 ret = __mm_set_imgp_info_s(_imgp_info_s, _src->color, _src->width, _src->height, _src->color, width, height, MM_UTIL_ROTATE_0);
586 if (ret != MM_UTIL_ERROR_NONE) {
587 mm_util_error("__mm_set_imgp_info_s failed [%d]", ret);
588 ret = MM_UTIL_ERROR_INVALID_OPERATION;
592 if (g_strrstr(g_module_name(_module), GST)) {
593 if (__mm_gst_can_resize_format(_imgp_info_s->src_format) == FALSE) {
594 mm_util_error("#RESIZE ERROR# IMAGE_NOT_SUPPORT_FORMAT");
595 ret = MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
600 ret = _mm_util_imgp_func(_imgp_info_s, _src->data, &output_buffer, IMGP_RSZ);
601 mm_util_debug("_mm_util_imgp_func, ret: %d", ret);
602 if (ret != MM_UTIL_ERROR_NONE) {
603 mm_util_error("image processing failed");
607 if ((_imgp_info_s->dst_width != _imgp_info_s->output_stride || _imgp_info_s->dst_height != _imgp_info_s->output_elevation)) {
608 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);
609 if (ret != MM_UTIL_ERROR_NONE) {
610 mm_util_error("mm_image_create_image failed");
611 ret = MM_UTIL_ERROR_INVALID_OPERATION;
615 ret = mm_util_crop_image(_resize_image, 0, 0, _imgp_info_s->dst_width, _imgp_info_s->dst_height, dst);
616 mm_image_destroy_image(_resize_image);
617 if (ret != MM_UTIL_ERROR_NONE) {
618 mm_util_error("mm_util_crop_image failed");
619 ret = MM_UTIL_ERROR_INVALID_OPERATION;
623 ret = mm_image_create_image(width, height, _src->color, output_buffer, _imgp_info_s->buffer_size, dst);
624 if (ret != MM_UTIL_ERROR_NONE) {
625 mm_util_error("mm_image_create_image failed");
626 ret = MM_UTIL_ERROR_INVALID_OPERATION;
633 __mm_util_imgp_finalize(_module, _imgp_info_s);
634 MMUTIL_SAFE_FREE(output_buffer);
641 int mm_util_rotate_image(mm_util_image_h src, mm_util_img_rotate_type angle, mm_util_image_h *dst)
643 int ret = MM_UTIL_ERROR_NONE;
644 IMGPInfoFunc _mm_util_imgp_func = NULL;
645 GModule *_module = NULL;
646 unsigned char *output_buffer = NULL;
647 unsigned int uint_w = 0;
648 unsigned int uint_h = 0;
649 mm_image_info_s *_src = (mm_image_info_s *)src;
650 mm_util_image_h _rotate_image = NULL;
654 mm_util_retvm_if(!IS_VALID_IMAGE(src), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid src");
655 mm_util_retvm_if((angle < MM_UTIL_ROTATE_0) || (angle >= MM_UTIL_ROTATE_NUM), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid angle [%d]", angle);
656 mm_util_retvm_if(!dst, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid dst");
658 mm_util_debug("[Input] angle[%d]", angle);
659 mm_image_debug_image(src, "Input");
661 _mm_util_imgp_func = __mm_util_initialize(IMGP_ROT, _src->color, 0, &_module);
662 if (_mm_util_imgp_func == NULL) {
663 mm_util_error("ERROR - __mm_util_initialize");
664 return MM_UTIL_ERROR_INVALID_OPERATION;
667 imgp_info_s *_imgp_info_s = (imgp_info_s *) calloc(1, sizeof(imgp_info_s));
668 if (_imgp_info_s == NULL) {
669 mm_util_error("ERROR - alloc handle");
670 ret = MM_UTIL_ERROR_OUT_OF_MEMORY;
674 if ((angle == MM_UTIL_ROTATE_90) || (angle == MM_UTIL_ROTATE_270)) {
675 uint_w = _src->height;
676 uint_h = _src->width;
678 uint_w = _src->width;
679 uint_h = _src->height;
682 ret = __mm_set_imgp_info_s(_imgp_info_s, _src->color, _src->width, _src->height, _src->color, uint_w, uint_h, angle);
683 mm_util_debug("__mm_set_imgp_info_s");
684 if (ret != MM_UTIL_ERROR_NONE) {
685 mm_util_error("__mm_set_imgp_info_s failed");
686 ret = MM_UTIL_ERROR_INVALID_OPERATION;
690 if (g_strrstr(g_module_name(_module), GST)) {
691 if (__mm_gst_can_rotate_format(_imgp_info_s->src_format) == FALSE) {
692 mm_util_error("#gstreamer ROTATE ERROR# IMAGE_NOT_SUPPORT_FORMAT");
693 ret = MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
698 ret = _mm_util_imgp_func(_imgp_info_s, _src->data, &output_buffer, IMGP_ROT);
699 if (ret != MM_UTIL_ERROR_NONE) {
700 mm_util_error("image processing failed");
704 if ((_imgp_info_s->dst_width != _imgp_info_s->output_stride || _imgp_info_s->dst_height != _imgp_info_s->output_elevation)) {
705 unsigned int start_x = 0;
706 unsigned int start_y = 0;
707 if (angle == MM_UTIL_ROTATE_90) {
710 } else if (angle == MM_UTIL_ROTATE_180) {
711 start_x = _imgp_info_s->output_stride-_imgp_info_s->dst_width;
713 } else if (angle == MM_UTIL_ROTATE_270) {
715 start_y = _imgp_info_s->output_elevation - _imgp_info_s->dst_height;
717 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);
718 if (ret != MM_UTIL_ERROR_NONE) {
719 mm_util_error("mm_image_create_image failed");
720 ret = MM_UTIL_ERROR_INVALID_OPERATION;
724 ret = mm_util_crop_image(_rotate_image, 0, 0, start_x, start_y, dst);
725 mm_image_destroy_image(_rotate_image);
726 if (ret != MM_UTIL_ERROR_NONE) {
727 mm_util_error("mm_util_crop_image failed");
728 ret = MM_UTIL_ERROR_INVALID_OPERATION;
732 ret = mm_image_create_image(uint_w, uint_h, _src->color, output_buffer, _imgp_info_s->buffer_size, dst);
733 if (ret != MM_UTIL_ERROR_NONE) {
734 mm_util_error("mm_image_create_image failed");
735 ret = MM_UTIL_ERROR_INVALID_OPERATION;
742 __mm_util_imgp_finalize(_module, _imgp_info_s);
743 MMUTIL_SAFE_FREE(output_buffer);
750 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)
752 int ret = MM_UTIL_ERROR_NONE;
753 mm_image_info_s *_src = (mm_image_info_s *)src;
754 unsigned int _width = width;
755 unsigned int _height = height;
756 unsigned char *_buffer = NULL;
757 size_t _buffer_size = 0;
761 mm_util_retvm_if(!IS_VALID_IMAGE(src), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid src");
762 mm_util_retvm_if((start_x + width > _src->width), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid position [%u][%u]", start_x, width);
763 mm_util_retvm_if((start_y + height > _src->height), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid position [%u][%u]", start_y, height);
764 mm_util_retvm_if(!dst, MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid dst");
766 mm_util_debug("[Input] start_x[%u] start_y[%u] width[%u] height[%u]", start_x, start_y, width, height);
767 mm_image_debug_image(src, "Input");
769 if (_src->color == MM_UTIL_COLOR_I420 || _src->color == MM_UTIL_COLOR_YUV420) {
770 if ((_width % 2) != 0) {
771 mm_util_warn("#YUV Width value(%u) must be even at least# ", _width);
772 _width = ((_width+1)>>1)<<1;
773 mm_util_debug("Image isplay is suceeded when YUV crop width value %u", _width);
776 if ((_height % 2) != 0) { /* height value must be also even when crop yuv image */
777 mm_util_warn("#YUV Height value(%u) must be even at least# ", _height);
778 _height = ((_height+1)>>1)<<1;
779 mm_util_debug("Image isplay is suceeded when YUV crop height value %u", _height);
783 __mm_util_get_crop_image_size(_src->color, _width, _height, &_buffer_size);
784 mm_util_retvm_if(!_buffer_size, MM_UTIL_ERROR_INVALID_OPERATION, "fail to get dst_buf_size");
786 _buffer = calloc(1, _buffer_size);
787 mm_util_retvm_if(!_buffer, MM_UTIL_ERROR_OUT_OF_MEMORY, "Memory allocation failed");
789 switch (_src->color) {
790 case MM_UTIL_COLOR_RGB16: {
791 ret = __mm_util_crop_rgb16(_src->data, _src->width, _src->height, start_x, start_y, _width, _height, _buffer);
794 case MM_UTIL_COLOR_RGB24: {
795 ret = __mm_util_crop_rgb24(_src->data, _src->width, _src->height, start_x, start_y, _width, _height, _buffer);
798 case MM_UTIL_COLOR_ARGB:
799 case MM_UTIL_COLOR_BGRA:
800 case MM_UTIL_COLOR_RGBA:
801 case MM_UTIL_COLOR_BGRX: {
802 ret = __mm_util_crop_rgb32(_src->data, _src->width, _src->height, start_x, start_y, _width, _height, _buffer);
805 case MM_UTIL_COLOR_I420:
806 case MM_UTIL_COLOR_YUV420: {
807 ret = __mm_util_crop_yuv420(_src->data, _src->width, _src->height, start_x, start_y, _width, _height, _buffer);
811 mm_util_debug("Not supported format");
812 MMUTIL_SAFE_FREE(_buffer);
813 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
816 ret = mm_image_create_image(_width, _height, _src->color, _buffer, _buffer_size, dst);
818 MMUTIL_SAFE_FREE(_buffer);
824 int mm_util_get_image_size(mm_util_color_format_e format, unsigned int width, unsigned int height, size_t *imgsize)
826 int ret = MM_UTIL_ERROR_NONE;
827 unsigned char x_chroma_shift = 0;
828 unsigned char y_chroma_shift = 0;
829 unsigned int w2, h2, stride, stride2;
834 mm_util_retvm_if((imgsize == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid imgsize");
835 mm_util_retvm_if((IS_VALID_COLOR(format) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid format [%d]", format);
836 mm_util_retvm_if((__check_valid_picture_size(width, height) != MM_UTIL_ERROR_NONE), MM_UTIL_ERROR_INVALID_PARAMETER, "image width & height is too big");
841 case MM_UTIL_COLOR_I420:
842 case MM_UTIL_COLOR_YUV420:
845 stride = MM_UTIL_ROUND_UP_4(width);
846 h2 = ROUND_UP_X(height, x_chroma_shift);
848 w2 = DIV_ROUND_UP_X(width, x_chroma_shift);
849 stride2 = MM_UTIL_ROUND_UP_4(w2);
850 h2 = DIV_ROUND_UP_X(height, y_chroma_shift);
851 size2 = stride2 * h2;
852 *imgsize = size + 2 * size2;
854 case MM_UTIL_COLOR_YUV422:
855 case MM_UTIL_COLOR_YUYV:
856 case MM_UTIL_COLOR_UYVY:
857 case MM_UTIL_COLOR_NV16:
858 case MM_UTIL_COLOR_NV61:
859 stride = MM_UTIL_ROUND_UP_4(width) * 2;
860 size = stride * height;
864 case MM_UTIL_COLOR_RGB16:
865 stride = MM_UTIL_ROUND_UP_4(width) * 2;
866 size = stride * height;
870 case MM_UTIL_COLOR_RGB24:
871 stride = MM_UTIL_ROUND_UP_4(width) * 3;
872 size = stride * height;
876 case MM_UTIL_COLOR_ARGB:
877 case MM_UTIL_COLOR_BGRA:
878 case MM_UTIL_COLOR_RGBA:
879 case MM_UTIL_COLOR_BGRX:
881 size = stride * height;
885 case MM_UTIL_COLOR_NV12:
886 case MM_UTIL_COLOR_NV12_TILED:
887 case MM_UTIL_COLOR_NV21:
890 stride = MM_UTIL_ROUND_UP_4(width);
891 h2 = ROUND_UP_X(height, y_chroma_shift);
893 w2 = 2 * DIV_ROUND_UP_X(width, x_chroma_shift);
894 stride2 = MM_UTIL_ROUND_UP_4(w2);
895 h2 = DIV_ROUND_UP_X(height, y_chroma_shift);
896 size2 = stride2 * h2;
897 *imgsize = size + size2;
901 mm_util_error("Not supported format");
902 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
905 mm_util_debug("format: %u, *imgsize: %zu", format, *imgsize);