Adding gray8, nv12 and nv21 support in ImageBuffer.
[platform/framework/native/image.git] / src / FMedia_ImageBufferImpl.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_ImageBufferImpl.cpp
20  * @brief  This file contains the implementation of ImageBuffer's impl layer.
21  */
22
23 #include <unique_ptr.h>
24 #include <FBaseColArrayListT.h>
25 #include <FMediaImageBuffer.h>
26 #include <FBaseInternalTypes.h>
27 #include <FBaseSysLog.h>
28 #include <FApp_AppInfo.h>
29 #include <FMedia_MediaUtil.h>
30 #include <FMediaImageTypes.h>
31 #include "FMedia_ImageBufferImpl.h"
32 #include "FMedia_ImageUtil.h"
33 #include "FMedia_ImageUtilImpl.h"
34 #include "FMedia_ImageDecoder.h"
35 #include "FMedia_ImageEncoder.h"
36 #include "FMedia_ColorConverter.h"
37 #include "FMedia_ExifUtil.h"
38 #include "FUi_CoordinateSystemUtils.h"
39 #include "FGrp_BitmapImpl.h"
40
41 using namespace Tizen::Graphics;
42 using namespace Tizen::Base;
43 using namespace Tizen::Base::Collection;
44 using namespace Tizen::Io;
45 using namespace Tizen::App;
46 using namespace Tizen::Ui;
47
48 namespace Tizen { namespace Media
49 {
50
51 typedef struct {
52         ImageRotationType rotateType;
53         ImageFlipType flipType;
54         bool dimensionSwitch;
55 } _ImageExifInfo;
56
57 static const _ImageExifInfo _IMAGE_ROTATE_FLIP_MAP[] = {
58         { IMAGE_ROTATION_0,   IMAGE_FLIP_NONE,       false }, /* NONE         */
59         { IMAGE_ROTATION_0,   IMAGE_FLIP_NONE,       false }, /* TOP_LEFT     */
60         { IMAGE_ROTATION_0,   IMAGE_FLIP_VERTICAL,   false }, /* TOP_RIGHT    */
61         { IMAGE_ROTATION_180, IMAGE_FLIP_NONE,       false }, /* BOTTOM_RIGHT */
62         { IMAGE_ROTATION_0,   IMAGE_FLIP_HORIZONTAL, false }, /* BOTTOM_LEFT  */
63         { IMAGE_ROTATION_90,  IMAGE_FLIP_VERTICAL,   true  }, /* LEFT_TOP     */
64         { IMAGE_ROTATION_90,  IMAGE_FLIP_NONE,       true  }, /* RIGHT_TOP    */
65         { IMAGE_ROTATION_90,  IMAGE_FLIP_HORIZONTAL, true  }, /* RIGHT_BOTTOM */
66         { IMAGE_ROTATION_270, IMAGE_FLIP_NONE,       true  }  /* LEFT_BOTTOM  */
67 };
68
69 static const ExifOrientation _ORIENTATION_MAP[] ={
70         EXIF_ORIENTATION_TOP_LEFT,
71         EXIF_ORIENTATION_TOP_LEFT,
72         EXIF_ORIENTATION_TOP_RIGHT,
73         EXIF_ORIENTATION_BOTTOM_RIGHT,
74         EXIF_ORIENTATION_BOTTOM_LEFT,
75         EXIF_ORIENTATION_LEFT_TOP,
76         EXIF_ORIENTATION_RIGHT_TOP,
77         EXIF_ORIENTATION_RIGHT_BOTTOM,
78         EXIF_ORIENTATION_LEFT_BOTTOM
79 };
80
81 static const MediaPixelFormat _IMAGE_BUFFER_PIXEL_FORMATS[] =
82 {
83         MEDIA_PIXEL_FORMAT_RGB565LE,
84         MEDIA_PIXEL_FORMAT_BGRA8888,
85         MEDIA_PIXEL_FORMAT_YUV420P,
86         MEDIA_PIXEL_FORMAT_NV12,
87         MEDIA_PIXEL_FORMAT_NV21,
88         MEDIA_PIXEL_FORMAT_GRAY
89 };
90
91 _ImageBufferImpl::_ImageBufferImpl(void)
92         : __pBuffer(null)
93         , __width(0)
94         , __height(0)
95         , __orientation(EXIF_ORIENTATION_TOP_LEFT)
96         , __pixelFormat(MEDIA_PIXEL_FORMAT_NONE)
97         , __isLocked(false)
98         , __transparent(false)
99         , __maskColor(0xf81f) // MAGENTA
100 {
101 }
102
103 _ImageBufferImpl::~_ImageBufferImpl(void)
104 {
105 }
106
107 result
108 _ImageBufferImpl::Construct(int width, int height, MediaPixelFormat pixelFormat)
109 {
110         result r = E_SUCCESS;
111         int length = 0;
112
113         __width = width;
114         __height = height;
115         __pixelFormat = pixelFormat;
116
117         SysTryReturn(NID_MEDIA, IsSupportedPixelFormat(pixelFormat) == true , null, E_UNSUPPORTED_FORMAT,
118                 "[E_UNSUPPORTED_FORMAT] The specified pixelFormat is not supported.")
119
120         length = _ImageUtil::GetBufferSize(__pixelFormat, __width, __height);
121         SysTryReturn(NID_MEDIA, length > 0, E_INVALID_ARG, E_INVALID_ARG,
122                 "[E_INVALID_ARG] Check inputs: (%d x %d), pixel format (%d).",
123                 __width, __height, __pixelFormat);
124
125         __pBuffer.reset(new (std::nothrow) byte[length]);
126         SysTryReturn(NID_MEDIA, __pBuffer.get() != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
127                 "[E_OUT_OF_MEMORY] Construct instance failed.");
128         memset(__pBuffer.get(), 0, length);
129         __bufSize = length;
130
131         return r;
132 }
133
134 result
135 _ImageBufferImpl::Construct(int width, int height, MediaPixelFormat pixelFormat,
136         const byte* pData, int length)
137 {
138         result r = E_SUCCESS;
139         int reqBufferSize = 0;
140
141         SysTryReturn(NID_MEDIA, IsSupportedPixelFormat(pixelFormat) == true , E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT,
142                 "[E_UNSUPPORTED_FORMAT] The specified pixelFormat is not supported.")
143
144         SysTryReturn(NID_MEDIA, (width > 0) && (height > 0), E_INVALID_ARG, E_INVALID_ARG,
145                 "[E_INVALID_ARG] Dimensions should be greater than zero : (%d x %d).", width, height);
146
147         reqBufferSize = _ImageUtil::GetBufferSize(pixelFormat, width, height);
148         SysTryReturn(NID_MEDIA, reqBufferSize > 0, GetLastResult(), GetLastResult(),
149                         "[%s] Could not get output buffer size.", GetErrorMessage(GetLastResult()));
150
151         if (pData != null)
152         {
153                 SysTryReturn(NID_MEDIA, reqBufferSize <= length, E_INVALID_ARG, E_INVALID_ARG,
154                         "[E_INVALID_ARG] Check length. Required for (%d x %d) in %d format is %d : arg = %d.",
155                         width, height, pixelFormat, length);
156         }
157
158         __width = width;
159         __height = height;
160         __pixelFormat = pixelFormat;
161
162         __pBuffer.reset(new (std::nothrow) byte[reqBufferSize]);
163         SysTryReturn(NID_MEDIA, __pBuffer.get() != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
164                 "[E_OUT_OF_MEMORY] Construct instance failed.");
165         memset(__pBuffer.get(), 0, reqBufferSize);
166         __bufSize = reqBufferSize;
167
168         if (pData != null)
169         {
170                 memcpy(__pBuffer.get(), pData, reqBufferSize);
171         }
172         return r;
173 }
174
175 result
176 _ImageBufferImpl::Construct(const Tizen::Base::String &srcImagePath, const Rectangle *pDecodingRegion, bool autoRotate)
177 {
178         result r = E_SUCCESS;
179
180         std::unique_ptr<ByteBuffer> pBuf;
181         pBuf.reset(_MediaUtil::FileToBufferN(srcImagePath));
182         SysTryReturn(NID_MEDIA, pBuf.get() != null, GetLastResult(), GetLastResult(),
183                            "[%s] FileToBufferN %S", GetErrorMessage(GetLastResult()), srcImagePath.GetPointer());
184         r = Construct(*pBuf.get(), pDecodingRegion, autoRotate);
185         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] ImageBuffer construct failed.", GetErrorMessage(r));
186         return r;
187 }
188
189 result
190 _ImageBufferImpl::Construct(const Tizen::Base::ByteBuffer &srcImageBuf, const Tizen::Graphics::Rectangle *pDecodingRegion, bool autoRotate)
191 {
192         result r = E_SUCCESS;
193
194         _ImageDecoder dec;
195         std::unique_ptr<byte[]> pDstBuf;
196         Tizen::Graphics::Rectangle transformRegion;
197         int orientationInfo = 0;
198         Boolean transparency(false);
199         Integer chromaKey;
200
201         r = dec.Construct(srcImageBuf);
202         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Decoder construct failed.", GetErrorMessage(r));
203
204         __pixelFormat = dec.GetPixelFormat();
205         r = GetLastResult();
206         SysTryReturn(NID_MEDIA, __pixelFormat != MEDIA_PIXEL_FORMAT_NONE, r, r,
207                 "[%s] GetPixelFormat failed.", GetErrorMessage(r));
208
209         _ExifUtil imgExif;
210         imgExif.Construct(srcImageBuf.GetPointer(), srcImageBuf.GetCapacity());
211         imgExif.GetValue(EXIF_TAG_IMAGE_ORIENTATION, orientationInfo);
212         // imgExif.GetValue() will return "r = E_OBJ_NOT_FOUND" if it could not be found exif infomation.
213         // However, the result should be decided by result of construct in this function.
214         SetLastResult(E_SUCCESS);
215         __orientation = _ORIENTATION_MAP[orientationInfo];
216
217         if (pDecodingRegion != null)
218         {
219                 int imgWidth = 0;
220                 int imgHeight = 0;
221                 ImageRotationType rotateType = _IMAGE_ROTATE_FLIP_MAP[orientationInfo].rotateType;
222                 ImageFlipType flipType = _IMAGE_ROTATE_FLIP_MAP[orientationInfo].flipType;
223
224                 r = dec.GetDimension(imgWidth, imgHeight);
225                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] dec.GetDimension", GetErrorMessage(r));
226
227                 if (rotateType == IMAGE_ROTATION_90 || rotateType == IMAGE_ROTATION_270)
228                 {
229                         SysTryReturn(NID_MEDIA, imgHeight >= (pDecodingRegion->x + pDecodingRegion->width)
230                                 && imgWidth >= (pDecodingRegion->y + pDecodingRegion->height),
231                                 E_INVALID_ARG, E_INVALID_ARG,
232                                 "[E_INVALID_ARG] imageWidth = %d, imageHeight = %d, x = %d, y = %d, width = %d, height = %d",
233                                 imgHeight, imgWidth, pDecodingRegion->x, pDecodingRegion->y,
234                                 pDecodingRegion->width, pDecodingRegion->height);
235                 }
236                 else
237                 {
238                         SysTryReturn(NID_MEDIA, imgWidth >= (pDecodingRegion->x + pDecodingRegion->width)
239                                 && imgHeight >= (pDecodingRegion->y + pDecodingRegion->height),
240                                 E_INVALID_ARG, E_INVALID_ARG,
241                                 "[E_INVALID_ARG] imageWidth = %d, imageHeight = %d, x = %d, y = %d, width = %d, height = %d",
242                                 imgWidth, imgHeight, pDecodingRegion->x, pDecodingRegion->y,
243                                 pDecodingRegion->width, pDecodingRegion->height);
244                 }
245
246                 if(autoRotate == true)
247                 {
248                         if (rotateType == IMAGE_ROTATION_90)
249                         {
250                                 transformRegion.x =  pDecodingRegion->y;
251                                 transformRegion.y =  imgHeight-(pDecodingRegion->width+pDecodingRegion->x);
252                                 transformRegion.width  = pDecodingRegion->height;
253                                 transformRegion.height = pDecodingRegion->width;
254                         }
255                         else if (rotateType == IMAGE_ROTATION_180)
256                         {
257                                 transformRegion.x =  imgWidth-(pDecodingRegion->width+pDecodingRegion->x);
258                                 transformRegion.y =  imgHeight-(pDecodingRegion->height+pDecodingRegion->y);
259                                 transformRegion.width  = pDecodingRegion->width;
260                                 transformRegion.height = pDecodingRegion->height;
261                         }
262                         else if (rotateType == IMAGE_ROTATION_270)
263                         {
264                                 transformRegion.x =  imgWidth-(pDecodingRegion->height+pDecodingRegion->y);
265                                 transformRegion.y =  pDecodingRegion->x;
266                                 transformRegion.width  = pDecodingRegion->height;
267                                 transformRegion.height = pDecodingRegion->width;
268                         }
269                         else
270                         {
271                                 transformRegion.x =  pDecodingRegion->x;
272                                 transformRegion.y =  pDecodingRegion->y;
273                                 transformRegion.width  = pDecodingRegion->width;
274                                 transformRegion.height = pDecodingRegion->height;
275                         }
276
277                         if (flipType == IMAGE_FLIP_VERTICAL)
278                         {
279                                 transformRegion.x = imgWidth-(transformRegion.width+transformRegion.x);
280                         }
281                         else if (flipType == IMAGE_FLIP_HORIZONTAL)
282                         {
283                                 transformRegion.y = imgHeight-(transformRegion.height+transformRegion.y);
284                         }
285                 }
286                 else
287                 {
288                         transformRegion.x =  pDecodingRegion->x;
289                         transformRegion.y =  pDecodingRegion->y;
290                         transformRegion.width  = pDecodingRegion->width;
291                         transformRegion.height = pDecodingRegion->height;
292                 }
293
294                 r = dec.SetDecodingRegion(transformRegion.x, transformRegion.y,
295                         transformRegion.width, transformRegion.height);
296
297                 SysTryReturn(NID_MEDIA, r == E_SUCCESS || r == E_UNSUPPORTED_OPERATION, r, r,
298                         "[%s] dec.SetDecodingRegion:%d %d %d %d", GetErrorMessage(r),
299                         pDecodingRegion->x, pDecodingRegion->y, pDecodingRegion->width, pDecodingRegion->height);
300
301                 __width = transformRegion.width;
302                 __height = transformRegion.height;
303
304                 if (r == E_SUCCESS)
305                 {
306                         __pBuffer.reset(dec.DecodeN(__bufSize));
307                         SysTryReturn(NID_MEDIA, __pBuffer.get() != null, r, r,
308                                 "[%s] DecodeN returned empty buffer.", GetErrorMessage(r));
309                         r = dec.GetValue("transparency", transparency);
310                         if (r != E_SUCCESS)
311                         {
312                                 __transparent = false;
313                                 r = E_SUCCESS;
314                         }
315                         else
316                         {
317                                 __transparent = transparency.ToBool();
318                                 if (__transparent == true)
319                                 {
320                                         r = dec.GetValue(L"chromaKey", chromaKey);
321                                         if (r != E_SUCCESS)
322                                         {
323                                                 __transparent = false;
324                                                 r = E_SUCCESS;
325                                         }
326                                         else
327                                         {
328                                                 __maskColor = chromaKey.ToInt();
329                                         }
330                                 }
331                         }
332                 }
333                 else if (r == E_UNSUPPORTED_OPERATION)
334                 {
335                         // crop image
336                         std::unique_ptr<byte[]> pTmpbyte;
337
338                         pTmpbyte.reset(dec.DecodeN(__bufSize));
339                         r = GetLastResult();
340                         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] DecodeN failed.", GetErrorMessage(r));
341                         SysTryReturn(NID_MEDIA, pTmpbyte.get() != null, r, r,
342                                 "[%s] DecodeN returned empty buffer.", GetErrorMessage(r));
343
344                         __pBuffer.reset(_ImageUtil::CropN(pTmpbyte.get(), __pixelFormat, imgWidth, imgHeight,
345                                 transformRegion.x, transformRegion.y, transformRegion.width, transformRegion.height));
346
347                         SysTryReturn(NID_MEDIA, __pBuffer.get() != null, GetLastResult(), GetLastResult(),
348                                 "[%s] Crop:%x %d %d %d %d %d %d %d", GetErrorMessage(GetLastResult()), pTmpbyte.get(),
349                                 __pixelFormat, imgWidth, imgHeight, pDecodingRegion->x, pDecodingRegion->y,
350                                 pDecodingRegion->width, pDecodingRegion->height);
351
352                         __bufSize = _ImageUtil::GetBufferSize(__pixelFormat, pDecodingRegion->width, pDecodingRegion->height);
353                         SysTryReturn(NID_MEDIA, __bufSize > 0, GetLastResult(), GetLastResult(),
354                         "[%s] Could not get output buffer size.", GetErrorMessage(GetLastResult()));
355
356                         r = dec.GetValue("transparency", transparency);
357                         if (r != E_SUCCESS)
358                         {
359                                 __transparent = false;
360                                 r = E_SUCCESS;
361                         }
362                         else
363                         {
364                                 __transparent = transparency.ToBool();
365                                 if (__transparent == true)
366                                 {
367                                         r = dec.GetValue(L"chromaKey", chromaKey);
368                                         if (r != E_SUCCESS)
369                                         {
370                                                 __transparent = false;
371                                                 r = E_SUCCESS;
372                                         }
373                                         else
374                                         {
375                                                 __maskColor = chromaKey.ToInt();
376                                         }
377                                 }
378                         }
379                 }
380         }
381         else
382         {
383                 r = dec.GetDimension(__width, __height);
384                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] GetDimension failed.",
385                         GetErrorMessage(r));
386
387                 __pBuffer.reset(dec.DecodeN(__bufSize));
388                 r = GetLastResult();
389                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] DecodeN failed.", GetErrorMessage(r));
390                 SysTryReturn(NID_MEDIA, __pBuffer.get() != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
391                         "[E_OUT_OF_MEMORY] Propagated.");
392
393                 r = dec.GetValue("transparency", transparency);
394                 if (r != E_SUCCESS)
395                 {
396                         __transparent = false;
397                         r = E_SUCCESS;
398                 }
399                 else
400                 {
401                         __transparent = transparency.ToBool();
402                         if (__transparent == true)
403                         {
404                                 r = dec.GetValue(L"chromaKey", chromaKey);
405                                 if (r != E_SUCCESS)
406                                 {
407                                         __transparent = false;
408                                         r = E_SUCCESS;
409                                 }
410                                 else
411                                 {
412                                         __maskColor = chromaKey.ToInt();
413                                 }
414                         }
415                 }
416         }
417
418         if (autoRotate == true)
419         {
420                 int dstWidth = 0;
421                 int dstHeight = 0;
422
423                 __orientation = EXIF_ORIENTATION_TOP_LEFT;
424
425                 if (orientationInfo == EXIF_ORIENTATION_TOP_LEFT || orientationInfo == 0)
426                 {
427                         return E_SUCCESS;
428                 }
429
430                 if (orientationInfo > EXIF_ORIENTATION_LEFT_BOTTOM || orientationInfo  < EXIF_ORIENTATION_TOP_LEFT)
431                 {
432                         return E_SUCCESS;
433                 }
434
435                 pDstBuf.reset(new (std::nothrow) byte[__bufSize]);
436                 SysTryReturn(NID_MEDIA, pDstBuf.get() != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY]");
437
438                 ImageRotationType rotateType = _IMAGE_ROTATE_FLIP_MAP[orientationInfo].rotateType;
439                 ImageFlipType flipType = _IMAGE_ROTATE_FLIP_MAP[orientationInfo].flipType;
440
441                 pDstBuf.reset(_ImageUtil::RotateN(__pBuffer.get(), __pixelFormat, __width, __height, rotateType, dstWidth, dstHeight));
442                 r = GetLastResult();
443                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] _ImageUtil:Resize", GetErrorMessage(r));
444
445                 __width = dstWidth;
446                 __height = dstHeight;
447
448                 __pBuffer.swap(pDstBuf);
449                 if (flipType != IMAGE_FLIP_NONE)
450                 {
451                         pDstBuf.reset(_ImageUtil::FlipN(__pBuffer.get(), __pixelFormat, __width, __height, flipType));
452                         r = GetLastResult();
453                         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] _ImageUtil:Flip", GetErrorMessage(r));
454
455                         __pBuffer.swap(pDstBuf);
456                 }
457         }
458         return r;
459 }
460
461 result
462 _ImageBufferImpl::Construct(const Bitmap &srcBitmap)
463 {
464         BufferInfo info;
465         Bitmap *pTmpBmp = null;
466         int bpp = 0;
467         int length = 0;
468         result r = E_SUCCESS;
469
470         pTmpBmp = (const_cast<Bitmap*>(&srcBitmap));
471         SysTryReturn(NID_MEDIA, pTmpBmp != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
472                 "[E_OUT_OF_MEMORY] Construct instance failed.");
473
474         r = pTmpBmp->Lock(info);
475         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Bitmap.Lock failed.",
476                 GetErrorMessage(r));
477
478         __width = info.width;
479         __height = info.height;
480         bpp = info.bitsPerPixel / 8;
481         length = __width * __height * bpp;
482
483         __pixelFormat = _ImageUtilImpl::ToMediaPixelFormat(srcBitmap.GetPixelColorFormat());
484
485         __pBuffer.reset(new (std::nothrow) byte[length]);
486         SysTryCatch(NID_MEDIA, __pBuffer.get() != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
487                 "[E_OUT_OF_MEMORY] Construct instance failed.");
488         __bufSize = length;
489         memcpy(__pBuffer.get(), (byte*)info.pPixels, length);
490
491         r = pTmpBmp->Unlock();
492         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Bitmap.Unlock failed.", GetErrorMessage(r));
493
494         return r;
495 CATCH:
496         pTmpBmp->Unlock();
497
498         return r;
499 }
500
501
502
503
504 result
505 _ImageBufferImpl::Construct(const Tizen::Base::String &srcImagePath, int destWidth, int destHeight, ImageScalingMethod scalingMethod)
506 {
507         result r = E_SUCCESS;
508
509         std::unique_ptr<ByteBuffer> pBuf;
510         pBuf.reset(_MediaUtil::FileToBufferN(srcImagePath));
511         SysTryReturn(NID_MEDIA, pBuf.get() != null, GetLastResult(), GetLastResult(),
512                            "[%s] FileToBufferN %S", GetErrorMessage(GetLastResult()), srcImagePath.GetPointer());
513         r = Construct(*pBuf.get(), destWidth, destHeight, scalingMethod);
514         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] ImageBuffer construct failed.", GetErrorMessage(r));
515         return r;
516 }
517
518 result
519 _ImageBufferImpl::Construct(const Tizen::Base::ByteBuffer &srcImageBuf, int destWidth, int destHeight, ImageScalingMethod scalingMethod)
520 {
521         result r = E_SUCCESS;
522         int orientationInfo = 0;
523         _ImageDecoder dec;
524         std::unique_ptr<byte[]> pDstBuf;
525         Tizen::Graphics::Rectangle transformRegion;
526         Boolean transparency(false);
527         Integer chromaKey;
528
529         r = dec.Construct(srcImageBuf);
530         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Decoder construct failed.", GetErrorMessage(r));
531
532         __pixelFormat = dec.GetPixelFormat();
533         r = GetLastResult();
534         SysTryReturn(NID_MEDIA, __pixelFormat != MEDIA_PIXEL_FORMAT_NONE, r, r,
535                 "[%s] GetPixelFormat failed.", GetErrorMessage(r));
536
537         _ExifUtil imgExif;
538         imgExif.Construct(srcImageBuf.GetPointer(), srcImageBuf.GetCapacity());
539         imgExif.GetValue(EXIF_TAG_IMAGE_ORIENTATION, orientationInfo);
540         // imgExif.GetValue() will return "r = E_OBJ_NOT_FOUND" if it could not be found exif infomation.
541         // However, the result should be decided by result of construct in this function.
542         SetLastResult(E_SUCCESS);
543
544         __orientation = _ORIENTATION_MAP[orientationInfo];
545
546         dec.SetOutputDimension(destWidth, destHeight, false);
547
548         __pBuffer.reset(dec.DecodeN(__bufSize, scalingMethod));
549         r = GetLastResult();
550         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] DecodeN failed.", GetErrorMessage(r));
551         SysTryReturn(NID_MEDIA, __pBuffer.get() != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
552                 "[E_OUT_OF_MEMORY] Propagated.");
553
554         r = dec.GetValue("transparency", transparency);
555         if (r != E_SUCCESS)
556         {
557                 __transparent = false;
558                 r = E_SUCCESS;
559         }
560         else
561         {
562                 __transparent = transparency.ToBool();
563                 if (__transparent == true)
564                 {
565                         r = dec.GetValue(L"chromaKey", chromaKey);
566                         if (r != E_SUCCESS)
567                         {
568                                 __transparent = false;
569                                 r = E_SUCCESS;
570                         }
571                         else
572                         {
573                                 __maskColor = chromaKey.ToInt();
574                         }
575                 }
576         }
577
578         r = dec.GetDimension(__width, __height);
579         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] GetDimension failed.",
580                 GetErrorMessage(r));
581
582         __bufSize = _ImageUtil::GetBufferSize(__pixelFormat, __width, __height);
583         SysTryReturn(NID_MEDIA, __bufSize > 0, GetLastResult(), GetLastResult(),
584                         "[%s] Could not get output buffer size.", GetErrorMessage(GetLastResult()));
585         return r;
586 }
587
588
589 bool
590 _ImageBufferImpl::Equals(ImageBuffer* pRhs) const
591 {
592         _ImageBufferImpl* pRhsImpl = null;
593         byte* pRawOther = null;
594         int lengthOther = 0;
595         MediaPixelFormat pixFmtOther = MEDIA_PIXEL_FORMAT_NONE;
596
597         byte* pRawThis = null;
598         int lengthThis = 0;
599         MediaPixelFormat pixFmtThis = MEDIA_PIXEL_FORMAT_NONE;
600
601         bool out = false;
602         result r = E_SUCCESS;
603
604         if (pRhs == null)
605         {
606                 out = false;
607         }
608         else
609         {
610                 pRhsImpl = GetInstance(*pRhs);
611                 if (pRhsImpl == null)
612                 {
613                         out = false;
614                 }
615                 else if (pRhsImpl == this)
616                 {
617                         out = true;
618                 }
619                 else
620                 {
621                         // Compare dimensions.
622                         if ((__height != pRhsImpl->GetHeight()) || (__width != pRhsImpl->GetWidth()))
623                         {
624                                 out = false;
625                         }
626                         else
627                         {
628                                 r = const_cast<_ImageBufferImpl*>(pRhsImpl)->Lock(pRawOther, lengthOther, pixFmtOther);
629                                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, false, r,
630                                         "[%s] Could not lock RHS ImageBuffer contents.", GetErrorMessage(r));
631
632                                 r = const_cast<_ImageBufferImpl *>(this)->Lock(pRawThis, lengthThis, pixFmtThis);
633                                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, false, r,
634                                         "[%s] Could not lock this ImageBuffer contents.", GetErrorMessage(r));
635
636                                 // Check if contents are equal.
637                                 if ((__pixelFormat != pixFmtOther) || (__bufSize != lengthOther))
638                                 {
639                                         out = false;
640                                 }
641                                 else
642                                 {
643                                         if (memcmp(pRawOther, pRawThis, lengthOther) == 0)
644                                         {
645                                                 out = true;
646                                         }
647                                         else
648                                         {
649                                                 out = false;
650                                         }
651                                 }
652                         }
653                 }
654         }
655
656         return out;
657 }
658
659 int
660 _ImageBufferImpl::GetHashCode() const
661 {
662         int hashCode = 0;
663         int len = __bufSize / sizeof(len);
664
665         for (int i = 0; i < len; ++i)
666         {
667                 hashCode = (hashCode << 5) - hashCode + static_cast <int>(__pBuffer[(i * sizeof(hashCode))]);
668         }
669
670         hashCode = (hashCode ^ (__width * __height)) | (hashCode & __pixelFormat);
671
672         return hashCode;
673 }
674
675 int
676 _ImageBufferImpl::GetHeight() const
677 {
678         return __height;
679 }
680
681 int
682 _ImageBufferImpl::GetWidth() const
683 {
684         return __width;
685 }
686
687 MediaPixelFormat
688 _ImageBufferImpl::GetPixelFormat() const
689 {
690         return __pixelFormat;
691 }
692
693 ExifOrientation
694 _ImageBufferImpl::GetExifOrientation(void) const
695 {
696         return __orientation;
697 }
698
699 result
700 _ImageBufferImpl::Lock(byte* &data, int &length, MediaPixelFormat &pixelFormat)
701 {
702         result r = E_SUCCESS;
703
704         SysTryReturn(NID_MEDIA, __isLocked != true, E_INVALID_STATE, E_INVALID_STATE,
705                 "[E_INVALID_STATE] Instance is locked. Unlock to use.");
706
707         data = const_cast<byte *>(__pBuffer.get());
708         length = _ImageUtil::GetBufferSize(__pixelFormat, __width, __height);
709         pixelFormat = __pixelFormat;
710
711         __isLocked = true;
712
713         return r;
714 }
715
716 result
717 _ImageBufferImpl::Unlock()
718 {
719         result r = E_SUCCESS;
720
721         SysTryReturn(NID_MEDIA, __isLocked, E_INVALID_STATE, E_INVALID_STATE,
722                 "[E_INVALID_STATE] Instance is not locked.");
723
724         __isLocked = false;
725
726         return r;
727 }
728
729 ByteBuffer*
730 _ImageBufferImpl::EncodeToBufferN(ImageFormat destImageFormat, int quality) const
731 {
732         result r = E_SUCCESS;
733         int inLength = 0;
734         ByteBuffer* pBuf = null;
735
736         SysTryReturn(NID_MEDIA, !__isLocked, null, E_INVALID_STATE,
737                 "[E_INVALID_STATE] Instance is locked. Unlock to use.");
738
739         inLength = _ImageUtil::GetBufferSize(__pixelFormat, __width, __height);
740         pBuf = _ImageEncoder::EncodeN(destImageFormat, (const byte*)__pBuffer.get(), inLength, __width, __height,
741                 __pixelFormat, quality);
742         SysTryReturn(NID_MEDIA, pBuf != null, null, GetLastResult(), "[%s] Propagated. ", GetErrorMessage(GetLastResult()));
743
744         SetLastResult(r);
745         return pBuf;
746 }
747
748 result
749 _ImageBufferImpl::EncodeToFile(const String &destImagePath, ImageFormat destImageFormat,
750         bool overwrite, int quality) const
751 {
752         result r = E_SUCCESS;
753         std::unique_ptr<ByteBuffer> pBuf;
754
755         SysTryReturn(NID_MEDIA, !__isLocked, E_INVALID_STATE, E_INVALID_STATE,
756                 "[E_INVALID_STATE] Instance is locked. Unlock to use.");
757
758         pBuf.reset(this->EncodeToBufferN(destImageFormat, quality));
759         SysTryReturn(NID_MEDIA, pBuf.get() != null, GetLastResult(), GetLastResult(),
760                 "[%s] Propagated. ", GetErrorMessage(GetLastResult()));
761
762         r = _MediaUtil::BufferToFile(*pBuf.get(), destImagePath, overwrite);
763         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagated. ", GetErrorMessage(r));
764
765         return r;
766 }
767
768 Bitmap*
769 _ImageBufferImpl::GetBitmapN(BitmapPixelFormat pixelFormat, BufferScaling bufferScaling) const
770 {
771         result r = E_SUCCESS;
772         std::unique_ptr<Bitmap> pOutBitmap;
773         std::unique_ptr<ByteBuffer> pConverted;
774         MediaPixelFormat inPixelFormat = MEDIA_PIXEL_FORMAT_NONE;
775
776         SysTryReturn(NID_MEDIA, !__isLocked, null, E_INVALID_STATE,
777                 "[E_INVALID_STATE] Instance is locked. Unlock to use.");
778
779         inPixelFormat = _ImageUtilImpl::ToMediaPixelFormat(pixelFormat);
780         SysTryReturn(NID_MEDIA, inPixelFormat != MEDIA_PIXEL_FORMAT_NONE, null, E_INVALID_ARG,
781                 "[E_INVALID_ARG] Pixel format is %d, invalid or not supported.", pixelFormat);
782
783         if (inPixelFormat != __pixelFormat)
784         {
785                 // Convert raw data to the required pixel format.
786                 pConverted.reset(GetByteBufferN(inPixelFormat));
787                 r = GetLastResult();
788                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
789         }
790
791         pOutBitmap.reset(new (std::nothrow) Bitmap);
792         SysTryReturn(NID_MEDIA, pOutBitmap.get() != null, null, E_OUT_OF_MEMORY,
793                 "[E_OUT_OF_MEMORY] Propagated.");
794
795         if (inPixelFormat != __pixelFormat)
796         {
797                 r = pOutBitmap->Construct(*pConverted.get(), Dimension(__width, __height), pixelFormat, bufferScaling);
798         }
799         else
800         {
801                 std::unique_ptr<ByteBuffer> pTmpByteBuffer (new (std::nothrow) ByteBuffer());
802                 r = pTmpByteBuffer->Construct(__pBuffer.get(), 0, __bufSize, __bufSize);
803                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
804                         "[%s] Construct instance failed.", GetErrorMessage(r));
805
806                 r = pOutBitmap->Construct(*pTmpByteBuffer.get(), Dimension(__width, __height), pixelFormat, bufferScaling);
807         }
808
809         if ((__transparent == true) && (pixelFormat == BITMAP_PIXEL_FORMAT_RGB565))
810         {
811                 byte red = 0;
812                 byte green = 0;
813                 byte blue = 0;
814                 Color *pMaskingColor = null;
815
816                 if (__pixelFormat == MEDIA_PIXEL_FORMAT_BGRA8888)
817                 {
818                         blue = (__maskColor & 0x000000ff);
819                         green = (__maskColor & 0x0000ff00) >> 8;
820                         red = (__maskColor & 0x00ff0000) >> 16;
821                 }
822                 else
823                 {
824                         red = (__maskColor & 0xf800) >> 8;
825                         red = red | (red >> 5);
826                         green = (__maskColor & 0x07e0) >> 3;
827                         green = green | (green >> 6);
828                         blue = (__maskColor & 0x001f) << 3;
829                         blue = blue | (blue >> 5);
830                 }
831
832                 pMaskingColor = new Color(red, green, blue);
833                 SysTryReturn(NID_MEDIA, pMaskingColor != null, pOutBitmap.release(), E_SUCCESS,
834                         "[%s] Could not apply masking color.", GetErrorMessage(r));
835                 r = pOutBitmap->SetMaskingColor(pMaskingColor);
836                 delete pMaskingColor;
837                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, pOutBitmap.release(), E_SUCCESS,
838                         "[%s] Could not set masking color.", GetErrorMessage(r));
839         }
840
841         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.",
842                 GetErrorMessage(r));
843         return pOutBitmap.release();
844 }
845
846 Bitmap*
847 _ImageBufferImpl::GetBitmapN(BitmapPixelFormat pixelFormat, const FloatDimension &destDim) const
848 {
849         result r = E_SUCCESS;
850         std::unique_ptr<Bitmap> pOutBitmap;
851         std::unique_ptr<ByteBuffer> pConverted;
852         MediaPixelFormat inPixelFormat = MEDIA_PIXEL_FORMAT_NONE;
853         Dimension convertDim;
854
855         SysTryReturn(NID_MEDIA, !__isLocked, null, E_INVALID_STATE,
856                 "[E_INVALID_STATE] Instance is locked. Unlock to use.");
857
858         inPixelFormat = _ImageUtilImpl::ToMediaPixelFormat(pixelFormat);
859         SysTryReturn(NID_MEDIA, (inPixelFormat > MEDIA_PIXEL_FORMAT_NONE) && (inPixelFormat <= MEDIA_PIXEL_FORMAT_GRAY),
860                                  null, E_INVALID_ARG, "[E_INVALID_ARG] Pixel format is invalid.", inPixelFormat);
861
862         pOutBitmap.reset(new (std::nothrow) Bitmap);
863         SysTryReturn(NID_MEDIA, pOutBitmap.get() != null, null, E_OUT_OF_MEMORY,
864                 "[E_OUT_OF_MEMORY] Propagated.");
865
866         convertDim.width = _CoordinateSystemUtils::ConvertToInteger(destDim.width);
867         convertDim.height = _CoordinateSystemUtils::ConvertToInteger(destDim.height);
868
869         std::unique_ptr<ByteBuffer> pTmpByteBuffer (new (std::nothrow) ByteBuffer());
870         r = pTmpByteBuffer->Construct(__pBuffer.get(), 0, __bufSize, __bufSize);
871         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
872                                 "[%s] Construct instance failed.", GetErrorMessage(r));
873
874         if (inPixelFormat == __pixelFormat && convertDim.width == __width && convertDim.height == __height)
875         {
876                 pOutBitmap.reset(_BitmapImpl::GetNonScaledBitmapN(*pTmpByteBuffer.get(), convertDim, pixelFormat, destDim));
877         }
878         else
879         {
880                 std::unique_ptr<ByteBuffer> pOutBuf;
881                 _ColorConverter cvt;
882
883                 r = cvt.Construct(__pixelFormat, __width, __height, inPixelFormat, convertDim.width, convertDim.height);
884                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
885
886                 pOutBuf.reset(cvt.ConvertN(*pTmpByteBuffer));
887                 r = GetLastResult();
888                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
889
890                 pOutBitmap.reset(_BitmapImpl::GetNonScaledBitmapN(*pOutBuf.get(), convertDim, pixelFormat, destDim));
891         }
892
893         if ((__transparent == true) && (pixelFormat == BITMAP_PIXEL_FORMAT_RGB565))
894         {
895                 byte red = 0;
896                 byte green = 0;
897                 byte blue = 0;
898                 Color *pMaskingColor = null;
899
900                 if (__pixelFormat == MEDIA_PIXEL_FORMAT_BGRA8888)
901                 {
902                         blue = (__maskColor & 0x000000ff);
903                         green = (__maskColor & 0x0000ff00) >> 8;
904                         red = (__maskColor & 0x00ff0000) >> 16;
905                 }
906                 else
907                 {
908                         red = (__maskColor & 0xf800) >> 8;
909                         red = red | (red >> 5);
910                         green = (__maskColor & 0x07e0) >> 3;
911                         green = green | (green >> 6);
912                         blue = (__maskColor & 0x001f) << 3;
913                         blue = blue | (blue >> 5);
914                 }
915
916                 pMaskingColor = new Color(red, green, blue);
917                 SysTryReturn(NID_MEDIA, pMaskingColor != null, pOutBitmap.release(), E_SUCCESS,
918                         "[%s] Could not apply masking color.", GetErrorMessage(r));
919                 r = pOutBitmap->SetMaskingColor(pMaskingColor);
920                 delete pMaskingColor;
921                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, pOutBitmap.release(), E_SUCCESS,
922                         "[%s] Could not set masking color.", GetErrorMessage(r));
923         }
924
925         SysTryReturn(NID_MEDIA, pOutBitmap.get() != null, null, GetLastResult(), "[%s] Propagated.", GetErrorMessage(GetLastResult()));
926         return pOutBitmap.release();
927 }
928
929 ByteBuffer*
930 _ImageBufferImpl::GetByteBufferN(MediaPixelFormat inPixelFormat) const
931 {
932         result r = E_SUCCESS;
933         std::unique_ptr<ByteBuffer> pOutBuf;
934
935         SysTryReturn(NID_MEDIA, !__isLocked, null, E_INVALID_STATE,
936                 "[E_INVALID_STATE] Instance is locked. Unlock to use.");
937
938         SysTryReturn(NID_MEDIA, IsSupportedPixelFormat(inPixelFormat) == true , null, E_UNSUPPORTED_FORMAT,
939                 "[E_UNSUPPORTED_FORMAT] The specified pixelFormat is not supported.")
940
941         std::unique_ptr<ByteBuffer> pTmpByteBuffer (new (std::nothrow) ByteBuffer());
942         r = pTmpByteBuffer->Construct(__pBuffer.get(), 0, __bufSize, __bufSize);
943         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
944                         "[%s] Construct instance failed.", GetErrorMessage(r));
945
946         if (inPixelFormat != __pixelFormat)
947         {
948                 // Convert raw data to the required pixel format.
949                 _ColorConverter cvt;
950
951                 r = cvt.Construct(__pixelFormat, __width, __height,
952                         inPixelFormat, __width, __height);
953                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
954
955                 pOutBuf.reset(cvt.ConvertN(*pTmpByteBuffer));
956                 r = GetLastResult();
957                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
958         }
959         else
960         {
961                 pOutBuf.reset(new (std::nothrow) ByteBuffer);
962                 SysTryReturn(NID_MEDIA, pOutBuf.get() != null, null, E_OUT_OF_MEMORY,
963                         "[E_OUT_OF_MEMORY] Propagated.");
964
965                 r = pOutBuf->Construct(*pTmpByteBuffer);
966                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
967                         "[%s] Propagated.", GetErrorMessage(r));
968         }
969
970         SetLastResult(r);
971         return pOutBuf.release();
972 }
973
974 ImageBuffer*
975 _ImageBufferImpl::CloneN() const
976 {
977         std::unique_ptr<ImageBuffer> pImgBuffer;
978         result r = E_SUCCESS;
979         byte* pData = null;
980         int length = 0;
981         MediaPixelFormat pixFmt = MEDIA_PIXEL_FORMAT_NONE;
982         _ImageBufferImpl* pClonedImpl = null;
983
984         r = const_cast<_ImageBufferImpl *>(this)->Lock(pData, length, pixFmt);
985         SysTryReturn(NID_MEDIA, r == E_SUCCESS, pImgBuffer.get(), r, "[%s] Propagated.", GetErrorMessage(r));
986
987         pImgBuffer.reset(new (std::nothrow) ImageBuffer);
988         SysTryReturn(NID_MEDIA, pImgBuffer.get() != null, null, E_OUT_OF_MEMORY,
989                 "[E_OUT_OF_MEMORY] Could not create new instance.")
990
991         r = pImgBuffer->Construct(__width, __height, pixFmt, pData, length);
992         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
993                 "[%s] Failed to construct the cloned ImageBuffer.", GetErrorMessage(r));
994
995         pClonedImpl = GetInstance(*pImgBuffer);
996         SysTryReturn(NID_MEDIA, pClonedImpl != null, null, r,
997                 "[%s] Failed to GetInstance.", GetErrorMessage(r));
998         pClonedImpl->__maskColor = __maskColor;
999         pClonedImpl->__transparent = __transparent;
1000
1001         const_cast<_ImageBufferImpl *>(this)->Unlock();
1002
1003         SetLastResult(r);
1004         return pImgBuffer.release();
1005 }
1006
1007 ImageBuffer*
1008 _ImageBufferImpl::ConvertPixelFormatN(MediaPixelFormat pixelFormat) const
1009 {
1010         std::unique_ptr<ImageBuffer> pImgBuffer;
1011         result r = E_SUCCESS;
1012         byte* pData = null;
1013         std::unique_ptr<byte[]> pDataConvert;
1014         int length = 0;
1015         int dstLength = 0;
1016         MediaPixelFormat pixFmt = MEDIA_PIXEL_FORMAT_NONE;
1017         _ImageBufferImpl* pConvertedImpl = null;
1018
1019         SysTryReturn(NID_MEDIA, IsSupportedPixelFormat(pixelFormat) == true , null, E_UNSUPPORTED_FORMAT,
1020                 "[E_UNSUPPORTED_FORMAT] The specified pixelFormat is not supported.")
1021
1022         SysTryReturn(NID_MEDIA, _ImageUtil::IsValidDimension(pixelFormat, __width, __height) == true, null, E_INVALID_ARG,
1023                 "[E_INVALID_ARG] Dimensions should be even for this pixel format: (%d x %d)", __width, __height);
1024
1025         if (pixelFormat != __pixelFormat)
1026         {
1027                 _ColorConverter cvt;
1028
1029                 r = cvt.Construct(__pixelFormat, __width, __height,
1030                         pixelFormat, __width, __height);
1031                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagated.", GetErrorMessage(r));
1032
1033                 r = const_cast<_ImageBufferImpl *>(this)->Lock(pData, length, pixFmt);
1034                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r,
1035                         "[%s] Lock failed. Propagated.", GetErrorMessage(r));
1036
1037                 pDataConvert.reset(cvt.ConvertN(pData, length, dstLength));
1038                 r = GetLastResult();
1039                 SysTryCatch(NID_MEDIA, (r == E_SUCCESS) && (pDataConvert.get() != null), , r,
1040                         "[%s] Failed to convert data to required pixelformat.", GetErrorMessage(r));
1041
1042                 const_cast<_ImageBufferImpl *>(this)->Unlock();
1043
1044                 pImgBuffer.reset(new (std::nothrow) ImageBuffer);
1045                 SysTryCatch(NID_MEDIA, pImgBuffer.get() != null, , E_OUT_OF_MEMORY,
1046                         "[E_OUT_OF_MEMORY] Could not create new instance.")
1047
1048                 r = pImgBuffer->Construct(__width, __height, pixelFormat, pDataConvert.get(), dstLength);
1049                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
1050                         "[%s] Failed to construct the converted ImageBuffer.", GetErrorMessage(r));
1051
1052                 pConvertedImpl = GetInstance(*pImgBuffer);
1053                 SysTryReturn(NID_MEDIA, pConvertedImpl != null, null, r,
1054                         "[%s] Failed to GetInstance.", GetErrorMessage(r));
1055                 pConvertedImpl->__maskColor = __maskColor;
1056                 pConvertedImpl->__transparent = __transparent;
1057
1058         }
1059         else
1060         {
1061                 pImgBuffer.reset(CloneN());
1062         }
1063
1064         SetLastResult(r);
1065         return pImgBuffer.release();
1066
1067 CATCH:
1068         const_cast<_ImageBufferImpl *>(this)->Unlock();
1069         SetLastResult(r);
1070         return null;
1071 }
1072
1073 ImageBuffer*
1074 _ImageBufferImpl::ResizeN(int width, int height) const
1075 {
1076         std::unique_ptr<ImageBuffer> pImgBuffer;
1077         result r = E_SUCCESS;
1078         byte* pData = null;
1079         std::unique_ptr<byte[]> pDataResized;
1080         int length = 0;
1081         int dstLength = 0;
1082         MediaPixelFormat pixFmt = MEDIA_PIXEL_FORMAT_NONE;
1083         _ImageBufferImpl* pResizedImpl = null;
1084
1085         SysTryReturn(NID_MEDIA, (width > 0) && (height > 0), null, E_INVALID_ARG,
1086                 "[E_INVALID_ARG] Dimensions should be greater than zero: (%d x %d)", width, height);
1087
1088         SysTryReturn(NID_MEDIA, _ImageUtil::IsValidDimension(__pixelFormat, width, height) == true, null, E_INVALID_ARG,
1089                 "[E_INVALID_ARG] Dimensions should be even for this pixel format: (%d x %d)", width, height);
1090
1091         if ((width != __width) && (height != __height))
1092         {
1093                 dstLength = _ImageUtil::GetBufferSize(__pixelFormat, width, height);
1094                 SysTryReturn(NID_MEDIA, dstLength > 0, pImgBuffer.get(), GetLastResult(),
1095                         "[%s] Failed to get valid buffer length for (%d x %d), pixel format %d.",
1096                         GetErrorMessage(GetLastResult()), width, height, __pixelFormat);
1097
1098                 pDataResized.reset(new (std::nothrow) byte[dstLength]);
1099                 SysTryReturn(NID_MEDIA, pDataResized.get() != null, pImgBuffer.get(), E_OUT_OF_MEMORY,
1100                         "[E_OUT_OF_MEMORY] Failed to allocate %d bytes.", dstLength);
1101
1102                 r = const_cast<_ImageBufferImpl *>(this)->Lock(pData, length, pixFmt);
1103                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r,
1104                         "[%s] Lock failed. Propagated.", GetErrorMessage(r));
1105
1106                 r = _ImageUtil::ResizeBuffer(pData, __pixelFormat, __width, __height,
1107                         pDataResized.get(), width, height);
1108                 SysTryCatch(NID_MEDIA, (r == E_SUCCESS) && (pDataResized.get() != null), , r,
1109                         "[%s] Could not resize buffer.", GetErrorMessage(r));
1110
1111                 const_cast<_ImageBufferImpl *>(this)->Unlock();
1112
1113                 pImgBuffer.reset(new (std::nothrow) ImageBuffer);
1114                 SysTryCatch(NID_MEDIA, pImgBuffer.get() != null, , E_OUT_OF_MEMORY,
1115                         "[E_OUT_OF_MEMORY] Could not create new instance.")
1116
1117                 r = pImgBuffer->Construct(width, height, __pixelFormat, pDataResized.release(), dstLength);
1118                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
1119                         "[%s] Failed to construct the resized ImageBuffer.", GetErrorMessage(r));
1120
1121                 pResizedImpl = GetInstance(*pImgBuffer);
1122                 SysTryReturn(NID_MEDIA, pResizedImpl != null, null, r,
1123                         "[%s] Failed to GetInstance.", GetErrorMessage(r));
1124                 pResizedImpl->__maskColor = __maskColor;
1125                 pResizedImpl->__transparent = __transparent;
1126         }
1127         else
1128         {
1129                 pImgBuffer.reset(CloneN());
1130         }
1131
1132         SetLastResult(r);
1133         return pImgBuffer.release();
1134
1135 CATCH:
1136
1137         const_cast<_ImageBufferImpl *>(this)->Unlock();
1138         SetLastResult(r);
1139         return null;
1140 }
1141
1142 ImageBuffer*
1143 _ImageBufferImpl::FlipN(ImageFlipType flipType) const
1144 {
1145         std::unique_ptr<ImageBuffer> pImgBuffer;
1146         result r = E_SUCCESS;
1147         byte* pData = null;
1148         std::unique_ptr<byte[]> pDataFlip;
1149         int length = 0;
1150         MediaPixelFormat pixFmt = MEDIA_PIXEL_FORMAT_NONE;
1151         _ImageBufferImpl* pFlippedImpl = null;
1152
1153         SysTryReturn(NID_MEDIA, (flipType >= IMAGE_FLIP_NONE) && (flipType <= IMAGE_FLIP_VERTICAL),
1154                 pImgBuffer.get(), E_INVALID_ARG, "[E_INVALID_ARG] Flip type is not valid: %d.", flipType);
1155
1156         if (flipType != IMAGE_FLIP_NONE)
1157         {
1158                 r = const_cast<_ImageBufferImpl *>(this)->Lock(pData, length, pixFmt);
1159                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, pImgBuffer.get(), r,
1160                         "[%s] Lock failed. Propagated.", GetErrorMessage(r));
1161
1162                 pDataFlip.reset(new (std::nothrow) byte[length]);
1163                 SysTryCatch(NID_MEDIA, pDataFlip.get() != null, , E_OUT_OF_MEMORY,
1164                         "[E_OUT_OF_MEMORY] Could not allocate %d bytes for flipped output.", length);
1165
1166                 r = _ImageUtil::FlipBuffer(pData, __pixelFormat, __width, __height, pDataFlip.get(), flipType);
1167                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r,
1168                         "[%s] Could not flip the data.", GetErrorMessage(r));
1169                 
1170                 const_cast<_ImageBufferImpl *>(this)->Unlock();
1171
1172                 pImgBuffer.reset(new (std::nothrow) ImageBuffer);
1173                 SysTryCatch(NID_MEDIA, pImgBuffer.get() != null, , E_OUT_OF_MEMORY,
1174                         "[E_OUT_OF_MEMORY] Could not create new instance.")
1175
1176                 r = pImgBuffer->Construct(__width, __height, __pixelFormat, pDataFlip.get(), length);
1177                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r,
1178                         "[%s] Failed to construct the fliped ImageBuffer.", GetErrorMessage(r));
1179
1180                 pFlippedImpl = GetInstance(*pImgBuffer);
1181                 SysTryReturn(NID_MEDIA, pFlippedImpl != null, null, r,
1182                         "[%s] Failed to GetInstance.", GetErrorMessage(r));
1183                 pFlippedImpl->__maskColor = __maskColor;
1184                 pFlippedImpl->__transparent = __transparent;
1185         }
1186         else
1187         {
1188                 pImgBuffer.reset(CloneN());
1189         }
1190
1191         SetLastResult(r);
1192         return pImgBuffer.release();
1193
1194 CATCH:
1195
1196         const_cast<_ImageBufferImpl *>(this)->Unlock();
1197
1198         SetLastResult(r);
1199         return null;
1200 }
1201
1202 ImageBuffer*
1203 _ImageBufferImpl::RotateN(ImageRotationType rotationType) const
1204 {
1205         std::unique_ptr<ImageBuffer> pImgBuffer;
1206         result r = E_SUCCESS;
1207         byte* pData = null;
1208         std::unique_ptr<byte[]> pDataRotate;
1209         int length = 0;
1210         int rotatedWidth= 0;
1211         int rotatedHeight = 0;
1212         MediaPixelFormat pixFmt = MEDIA_PIXEL_FORMAT_NONE;
1213         _ImageBufferImpl* pRotatedImpl = null;
1214
1215         SysTryReturn(NID_MEDIA, (rotationType >= IMAGE_ROTATION_0) && (rotationType <= IMAGE_ROTATION_270),
1216                 pImgBuffer.get(), E_INVALID_ARG, "[E_INVALID_ARG] Rotation type is not valid: %d.", rotationType);
1217
1218         if (rotationType != IMAGE_ROTATION_0)
1219         {
1220                 r = const_cast<_ImageBufferImpl *>(this)->Lock(pData, length, pixFmt);
1221                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, pImgBuffer.get(), r,
1222                         "[%s] Lock failed. Propagated.", GetErrorMessage(r));
1223
1224                 pDataRotate.reset(new (std::nothrow) byte[length]);
1225                 SysTryCatch(NID_MEDIA, pDataRotate.get() != null, , E_OUT_OF_MEMORY,
1226                         "[E_OUT_OF_MEMORY] Could not allocate %d bytes for rotated output.", length);
1227
1228                 r = _ImageUtil::RotateBuffer(pData, __pixelFormat, __width, __height, pDataRotate.get(),
1229                         rotatedWidth, rotatedHeight, rotationType);
1230                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r,
1231                         "[%s] Could not rotate the data.", GetErrorMessage(r));
1232
1233                 const_cast<_ImageBufferImpl *>(this)->Unlock();
1234
1235                 pImgBuffer.reset(new (std::nothrow) ImageBuffer);
1236                 SysTryCatch(NID_MEDIA, pImgBuffer.get() != null, , E_OUT_OF_MEMORY,
1237                         "[E_OUT_OF_MEMORY] Could not create new instance.")
1238
1239                 r = pImgBuffer->Construct(rotatedWidth, rotatedHeight, __pixelFormat, pDataRotate.get(), length);
1240                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
1241                         "[%s] Failed to construct the rotated ImageBuffer.", GetErrorMessage(r));
1242
1243                 pRotatedImpl = GetInstance(*pImgBuffer);
1244                 SysTryReturn(NID_MEDIA, pRotatedImpl != null, null, r,
1245                         "[%s] Failed to GetInstance.", GetErrorMessage(r));
1246                 pRotatedImpl->__maskColor = __maskColor;
1247                 pRotatedImpl->__transparent = __transparent;
1248         }
1249         else
1250         {
1251                 pImgBuffer.reset(CloneN());
1252         }
1253
1254         SetLastResult(r);
1255         return pImgBuffer.release();
1256
1257 CATCH:
1258
1259         const_cast<_ImageBufferImpl *>(this)->Unlock();
1260
1261         SetLastResult(r);
1262         return null;
1263 }
1264
1265 ImageBuffer*
1266 _ImageBufferImpl::CropN(int x, int y, int width, int height) const
1267 {
1268         std::unique_ptr<ImageBuffer> pImgBuffer;
1269         result r = E_SUCCESS;
1270         byte* pData = null;
1271         std::unique_ptr<byte[]> pDataCropped;
1272         int length = 0;
1273         int dstLength = 0;
1274         MediaPixelFormat pixFmt = MEDIA_PIXEL_FORMAT_NONE;
1275         _ImageBufferImpl *pCroppedImpl = null;
1276
1277         SysTryReturn(NID_MEDIA, (x >= 0) && (y >= 0) && (x <= __width) && (y <= __height),
1278                 pImgBuffer.get(), E_INVALID_ARG,
1279                 "[E_INVALID_ARG] Origin should lie within image: (%d, %d) is outside (0, 0) - (%d, %d).",
1280                 x, y, __width, __height);
1281
1282         SysTryReturn(NID_MEDIA, (width > 0) && (height > 0),
1283                 pImgBuffer.get(), E_INVALID_ARG,
1284                 "[E_INVALID_ARG] Dimensions of cropped region should greater than zero: (%d, %d).",
1285                 width, height);
1286
1287         SysTryReturn(NID_MEDIA, (x + width <= __width) && (y + height <= __height),
1288                 pImgBuffer.get(), E_INVALID_ARG,
1289                 "[E_INVALID_ARG] End of cropped region should lie within image: (%d, %d) is outside (0, 0) - (%d, %d).",
1290                 x + width, y + height, __width, __height);
1291
1292         SysTryReturn(NID_MEDIA, _ImageUtil::IsValidDimension(__pixelFormat, width, height) == true,
1293                 pImgBuffer.get(), E_INVALID_ARG,
1294                 "[E_INVALID_ARG] Current pixel format does not support odd dimensions (%d, %d).",
1295                 width, height);
1296
1297         if ((x != 0) || (y != 0) || (width != __width) || (height != __height))
1298         {
1299                 r = const_cast<_ImageBufferImpl *>(this)->Lock(pData, length, pixFmt);
1300                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, pImgBuffer.get(), r,
1301                         "[%s] Lock failed. Propagated.", GetErrorMessage(r));
1302
1303                 dstLength = _ImageUtil::GetBufferSize(__pixelFormat, width, height);
1304                 SysTryCatch(NID_MEDIA, dstLength > 0, , GetLastResult(),
1305                         "[%s] Could not get output buffer size.", GetErrorMessage(GetLastResult()));
1306
1307                 pDataCropped.reset(new (std::nothrow) byte[dstLength]);
1308                 SysTryCatch(NID_MEDIA, pDataCropped.get() != null, , E_OUT_OF_MEMORY,
1309                         "[E_OUT_OF_MEMORY] Could not allocate %d bytes for cropped output.", dstLength);
1310
1311                 r = _ImageUtil::CropBuffer(pData, __pixelFormat, __width, __height,
1312                         pDataCropped.get(), x, y, width, height);
1313                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r,
1314                         "[%s] Could not Crop the data.", GetErrorMessage(r));
1315
1316                 const_cast<_ImageBufferImpl *>(this)->Unlock();
1317
1318                 pImgBuffer.reset(new (std::nothrow) ImageBuffer);
1319                 SysTryCatch(NID_MEDIA, pImgBuffer.get() != null, , E_OUT_OF_MEMORY,
1320                         "[E_OUT_OF_MEMORY] Could not create new instance.")
1321
1322                 r = pImgBuffer->Construct(width, height, __pixelFormat, pDataCropped.get(), dstLength);
1323                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
1324                         "[%s] Failed to construct the croped ImageBuffer.", GetErrorMessage(r));
1325
1326                 pCroppedImpl = GetInstance(*pImgBuffer);
1327                 SysTryReturn(NID_MEDIA, pCroppedImpl != null, null, r,
1328                         "[%s] Failed to GetInstance.", GetErrorMessage(r));
1329                 pCroppedImpl->__maskColor = __maskColor;
1330                 pCroppedImpl->__transparent = __transparent;
1331         }
1332         else
1333         {
1334                 pImgBuffer.reset(CloneN());
1335         }
1336
1337         SetLastResult(r);
1338         return pImgBuffer.release();
1339
1340 CATCH:
1341
1342         const_cast<_ImageBufferImpl *>(this)->Unlock();
1343
1344         SetLastResult(r);
1345         return null;
1346 }
1347
1348 result
1349 _ImageBufferImpl::GetImageInfo(const String& srcImagePath, ImageFormat& imageFormat,
1350         int &width, int &height)
1351 {
1352         result r = E_SUCCESS;
1353
1354         std::unique_ptr<ByteBuffer> pSrcBuf(_MediaUtil::FileToBufferN(srcImagePath, 0));
1355         SysTryReturn(NID_MEDIA, pSrcBuf.get() != null, GetLastResult(), GetLastResult(),
1356                 "[%s] Propagated.", GetErrorMessage(GetLastResult()));
1357
1358         r = GetImageInfo(*pSrcBuf.get(), imageFormat, width, height);
1359
1360         return r;
1361 }
1362
1363 result
1364 _ImageBufferImpl::GetImageInfo(const ByteBuffer& srcImageBuf, ImageFormat& imageFormat,
1365         int &width, int &height)
1366 {
1367         result r = E_SUCCESS;
1368         _ImageDecoder dec;
1369
1370         r = dec.Construct(srcImageBuf, MEDIA_PIXEL_FORMAT_RGB565LE);
1371         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] dec.Construct", GetErrorMessage(r));
1372         imageFormat = dec.GetImageFormat();
1373         r = dec.GetDimension(width, height);
1374         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] dec.GetDimension", GetErrorMessage(r));
1375
1376         return r;
1377 }
1378
1379 bool
1380 _ImageBufferImpl::IsSupportedPixelFormat(MediaPixelFormat pixelFormat)
1381 {
1382         for (unsigned int i = 0; i < sizeof(_IMAGE_BUFFER_PIXEL_FORMATS)/sizeof(_IMAGE_BUFFER_PIXEL_FORMATS[0]) ; i++)
1383         {
1384                 if(pixelFormat == _IMAGE_BUFFER_PIXEL_FORMATS[i])
1385                 {
1386                         return true;
1387                 }
1388         }
1389         return false;
1390 }
1391
1392 IListT<MediaPixelFormat>*
1393 _ImageBufferImpl::GetSupportedPixelFormatListN()
1394 {
1395         result r = E_SUCCESS;
1396         std::unique_ptr<ArrayListT<MediaPixelFormat> > pList(new (std::nothrow) ArrayListT<MediaPixelFormat>());
1397         SysTryReturn(NID_MEDIA, pList.get() != null, null, E_OUT_OF_MEMORY,
1398                 "[E_OUT_OF_MEMORY] Could not allocate memory for output.");
1399
1400         // TODO update list later for supported color formats in color converter?.
1401         for (unsigned int i=0; i<sizeof(_IMAGE_BUFFER_PIXEL_FORMATS)/sizeof(_IMAGE_BUFFER_PIXEL_FORMATS[0]); i++)
1402         {
1403                 r = pList->Add(_IMAGE_BUFFER_PIXEL_FORMATS[i]);
1404                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
1405                                         "[%s] Adding elements to list failed. List is not complete.", GetErrorMessage(r));
1406         }
1407
1408         SetLastResult(r);
1409         return pList.release();
1410 }
1411
1412 _ImageBufferImpl*
1413 _ImageBufferImpl::GetInstance(ImageBuffer& a)
1414 {
1415         return a.__pImpl;
1416 }
1417
1418 const _ImageBufferImpl*
1419 _ImageBufferImpl::GetInstance(const ImageBuffer& a)
1420 {
1421         return a.__pImpl;
1422 }
1423
1424 }} // Tizen::Media
1425