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