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