merge with master
[framework/osp/image-core.git] / src / FMedia_ImageUtil.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file   FMedia_ImageUtil.cpp
20  * @brief  This is the implementation file for the _ImageUtil.
21  */
22
23 #include <unique_ptr.h>
24 #include <FBaseSysLog.h>
25 #include <FBaseInteger.h>
26 #include <FBaseFloat.h>
27 #include <FBaseDouble.h>
28 #include <image_util.h>
29 #include <mmf/mm_error.h>
30 #include <mmf/mm_util_imgp.h>
31 #include "FMedia_ImageUtil.h"
32 #include "FMedia_Ffmpeg.h"
33 #include <arpa/inet.h>
34 #include "FMedia_MediaUtil.h"
35 #include "FMedia_SlpUtil.h"
36
37 using namespace Tizen::Base;
38 using namespace Tizen::Io;
39
40 #define USE_MM_UTIL
41 #define USE_FFMPEG
42 namespace Tizen { namespace Media
43 {
44
45 #define IS_VALID_PIXEL(x)                                                                                                                       \
46         ((x == MEDIA_PIXEL_FORMAT_YUV420P) || (x == MEDIA_PIXEL_FORMAT_NV12)            \
47         || (x == MEDIA_PIXEL_FORMAT_YUYV422) || (x == MEDIA_PIXEL_FORMAT_RGB565LE)      \
48         || (x == MEDIA_PIXEL_FORMAT_BGRA8888) || (x == MEDIA_PIXEL_FORMAT_RGBA8888)     \
49         || (x == MEDIA_PIXEL_FORMAT_BGR888) || (x == MEDIA_PIXEL_FORMAT_RGB888)         \
50         || (x == MEDIA_PIXEL_FORMAT_NV21) || ( x == MEDIA_PIXEL_FORMAT_YUV444P))
51
52 #define IS_VALID_BUF(buf, format, w, h)                                                          \
53         (_ImageUtil::GetBufferSize(format, w, h) <= buf.GetCapacity())
54
55 typedef struct
56 {
57         MediaPixelFormat mediaPixelFmt;
58         PixelFormat pixelFmt;
59         float bpp;
60 } _PixelFormatMap;
61
62 static const _PixelFormatMap _PIXEL_FORMAT_MAP[] =
63 {
64         { MEDIA_PIXEL_FORMAT_RGB565LE, PIX_FMT_RGB565LE, 2 },
65         { MEDIA_PIXEL_FORMAT_BGRA8888, PIX_FMT_BGRA, 4 },
66         { MEDIA_PIXEL_FORMAT_RGBA8888, PIX_FMT_RGBA, 4 },
67         { MEDIA_PIXEL_FORMAT_RGB565BE, PIX_FMT_RGB565BE, 2 },
68         { MEDIA_PIXEL_FORMAT_RGB888, PIX_FMT_RGB24, 3 },
69         { MEDIA_PIXEL_FORMAT_BGR888, PIX_FMT_BGR24, 3 },
70         { MEDIA_PIXEL_FORMAT_YUV420P, PIX_FMT_YUV420P, 1.5 },
71         { MEDIA_PIXEL_FORMAT_YUV444P, PIX_FMT_YUV444P, 3 },
72         { MEDIA_PIXEL_FORMAT_YUYV422, PIX_FMT_YUYV422, 2 },
73         { MEDIA_PIXEL_FORMAT_UYVY422, PIX_FMT_UYVY422, 2 },
74         { MEDIA_PIXEL_FORMAT_NV12, PIX_FMT_NV12, 1.5 },
75         { MEDIA_PIXEL_FORMAT_NV12_TILE, PIX_FMT_NV12, 1.5 },
76         { MEDIA_PIXEL_FORMAT_NV21, PIX_FMT_NV21, 1.5 }
77 };
78
79 static const int _BPP_RGB565 = 2;
80 static const int _BPP_RGB888 = 3;
81 static const int _BPP_ARGB8888 = 4;
82 static const int _BPP_YUV444 = 3;
83 static const float _BPP_YUV420 = 1.5;
84 static const float _BPP_NV12 = 1.5;
85
86 /*
87 * Input is assumed to be 8888
88 * pDataIn       => Input ARGB/BGRA/RGBA 8888 Buffer
89 * pDataOut      => Output buffer, allocated by caller
90 * inWidth       => Input Width
91 * inHeight      => Input Height
92 * outWidth      => Output Width
93 * outHeight     => Output Height
94 */
95 result
96 _ImageUtil::Resize8888(const byte* pDataIn, byte* pDataOut, int inWidth, int inHeight, int outWidth, int outHeight)
97 {
98         int scaleX = 0;
99         int scaleY = 0;
100         int i = 0;
101         int j = 0;
102
103         int iRow = 0;
104         int iIndex = 0;
105
106         byte* pOutput = pDataOut;
107         byte* pOut = pDataOut;
108         const byte* pIn = null;
109
110         std::unique_ptr<int []> pColLUT (new (std::nothrow) int[sizeof(int) * outWidth]);
111         SysTryReturn(NID_MEDIA, pColLUT.get() != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
112                 "[E_OUT_OF_MEMORY] Could not allocate memory.");
113
114         /* Calculate X Scale factor */
115         scaleX = inWidth * 256 / outWidth;
116
117         /* Calculate Y Scale factor, aspect ratio is not maintained */
118         scaleY = inHeight * 256 / outHeight;
119
120         for (j = 0; j < outWidth; j++)
121         {
122                 /* Get input index based on column scale factor */
123
124                 /* To get more optimization, this is calculated once and
125                 * is placed in a LUT and used for indexing
126                 */
127                 pColLUT [j] = ((j * scaleX) >> 8) * _BPP_ARGB8888;
128         }
129
130         pOut = pOutput;
131
132         for (i = 0; i < outHeight; i++)
133         {
134                 /* Get input routWidth index based on routWidth scale factor */
135                 iRow = (i * scaleY >> 8) * inWidth * _BPP_ARGB8888;
136
137                 /* Loop could be unrolled for more optimization */
138                 for (j = 0; j < (outWidth); j++)
139                 {
140                         /* Get input index based on column scale factor */
141                         iIndex = iRow + pColLUT [j];
142
143                         pIn = pDataIn + iIndex;
144                         *pOut++ = *pIn++;
145                         *pOut++ = *pIn++;
146                         *pOut++ = *pIn++;
147                         *pOut++ = *pIn++;
148                 }
149         }
150
151         return E_SUCCESS;
152 }
153
154 /*
155 * Input is assumed to be RGB888
156 * pDataIn       => Input RGB888 Buffer
157 * pDataOut      => Output buffer, allocated by caller
158 * inWidth       => Input Width
159 * inHeight      => Input Height
160 * outWidth      => Output Width
161 * outHeight     => Output Height
162 */
163 result
164 _ImageUtil::ResizeRGB888(const byte* pDataIn, byte* pDataOut, int inWidth, int inHeight, int outWidth, int outHeight)
165 {
166         int scaleX = 0;
167         int scaleY = 0;
168         int i = 0;
169         int j = 0;
170
171         int iRow = 0;
172         int iIndex = 0;
173
174         byte* pOutput = pDataOut;
175         byte* pOut = pDataOut;
176         const byte* pIn = null;
177
178         std::unique_ptr<int []> pColLUT (new (std::nothrow) int[sizeof(int) * outWidth]);
179         SysTryReturn(NID_MEDIA, pColLUT.get() != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
180                 "[E_OUT_OF_MEMORY] Could not allocate memory.");
181
182         /* Calculate X Scale factor */
183         scaleX = inWidth * 256 / outWidth;
184
185         /* Calculate Y Scale factor, aspect ratio is not maintained */
186         scaleY = inHeight * 256 / outHeight;
187
188         for (j = 0; j < outWidth; j++)
189         {
190                 /* Get input index based on column scale factor */
191
192                 /* To get more optimization, this is calculated once and
193                 * is placed in a LUT and used for indexing
194                 */
195                 pColLUT[j] = ((j * scaleX) >> 8) * _BPP_RGB888;
196         }
197
198         pOut = pOutput;
199
200         for (i = 0; i < outHeight; i++)
201         {
202                 /* Get input routWidth index based on routWidth scale factor */
203                 iRow = (i * scaleY >> 8) * inWidth * _BPP_RGB888;
204
205                 /* Loop could be unrolled for more optimization */
206                 for (j = 0; j < (outWidth); j++)
207                 {
208                         /* Get input index based on column scale factor */
209                         iIndex = iRow + pColLUT [j];
210                         pIn = pDataIn + iIndex;
211
212                         *pOut++ = *pIn++;
213                         *pOut++ = *pIn++;
214                         *pOut++ = *pIn++;
215                 }
216         }
217
218         return E_SUCCESS;
219 }
220
221 /*
222 * Input is assumed to be RGB565
223 * pDataIn       => Input RGB565 Buffer
224 * pDataOut      => Output RGB565 Buffer (memory is assumed to be already allocated)
225 * inWidth       => Input Width
226 * inHeight      => Input Height
227 * outWidth      => Output Width
228 * outHeight     => Output Height
229 */
230 result
231 _ImageUtil::ResizeRGB565(const byte* pDataIn, byte* pDataOut, int inWidth, int inHeight, int outWidth, int outHeight)
232 {
233         int scaleX = 0;
234         int scaleY = 0;
235         int i = 0;
236         int j = 0;
237
238         int iRow = 0;
239         int iIndex = 0;
240
241         byte* pOutput = pDataOut;
242         byte* pOut = pDataOut;
243         const byte* pIn = null;
244
245         std::unique_ptr<int []> pColLUT (new (std::nothrow) int[sizeof(int) * outWidth]);
246         SysTryReturn(NID_MEDIA, pColLUT.get() != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
247                 "[E_OUT_OF_MEMORY] Could not allocate memory.");
248
249         /* Calculate X Scale factor */
250         scaleX = inWidth * 256 / outWidth;
251
252         /* Calculate Y Scale factor, aspect ratio is not maintained */
253         scaleY = inHeight * 256 / outHeight;
254
255         for (j = 0; j < outWidth; j++)
256         {
257                 /* Get input index based on column scale factor */
258
259                 /* To get more optimization, this is calculated once and
260                 * is placed in a LUT and used for indexing
261                 */
262                 pColLUT [j] = ((j * scaleX) >> 8) * _BPP_RGB565;
263         }
264
265         pOut = pOutput;
266
267         for (i = 0; i < outHeight; i++)
268         {
269                 /* Get input row index based on row scale factor */
270                 iRow = (i * scaleY >> 8) * inWidth * _BPP_RGB565;
271
272                 /* Loop could be unrolled for more optimization */
273                 for (j = 0; j < (outWidth); j++)
274                 {
275                         /* Get input index based on column scale factor */
276                         iIndex = iRow + pColLUT [j];
277
278                         pIn = pDataIn + iIndex;
279                         *pOut++ = *pIn++;
280                         *pOut++ = *pIn++;
281                 }
282         }
283
284         return E_SUCCESS;
285 }
286
287 /*
288 * Input is assumed to be YUV444
289 * pDataIn       => Input YUV444 Buffer
290 * pDataOut      => Output buffer, allocated by caller
291 * inWidth       => Input Width
292 * inHeight      => Input Height
293 * outWidth      => Output Width
294 * outHeight     => Output Height
295 */
296 result
297 _ImageUtil::ResizeYUV444(const byte* pDataIn, byte* pDataOut, int inWidth, int inHeight, int outWidth, int outHeight)
298 {
299         int scaleX = 0;
300         int scaleY = 0;
301         int i = 0;
302         int j = 0;
303
304         int iRow = 0;
305         int iIndex = 0;
306
307         int ipixelcount = inWidth * inHeight;
308         int opixelcount = outWidth * outHeight;
309         byte* pOutput = pDataOut;
310         byte* pOutY = null;
311         byte* pOutU = null;
312         byte* pOutV = null;
313         const byte* pInY = null;
314         const byte* pInU = null;
315         const byte* pInV = null;
316
317         std::unique_ptr<int []> pColLUT (new (std::nothrow) int[sizeof(int) * outWidth]);
318         SysTryReturn(NID_MEDIA, pColLUT.get() != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
319                 "[E_OUT_OF_MEMORY] Could not allocate memory.");
320
321         /* Calculate X Scale factor */
322         scaleX = inWidth * 256 / outWidth;
323
324         /* Calculate Y Scale factor, aspect ratio is not maintained */
325         scaleY = inHeight * 256 / outHeight;
326
327         for (j = 0; j < outWidth; j++)
328         {
329                 /* Get input index based on column scale factor */
330
331                 /* To get more optimization, this is calculated once and
332                 * is placed in a LUT and used for indexing
333                 */
334                 pColLUT[j] = ((j * scaleX) >> 8);
335         }
336
337         pOutY = pOutput;
338         pOutU = pOutY + opixelcount;
339         pOutV = pOutU + opixelcount;
340
341         pInY = pDataIn;
342         pInU = pInY + ipixelcount;
343         pInV = pInU + ipixelcount;
344
345         for (i = 0; i < outHeight; i++)
346         {
347                 /* Get input row index based on row scale factor */
348                 iRow = (i * scaleY >> 8) * inWidth;
349
350                 /* Loop could be unrolled for more optimization */
351                 for (j = 0; j < outWidth; j++)
352                 {
353                         /* Get input index based on column scale factor */
354                         iIndex = iRow + pColLUT [j];
355
356                         *(pOutY++) = *(pInY + iIndex);
357                         *(pOutU++) = *(pInU + iIndex);
358                         *(pOutV++) = *(pInV + iIndex);
359                 }
360         }
361
362         return E_SUCCESS;
363 }
364
365 /*
366 * Input is assumed to be YUYV422
367 * pDataIn       => Input YUYV422 Buffer
368 * pDataOut      => Output buffer, allocated by caller
369 * inWidth       => Input Width
370 * inHeight      => Input Height
371 * outWidth      => Output Width
372 * outHeight     => Output Height
373 */
374 result
375 _ImageUtil::ResizeYUYV422(const byte* pDataIn, byte* pDataOut, int inWidth, int inHeight, int outWidth, int outHeight)
376 {
377
378         return ResizeRGB565(pDataIn, pDataOut, inWidth, inHeight, outWidth, outHeight);
379 }
380
381 /*
382 * Input is assumed to be YUV420P
383 * pDataIn       => Input YUV420P Buffer
384 * pDataOut      => Output buffer, allocated by caller
385 * inWidth       => Input Width
386 * inHeight      => Input Height
387 * outWidth      => Output Width
388 * outHeight     => Output Height
389 */
390 result
391 _ImageUtil::ResizeYUV420P(const byte* pDataIn, byte* pDataOut, int inWidth, int inHeight, int outWidth, int outHeight)
392 {
393         int scaleX = 0;
394         int scaleY = 0;
395         int i = 0;
396         int j = 0;
397
398         int iRow = 0;
399         int iIndex = 0;
400
401         int ipixelcount = inWidth * inHeight;
402         int opixelcount = outWidth * outHeight;
403         byte* pOutput = pDataOut;
404         byte* pOutY = null;
405         byte* pOutU = null;
406         byte* pOutV = null;
407
408         std::unique_ptr<int []> pColLUT (new (std::nothrow) int[sizeof(int) * outWidth]);
409         SysTryReturn(NID_MEDIA, pColLUT.get() != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
410                 "[E_OUT_OF_MEMORY] Could not allocate memory.");
411
412         /* Calculate X Scale factor */
413         scaleX = inWidth * 256 / outWidth;
414
415         /* Calculate Y Scale factor, aspect ratio is not maintained */
416         scaleY = inHeight * 256 / outHeight;
417
418         for (j = 0; j < outWidth; j++)
419         {
420                 /* Get input index based on column scale factor */
421
422                 /* To get more optimization, this is calculated once and
423                 * is placed in a LUT and used for indexing
424                 */
425                 pColLUT[j] = ((j * scaleX) >> 8);
426         }
427
428         pOutY = pOutput;
429
430         for (i = 0; i < outHeight; i++)
431         {
432                 /* Get input row index based on row scale factor */
433                 iRow = (i * scaleY >> 8) * inWidth;
434
435                 /* Loop could be unrolled for more optimization */
436                 for (j = 0; j < (outWidth); j++)
437                 {
438                         /* Get input index based on column scale factor */
439                         iIndex = iRow + pColLUT[j];
440
441                         *pOutY++ = pDataIn[iIndex];
442                 }
443         }
444
445         pOutU = pOutput + opixelcount;
446         pOutV = pOutU + (opixelcount/4);
447
448         for (i = 0; i < (outHeight + 1) / 2; i++)
449         {
450                 /* Get input row index based on row scale factor */
451                 iRow = (i * scaleY >> 8) * inWidth/2;
452
453                 /* Loop could be unrolled for more optimization */
454                 for (j = 0; j < (outWidth)/2; j++)
455                 {
456                         /* Get input index based on column scale factor */
457                         iIndex = iRow + pColLUT[j];
458
459                         *pOutU++ = pDataIn[iIndex + ipixelcount];
460                         *pOutV++  = pDataIn[iIndex + ipixelcount + (ipixelcount/4)];
461                 }
462         }
463
464         return E_SUCCESS;
465 }
466
467 /*
468 * Input is assumed to be NV12
469 * pDataIn       => Input NV12 Buffer
470 * pDataOut      => Output buffer, allocated by caller
471 * inWidth       => Input Width
472 * inHeight      => Input Height
473 * outWidth      => Output Width
474 * outHeight     => Output Height
475 */
476 result
477 _ImageUtil::ResizeNV12(const byte* pDataIn, byte* pDataOut, int inWidth, int inHeight, int outWidth, int outHeight)
478 {
479         int scaleX = 0;
480         int scaleY = 0;
481         int i = 0;
482         int j = 0;
483
484         int iRow = 0;
485         int iIndex = 0;
486
487         int ipixelcount = inWidth * inHeight;
488         int opixelcount = outWidth * outHeight;
489         byte* pOutput = pDataOut;
490         byte* pOutY = null;
491         byte* pOutUV = null;
492
493         std::unique_ptr<int []> pColLUT (new (std::nothrow) int[sizeof(int) * outWidth]);
494         SysTryReturn(NID_MEDIA, pColLUT.get() != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
495                 "[E_OUT_OF_MEMORY] Could not allocate memory.");
496
497         /* Calculate X Scale factor */
498         scaleX = inWidth * 256 / outWidth;
499
500         /* Calculate Y Scale factor, aspect ratio is not maintained */
501         scaleY = inHeight * 256 / outHeight;
502
503         for (j = 0; j < outWidth; j++)
504         {
505                 /* Get input index based on column scale factor */
506
507                 /* To get more optimization, this is calculated once and
508                 * is placed in a LUT and used for indexing
509                 */
510                 pColLUT[j] = ((j * scaleX) >> 8);
511         }
512
513         pOutY = pOutput;
514
515         for (i = 0; i < outHeight; i++)
516         {
517                 /* Get input row index based on row scale factor */
518                 iRow = (i * scaleY >> 8) * inWidth;
519
520                 /* Loop could be unrolled for more optimization */
521                 for (j = 0; j < (outWidth); j++)
522                 {
523                         /* Get input index based on column scale factor */
524                         iIndex = iRow + pColLUT[j];
525
526                         *pOutY++ = pDataIn[iIndex];
527                 }
528         }
529
530         pOutUV = pOutput + opixelcount;
531
532         for (i = 0; i < (outHeight + 1) / 2; i++)
533         {
534                 /* Get input row index based on row scale factor */
535                 iRow = (i * scaleY >> 8) * inWidth/2;
536
537                 /* Loop could be unrolled for more optimization */
538                 for (j = 0; j < (outWidth)/2; j++)
539                 {
540                         /* Get input index based on column scale factor */
541                         iIndex = iRow + pColLUT[j];
542
543                         *pOutUV++ = pDataIn[iIndex + ipixelcount];
544                         *pOutUV++ = pDataIn[iIndex + ipixelcount + 1];
545                 }
546         }
547
548         return E_SUCCESS;
549 }
550
551 result
552 _ImageUtil::ResizeBuffer(const byte* pInBuf, MediaPixelFormat pixelFormat,
553         int srcWidth, int srcHeight, byte* pOutBuf, int dstWidth, int dstHeight)
554 {
555         result r = E_SUCCESS;
556
557         switch (pixelFormat)
558         {
559
560                 case MEDIA_PIXEL_FORMAT_RGBA8888:
561                 case MEDIA_PIXEL_FORMAT_BGRA8888:
562                 {
563                          r = Resize8888(pInBuf, pOutBuf, srcWidth, srcHeight, dstWidth, dstHeight);
564                 }
565                 break;
566
567                 case MEDIA_PIXEL_FORMAT_RGB888:
568                 {
569                         r = ResizeRGB888(pInBuf, pOutBuf, srcWidth, srcHeight, dstWidth, dstHeight);
570                 }
571                 break;
572
573                 case MEDIA_PIXEL_FORMAT_RGB565LE:
574                 {
575                         r = ResizeRGB565(pInBuf, pOutBuf, srcWidth, srcHeight, dstWidth, dstHeight);
576                 }
577                 break;
578
579                 case MEDIA_PIXEL_FORMAT_YUV444P:
580                 {
581                         r = ResizeYUV444(pInBuf, pOutBuf, srcWidth, srcHeight, dstWidth, dstHeight);
582                 }
583                 break;
584
585                 case MEDIA_PIXEL_FORMAT_YUYV422:
586                 {
587                         r = ResizeYUYV422(pInBuf, pOutBuf, srcWidth, srcHeight, dstWidth, dstHeight);
588                 }
589                 break;
590
591                 case MEDIA_PIXEL_FORMAT_YUV420P:
592                 {
593                         r = ResizeYUV420P(pInBuf, pOutBuf, srcWidth, srcHeight, dstWidth, dstHeight);
594                 }
595                 break;
596
597                 case MEDIA_PIXEL_FORMAT_NV12:
598                 {
599                         r = ResizeNV12(pInBuf, pOutBuf, srcWidth, srcHeight, dstWidth, dstHeight);
600                 }
601                 break;
602
603                 default:
604                         r = E_UNSUPPORTED_FORMAT;
605         }
606
607         return r;
608 }
609
610 result
611 _ImageUtil::RotateBuffer(const byte* srcBuf, MediaPixelFormat pixelFormat,
612         int width, int height, byte* dstBuf, int& outWidth, int& outHeight,
613         ImageRotationType rotate)
614 {
615         result r = E_SUCCESS;
616         int ret = 0;
617 #ifdef USE_MM_UTIL
618         mm_util_img_format colorFormat = MM_UTIL_IMG_FMT_NUM;
619         mm_util_img_rotate_type rotation = MM_UTIL_ROTATE_NUM;
620 #else
621         image_util_colorspace_e colorFormat = IMAGE_UTIL_COLORSPACE_RGB565;
622         image_util_rotation_e rotation = IMAGE_UTIL_ROTATION_NONE;
623 #endif
624
625         SysTryCatch(NID_MEDIA, width > 0 && height > 0, r = E_INVALID_ARG, E_INVALID_ARG,
626                 "[E_INVALID_ARG] Invalid dimension: Should be greater than zero: (%d x %d)",
627                 width, height);
628
629         SysTryCatch(NID_MEDIA, IS_VALID_PIXEL(pixelFormat), r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
630                 "[E_UNSUPPORTED_FORMAT] Unsupported pixelFormat: %d", pixelFormat);
631
632         SysTryCatch(NID_MEDIA, IsValidDimension(pixelFormat, width, height),
633                 r = E_INVALID_ARG, E_INVALID_ARG,
634                 "[E_INVALID_ARG] Dimensions should be even (%d x %d).", width, height);
635
636         if (rotate == IMAGE_ROTATION_0)
637         {
638                 int length = GetBufferSize(pixelFormat, width, height);
639                 memcpy(dstBuf, srcBuf, length);
640                 return r;
641         }
642
643         // Set output dimensions;
644         if ((rotate == IMAGE_ROTATION_90) || (rotate == IMAGE_ROTATION_270))
645         {
646                 outWidth = height;
647                 outHeight = width;
648         }
649         else
650         {
651                 outWidth = width;
652                 outHeight = height;
653         }
654
655         if (pixelFormat == MEDIA_PIXEL_FORMAT_RGB565LE)
656         {
657                 switch (rotate)
658                 {
659                 case IMAGE_ROTATION_90:
660                 {
661                         int rowCount = 0;
662                         int colCount = 0;
663                         unsigned short* pSrcBuf = (unsigned short *)srcBuf;
664                         unsigned short* pDstBuf = (unsigned short *)dstBuf;
665                         unsigned short* pTmpOutCol = null;
666
667                         // Copying from all source rows to destination columns.
668                         for (rowCount = 0; rowCount < height; rowCount++)
669                         {
670                                 // pTmpOutCol points to the top of the output column being filled.
671                                 pTmpOutCol = pDstBuf + outWidth - 1 - rowCount;
672
673                                 for (colCount = 0; colCount < width; colCount++)
674                                 {
675                                         *pTmpOutCol = *pSrcBuf++;
676                                         pTmpOutCol += outWidth;
677                                 }
678                         }
679                 }
680                 break;
681
682                 case IMAGE_ROTATION_180:
683                 {
684                         int pixCount = 0;
685                         unsigned short* pSrcBuf = (unsigned short *)srcBuf;
686                         unsigned short* pDstBuf = (unsigned short *)dstBuf;
687
688                         // pDstBuf points to the bottom right corner of the output image.
689                         pDstBuf += (outWidth * outHeight) - 1;
690
691                         for (pixCount = (width * height); pixCount > 0; pixCount--)
692                         {
693                                 *pDstBuf = *pSrcBuf++;
694                                 pDstBuf--;
695                         }
696                 }
697                 break;
698
699                 case IMAGE_ROTATION_270:
700                 {
701                         int rowCount = 0;
702                         int colCount = 0;
703                         unsigned short* pSrcBuf = (unsigned short *)srcBuf;
704                         unsigned short* pDstBuf = (unsigned short *)dstBuf;
705                         unsigned short* pTmpOutCol = null;
706
707                         // Copying all source rows to destination columns.
708                         for (rowCount = 0; rowCount < height; rowCount++)
709                         {
710                                 // pTmpOutCol points to the bottom of the column being filled.
711                                 pTmpOutCol = pDstBuf + (outWidth *  (outHeight - 1)) + rowCount;
712
713                                 for (colCount = 0; colCount < width; colCount++)
714                                 {
715                                         *pTmpOutCol = *pSrcBuf++;
716                                         pTmpOutCol -= outWidth;
717                                 }
718                         }
719                 }
720                 break;
721
722                 default:
723                 break;
724                 }
725         }
726         else if (pixelFormat == MEDIA_PIXEL_FORMAT_RGBA8888 || pixelFormat == MEDIA_PIXEL_FORMAT_BGRA8888)
727         {
728                 switch (rotate)
729                 {
730                 case IMAGE_ROTATION_90:
731                 {
732                         int rowCount = 0;
733                         int colCount = 0;
734                         unsigned int* pSrcBuf = (unsigned int *)srcBuf;
735                         unsigned int* pDstBuf = (unsigned int *)dstBuf;
736                         unsigned int* pTmpOutCol = null;
737
738                         // Copying from all source rows to destination columns.
739                         for (rowCount = 0; rowCount < height; rowCount++)
740                         {
741                                 // pTmpOutCol points to the top of the output column being filled.
742                                 pTmpOutCol = pDstBuf + outWidth - 1 - rowCount;
743
744                                 for (colCount = 0; colCount < width; colCount++)
745                                 {
746                                         *pTmpOutCol = *pSrcBuf++;
747                                         pTmpOutCol += outWidth;
748                                 }
749                         }
750                 }
751                 break;
752
753                 case IMAGE_ROTATION_180:
754                 {
755                         int pixCount = 0;
756                         unsigned int* pSrcBuf = (unsigned int *)srcBuf;
757                         unsigned int* pDstBuf = (unsigned int *)dstBuf;
758
759                         // pDstBuf points to the bottom right corner of the output image.
760                         pDstBuf += (outWidth * outHeight) - 1;
761
762                         for (pixCount = (width * height); pixCount > 0; pixCount--)
763                         {
764                                 *pDstBuf = *pSrcBuf++;
765                                 pDstBuf--;
766                         }
767                 }
768                 break;
769
770                 case IMAGE_ROTATION_270:
771                 {
772                         int rowCount = 0;
773                         int colCount = 0;
774                         unsigned int* pSrcBuf = (unsigned int *)srcBuf;
775                         unsigned int* pDstBuf = (unsigned int *)dstBuf;
776                         unsigned int* pTmpOutCol = null;
777
778                         // Copying all source rows to destination columns.
779                         for (rowCount = 0; rowCount < height; rowCount++)
780                         {
781                                 // pTmpOutCol points to the bottom of the column being filled.
782                                 pTmpOutCol = pDstBuf + (outWidth *  (outHeight - 1)) + rowCount;
783
784                                 for (colCount = 0; colCount < width; colCount++)
785                                 {
786                                         *pTmpOutCol = *pSrcBuf++;
787                                         pTmpOutCol -= outWidth;
788                                 }
789                         }
790                 }
791                 break;
792
793                 default:
794                 break;
795                 }
796         }
797         else
798         {
799 #ifdef USE_MM_UTIL
800
801                 colorFormat = _SlpUtil::ToMmUtilImgFormat(pixelFormat);
802                 rotation = _SlpUtil::ToMmUtilRotateType(rotate);
803
804                 ret = mm_util_rotate_image((unsigned char*)srcBuf, width, height, colorFormat,
805                                                                 (unsigned char*)dstBuf, (unsigned int *)&outWidth, (unsigned int *)&outHeight, rotation);
806
807                 SysTryCatch(NID_MEDIA, ret == 0, r = E_SYSTEM, E_SYSTEM,
808                         "mm_util_rotate_image: %0x", ret);
809
810 #else
811
812                 colorFormat = _SlpUtil::ToColorspace(pixelFormat);
813                 rotation = _SlpUtil::ToRotation(rotate);
814
815                 ret = image_util_transform(dstBuf, &outWidth, &outHeight, rotation,
816                                                                 srcBuf, width, height, colorFormat);
817
818                 SysTryCatch(NID_MEDIA, ret == IMAGE_UTIL_ERROR_NONE, r = E_SYSTEM, E_SYSTEM,
819                         "[E_SYSTEM] util_transform failed: %0x", ret);
820 #endif
821         }
822
823         return r;
824
825 CATCH:
826         return r;
827 }
828
829 result
830 _ImageUtil::FlipBuffer(const byte* srcBuf, MediaPixelFormat pixelFormat,
831                                  int width, int height,
832                                  byte* dstBuf, ImageFlipType flip)
833 {
834         result r = E_SUCCESS;
835         int ret = 0;
836 #ifdef USE_MM_UTIL
837         mm_util_img_format colorFormat = MM_UTIL_IMG_FMT_NUM;
838         mm_util_img_rotate_type rotation = MM_UTIL_ROTATE_NUM;
839
840         unsigned int outWidth = 0;
841         unsigned int outHeight = 0;
842 #else
843         image_util_colorspace_e colorFormat = IMAGE_UTIL_COLORSPACE_RGB565;
844         image_util_rotation_e rotation = IMAGE_UTIL_ROTATION_NONE;
845         int outWidth = 0;
846         int outHeight = 0;
847 #endif
848
849         SysTryCatch(NID_MEDIA, width > 0 && height > 0, r = E_INVALID_ARG, E_INVALID_ARG,
850                 "[E_INVALID_ARG] Invalid dimension: Should be greater than zero: (%d x %d)",
851                 width, height);
852
853         SysTryCatch(NID_MEDIA, IS_VALID_PIXEL(pixelFormat), r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
854                 "[E_UNSUPPORTED_FORMAT] Unsupported pixelFormat: %d", pixelFormat);
855
856         SysTryCatch(NID_MEDIA, IsValidDimension(pixelFormat, width, height),
857                 r = E_INVALID_ARG, E_INVALID_ARG,
858                 "[E_INVALID_ARG] Dimensions should be even (%d x %d).", width, height);
859
860         if (flip == IMAGE_FLIP_NONE)
861         {
862                 int length = GetBufferSize(pixelFormat, width, height);
863                 memcpy(dstBuf, srcBuf, length);
864                 return r;
865         }
866
867         // Set output dimensions;
868         outWidth = width;
869         outHeight = height;
870
871         if (pixelFormat == MEDIA_PIXEL_FORMAT_RGB565LE)
872         {
873                 if (flip == IMAGE_FLIP_HORIZONTAL)
874                 {
875                         int rowCount = 0;
876                         int colCount = 0;
877                         unsigned short* pSrcBuf = (unsigned short *)srcBuf;
878                         unsigned short* pDstBuf = (unsigned short *)dstBuf;
879                         // pTmpOutRow points to last column of first row of destination.
880                         unsigned short* pTmpOutRow = pDstBuf + width - 1;
881
882                         for (rowCount = 0; rowCount < height; rowCount++)
883                         {
884                                 for (colCount = 0; colCount < width; colCount++)
885                                 {
886                                         *pTmpOutRow-- = *pSrcBuf++; // copy source row in reverse to destination.
887                                 }
888                                 pTmpOutRow += (2 * outWidth);
889                         }
890                 }
891                 else
892                 {
893                         int rowCount = 0;
894                         unsigned short* pSrcBuf = (unsigned short *)srcBuf;
895                         unsigned short* pDstBuf = (unsigned short *)dstBuf;
896                         // pTmpOutRow points to the start of last row in destination buffer.
897                         unsigned short* pTmpOutRow = pDstBuf + (width * (height - 1));
898
899                         for (rowCount = 0; rowCount < height; rowCount++)
900                         {
901                                 // copy one row worth of data.
902                                 memcpy(pTmpOutRow, pSrcBuf, sizeof(unsigned short) * width);
903                                 pTmpOutRow -= width; // go to one higher row.
904                                 pSrcBuf += width; // go to next row.
905                         }
906                 }
907         }
908         else
909         {
910 #ifdef USE_MM_UTIL
911
912                 colorFormat = _SlpUtil::ToMmUtilImgFormat(pixelFormat);
913                 rotation = _SlpUtil::ToMmUtilRotateType(flip);
914
915                 ret = mm_util_rotate_image((unsigned char*)srcBuf, width, height, colorFormat,
916                                                                 (unsigned char*)dstBuf, &outWidth, &outHeight, rotation);
917
918                 SysTryCatch(NID_MEDIA, ret == 0, r = E_SYSTEM, E_SYSTEM,
919                         "mm_util_rotate_image failed with error code: %0x", ret);
920 #else
921                 colorFormat = _SlpUtil::ToColorspace(pixelFormat);
922                 rotation = _SlpUtil::ToRotation(flip);
923
924                 ret = image_util_transform(dstBuf, &outWidth, &outHeight, rotation,
925                                                                 srcBuf, width, height, colorFormat);
926                 SysTryCatch(NID_MEDIA, ret == IMAGE_UTIL_ERROR_NONE, r = E_SYSTEM, E_SYSTEM,
927                         "util_transform failed with error code: %0x", ret);
928 #endif
929         }
930
931 CATCH:
932         return r;
933 }
934
935 result
936 _ImageUtil::ConvertPixelFormat(const ByteBuffer& srcBuf,
937                                                                 MediaPixelFormat srcFormat, int srcWidth, int srcHeight,
938                                                                 ByteBuffer& dstBuf,  MediaPixelFormat dstFormat)
939 {
940         result r = E_SUCCESS;
941
942 #ifndef USE_FFMPEG
943         int ret = 0;
944         image_util_colorspace_e srcColor = IMAGE_UTIL_COLORSPACE_RGB565;
945         image_util_colorspace_e dstColor = IMAGE_UTIL_COLORSPACE_RGB565;
946
947         SysTryCatch(NID_MEDIA, srcWidth > 0 && srcHeight > 0, r = E_INVALID_ARG, E_INVALID_ARG,
948                 "[E_INVALID_ARG] Invalid dimension: Should be greater than zero. (%d x %d)", srcWidth, srcHeight);
949
950         SysTryCatch(NID_MEDIA, IS_VALID_PIXEL(srcFormat), r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
951                 "[E_UNSUPPORTED_FORMAT] Unsupported srcPixelFormat:%d", srcFormat);
952         SysTryCatch(NID_MEDIA, IS_VALID_PIXEL(dstFormat), r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
953                 "[E_UNSUPPORTED_FORMAT] Unsupported dstPixelFormat:%d", dstFormat);
954
955         SysTryCatch(NID_MEDIA, IsValidDimension(srcFormat, srcWidth, srcHeight),
956                 r = E_INVALID_ARG, E_INVALID_ARG,
957                 "[E_INVALID_ARG] Dimensions should be even (%d x %d).", srcWidth, srcHeight);
958
959         SysTryCatch(NID_MEDIA, IS_VALID_BUF(dstBuf, dstFormat, srcWidth, srcHeight),
960                 r = E_INVALID_ARG, E_INVALID_ARG,
961                 "[E_INVALID_ARG] Invalid buffer size (%d) for format (%d), width (%d), height (%d)",
962                 dstBuf.GetLimit(), dstFormat, srcWidth, srcHeight);
963
964         srcColor = _SlpUtil::ToColorspace(srcFormat);
965         dstColor = _SlpUtil::ToColorspace(dstFormat);
966
967         ret = image_util_convert_colorspace((unsigned char*) dstBuf.GetPointer(), dstColor,
968                                                                                 (byte*)srcBuf.GetPointer(), srcWidth, srcHeight, srcColor);
969         SysTryCatch(NID_MEDIA, ret == IMAGE_UTIL_ERROR_NONE, r = E_SYSTEM, E_SYSTEM,
970                 "[E_SYSTEM] convert_colorspace failed with error code %d", ret);
971         r = dstBuf.SetLimit(_ImageUtil::GetBufferSize(dstFormat, srcWidth, srcHeight));
972         SysTryCatch(NID_MEDIA, r==E_SUCCESS, , r,
973                 "[%s] SetLimit to %d failed for buffer.", GetErrorMessage(r),
974                 _ImageUtil::GetBufferSize(dstFormat, srcWidth, srcHeight));
975 #else
976         AVFrame srcFrame;
977         AVFrame dstFrame;
978
979         int dstWidth = srcWidth;
980         int dstHeight = srcHeight;
981         int width = srcWidth;
982         int size = 0;
983         int srcLength = srcBuf.GetCapacity();
984         int dstLength = 0;
985         byte* pSrcBuf;
986         std::unique_ptr<byte []> pDstBuf;
987         struct SwsContext* pCvtCtxt = null;
988         // Get ffmpeg format type
989         PixelFormat ffSrcFormat = (PixelFormat)_ImageUtil::ToFfmpegPixelFormat(srcFormat);
990         PixelFormat ffDstFormat = (PixelFormat)_ImageUtil::ToFfmpegPixelFormat(dstFormat);
991
992         SysTryReturn(NID_MEDIA, srcWidth > 0 && srcHeight > 0, E_INVALID_ARG, E_INVALID_ARG,
993                 "[E_INVALID_ARG] Invalid dimension: Should be greater that zero (%d x %d)", srcWidth, srcHeight);
994
995         SysTryReturn(NID_MEDIA, ffSrcFormat != PIX_FMT_NONE, E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
996                 "[E_UNSUPPORTED_FORMAT] Unsupported srcPixelFormat: %d", srcFormat);
997         SysTryReturn(NID_MEDIA, ffDstFormat != PIX_FMT_NONE, E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
998                 "[E_UNSUPPORTED_FORMAT] Unsupported dstPixelFormat: %d", dstFormat);
999
1000         SysTryReturn(NID_MEDIA, IsValidDimension(srcFormat, srcWidth, srcHeight),
1001                 E_INVALID_ARG, E_INVALID_ARG,
1002                 "[E_INVALID_ARG] Dimensions should be even (%d x %d).", srcWidth, srcHeight);
1003
1004         SysTryReturn(NID_MEDIA, IS_VALID_BUF(srcBuf, srcFormat, srcWidth, srcHeight),
1005                 E_INVALID_ARG, E_INVALID_ARG,
1006                 "[E_INVALID_ARG] Invalid buffer size (%d) for format (%d), width (%d), height (%d)",
1007                 srcBuf.GetLimit(), srcFormat, srcWidth, srcHeight);
1008
1009         SysTryReturn(NID_MEDIA, IsValidDimension(dstFormat, srcWidth, srcHeight),
1010                 E_INVALID_ARG, E_INVALID_ARG,
1011                 "[E_INVALID_ARG] Dimensions should be even (%d x %d).", srcWidth, srcHeight);
1012
1013         SysTryReturn(NID_MEDIA, IS_VALID_BUF(dstBuf, dstFormat, srcWidth, srcHeight),
1014                 E_INVALID_ARG, E_INVALID_ARG,
1015                 "[E_INVALID_ARG] Invalid dst buffer size (%d) for pixelformat (%d) and size (%d x %d)",
1016                 dstBuf.GetLimit(), dstFormat, srcWidth, srcHeight);
1017
1018         avcodec_register_all();
1019
1020         if (srcWidth < 8)
1021         {
1022                 int row = 0;
1023                 std::unique_ptr<byte []> pSrcBufUPtr;
1024                 const byte* pSrcData = null;
1025                 byte* pDstData = null;
1026
1027                 width = srcWidth;
1028                 srcWidth = 8;
1029                 dstWidth = 8;
1030
1031                 size = GetBufferSize(srcFormat, srcWidth, srcHeight);
1032
1033                 pSrcBufUPtr.reset(new (std::nothrow) byte[size]);
1034                 pSrcBuf = pSrcBufUPtr.get();
1035                 SysTryReturn(NID_MEDIA, pSrcBuf != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
1036                         "[E_OUT_OF_MEMORY] Couldn't allocate buffer");
1037                 memset(pSrcBuf, 0, size);
1038
1039                 pSrcData = srcBuf.GetPointer();
1040                 SysTryReturn(NID_MEDIA, pSrcData != null, GetLastResult(), GetLastResult(),
1041                         "[%s] ByteBuffer::GetPointer() returned null", GetErrorMessage(GetLastResult()));
1042
1043                 pDstData = pSrcBuf;
1044
1045                 // Create a new buffer with input buffer, padded to increase width to be 8 pixels wide.
1046                 for (row = 0; row < srcHeight; row++)
1047                 {
1048                         memcpy(pDstData, pSrcData, srcWidth);
1049                         pDstData += 8;
1050                         pSrcData += srcWidth;
1051                 }
1052         }
1053         else
1054         {
1055                 width = srcWidth;
1056                 pSrcBuf = (const_cast<byte *>(srcBuf.GetPointer()));
1057                 SysTryReturn(NID_MEDIA, pSrcBuf != null, GetLastResult(), GetLastResult(),
1058                         "[%s] srcBuf.GetPointer failed", GetErrorMessage(GetLastResult()));
1059
1060         }
1061         dstWidth = width;
1062
1063         // Create scale context
1064         pCvtCtxt = sws_getContext(srcWidth, srcHeight, ffSrcFormat,
1065                                 dstWidth, dstHeight, ffDstFormat,
1066                                 SWS_BICUBIC, NULL, NULL, NULL);
1067
1068         SysTryReturn(NID_MEDIA, pCvtCtxt != null, E_SYSTEM, E_SYSTEM,
1069                 "[E_SYSTEM] sws_getContext failed for src size (%d x %d), pix (%d), and dst size (%d x %d), pix (%d)",
1070                 srcWidth, srcHeight, ffSrcFormat,
1071                 dstWidth, dstHeight, ffDstFormat);
1072
1073         // Calculate src/dest size
1074         size = avpicture_get_size(ffSrcFormat, srcWidth, srcHeight);
1075         SysTryReturn(NID_MEDIA, size <= srcLength, E_INVALID_ARG, E_INVALID_ARG,
1076                 "[E_INVALID_ARG] underflow: Required buffer size (%d) < given buffer size (%d), for pix (%d), (%d x %d)",
1077                 size, srcLength, srcFormat, srcWidth, srcHeight);
1078
1079         size = avpicture_get_size(ffDstFormat, dstWidth, dstHeight);
1080         SysTryReturn(NID_MEDIA, size >= 0, E_FAILURE, E_FAILURE,
1081                 "[E_FAILURE] Not able find size of dest frame for pix (%d), size (%d x %d)");
1082
1083         pDstBuf.reset(new (std::nothrow) byte[size]);
1084         SysTryReturn(NID_MEDIA, pDstBuf.get() != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
1085                 "[E_OUT_OF_MEMORY] Could not allocate %d bytes for output.", size);
1086         dstLength = size;
1087
1088         memset(&srcFrame, 0, sizeof(srcFrame));
1089         memset(&dstFrame, 0, sizeof(dstFrame));
1090
1091         // Fill source frame
1092         avpicture_fill((AVPicture*)&srcFrame, (byte*)pSrcBuf, ffSrcFormat, srcWidth, srcHeight);
1093
1094         // Fill dest frame
1095         avpicture_fill((AVPicture*)&dstFrame, (byte*)pDstBuf.get(), ffDstFormat, dstWidth, dstHeight);
1096
1097         // Scaling
1098         sws_scale(pCvtCtxt, srcFrame.data, srcFrame.linesize, 0, srcHeight,
1099                 dstFrame.data, dstFrame.linesize);
1100
1101         if (width == srcWidth)
1102         {
1103                 r = dstBuf.SetArray(pDstBuf.get(), 0, dstLength);
1104                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r,
1105                         "[%s] Propagated.", GetErrorMessage(r));
1106                 dstBuf.Flip();
1107         }
1108         else
1109         {
1110                 // The padding must be removed from output buffer.
1111                 int row = 0;
1112                 std::unique_ptr<byte []> pUnpadded;
1113                 byte *pSrcData = null;
1114                 byte *pDstData = null;
1115
1116                 srcWidth = width;
1117                 size = GetBufferSize(srcFormat, srcWidth, srcHeight);
1118
1119                 pUnpadded.reset(new (std::nothrow) byte[size]);
1120                 SysTryReturn(NID_MEDIA, pUnpadded.get() != null, E_OUT_OF_MEMORY,
1121                         E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Couldn't allocate buffer");
1122                 memset(pUnpadded.get(), 0, size);
1123
1124                 pSrcData = pDstBuf.get();
1125
1126                 pDstData = pUnpadded.get();
1127
1128                 // Create a new buffer with input buffer, padded to increase width to be 8 pixels wide.
1129                 for (row = 0; row < srcHeight; row++)
1130                 {
1131                         memcpy(pDstData, pSrcData, srcWidth);
1132                         pDstData += srcWidth;
1133                         pSrcData += 8;
1134                 }
1135
1136                 r = dstBuf.SetArray(pUnpadded.get(), 0, size);
1137                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, r,
1138                         r, "[%s] Propagated.", GetErrorMessage(r));
1139                 dstBuf.Flip();
1140         }
1141
1142         if (pCvtCtxt != NULL)
1143         {
1144                 sws_freeContext(pCvtCtxt);
1145         }
1146
1147 #endif
1148
1149 #ifndef USE_FFMPEG
1150 CATCH:
1151 #endif
1152         return r;
1153 }
1154
1155
1156 result
1157 _ImageUtil::Resize(const ByteBuffer& srcBuf,
1158                                         MediaPixelFormat pixelFormat,
1159                                         int srcWidth, int srcHeight,
1160                                         ByteBuffer& dstBuf,
1161                                         int dstWidth, int dstHeight)
1162 {
1163         result r = E_SUCCESS;
1164         unsigned int outWidth = dstWidth;
1165         unsigned int outHeight = dstHeight;
1166         byte* pDataOut = null;
1167
1168         SysTryCatch(NID_MEDIA, srcWidth > 0 && srcHeight > 0, r = E_INVALID_ARG, E_INVALID_ARG,
1169                 "Invalid src dimension: Should be greater than zero: (%d x %d)", srcWidth, srcHeight);
1170         SysTryCatch(NID_MEDIA, dstWidth > 0 && dstHeight > 0, r = E_INVALID_ARG, E_INVALID_ARG,
1171                 "Invalid dst dimension: Should be greater than zero: (%d x %d)", dstWidth, dstHeight);
1172
1173         SysTryCatch(NID_MEDIA, IS_VALID_PIXEL(pixelFormat), r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
1174                 "Unsupported pixelFormat: %d", pixelFormat);
1175
1176         SysTryCatch(NID_MEDIA, IsValidDimension(pixelFormat, srcWidth, srcHeight),
1177                 r = E_INVALID_ARG, E_INVALID_ARG,
1178                 "[E_INVALID_ARG] Dimensions should be even (%d x %d).", srcWidth, srcHeight);
1179
1180         SysTryCatch(NID_MEDIA, IS_VALID_BUF(srcBuf, pixelFormat, srcWidth, srcHeight),
1181                 r = E_INVALID_ARG, E_INVALID_ARG,
1182                 "Invalid buffer size (%d) for format (%d), width (%d), height (%d)",
1183                 srcBuf.GetLimit(), pixelFormat, srcWidth, srcHeight);
1184
1185         SysTryCatch(NID_MEDIA, IsValidDimension(pixelFormat, dstWidth, dstHeight),
1186                 r = E_INVALID_ARG, E_INVALID_ARG,
1187                 "[E_INVALID_ARG] Dimensions should be even (%d x %d).", dstWidth, dstHeight);
1188
1189         SysTryCatch(NID_MEDIA, IS_VALID_BUF(dstBuf, pixelFormat, dstWidth, dstHeight),
1190                 r = E_INVALID_ARG, E_INVALID_ARG,
1191                 "Invalid buffer size (%d) for format (%d), width (%d), height (%d)",
1192                 dstBuf.GetLimit(), pixelFormat, dstWidth, dstHeight);
1193
1194         pDataOut = const_cast<byte*>(dstBuf.GetPointer());
1195
1196         r = ResizeBuffer(const_cast<byte*>(srcBuf.GetPointer()), pixelFormat,
1197                 srcWidth, srcHeight, pDataOut, dstWidth, dstHeight);
1198         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Resize failed.", GetErrorMessage(r));
1199
1200         r = dstBuf.SetLimit(_ImageUtil::GetBufferSize(pixelFormat, outWidth, outHeight));
1201         SysTryCatch(NID_MEDIA, r==E_SUCCESS, , r,
1202                 "[%s] dstBuf.SetLimit to %d failed.", GetErrorMessage(r),
1203                 _ImageUtil::GetBufferSize(pixelFormat, outWidth, outHeight));
1204
1205 CATCH:
1206         return r;
1207 }
1208
1209 result
1210 _ImageUtil::Rotate(const ByteBuffer& srcBuf,
1211                                         MediaPixelFormat pixelFormat,
1212                                         int width, int height,
1213                                         ByteBuffer& dstBuf,
1214                                         ImageRotationType rotate)
1215 {
1216         result r = E_SUCCESS;
1217         int ret = 0;
1218 #ifdef USE_MM_UTIL
1219         mm_util_img_format colorFormat = MM_UTIL_IMG_FMT_NUM;
1220         mm_util_img_rotate_type rotation = MM_UTIL_ROTATE_NUM;
1221
1222         unsigned int outWidth = 0;
1223         unsigned int outHeight = 0;
1224 #else
1225         image_util_colorspace_e colorFormat = IMAGE_UTIL_COLORSPACE_RGB565;
1226         image_util_rotation_e rotation = IMAGE_UTIL_ROTATION_NONE;
1227         int outWidth = 0;
1228         int outHeight = 0;
1229 #endif
1230
1231
1232         SysTryCatch(NID_MEDIA, width > 0 && height > 0, r = E_INVALID_ARG, E_INVALID_ARG,
1233                 "[E_INVALID_ARG] Invalid dimension: Should be greater than zero: (%d x %d)",
1234                 width, height);
1235
1236         SysTryCatch(NID_MEDIA, IS_VALID_PIXEL(pixelFormat), r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
1237                 "[E_UNSUPPORTED_FORMAT] Unsupported pixelFormat: %d", pixelFormat);
1238
1239         SysTryCatch(NID_MEDIA, IsValidDimension(pixelFormat, width, height),
1240                 r = E_INVALID_ARG, E_INVALID_ARG,
1241                 "[E_INVALID_ARG] Dimensions should be even (%d x %d).", width, height);
1242
1243         SysTryCatch(NID_MEDIA, IS_VALID_BUF(srcBuf, pixelFormat, width, height),
1244                 r = E_INVALID_ARG, E_INVALID_ARG,
1245                 "Invalid buffer size (%d) for format (%d), width (%d), height (%d)",
1246                 srcBuf.GetLimit(), pixelFormat, width, height);
1247
1248         SysTryCatch(NID_MEDIA, IS_VALID_BUF(dstBuf, pixelFormat, width, height),
1249                 r = E_INVALID_ARG, E_INVALID_ARG,
1250                 "Invalid buffer size (%d) for format (%d), width (%d), height (%d)",
1251                 dstBuf.GetLimit(), pixelFormat, width, height);
1252
1253         if (rotate == IMAGE_ROTATION_0)
1254         {
1255                 r = dstBuf.SetArray(srcBuf.GetPointer(), 0, srcBuf.GetLimit());
1256                 SysTryCatch(NID_MEDIA, r==E_SUCCESS, , r,
1257                         "[%s] dstBuf.SetArray failed. SrcBuffer = %d, SrcBuffer.Limit = %d, dstBuffer.Position = %d, dstBuffer.Capacity = %d.",
1258                         GetErrorMessage(r), srcBuf.GetPointer(), srcBuf.GetLimit(), dstBuf.GetPosition(), dstBuf.GetCapacity());
1259                 dstBuf.Flip();
1260                 return r;
1261         }
1262
1263         // Set output dimensions;
1264         if ((rotate == IMAGE_ROTATION_90) || (rotate == IMAGE_ROTATION_270))
1265         {
1266                 outWidth = height;
1267                 outHeight = width;
1268         }
1269         else
1270         {
1271                 outWidth = width;
1272                 outHeight = height;
1273         }
1274
1275         if (pixelFormat == MEDIA_PIXEL_FORMAT_RGB888)
1276         {
1277                 int rowCount = 0;
1278                 int colCount = 0;
1279                 byte* pSrcBuf = (byte *)srcBuf.GetPointer();
1280                 byte* pDstBuf = (byte *)dstBuf.GetPointer();
1281                 byte* pTmpOutCol = null;
1282
1283                 switch (rotate)
1284                 {
1285                 case IMAGE_ROTATION_90:
1286                 {
1287                         // Copying from all source rows to destination columns.
1288                         for (rowCount = 0; rowCount < height; rowCount++)
1289                         {
1290                                 // pTmpOutCol points to the top of the output column being filled.
1291                                 pTmpOutCol = pDstBuf + outWidth * 3 - 1 - rowCount * 3;
1292
1293                                 for (colCount = 0; colCount < width / 2; colCount++)
1294                                 {
1295                                         pTmpOutCol = pTmpOutCol - 2;
1296                                         *pTmpOutCol++ = *pSrcBuf++; // copied R byte
1297                                         *pTmpOutCol++ = *pSrcBuf++; // copied G byte
1298                                         *pTmpOutCol = *pSrcBuf++; // copied B byte
1299                                         pTmpOutCol += outWidth * 3;
1300
1301                                         pTmpOutCol = pTmpOutCol - 2;
1302                                         *pTmpOutCol++ = *pSrcBuf++; // copied R byte
1303                                         *pTmpOutCol++ = *pSrcBuf++; // copied G byte
1304                                         *pTmpOutCol = *pSrcBuf++; // copied B byte
1305                                         pTmpOutCol += outWidth * 3;
1306                                 }
1307                         }
1308                 }
1309                 break;
1310                 case IMAGE_ROTATION_180:
1311                 {
1312                         // Copying all source rows to destination columns.
1313                         for (rowCount = 0; rowCount < height; rowCount++)
1314                         {
1315                                 // pTmpOutCol points to the bottom of the column being filled.
1316                                 pTmpOutCol = pDstBuf + ((outWidth * outHeight * 3) - 1) - (rowCount * outWidth * 3);
1317
1318                                 for (colCount = 0; colCount < width / 2; colCount++)
1319                                 {
1320                                         pTmpOutCol -= 2;         // move to R bye of pixel
1321                                         *pTmpOutCol++ = *pSrcBuf++; // copied R
1322                                         *pTmpOutCol++ = *pSrcBuf++; // copied G
1323                                         *pTmpOutCol = *pSrcBuf++;   // copied B
1324                                         pTmpOutCol -= 3; // move to  next pixel to get copied
1325
1326                                         pTmpOutCol -= 2;         // move to R bye of pixel
1327                                         *pTmpOutCol++ = *pSrcBuf++; // copied R
1328                                         *pTmpOutCol++ = *pSrcBuf++; // copied G
1329                                         *pTmpOutCol = *pSrcBuf++;   // copied B
1330                                         pTmpOutCol -= 3; // move to  next pixel to get copied
1331                                 }
1332                         }
1333                 }
1334                 break;
1335                 case IMAGE_ROTATION_270:
1336                 {
1337                         // Copying all source rows to destination columns.
1338                         for (rowCount = 0; rowCount < height; rowCount++)
1339                         {
1340                                 // pTmpOutCol points to the bottom of the column being filled.
1341                                 pTmpOutCol = pDstBuf + (outWidth * 3  *  (outHeight - 1)) + rowCount * 3;
1342
1343                                 for (colCount = 0; colCount < width / 2; colCount++)
1344                                 {
1345                                         *pTmpOutCol++ = *pSrcBuf++; // copied R
1346                                         *pTmpOutCol++ = *pSrcBuf++; // copied G
1347                                         *pTmpOutCol = *pSrcBuf++;   // copied B
1348                                         pTmpOutCol -= 2; // take pointer back to R
1349                                         pTmpOutCol -= outWidth * 3;
1350
1351                                         *pTmpOutCol++ = *pSrcBuf++; // copied R
1352                                         *pTmpOutCol++ = *pSrcBuf++; // copied G
1353                                         *pTmpOutCol = *pSrcBuf++;   // copied B
1354                                         pTmpOutCol -= 2; // take pointer back to R
1355                                         pTmpOutCol -= outWidth * 3;
1356                                 }
1357                         }
1358                 }
1359                 break;
1360                 default:
1361                 break;
1362                 }
1363         }
1364
1365         else if (pixelFormat == MEDIA_PIXEL_FORMAT_RGB565LE)
1366         {
1367                 switch (rotate)
1368                 {
1369                 case IMAGE_ROTATION_90:
1370                 {
1371                         int rowCount = 0;
1372                         int colCount = 0;
1373                         unsigned short* pSrcBuf = (unsigned short *)srcBuf.GetPointer();
1374                         unsigned short* pDstBuf = (unsigned short *)dstBuf.GetPointer();
1375                         unsigned short* pTmpOutCol = null;
1376
1377                         // Copying from all source rows to destination columns.
1378                         for (rowCount = 0; rowCount < height; rowCount++)
1379                         {
1380                                 // pTmpOutCol points to the top of the output column being filled.
1381                                 pTmpOutCol = pDstBuf + outWidth - 1 - rowCount;
1382
1383                                 for (colCount = 0; colCount < width; colCount++)
1384                                 {
1385                                         *pTmpOutCol = *pSrcBuf++;
1386                                         pTmpOutCol += outWidth;
1387                                 }
1388                         }
1389                 }
1390                 break;
1391
1392                 case IMAGE_ROTATION_180:
1393                 {
1394                         int pixCount = 0;
1395                         unsigned short* pSrcBuf = (unsigned short *)srcBuf.GetPointer();
1396                         unsigned short* pDstBuf = (unsigned short *)dstBuf.GetPointer();
1397
1398                         // pDstBuf points to the bottom right corner of the output image.
1399                         pDstBuf += (outWidth * outHeight) - 1;
1400
1401                         for (pixCount = (width * height); pixCount > 0; pixCount--)
1402                         {
1403                                 *pDstBuf = *pSrcBuf++;
1404                                 pDstBuf--;
1405                         }
1406                 }
1407                 break;
1408
1409                 case IMAGE_ROTATION_270:
1410                 {
1411                         int rowCount = 0;
1412                         int colCount = 0;
1413                         unsigned short* pSrcBuf = (unsigned short *)srcBuf.GetPointer();
1414                         unsigned short* pDstBuf = (unsigned short *)dstBuf.GetPointer();
1415                         unsigned short* pTmpOutCol = null;
1416
1417                         // Copying all source rows to destination columns.
1418                         for (rowCount = 0; rowCount < height; rowCount++)
1419                         {
1420                                 // pTmpOutCol points to the bottom of the column being filled.
1421                                 pTmpOutCol = pDstBuf + (outWidth *  (outHeight - 1)) + rowCount;
1422
1423                                 for (colCount = 0; colCount < width; colCount++)
1424                                 {
1425                                         *pTmpOutCol = *pSrcBuf++;
1426                                         pTmpOutCol -= outWidth;
1427                                 }
1428                         }
1429                 }
1430                 break;
1431
1432                 default:
1433                 break;
1434                 }
1435         }
1436         else if (pixelFormat == MEDIA_PIXEL_FORMAT_RGBA8888 || pixelFormat == MEDIA_PIXEL_FORMAT_BGRA8888)
1437         {
1438                 switch (rotate)
1439                 {
1440                 case IMAGE_ROTATION_90:
1441                 {
1442                         int rowCount = 0;
1443                         int colCount = 0;
1444                         unsigned int* pSrcBuf = (unsigned int *)srcBuf.GetPointer();
1445                         unsigned int* pDstBuf = (unsigned int *)dstBuf.GetPointer();
1446                         unsigned int* pTmpOutCol = null;
1447
1448                         // Copying from all source rows to destination columns.
1449                         for (rowCount = 0; rowCount < height; rowCount++)
1450                         {
1451                                 // pTmpOutCol points to the top of the output column being filled.
1452                                 pTmpOutCol = pDstBuf + outWidth - 1 - rowCount;
1453
1454                                 for (colCount = 0; colCount < width; colCount++)
1455                                 {
1456                                         *pTmpOutCol = *pSrcBuf++;
1457                                         pTmpOutCol += outWidth;
1458                                 }
1459                         }
1460                 }
1461                 break;
1462
1463                 case IMAGE_ROTATION_180:
1464                 {
1465                         int pixCount = 0;
1466                         unsigned int* pSrcBuf = (unsigned int *)srcBuf.GetPointer();
1467                         unsigned int* pDstBuf = (unsigned int *)dstBuf.GetPointer();
1468
1469                         // pDstBuf points to the bottom right corner of the output image.
1470                         pDstBuf += (outWidth * outHeight) - 1;
1471
1472                         for (pixCount = (width * height); pixCount > 0; pixCount--)
1473                         {
1474                                 *pDstBuf = *pSrcBuf++;
1475                                 pDstBuf--;
1476                         }
1477                 }
1478                 break;
1479
1480                 case IMAGE_ROTATION_270:
1481                 {
1482                         int rowCount = 0;
1483                         int colCount = 0;
1484                         unsigned int* pSrcBuf = (unsigned int *)srcBuf.GetPointer();
1485                         unsigned int* pDstBuf = (unsigned int *)dstBuf.GetPointer();
1486                         unsigned int* pTmpOutCol = null;
1487
1488                         // Copying all source rows to destination columns.
1489                         for (rowCount = 0; rowCount < height; rowCount++)
1490                         {
1491                                 // pTmpOutCol points to the bottom of the column being filled.
1492                                 pTmpOutCol = pDstBuf + (outWidth *  (outHeight - 1)) + rowCount;
1493
1494                                 for (colCount = 0; colCount < width; colCount++)
1495                                 {
1496                                         *pTmpOutCol = *pSrcBuf++;
1497                                         pTmpOutCol -= outWidth;
1498                                 }
1499                         }
1500                 }
1501                 break;
1502
1503                 default:
1504                 break;
1505                 }
1506         }
1507         else if (pixelFormat == MEDIA_PIXEL_FORMAT_YUV420P)
1508         {
1509                 int rowCount = 0;
1510                 int colCount = 0;
1511                 byte* pDstY = (byte *)dstBuf.GetPointer();
1512                 byte* pDstU = pDstY + outWidth * outHeight;
1513                 byte* pDstV = pDstU + (outWidth / 2) * (outHeight / 2);
1514
1515                 byte* pSrcY = (byte *) srcBuf.GetPointer();
1516                 byte* pSrcU = pSrcY + width * height;
1517                 byte* pSrcV = pSrcU + (width /2) * ( height / 2);
1518                 byte* pTmpOutColY = null;
1519                 byte* pTmpOutColU = null;
1520                 byte* pTmpOutColV = null;
1521                 switch (rotate)
1522                 {
1523                 case IMAGE_ROTATION_90:
1524                 {
1525                         // Copying from all source rows to destination columns of Y plane.
1526                         for (rowCount = 0; rowCount < height / 2; rowCount++)
1527                         {
1528                                 // pTmpOutCol points to the top of the output column being filled.
1529                                 pTmpOutColU = pDstU + (outWidth / 2)  - 1 - rowCount;
1530                                 pTmpOutColV = pDstV + (outWidth / 2)  - 1 - rowCount;
1531                                 pTmpOutColY = pDstY + outWidth - 1 - rowCount;
1532                                 for (colCount = 0; colCount < width / 2; colCount++)
1533                                 {
1534                                         *pTmpOutColU = *pSrcU++;
1535                                         pTmpOutColU += outWidth / 2;
1536                                         *pTmpOutColV = *pSrcV++;
1537                                         pTmpOutColV += outWidth / 2;
1538                                         *pTmpOutColY = *pSrcY++;
1539                                         pTmpOutColY += outWidth;
1540                                 }
1541                                 for (colCount = width / 2; colCount < width; colCount++)
1542                                 {
1543                                         *pTmpOutColY = *pSrcY++;
1544                                         pTmpOutColY += outWidth;
1545                                 }
1546                         }
1547                         for (rowCount = height / 2; rowCount < height; rowCount++)
1548                         {
1549                                 pTmpOutColY = pDstY + outWidth - 1 - rowCount;
1550                                 for (colCount = 0; colCount < width; colCount++)
1551                                 {
1552                                         *pTmpOutColY = *pSrcY++;
1553                                         pTmpOutColY += outWidth;
1554                                 }
1555                         }
1556                 }
1557                 break;
1558                 case IMAGE_ROTATION_180:
1559                 {
1560                         // Copying from all source rows to destination columns of Y plane.
1561                         pTmpOutColY = pDstY + outWidth * outHeight - 1;
1562                         pTmpOutColU = pDstU + (outWidth / 2) * (outHeight / 2) - 1;
1563                         pTmpOutColV = pDstV + (outWidth / 2) * (outHeight / 2) - 1;
1564                         for (colCount = 0; colCount < (outWidth / 2 * outHeight / 2); colCount++)
1565                         {
1566                                 *pTmpOutColY-- = *pSrcY++;
1567                                 *pTmpOutColU-- = *pSrcU++;
1568                                 *pTmpOutColV-- = *pSrcV++;
1569                         }
1570                         for (colCount = (outWidth / 2  * outHeight / 2); colCount < (outWidth * outHeight); colCount++)
1571                         {
1572                                 *pTmpOutColY-- = *pSrcY++;
1573                         }
1574                 }
1575                 break;
1576                 case IMAGE_ROTATION_270:
1577                 {
1578
1579                         // Copying from all source rows to destination columns of Y plane.
1580                         for (rowCount = 0; rowCount < height / 2; rowCount++)
1581                         {
1582                                 // pTmpOutCol points to the top of the output column being filled.
1583                                 pTmpOutColY = pDstY + (outWidth *  (outHeight - 1)) + rowCount;
1584                                 pTmpOutColU = pDstU + (outWidth / 2) * (outHeight / 2 - 1) + rowCount;
1585                                 pTmpOutColV = pDstV + (outWidth / 2) * (outHeight / 2 - 1) + rowCount;
1586                                 for (colCount = 0; colCount < width / 2; colCount++)
1587                                 {
1588                                         *pTmpOutColY = *pSrcY++;
1589                                         pTmpOutColY -= outWidth;
1590                                         *pTmpOutColU = *pSrcU++;
1591                                         pTmpOutColU -= outWidth / 2;
1592                                         *pTmpOutColV = *pSrcV++;
1593                                         pTmpOutColV -= outWidth / 2;
1594                                 }
1595                                 for (colCount = width / 2; colCount < width; colCount++)
1596                                 {
1597                                         *pTmpOutColY = *pSrcY++;
1598                                         pTmpOutColY -= outWidth;
1599                                 }
1600                         }
1601                         for (rowCount = height / 2; rowCount < height; rowCount++)
1602                         {
1603                                 pTmpOutColY = pDstY + (outWidth *  (outHeight - 1)) + rowCount;
1604                                 // pTmpOutCol points to the top of the output column being filled.
1605                                 for (colCount = 0; colCount < width; colCount++)
1606                                 {
1607                                         *pTmpOutColY = *pSrcY++;
1608                                         pTmpOutColY -= outWidth;
1609                                 }
1610                         }
1611                 }
1612                 break;
1613                 default:
1614                 break;
1615                 }
1616         }
1617         else if (pixelFormat == MEDIA_PIXEL_FORMAT_NV12
1618                         || pixelFormat == MEDIA_PIXEL_FORMAT_NV21)
1619         {
1620                 int rowCount = 0;
1621                 int colCount = 0;
1622                 byte* pDstY = (byte *)dstBuf.GetPointer();
1623                 short* pDstUV = (short* )(pDstY + outWidth * outHeight);
1624
1625                 byte* pSrcY = (byte* ) srcBuf.GetPointer();
1626                 short* pSrcUV = (short* )(pSrcY + width * height);
1627                 byte* pTmpOutColY = null;
1628                 short* pTmpOutColUV = null;
1629
1630                 switch (rotate)
1631                 {
1632                 case IMAGE_ROTATION_90:
1633                 {
1634                         // Copying from all source rows to destination columns of Y plane.
1635                         for (rowCount = 0; rowCount < height / 2; rowCount++)
1636                         {
1637                                 // pTmpOutCol points to the top of the output column being filled.
1638                                 pTmpOutColUV = pDstUV + (outWidth / 2)  - 1 - rowCount;
1639                                 pTmpOutColY = pDstY + outWidth - 1 - rowCount;
1640                                 for (colCount = 0; colCount < width / 2; colCount++)
1641                                 {
1642                                         *pTmpOutColUV = *pSrcUV++;
1643                                         pTmpOutColUV += outWidth / 2 ;
1644                                         *pTmpOutColY = *pSrcY++;
1645                                         pTmpOutColY += outWidth;
1646                                 }
1647                                 for (colCount = width / 2; colCount < width; colCount++)
1648                                 {
1649                                         *pTmpOutColY = *pSrcY++;
1650                                         pTmpOutColY += outWidth;
1651                                 }
1652                         }
1653                         for (rowCount = height / 2; rowCount < height; rowCount++)
1654                         {
1655                                 // pTmpOutCol points to the top of the output column being filled.
1656                                 pTmpOutColY = pDstY + outWidth - 1 - rowCount;
1657                                 for (colCount = 0; colCount < width; colCount++)
1658                                 {
1659                                         *pTmpOutColY = *pSrcY++;
1660                                         pTmpOutColY += outWidth;
1661                                 }
1662                         }
1663                 }
1664                 break;
1665                 case IMAGE_ROTATION_180:
1666                 {
1667                         // Copying from all source rows to destination columns of Y plane.
1668                         pTmpOutColY = pDstY + outWidth * outHeight - 1;
1669                         pTmpOutColUV = pDstUV + (outWidth / 2) * (outHeight / 2) - 1;
1670                         for (colCount = 0; colCount < (outWidth / 2 * outHeight / 2); colCount++)
1671                         {
1672                                 *pTmpOutColY-- = *pSrcY++;
1673                                 *pTmpOutColUV-- = *pSrcUV++;
1674                         }
1675                         for (colCount = (outWidth / 2 * outHeight / 2); colCount < outWidth * outHeight; colCount++)
1676                         {
1677                                 *pTmpOutColY-- = *pSrcY++;
1678                         }
1679                 }
1680                 break;
1681                 case IMAGE_ROTATION_270:
1682                 {
1683                         // Copying from all source rows to destination columns of Y plane.
1684                         for (rowCount = 0; rowCount < height / 2; rowCount++)
1685                         {
1686                                 // pTmpOutCol points to the top of the output column being filled.
1687                                 pTmpOutColY = pDstY + (outWidth *  (outHeight - 1)) + rowCount;
1688                                 pTmpOutColUV = pDstUV + (outWidth / 2) * (outHeight / 2 - 1) + rowCount;
1689                                 for (colCount = 0; colCount < width / 2; colCount++)
1690                                 {
1691                                         *pTmpOutColY = *pSrcY++;
1692                                         pTmpOutColY -= outWidth;
1693                                         *pTmpOutColUV = *pSrcUV++;
1694                                         pTmpOutColUV -= outWidth / 2;
1695                                 }
1696                                 for (colCount = width / 2; colCount < width; colCount++)
1697                                 {
1698                                         *pTmpOutColY = *pSrcY++;
1699                                         pTmpOutColY -= outWidth;
1700                                 }
1701                         }
1702                         for (rowCount = height / 2; rowCount < height; rowCount++)
1703                         {
1704                                 // pTmpOutCol points to the top of the output column being filled.
1705                                 pTmpOutColY = pDstY + (outWidth *  (outHeight - 1)) + rowCount;
1706                                 for (colCount = 0; colCount < width; colCount++)
1707                                 {
1708                                         *pTmpOutColY = *pSrcY++;
1709                                         pTmpOutColY -= outWidth;
1710                                 }
1711                         }
1712                 }
1713                 break;
1714                 default:
1715                 break;
1716                 }
1717         }
1718
1719         else if (pixelFormat == MEDIA_PIXEL_FORMAT_YUV444P)
1720         {
1721                 int rowCount = 0;
1722                 int colCount = 0;
1723                 byte* pDstY = (byte *)dstBuf.GetPointer();
1724                 byte* pDstU = pDstY + outWidth * outHeight;
1725                 byte* pDstV = pDstU + outWidth * outHeight;
1726
1727                 byte* pSrcY = (byte *) srcBuf.GetPointer();
1728                 byte* pSrcU = pSrcY + width * height;
1729                 byte* pSrcV = pSrcU + width * height;
1730                 byte* pTmpOutColY = null;
1731                 byte* pTmpOutColU = null;
1732                 byte* pTmpOutColV = null;
1733
1734                 switch (rotate)
1735                 {
1736                 case IMAGE_ROTATION_90:
1737                 {
1738                         // Copying from all source rows to destination columns of Y plane.
1739                         for (rowCount = 0; rowCount < height; rowCount++)
1740                         {
1741                                 // pTmpOutCol points to the top of the output column being filled.
1742                                 pTmpOutColU = pDstU + outWidth - 1 - rowCount;
1743                                 pTmpOutColV = pDstV + outWidth - 1 - rowCount;
1744                                 pTmpOutColY = pDstY + outWidth - 1 - rowCount;
1745                                 for (colCount = 0; colCount < width / 2; colCount++)
1746                                 {
1747                                         *pTmpOutColU = *pSrcU++;
1748                                         pTmpOutColU += outWidth;
1749                                         *pTmpOutColV = *pSrcV++;
1750                                         pTmpOutColV += outWidth;
1751                                         *pTmpOutColY = *pSrcY++;
1752                                         pTmpOutColY += outWidth;
1753
1754                                         *pTmpOutColU = *pSrcU++;
1755                                         pTmpOutColU += outWidth;
1756                                         *pTmpOutColV = *pSrcV++;
1757                                         pTmpOutColV += outWidth;
1758                                         *pTmpOutColY = *pSrcY++;
1759                                         pTmpOutColY += outWidth;
1760                                 }
1761                         }
1762                 }
1763                 break;
1764                 case IMAGE_ROTATION_180:
1765                 {
1766                         // Copying from all source rows to destination columns of Y plane.
1767                         pTmpOutColY = pDstY + outWidth * outHeight - 1;
1768                         pTmpOutColU = pDstU + outWidth * outHeight - 1;
1769                         pTmpOutColV = pDstV + outWidth * outHeight - 1;
1770                         for (colCount = (outWidth * outHeight); colCount > 0; colCount--)
1771                         {
1772                                 *pTmpOutColY-- = *pSrcY++;
1773                                 *pTmpOutColU-- = *pSrcU++;
1774                                 *pTmpOutColV-- = *pSrcV++;
1775                         }
1776                 }
1777                 break;
1778                 case IMAGE_ROTATION_270:
1779                 {
1780                         // Copying from all source rows to destination columns of Y plane.
1781                         for (rowCount = 0; rowCount < height; rowCount++)
1782                         {
1783                                 // pTmpOutCol points to the top of the output column being filled.
1784                                 pTmpOutColY = pDstY + (outWidth * (outHeight - 1)) + rowCount;
1785                                 pTmpOutColU = pDstU + (outWidth * (outHeight - 1)) + rowCount;
1786                                 pTmpOutColV = pDstV + (outWidth * (outHeight - 1)) + rowCount;
1787                                 for (colCount = 0; colCount < width / 2; colCount++)
1788                                 {
1789                                         *pTmpOutColY = *pSrcY++;
1790                                         pTmpOutColY -= outWidth;
1791                                         *pTmpOutColU = *pSrcU++;
1792                                         pTmpOutColU -= outWidth;
1793                                         *pTmpOutColV = *pSrcV++;
1794                                         pTmpOutColV -= outWidth;
1795
1796                                         *pTmpOutColY = *pSrcY++;
1797                                         pTmpOutColY -= outWidth;
1798                                         *pTmpOutColU = *pSrcU++;
1799                                         pTmpOutColU -= outWidth;
1800                                         *pTmpOutColV = *pSrcV++;
1801                                         pTmpOutColV -= outWidth;
1802                                 }
1803                         }
1804                 }
1805                 break;
1806                 default:
1807                 break;
1808                 }
1809         }
1810         else if (pixelFormat == MEDIA_PIXEL_FORMAT_YUYV422)
1811         {
1812                 int rowCount = 0;
1813                 int colCount = 0;
1814                 short* pSrcBuf = (short*)srcBuf.GetPointer();
1815                 short* pDstBuf = (short*)dstBuf.GetPointer();
1816                 short* pTmpOutCol = null;
1817
1818                 switch (rotate)
1819                 {
1820                 case IMAGE_ROTATION_90:
1821                 {
1822                         // Copying from all source rows to destination columns.
1823                         for (rowCount = 0; rowCount < height; rowCount++)
1824                         {
1825                                 // pTmpOutCol points to the top of the output column being filled.
1826                                 pTmpOutCol = pDstBuf + outWidth - 1 - rowCount;
1827                                 for (colCount = 0; colCount < width / 2 ; colCount++)
1828                                 {
1829                                         *pTmpOutCol = *pSrcBuf++; // copied Y0 U0
1830                                         pTmpOutCol += outWidth;
1831
1832                                         *pTmpOutCol = *pSrcBuf++; // copied Y1 V0
1833                                         pTmpOutCol += outWidth;
1834                                 }
1835                         }
1836                 }
1837                 break;
1838                 case IMAGE_ROTATION_180:
1839                 {
1840                         // Copying all source rows to destination columns.
1841                         for (rowCount = 0; rowCount < height; rowCount++)
1842                         {
1843                                 // pTmpOutCol points to the bottom of the column being filled.
1844                                 pTmpOutCol = pDstBuf + ((outWidth * outHeight ) - 1) - (rowCount * outWidth);
1845
1846                                 for (colCount = 0; colCount < width / 2; colCount++)
1847                                 {
1848                                         *pTmpOutCol-- = *pSrcBuf++;   // copied Y0 U0
1849                                         *pTmpOutCol-- = *pSrcBuf++;   // copied Y1 V0
1850                                 }
1851                         }
1852                 }
1853                 break;
1854                 case IMAGE_ROTATION_270:
1855                 {
1856                         // Copying all source rows to destination columns.
1857                         for (rowCount = 0; rowCount < height; rowCount++)
1858                         {
1859                                 // pTmpOutCol points to the bottom of the column being filled.
1860                                 pTmpOutCol = pDstBuf + (outWidth * (outHeight - 1)) + rowCount;
1861                                 for (colCount = 0; colCount < width / 2; colCount++)
1862                                 {
1863                                         *pTmpOutCol = *pSrcBuf++;   // copied B
1864                                         pTmpOutCol -= outWidth;
1865
1866                                         *pTmpOutCol = *pSrcBuf++;   // copied B
1867                                         pTmpOutCol -= outWidth;
1868                                 }
1869                         }
1870                 }
1871                 break;
1872                 default:
1873                 break;
1874                 }
1875         }
1876         else
1877         {
1878 #ifdef USE_MM_UTIL
1879
1880                 colorFormat = _SlpUtil::ToMmUtilImgFormat(pixelFormat);
1881                 rotation = _SlpUtil::ToMmUtilRotateType(rotate);
1882
1883                 ret = mm_util_rotate_image((unsigned char*)srcBuf.GetPointer(), width, height, colorFormat,
1884                                                                 (unsigned char*)dstBuf.GetPointer(), &outWidth, &outHeight, rotation);
1885
1886                 SysTryCatch(NID_MEDIA, ret == 0, r = E_SYSTEM, E_SYSTEM,
1887                         "mm_util_rotate_image: %0x", ret);
1888
1889 #else
1890
1891                 colorFormat = _SlpUtil::ToColorspace(pixelFormat);
1892                 rotation = _SlpUtil::ToRotation(rotate);
1893
1894                 ret = image_util_transform((byte*)dstBuf.GetPointer(), &outWidth, &outHeight, rotation,
1895                                                                 (byte*)srcBuf.GetPointer(), width, height, colorFormat);
1896
1897                 SysTryCatch(NID_MEDIA, ret == IMAGE_UTIL_ERROR_NONE, r = E_SYSTEM, E_SYSTEM,
1898                         "[E_SYSTEM] util_transform failed: %0x", ret);
1899 #endif
1900         }
1901
1902
1903         r = dstBuf.SetLimit(_ImageUtil::GetBufferSize(pixelFormat, outWidth, outHeight));
1904         SysTryCatch(NID_MEDIA, r==E_SUCCESS, , r,
1905                 "[%s] dstBuf.SetLimit failed for (%d x %d) pixel format: %d",
1906                 GetErrorMessage(r), outWidth, outHeight, pixelFormat);
1907
1908         return r;
1909
1910 CATCH:
1911         return r;
1912 }
1913
1914 result
1915 _ImageUtil::Flip(const ByteBuffer& srcBuf, MediaPixelFormat pixelFormat,
1916                                  int width, int height,
1917                                  ByteBuffer& dstBuf, ImageFlipType flip)
1918 {
1919         result r = E_SUCCESS;
1920         int ret = 0;
1921 #ifdef USE_MM_UTIL
1922         mm_util_img_format colorFormat = MM_UTIL_IMG_FMT_NUM;
1923         mm_util_img_rotate_type rotation = MM_UTIL_ROTATE_NUM;
1924
1925         unsigned int outWidth = 0;
1926         unsigned int outHeight = 0;
1927 #else
1928         image_util_colorspace_e colorFormat = IMAGE_UTIL_COLORSPACE_RGB565;
1929         image_util_rotation_e rotation = IMAGE_UTIL_ROTATION_NONE;
1930         int outWidth = 0;
1931         int outHeight = 0;
1932 #endif
1933
1934         SysTryCatch(NID_MEDIA, width > 0 && height > 0, r = E_INVALID_ARG, E_INVALID_ARG,
1935                 "[E_INVALID_ARG] Invalid dimension: Should be greater than zero: (%d x %d)",
1936                 width, height);
1937
1938         SysTryCatch(NID_MEDIA, IS_VALID_PIXEL(pixelFormat), r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
1939                 "[E_UNSUPPORTED_FORMAT] Unsupported pixelFormat: %d", pixelFormat);
1940
1941         SysTryCatch(NID_MEDIA, IsValidDimension(pixelFormat, width, height),
1942                 r = E_INVALID_ARG, E_INVALID_ARG,
1943                 "[E_INVALID_ARG] Dimensions should be even (%d x %d).", width, height);
1944
1945         SysTryCatch(NID_MEDIA, IS_VALID_BUF(srcBuf, pixelFormat, width, height),
1946                 r = E_INVALID_ARG, E_INVALID_ARG,
1947                 "Invalid buffer size (%d) for format (%d), width (%d), height (%d)",
1948                 srcBuf.GetLimit(), pixelFormat, width, height);
1949
1950         SysTryCatch(NID_MEDIA, IS_VALID_BUF(dstBuf, pixelFormat, width, height),
1951                 r = E_INVALID_ARG, E_INVALID_ARG,
1952                 "Invalid buffer size (%d) for format (%d), width (%d), height (%d)",
1953                 dstBuf.GetLimit(), pixelFormat, width, height);
1954
1955         if (flip == IMAGE_FLIP_NONE)
1956         {
1957                 r = dstBuf.SetArray(srcBuf.GetPointer(), 0, srcBuf.GetLimit());
1958                 SysTryCatch(NID_MEDIA, r==E_SUCCESS, , r,
1959                         "[%s] dstBuf.SetArray failed: source (%x %d), dst (%d %d)",
1960                         srcBuf.GetPointer(), srcBuf.GetLimit(),
1961                         dstBuf.GetPosition(), dstBuf.GetCapacity());
1962                 dstBuf.Flip();
1963                 return r;
1964         }
1965
1966         // Set output dimensions;
1967         outWidth = width;
1968         outHeight = height;
1969
1970         if (pixelFormat == MEDIA_PIXEL_FORMAT_RGB565LE)
1971         {
1972                 if (flip == IMAGE_FLIP_HORIZONTAL)
1973                 {
1974                         int rowCount = 0;
1975                         int colCount = 0;
1976                         unsigned short* pSrcBuf = (unsigned short *)srcBuf.GetPointer();
1977                         unsigned short* pDstBuf = (unsigned short *)dstBuf.GetPointer();
1978                         // pTmpOutRow points to last column of first row of destination.
1979                         unsigned short* pTmpOutRow = pDstBuf + width - 1;
1980
1981                         for (rowCount = 0; rowCount < height; rowCount++)
1982                         {
1983                                 for (colCount = 0; colCount < width; colCount++)
1984                                 {
1985                                         *pTmpOutRow-- = *pSrcBuf++; // copy source row in reverse to destination.
1986                                 }
1987                                 pTmpOutRow += (2 * outWidth);
1988                         }
1989                 }
1990                 else 
1991                 {
1992                         int rowCount = 0;
1993                         unsigned short* pSrcBuf = (unsigned short *)srcBuf.GetPointer();
1994                         unsigned short* pDstBuf = (unsigned short *)dstBuf.GetPointer();
1995                         // pTmpOutRow points to the start of last row in destination buffer.
1996                         unsigned short* pTmpOutRow = pDstBuf + (width * (height - 1));
1997
1998                         for (rowCount = 0; rowCount < height; rowCount++)
1999                         {
2000                                 // copy one row worth of data.
2001                                 memcpy(pTmpOutRow, pSrcBuf, sizeof(unsigned short) * width);
2002                                 pTmpOutRow -= width; // go to one higher row.
2003                                 pSrcBuf += width; // go to next row.
2004                         }
2005                 }
2006         }
2007         else
2008         {
2009 #ifdef USE_MM_UTIL
2010
2011                 colorFormat = _SlpUtil::ToMmUtilImgFormat(pixelFormat);
2012                 rotation = _SlpUtil::ToMmUtilRotateType(flip);
2013
2014                 ret = mm_util_rotate_image((unsigned char*)srcBuf.GetPointer(), width, height, colorFormat,
2015                                                                 (unsigned char*)dstBuf.GetPointer(), &outWidth, &outHeight, rotation);
2016
2017                 SysTryCatch(NID_MEDIA, ret == 0, r = E_SYSTEM, E_SYSTEM,
2018                         "mm_util_rotate_image failed with error code: %0x", ret);
2019 #else
2020                 colorFormat = _SlpUtil::ToColorspace(pixelFormat);
2021                 rotation = _SlpUtil::ToRotation(flip);
2022
2023                 ret = image_util_transform((byte*)dstBuf.GetPointer(), &outWidth, &outHeight, rotation,
2024                                                                 (byte*)srcBuf.GetPointer(), width, height, colorFormat);
2025                 SysTryCatch(NID_MEDIA, ret == IMAGE_UTIL_ERROR_NONE, r = E_SYSTEM, E_SYSTEM,
2026                         "util_transform failed with error code: %0x", ret);
2027 #endif
2028         }
2029
2030         r = dstBuf.SetLimit(_ImageUtil::GetBufferSize(pixelFormat, outWidth, outHeight));
2031         SysTryCatch(NID_MEDIA, r==E_SUCCESS, , r,
2032                 "[%s] SetLimit to %d failed for buffer.", GetErrorMessage(r),
2033                 _ImageUtil::GetBufferSize(pixelFormat, outWidth, outHeight));
2034
2035         return r;
2036
2037 CATCH:
2038         return r;
2039 }
2040
2041 Tizen::Media::ImageFormat
2042 _ImageUtil::GetImageFormat(const Tizen::Base::String& srcImageFile)
2043 {
2044         ImageFormat imgFormat;
2045         ByteBuffer* pBuf = null;
2046
2047         pBuf = _MediaUtil::FileToBufferN(srcImageFile, _ImageUtil::MinImageFormatLength());
2048         SysTryCatch(NID_MEDIA, pBuf != null, , GetLastResult(),
2049                 "[%s] _MediaUtil::FileToBufferN failed for %ls.",
2050                 GetErrorMessage(GetLastResult()), srcImageFile.GetPointer());
2051
2052         imgFormat = GetImageFormat(*pBuf);
2053
2054         if (pBuf != null)
2055         {
2056                 delete pBuf;
2057         }
2058         return imgFormat;
2059
2060 CATCH:
2061
2062         return IMG_FORMAT_NONE;
2063 }
2064
2065
2066 bool
2067 _ImageUtil::HasAlphaChannel(const Tizen::Base::String& srcImageFile)
2068 {
2069         bool hasAlpha = false;
2070         ByteBuffer* pBuf = null;
2071
2072         pBuf = _MediaUtil::FileToBufferN(srcImageFile);
2073         SysTryCatch(NID_MEDIA, pBuf != null, , GetLastResult(),
2074                 "[%s] _MediaUtil::FileToBufferN failed for %ls.",
2075                 GetErrorMessage(GetLastResult()), srcImageFile.GetPointer());
2076         hasAlpha = HasAlphaChannel(*pBuf);
2077
2078         // fall through
2079 CATCH :
2080         if (pBuf != null)
2081         {
2082                 delete pBuf;
2083         }
2084         return hasAlpha;
2085 }
2086
2087 // For check image format
2088 static byte _PNG_HEADER[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a };
2089 static byte _JPEG_HEADER[] = { 0xFF, 0xD8 };            // support only JFIF.
2090 static byte _GIF_HEADER[] = { 'G', 'I', 'F' };
2091 static byte _TIFF_HEADER[][4] = { { 0x49, 0x49, 0x2A, 0x00 }, { 0x4D, 0x4D, 0x00, 0x2A } };
2092 static byte _BMP_HEADER[] = { 'B', 'M' };
2093 static byte _WBMP_HEADER[] = { 0x00, 0x00 };
2094
2095 static const int MIN_IMAGE_FORMAT_LENGTH = sizeof(_PNG_HEADER);
2096
2097 int
2098 _ImageUtil::MinImageFormatLength(void)
2099 {
2100         return MIN_IMAGE_FORMAT_LENGTH;
2101 }
2102
2103 ImageFormat
2104 _ImageUtil::GetImageFormat(const Tizen::Base::ByteBuffer& srcBuf)
2105 {
2106         const byte* pBuf = null;
2107         static struct
2108         {
2109                 byte* pHeader;
2110                 int size;
2111                 ImageFormat format;
2112         } map[] = {
2113                 { _PNG_HEADER, sizeof(_PNG_HEADER), IMG_FORMAT_PNG },
2114                 { _JPEG_HEADER, sizeof(_JPEG_HEADER), IMG_FORMAT_JPG },
2115                 { _BMP_HEADER, sizeof(_BMP_HEADER), IMG_FORMAT_BMP },
2116                 { _GIF_HEADER, sizeof(_GIF_HEADER), IMG_FORMAT_GIF },
2117                 { _TIFF_HEADER[0], sizeof(_TIFF_HEADER[0]), IMG_FORMAT_TIFF },
2118                 { _TIFF_HEADER[1], sizeof(_TIFF_HEADER[1]), IMG_FORMAT_TIFF },
2119                 { _WBMP_HEADER, sizeof(_WBMP_HEADER), IMG_FORMAT_WBMP },
2120         };
2121         ImageFormat fmt = IMG_FORMAT_NONE;
2122         SysTryCatch(NID_MEDIA, &srcBuf != null, , E_INVALID_ARG,
2123                 "[E_INVALID_ARG] srcBuf is null");
2124         SysTryCatch(NID_MEDIA, srcBuf.GetLimit() >= MIN_IMAGE_FORMAT_LENGTH, , E_INVALID_DATA,
2125                 "[E_INVALID_DATA] data is too small:%d < %d", srcBuf.GetLimit(), MIN_IMAGE_FORMAT_LENGTH);
2126
2127         pBuf = (const byte*) (srcBuf.GetPointer());
2128         SysTryCatch(NID_MEDIA, pBuf != null, , E_INVALID_ARG,
2129                 "[E_INVALID_ARG] Could not get file header.");
2130         for (unsigned int i = 0; i < sizeof(map)/sizeof(map[0]); i++)
2131         {
2132                 if (memcmp(pBuf, map[i].pHeader, map[i].size) == 0)
2133                 {
2134                         fmt = map[i].format;
2135                         break;
2136                 }
2137         }
2138         if ((fmt == IMG_FORMAT_WBMP) && (pBuf[2] == 1 || pBuf[2] == 2) && pBuf[3] == 0 )
2139         {
2140                 fmt = IMG_FORMAT_NONE;
2141         }
2142         return fmt;
2143
2144
2145 CATCH:
2146         return IMG_FORMAT_NONE;
2147 }
2148
2149 bool
2150 _ImageUtil::HasAlphaChannel(const Tizen::Base::ByteBuffer& srcBuf)
2151 {
2152         ImageFormat imgFormat = IMG_FORMAT_NONE;
2153         const byte* pBuf = null;
2154         bool idatFlag = false;
2155         bool hasAlpha = false;
2156         unsigned int cnkLength = 0;
2157         int curPosition = 0;
2158         int value = 0;
2159         int bufSize = 0;
2160
2161         SysTryReturn(NID_MEDIA, &srcBuf != null, hasAlpha, E_INVALID_ARG,
2162                 "[E_INVALID_ARG] srcBuf is null");
2163
2164         imgFormat = GetImageFormat(srcBuf);
2165
2166         SysTryReturn(NID_MEDIA, imgFormat == IMG_FORMAT_PNG, hasAlpha, E_UNSUPPORTED_FORMAT,
2167                 "[E_UNSUPPORTED_FORMAT] The file is not of PNG format.");
2168
2169         pBuf = (const byte*)srcBuf.GetPointer();
2170         bufSize = srcBuf.GetCapacity();
2171
2172         curPosition = 25;
2173         // 25 means, Png ID(8byte) + IHDR length(4byte) + IHDR(4byte) +
2174         // Width(4byte) + Height(4byte) + Bitdepth(1byte) and next 1byte is
2175         // color type.
2176         // If color type is between 4 and 7, it uses alpha channel.
2177         SysTryReturn(NID_MEDIA, bufSize > (curPosition + 4), hasAlpha, E_UNSUPPORTED_FORMAT,
2178                 "[E_INVALID_DATA] data size is too small: %d < %d", bufSize, curPosition + 4);
2179
2180         value = pBuf[curPosition];
2181         if ((4 <= value) && (value <= 7))
2182         {
2183                 hasAlpha = true;
2184         }
2185         else if (value == 3)
2186         {
2187                 // check tRNS chunck existance if color type is 3(indexed palette).
2188                 // 25byte + remained IHDR 3byte(filter mode etc.) = 28byte
2189                 // 28byte + ?(4byte)
2190                 curPosition = 33;
2191                 // Chunk length(4byte)+ chunk name(4byte) + length(value of chunk length) + CRC(4byte)
2192                 // chunk can be pHYs, sBIT, gAMA, cHRM, tRNS, etc (before IDAT)
2193                 SysTryReturn(NID_MEDIA, bufSize > (curPosition + 4), hasAlpha, E_INVALID_DATA,
2194                         "[E_INVALID_DATA] data size is too small: %d < %d", bufSize, curPosition + 4);
2195
2196                 // Structure of chunk:
2197                 // |<----------------- A single chunk ---------------------->|
2198                 // |_________________________________________________________|
2199                 // |  4 bytes   ||  4 bytes || chunk length bytes || 4 bytes |
2200                 // |____________||__________||____________________||_________|
2201                 // |            ||          ||                    ||         |
2202                 // |Chunk length||Chunk name||     chunk data     || CRC sum |
2203                 //
2204                 // data is stored in network byte order; ie big endian.
2205                 // To get the value, convert to little endian.
2206
2207                 memcpy(&cnkLength, pBuf + curPosition, 4);
2208                 cnkLength = ntohl(cnkLength);
2209
2210                 // Increment position to point to chunk name, which follows the length.
2211                 curPosition = curPosition + 4;
2212
2213                 // Loop with starting chunk length.
2214                 while (curPosition < bufSize - 4)
2215                 {
2216                         if (!memcmp((void *)(pBuf + curPosition), (void *)"tRNS", 4))
2217                         {
2218                                 hasAlpha = true;
2219                         }
2220                         else if (!memcmp((void *)(pBuf + curPosition), (void *)"IDAT", 4))
2221                         {
2222                                 idatFlag = true;
2223                         }
2224                         else
2225                         {
2226                                 curPosition += 4;        // chunk name
2227                                 curPosition += cnkLength;
2228                                 curPosition += 4;        // CRC
2229                         }
2230
2231                         // tRNS chunk must be before IDAT chunk.
2232                         if (idatFlag || hasAlpha)
2233                         {
2234                                 break;
2235                         }
2236
2237                         if (curPosition >= bufSize - 4)
2238                         {
2239                                 break;
2240                         }
2241
2242                         // read next chunk length
2243                         memcpy(&cnkLength, pBuf + curPosition, 4);
2244                         cnkLength = ntohl(cnkLength);
2245                         curPosition = curPosition + 4;
2246                 }
2247         }
2248
2249         return hasAlpha;
2250 }
2251
2252 Tizen::Base::ByteBuffer*
2253 _ImageUtil::ResizeN(const Tizen::Base::ByteBuffer &srcBuf,
2254                                         MediaPixelFormat pixelFormat,
2255                                         int srcWidth, int srcHeight,
2256                                         int dstWidth, int dstHeight)
2257 {
2258         int bufSize = 0;
2259         std::unique_ptr <ByteBuffer> pOutBuf;
2260         result r = E_SUCCESS;
2261
2262         bufSize = GetBufferSize(pixelFormat, dstWidth, dstHeight);
2263         SysTryReturn(NID_MEDIA, bufSize > 0, null, GetLastResult(),
2264                 "[%s] Check dimensions (%d x %d) and pixelformat %d", GetErrorMessage(GetLastResult()),
2265                 dstWidth, dstHeight, pixelFormat);
2266
2267         pOutBuf.reset(new (std::nothrow) ByteBuffer());
2268         SysTryReturn(NID_MEDIA, pOutBuf.get() != null, null, E_OUT_OF_MEMORY,
2269                 "[%s] Failed to create new ByteBuffer", GetErrorMessage(GetLastResult()));
2270
2271         r = pOutBuf->Construct(bufSize);
2272         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
2273                 "[%s] ByteBuffer.Construct failed", GetErrorMessage(r));
2274
2275         r = Resize(srcBuf, pixelFormat, srcWidth, srcHeight, *pOutBuf.get(), dstWidth, dstHeight);
2276         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
2277                                 "[%s] ImageUtil.Resize", GetErrorMessage(r));
2278
2279         SetLastResult(E_SUCCESS);
2280         return pOutBuf.release();
2281 }
2282
2283 result
2284 _ImageUtil::Crop(const Tizen::Base::ByteBuffer &srcBuf,
2285                                  MediaPixelFormat pixelFormat,
2286                                  int srcWidth, int srcHeight,
2287                                  Tizen::Base::ByteBuffer &dstBuf,
2288                                  int dstX, int dstY, int dstWidth, int dstHeight)
2289 {
2290         result r = E_SUCCESS;
2291         byte* pInBuffer = null;
2292         byte* pOutBuffer = null;
2293         int copyRowWidth = 0;
2294         int srcRowWidth = 0;
2295         int bpp = 0;
2296
2297         SysTryCatch(NID_MEDIA, srcWidth > 0 && srcHeight > 0, r = E_INVALID_ARG, E_INVALID_ARG,
2298                 "[E_INVALID_ARG] Invalid src dimension: Should be greater than zero (%d x %d)", srcWidth, srcHeight);
2299         SysTryCatch(NID_MEDIA, dstWidth > 0 && dstHeight > 0, r = E_INVALID_ARG, E_INVALID_ARG,
2300                 "[E_INVALID_ARG] Invalid dst dimension: Should be greater than zero (%d x %d)", dstWidth, dstHeight);
2301         SysTryCatch(NID_MEDIA, dstX >= 0 && dstY >= 0, r = E_INVALID_ARG, E_INVALID_ARG,
2302                 "[E_INVALID_ARG] Invalid offset dimension: Should be greater than zero (%d x %d)", dstX, dstY);
2303
2304         SysTryCatch(NID_MEDIA, (pixelFormat == MEDIA_PIXEL_FORMAT_RGB565LE) ||
2305                 (pixelFormat == MEDIA_PIXEL_FORMAT_RGBA8888) ||
2306                 (pixelFormat == MEDIA_PIXEL_FORMAT_BGRA8888),
2307                 r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
2308                 "Unsupported pixelFormat: %d", pixelFormat);
2309
2310         SysTryCatch(NID_MEDIA, IsValidDimension(pixelFormat, srcWidth, srcHeight),
2311                 r = E_INVALID_ARG, E_INVALID_ARG,
2312                 "[E_INVALID_ARG] Dimensions should be even (%d x %d).", srcWidth, srcHeight);
2313
2314         SysTryCatch(NID_MEDIA, IS_VALID_BUF(srcBuf, pixelFormat, srcWidth, srcHeight),
2315                 r = E_INVALID_ARG, E_INVALID_ARG,
2316                 "Invalid buffer size (%d) for format (%d), width (%d), height (%d)",
2317                 srcBuf.GetLimit(), pixelFormat, srcWidth, srcHeight);
2318
2319         SysTryCatch(NID_MEDIA, IsValidDimension(pixelFormat, dstWidth, dstHeight),
2320                 r = E_INVALID_ARG, E_INVALID_ARG,
2321                 "[E_INVALID_ARG] Dimensions should be even (%d x %d).", dstWidth, dstHeight);
2322
2323         SysTryCatch(NID_MEDIA, IS_VALID_BUF(dstBuf, pixelFormat, dstWidth, dstHeight),
2324                 r = E_INVALID_ARG, E_INVALID_ARG,
2325                 "Invalid buffer size (%d) for format (%d), width (%d), height (%d)",
2326                 dstBuf.GetLimit(), pixelFormat, dstWidth, dstHeight);
2327
2328         SysTryCatch(NID_MEDIA, dstWidth + dstX <= srcWidth , r = E_INVALID_ARG, E_INVALID_ARG,
2329                 "Invalid Clip Area : destination \"x\" (%d) exceeds image width (%d).",
2330                 dstWidth + dstX, srcWidth);
2331
2332         SysTryCatch(NID_MEDIA, dstHeight + dstY <= srcHeight , r = E_INVALID_ARG, E_INVALID_ARG,
2333                 "Invalid Clip Area  : destination \"y\" (%d) exceeds image height (%d).",
2334                 dstHeight + dstY, srcHeight);
2335
2336         pOutBuffer = (byte *)dstBuf.GetPointer();
2337
2338         if (pixelFormat == MEDIA_PIXEL_FORMAT_RGB565LE)
2339         {
2340                 bpp = 2;
2341                 // pInBuffer points to the start of the region to be copied to destination.
2342                 pInBuffer = (byte *)srcBuf.GetPointer() + (dstY * srcWidth * bpp) + (dstX * bpp);
2343                 copyRowWidth = dstWidth * bpp;
2344                 srcRowWidth = srcWidth * bpp;
2345         }
2346         else
2347         {
2348                 bpp = 4;
2349                 // pInBuffer points to the start of the region to be copied to destination.
2350                 pInBuffer = (byte *)srcBuf.GetPointer() + (dstY * srcWidth * bpp) + (dstX * bpp);
2351                 copyRowWidth = dstWidth * bpp; // BGRA and RGBA are 4 bytes each.
2352                 srcRowWidth = srcWidth * bpp;
2353         }
2354
2355         for (int i = dstY; i < dstY + dstHeight; i++)
2356         {
2357                 memcpy(pOutBuffer, pInBuffer, copyRowWidth);
2358                 pOutBuffer += copyRowWidth;
2359                 pInBuffer += srcRowWidth;
2360         }
2361
2362         r = dstBuf.SetLimit(_ImageUtil::GetBufferSize(pixelFormat, dstWidth, dstHeight));
2363         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] ByteBuffer.SetLimit to %d failed.",
2364                 GetErrorMessage(r), _ImageUtil::GetBufferSize(pixelFormat, dstWidth, dstHeight));
2365         return r;
2366
2367 CATCH:
2368         return r;
2369 }
2370
2371 result
2372 _ImageUtil::CropBuffer(const byte* srcBuf,
2373                                  MediaPixelFormat pixelFormat,
2374                                  int srcWidth, int srcHeight,
2375                                  byte* dstBuf,
2376                                  int dstX, int dstY, int dstWidth, int dstHeight)
2377 {
2378         result r = E_SUCCESS;
2379         int copyRowWidth = 0;
2380         int srcRowWidth = 0;
2381         int bpp = 0;
2382         byte* pInBuffer = null;
2383         byte* pOutBuffer = null;
2384
2385         SysTryCatch(NID_MEDIA, srcWidth > 0 && srcHeight > 0, r = E_INVALID_ARG, E_INVALID_ARG,
2386                 "[E_INVALID_ARG] Invalid src dimension: Should be greater than zero (%d x %d)", srcWidth, srcHeight);
2387         SysTryCatch(NID_MEDIA, dstWidth > 0 && dstHeight > 0, r = E_INVALID_ARG, E_INVALID_ARG,
2388                 "[E_INVALID_ARG] Invalid dst dimension: Should be greater than zero (%d x %d)", dstWidth, dstHeight);
2389         SysTryCatch(NID_MEDIA, dstX >= 0 && dstY >= 0, r = E_INVALID_ARG, E_INVALID_ARG,
2390                 "[E_INVALID_ARG] Invalid offset dimension: Should be greater than zero (%d x %d)", dstX, dstY);
2391
2392         SysTryCatch(NID_MEDIA, (pixelFormat == MEDIA_PIXEL_FORMAT_RGB565LE) ||
2393                 (pixelFormat == MEDIA_PIXEL_FORMAT_RGBA8888) ||
2394                 (pixelFormat == MEDIA_PIXEL_FORMAT_BGRA8888),
2395                 r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
2396                 "Unsupported pixelFormat: %d", pixelFormat);
2397
2398         SysTryCatch(NID_MEDIA, IsValidDimension(pixelFormat, srcWidth, srcHeight),
2399                 r = E_INVALID_ARG, E_INVALID_ARG,
2400                 "[E_INVALID_ARG] Dimensions should be even (%d x %d).", srcWidth, srcHeight);
2401
2402         SysTryCatch(NID_MEDIA, IsValidDimension(pixelFormat, dstWidth, dstHeight),
2403                 r = E_INVALID_ARG, E_INVALID_ARG,
2404                 "[E_INVALID_ARG] Dimensions should be even (%d x %d).", dstWidth, dstHeight);
2405
2406         SysTryCatch(NID_MEDIA, dstWidth + dstX <= srcWidth , r = E_INVALID_ARG, E_INVALID_ARG,
2407                 "Invalid Clip Area : destination \"x\" (%d) exceeds image width (%d).",
2408                 dstWidth + dstX, srcWidth);
2409
2410         SysTryCatch(NID_MEDIA, dstHeight + dstY <= srcHeight , r = E_INVALID_ARG, E_INVALID_ARG,
2411                 "Invalid Clip Area  : destination \"y\" (%d) exceeds image height (%d).",
2412                 dstHeight + dstY, srcHeight);
2413
2414         pOutBuffer = dstBuf;
2415
2416         if (pixelFormat == MEDIA_PIXEL_FORMAT_RGB565LE)
2417         {
2418                 bpp = 2;
2419                 // pInBuffer points to the start of the region to be copied to destination.
2420                 pInBuffer = const_cast<byte*>(srcBuf) + (dstY * srcWidth * bpp) + (dstX * bpp);
2421                 copyRowWidth = dstWidth * bpp;
2422                 srcRowWidth = srcWidth * bpp;
2423         }
2424         else
2425         {
2426                 bpp = 4;
2427                 // pInBuffer points to the start of the region to be copied to destination.
2428                 pInBuffer = const_cast<byte*>(srcBuf) + (dstY * srcWidth * bpp) + (dstX * bpp);
2429                 copyRowWidth = dstWidth * bpp; // BGRA and RGBA are 4 bytes each.
2430                 srcRowWidth = srcWidth * bpp;
2431         }
2432
2433         for (int i = dstY; i < dstY + dstHeight; i++)
2434         {
2435                 memcpy(pOutBuffer, pInBuffer, copyRowWidth);
2436                 pOutBuffer += copyRowWidth;
2437                 pInBuffer += srcRowWidth;
2438         }
2439
2440 CATCH:
2441         return r;
2442 }
2443
2444 Tizen::Base::ByteBuffer*
2445 _ImageUtil::CropN(const Tizen::Base::ByteBuffer &srcBuf,
2446                                   MediaPixelFormat pixelFormat,
2447                                   int srcWidth, int srcHeight,
2448                                   int dstX, int dstY,
2449                                   int dstWidth, int dstHeight)
2450 {
2451         int bufSize = 0;
2452         std::unique_ptr <ByteBuffer> pOutBuf;
2453         result r = E_SUCCESS;
2454
2455         bufSize = GetBufferSize(pixelFormat, dstWidth, dstHeight);
2456         SysTryReturn(NID_MEDIA, bufSize > 0, null, GetLastResult(),
2457                 "[%s] Check dimensions (%d x %d) and pixel format (%d)",
2458                 GetErrorMessage(GetLastResult()), dstWidth, dstHeight, pixelFormat);
2459
2460         pOutBuf.reset(new (std::nothrow) ByteBuffer());
2461         SysTryReturn(NID_MEDIA, pOutBuf.get() != null, null, E_OUT_OF_MEMORY,
2462                 "[E_OUT_OF_MEMORY] Could not create new ByteBuffer.");
2463
2464         r = pOutBuf->Construct(bufSize);
2465         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
2466                 "[%s] buf.Construct failed.", GetErrorMessage(r));
2467
2468         r = Crop(srcBuf, pixelFormat, srcWidth, srcHeight, *pOutBuf.get(), dstX, dstY, dstWidth, dstHeight);
2469         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
2470                 "[%s] ImageUtil.Crop failed.", GetErrorMessage(r));
2471
2472         SetLastResult(E_SUCCESS);
2473         return pOutBuf.release();
2474 }
2475
2476 byte*
2477 _ImageUtil::CropN(const byte *srcBuf,
2478                                                 MediaPixelFormat pixelFormat,
2479                                                 int srcWidth, int srcHeight,
2480                                                 int dstX, int dstY, int dstWidth, int dstHeight)
2481 {
2482         int bufSize = 0;
2483         std::unique_ptr <byte[]> pOutBuf;
2484         result r = E_SUCCESS;
2485
2486         bufSize = GetBufferSize(pixelFormat, dstWidth, dstHeight);
2487         SysTryReturn(NID_MEDIA, bufSize > 0, null, GetLastResult(),
2488                 "[%s] Check dimensions (%d x %d) and pixel format (%d)",
2489                 GetErrorMessage(GetLastResult()), dstWidth, dstHeight, pixelFormat);
2490
2491         pOutBuf.reset(new (std::nothrow) byte[bufSize]);
2492         SysTryReturn(NID_MEDIA, pOutBuf.get() != null, null, E_OUT_OF_MEMORY,
2493                 "[E_OUT_OF_MEMORY] Could not create new ByteBuffer.");
2494
2495         r = CropBuffer(srcBuf, pixelFormat, srcWidth, srcHeight, pOutBuf.get(), dstX, dstY, dstWidth, dstHeight);
2496         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
2497                 "[%s] ImageUtil.CropN failed.", GetErrorMessage(r));
2498
2499         SetLastResult(E_SUCCESS);
2500         return pOutBuf.release();
2501 }
2502
2503 byte*
2504 _ImageUtil::RotateN(const byte *srcBuf,
2505                                                  MediaPixelFormat pixelFormat,
2506                                                  int srcWidth, int srcHeight,
2507                                                  ImageRotationType rotate,
2508                                                  int &dstWidth, int &dstHeight)
2509 {
2510         int bufSize = 0;
2511         std::unique_ptr <byte[]> pOutBuf;
2512         result r = E_SUCCESS;
2513
2514         bufSize = GetBufferSize(pixelFormat, srcWidth, srcHeight);
2515         SysTryReturn(NID_MEDIA, bufSize > 0, null, GetLastResult(),
2516                 "[%s] Check dimensions (%d x %d) and pixel format (%d)",
2517                 GetErrorMessage(GetLastResult()), dstWidth, dstHeight, pixelFormat);
2518
2519         pOutBuf.reset(new (std::nothrow) byte[bufSize]);
2520         SysTryReturn(NID_MEDIA, pOutBuf.get() != null, null, E_OUT_OF_MEMORY,
2521                 "[E_OUT_OF_MEMORY] Could not create new ByteBuffer.");
2522
2523         r = RotateBuffer(srcBuf, pixelFormat, srcWidth, srcHeight, pOutBuf.get(), dstWidth, dstHeight, rotate);
2524         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
2525                 "[%s] ImageUtil.RotateN failed.", GetErrorMessage(r));
2526
2527         SetLastResult(E_SUCCESS);
2528         return pOutBuf.release();
2529 }
2530
2531 byte*
2532 _ImageUtil::FlipN(const byte* srcBuf,
2533                                            MediaPixelFormat pixelFormat, int width, int height,
2534                                            ImageFlipType flip)
2535 {
2536         int bufSize = 0;
2537         std::unique_ptr <byte[]> pOutBuf;
2538         result r = E_SUCCESS;
2539
2540         bufSize = GetBufferSize(pixelFormat, width, height);
2541         SysTryReturn(NID_MEDIA, bufSize > 0, null, GetLastResult(),
2542                 "[%s] Check dimensions (%d x %d) and pixel format (%d)",
2543                 GetErrorMessage(GetLastResult()), width, height, pixelFormat);
2544
2545         pOutBuf.reset(new (std::nothrow) byte[bufSize]);
2546         SysTryReturn(NID_MEDIA, pOutBuf.get() != null, null, E_OUT_OF_MEMORY,
2547                 "[E_OUT_OF_MEMORY] Could not create new ByteBuffer.");
2548
2549         r = FlipBuffer(srcBuf, pixelFormat, width, height, pOutBuf.get(), flip);
2550         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
2551                 "[%s] ImageUtil.FlipN failed.", GetErrorMessage(r));
2552
2553         SetLastResult(E_SUCCESS);
2554         return pOutBuf.release();
2555 }
2556
2557 int
2558 _ImageUtil::GetBufferSize(MediaPixelFormat pixelFormat, int width, int height)
2559 {
2560         typedef struct _Rational
2561         {
2562                 int num;
2563                 int den;
2564         } rational;
2565
2566         static struct
2567         {
2568                 MediaPixelFormat key;
2569                 rational value;
2570         } map[] = {
2571                 { MEDIA_PIXEL_FORMAT_RGB565LE, {2, 1}},
2572                 { MEDIA_PIXEL_FORMAT_RGBA8888, {4, 1}},
2573                 { MEDIA_PIXEL_FORMAT_BGRA8888, {4, 1}},
2574                 { MEDIA_PIXEL_FORMAT_YUV420P, {3, 2}},
2575                 { MEDIA_PIXEL_FORMAT_NV12, {3, 2}},
2576                 { MEDIA_PIXEL_FORMAT_YUYV422, {2, 1}},
2577                 { MEDIA_PIXEL_FORMAT_BGR888, {3,1}},
2578                 { MEDIA_PIXEL_FORMAT_RGB888, {3,1}},
2579         };
2580         rational ret = {0, 0};
2581
2582         SysTryCatch(NID_MEDIA, width > 0 && height > 0, , E_INVALID_ARG,
2583                 "[E_INVALID_ARG] Dimensions should be greater than zero (%d x %d)", width, height);
2584
2585         for (unsigned int i = 0; i < sizeof(map)/sizeof(map[0]); i++)
2586         {
2587                 if (map[i].key == pixelFormat)
2588                 {
2589                         ret = map[i].value;
2590                         break;
2591                 }
2592         }
2593
2594         SysTryCatch(NID_MEDIA, ret.den != 0, , E_UNSUPPORTED_FORMAT,
2595                 "Could not find details for pixelformat %d.", pixelFormat);
2596
2597         SetLastResult(E_SUCCESS);
2598         return width * height * ret.num / ret.den;
2599
2600 CATCH:
2601         return 0;
2602 }
2603
2604 bool
2605 _ImageUtil::IsValidDimension(MediaPixelFormat pixelFormat, int width, int height)
2606 {
2607         MediaPixelFormat fmt[] = {
2608                 MEDIA_PIXEL_FORMAT_YUV420P,
2609                 MEDIA_PIXEL_FORMAT_NV12,
2610                 MEDIA_PIXEL_FORMAT_YUYV422,
2611         };
2612
2613         for (unsigned int i = 0; i < sizeof(fmt)/sizeof(fmt[0]); i++)
2614         {
2615                 if (fmt[i] == pixelFormat)
2616                 {
2617                         if ((width & 0x01) || (height & 0x01))
2618                         {
2619                                 return false;
2620                         }
2621                         return true;
2622                 }
2623         }
2624         // return true for other pixel formats
2625         return true;
2626 }
2627
2628 int
2629 _ImageUtil::ToFfmpegPixelFormat(MediaPixelFormat pixelFmt)
2630 {
2631         for (unsigned int i = 0; i < sizeof(_PIXEL_FORMAT_MAP)/sizeof(_PIXEL_FORMAT_MAP[0]); i++)
2632         {
2633                 if (pixelFmt == _PIXEL_FORMAT_MAP[i].mediaPixelFmt)
2634                 {
2635                 return _PIXEL_FORMAT_MAP[i].pixelFmt;
2636                 }
2637         }
2638         return PIX_FMT_NONE;
2639 }
2640
2641 MediaPixelFormat
2642 _ImageUtil::ToMediaPixelFormatFromFfmpeg(int pixelFormat)
2643 {
2644         for (unsigned int i = 0; i < sizeof(_PIXEL_FORMAT_MAP)/sizeof(_PIXEL_FORMAT_MAP[0]); i++)
2645         {
2646                 if (pixelFormat == _PIXEL_FORMAT_MAP[i].pixelFmt)
2647                 {
2648                 return _PIXEL_FORMAT_MAP[i].mediaPixelFmt;
2649                 }
2650         }
2651         return MEDIA_PIXEL_FORMAT_NONE;
2652 }
2653
2654 result
2655 _ImageUtil::GetResizedDimension(int srcWidth, int srcHeight, float dstWidth, float dstHeight,
2656                                                                 float &outWidth, float &outHeight)
2657 {
2658
2659         SysTryReturn(NID_MEDIA, (srcWidth > 0 && srcHeight > 0 && dstWidth > 0 && dstHeight > 0),
2660                                 E_INVALID_ARG, E_INVALID_ARG,
2661                                 "[E_INVALID_ARG] Dimensions should be greater than zero Source size(%d x %d), \
2662                                 Destination size(%f x %f)", srcWidth, srcHeight, dstWidth, dstHeight);
2663
2664         double xRatio = Float(dstWidth).ToDouble() / Integer(srcWidth).ToDouble();
2665         double yRatio = Float(dstHeight).ToDouble() / Integer(srcHeight).ToDouble();
2666
2667         if (xRatio >= 1.0 || yRatio >= 1.0)
2668         {
2669                 outWidth = Integer(srcWidth).ToFloat();
2670                 outHeight = Integer(srcHeight).ToFloat();
2671         }
2672         else if (xRatio < yRatio)
2673         {
2674                 outWidth = Double(srcWidth * yRatio).ToFloat();
2675                 outHeight = dstHeight;
2676         }
2677         else
2678         {
2679                 outWidth = dstWidth;
2680                 outHeight = Double(srcHeight * xRatio).ToFloat();
2681         }
2682         return E_SUCCESS;
2683 }
2684
2685 }} // Tizen::Media