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