67463106bce6e7d47e0edb3a295eb918a38b2288
[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 #define ISSUPPORTED(x)                                                                                                                  \
52         ((x == MEDIA_PIXEL_FORMAT_YUV420P) || (x == MEDIA_PIXEL_FORMAT_BGRA8888) ||     \
53         (x == MEDIA_PIXEL_FORMAT_RGB565LE) || (x == MEDIA_PIXEL_FORMAT_GRAY))
54
55 typedef struct {
56         ImageRotationType rotateType;
57         ImageFlipType flipType;
58         bool dimensionSwitch;
59 } _ImageExifInfo;
60
61 static const _ImageExifInfo _IMAGE_ROTATE_FLIP_MAP[] = {
62         { IMAGE_ROTATION_0,   IMAGE_FLIP_NONE,       false }, /* NONE         */
63         { IMAGE_ROTATION_0,   IMAGE_FLIP_NONE,       false }, /* TOP_LEFT     */
64         { IMAGE_ROTATION_0,   IMAGE_FLIP_VERTICAL,   false }, /* TOP_RIGHT    */
65         { IMAGE_ROTATION_180, IMAGE_FLIP_NONE,       false }, /* BOTTOM_RIGHT */
66         { IMAGE_ROTATION_0,   IMAGE_FLIP_HORIZONTAL, false }, /* BOTTOM_LEFT  */
67         { IMAGE_ROTATION_90,  IMAGE_FLIP_VERTICAL,   true  }, /* LEFT_TOP     */
68         { IMAGE_ROTATION_90,  IMAGE_FLIP_NONE,       true  }, /* RIGHT_TOP    */
69         { IMAGE_ROTATION_90,  IMAGE_FLIP_HORIZONTAL, true  }, /* RIGHT_BOTTOM */
70         { IMAGE_ROTATION_270, IMAGE_FLIP_NONE,       true  }  /* LEFT_BOTTOM  */
71 };
72
73 static const ExifOrientation _ORIENTATION_MAP[] ={
74         EXIF_ORIENTATION_TOP_LEFT,
75         EXIF_ORIENTATION_TOP_LEFT,
76         EXIF_ORIENTATION_TOP_RIGHT,
77         EXIF_ORIENTATION_BOTTOM_RIGHT,
78         EXIF_ORIENTATION_BOTTOM_LEFT,
79         EXIF_ORIENTATION_LEFT_TOP,
80         EXIF_ORIENTATION_RIGHT_TOP,
81         EXIF_ORIENTATION_RIGHT_BOTTOM,
82         EXIF_ORIENTATION_LEFT_BOTTOM
83 };
84
85 static const MediaPixelFormat _IMAGE_BUFFER_PIXEL_FORMATS[] =
86 {
87         MEDIA_PIXEL_FORMAT_RGB565LE,
88         MEDIA_PIXEL_FORMAT_BGRA8888,
89         MEDIA_PIXEL_FORMAT_YUV420P
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         SysTryReturn(NID_MEDIA, ISSUPPORTED(pixelFormat) == true, E_INVALID_ARG, E_INVALID_ARG,
149                 "[E_INVALID_ARG] Pixelformat is not supported : %d.", pixelFormat);
150
151         reqBufferSize = _ImageUtil::GetBufferSize(pixelFormat, width, height);
152         SysTryReturn(NID_MEDIA, reqBufferSize > 0, GetLastResult(), GetLastResult(),
153                         "[%s] Could not get output buffer size.", GetErrorMessage(GetLastResult()));
154
155         if (pData != null)
156         {
157                 SysTryReturn(NID_MEDIA, reqBufferSize <= length, E_INVALID_ARG, E_INVALID_ARG,
158                         "[E_INVALID_ARG] Check length. Required for (%d x %d) in %d format is %d : arg = %d.",
159                         width, height, pixelFormat, length);
160         }
161
162         __width = width;
163         __height = height;
164         __pixelFormat = pixelFormat;
165
166         __pBuffer.reset(new (std::nothrow) byte[reqBufferSize]);
167         SysTryReturn(NID_MEDIA, __pBuffer.get() != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
168                 "[E_OUT_OF_MEMORY] Construct instance failed.");
169         memset(__pBuffer.get(), 0, reqBufferSize);
170         __bufSize = reqBufferSize;
171
172         if (pData != null)
173         {
174                 memcpy(__pBuffer.get(), pData, 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         SysTryReturn(NID_MEDIA, pBuf.get() != null, GetLastResult(), GetLastResult(),
187                            "[%s] FileToBufferN %S", 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;
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("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.ToInt();
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("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.ToInt();
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("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.ToInt();
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         SysTryReturn(NID_MEDIA, pBuf.get() != null, GetLastResult(), GetLastResult(),
516                            "[%s] FileToBufferN %S", 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;
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("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.ToInt();
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                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, pOutBitmap.release(), E_SUCCESS,
841                         "[%s] Could not set masking color.", GetErrorMessage(r));
842                 delete pMaskingColor;
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                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, pOutBitmap.release(), E_SUCCESS,
925                         "[%s] Could not set masking color.", GetErrorMessage(r));
926                 delete pMaskingColor;
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, (inPixelFormat > MEDIA_PIXEL_FORMAT_NONE) && (inPixelFormat <= MEDIA_PIXEL_FORMAT_YUYV422),
943                 null, E_INVALID_ARG, "[E_INVALID_ARG] Pixel format is invalid.", inPixelFormat);
944
945         SysTryReturn(NID_MEDIA, IsSupportedPixelFormat(inPixelFormat) == true , null, E_UNSUPPORTED_FORMAT,
946                 "[E_UNSUPPORTED_FORMAT] The specified pixelFormat is not supported.")
947
948         std::unique_ptr<ByteBuffer> pTmpByteBuffer (new (std::nothrow) ByteBuffer());
949         r = pTmpByteBuffer->Construct(__pBuffer.get(), 0, __bufSize, __bufSize);
950         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
951                         "[%s] Construct instance failed.", GetErrorMessage(r));
952
953         if (inPixelFormat != __pixelFormat)
954         {
955                 // Convert raw data to the required pixel format.
956                 _ColorConverter cvt;
957
958                 r = cvt.Construct(__pixelFormat, __width, __height,
959                         inPixelFormat, __width, __height);
960                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
961
962                 pOutBuf.reset(cvt.ConvertN(*pTmpByteBuffer));
963                 r = GetLastResult();
964                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
965         }
966         else
967         {
968                 pOutBuf.reset(new (std::nothrow) ByteBuffer);
969                 SysTryReturn(NID_MEDIA, pOutBuf.get() != null, null, E_OUT_OF_MEMORY,
970                         "[E_OUT_OF_MEMORY] Propagated.");
971
972                 r = pOutBuf->Construct(*pTmpByteBuffer);
973                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
974                         "[%s] Propagated.", GetErrorMessage(r));
975         }
976
977         SetLastResult(r);
978         return pOutBuf.release();
979 }
980
981 ImageBuffer*
982 _ImageBufferImpl::CloneN() const
983 {
984         std::unique_ptr<ImageBuffer> pImgBuffer;
985         result r = E_SUCCESS;
986         byte* pData = null;
987         int length = 0;
988         MediaPixelFormat pixFmt = MEDIA_PIXEL_FORMAT_NONE;
989         _ImageBufferImpl* pClonedImpl = null;
990
991         r = const_cast<_ImageBufferImpl *>(this)->Lock(pData, length, pixFmt);
992         SysTryReturn(NID_MEDIA, r == E_SUCCESS, pImgBuffer.get(), r, "[%s] Propagated.", GetErrorMessage(r));
993
994         pImgBuffer.reset(new (std::nothrow) ImageBuffer);
995         SysTryReturn(NID_MEDIA, pImgBuffer.get() != null, null, E_OUT_OF_MEMORY,
996                 "[E_OUT_OF_MEMORY] Could not create new instance.")
997
998         r = pImgBuffer->Construct(__width, __height, pixFmt, pData, length);
999         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
1000                 "[%s] Failed to construct the cloned ImageBuffer.", GetErrorMessage(r));
1001
1002         pClonedImpl = GetInstance(*pImgBuffer);
1003         SysTryReturn(NID_MEDIA, pClonedImpl != null, null, r,
1004                 "[%s] Failed to GetInstance.", GetErrorMessage(r));
1005         pClonedImpl->__maskColor = __maskColor;
1006         pClonedImpl->__transparent = __transparent;
1007
1008         const_cast<_ImageBufferImpl *>(this)->Unlock();
1009
1010         SetLastResult(r);
1011         return pImgBuffer.release();
1012 }
1013
1014 ImageBuffer*
1015 _ImageBufferImpl::ConvertPixelFormatN(MediaPixelFormat pixelFormat) const
1016 {
1017         std::unique_ptr<ImageBuffer> pImgBuffer;
1018         result r = E_SUCCESS;
1019         byte* pData = null;
1020         std::unique_ptr<byte[]> pDataConvert;
1021         int length = 0;
1022         int dstLength = 0;
1023         MediaPixelFormat pixFmt = MEDIA_PIXEL_FORMAT_NONE;
1024         _ImageBufferImpl* pConvertedImpl = null;
1025
1026         SysTryReturn(NID_MEDIA, ISSUPPORTED(pixelFormat) == true, pImgBuffer.get(), E_INVALID_ARG,
1027                 "[E_INVALID_ARG] Pixel format %d is not supported.", pixelFormat);
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         else
1063         {
1064                 pImgBuffer.reset(CloneN());
1065         }
1066
1067         SetLastResult(r);
1068         return pImgBuffer.release();
1069
1070 CATCH:
1071         const_cast<_ImageBufferImpl *>(this)->Unlock();
1072         SetLastResult(r);
1073         return null;
1074 }
1075
1076 ImageBuffer*
1077 _ImageBufferImpl::ResizeN(int width, int height) const
1078 {
1079         std::unique_ptr<ImageBuffer> pImgBuffer;
1080         result r = E_SUCCESS;
1081         byte* pData = null;
1082         std::unique_ptr<byte[]> pDataResized;
1083         int length = 0;
1084         int dstLength = 0;
1085         MediaPixelFormat pixFmt = MEDIA_PIXEL_FORMAT_NONE;
1086         _ImageBufferImpl* pResizedImpl = null;
1087
1088         SysTryReturn(NID_MEDIA, (width > 0) && (height > 0), pImgBuffer.get(), E_INVALID_ARG,
1089                 "[E_INVALID_ARG] Dimensions should be greater than zero: (%d x %d)", width, height);
1090
1091         if ((width != __width) && (height != __height))
1092         {
1093                 dstLength = _ImageUtil::GetBufferSize(__pixelFormat, width, height);
1094                 SysTryReturn(NID_MEDIA, dstLength > 0, pImgBuffer.get(), GetLastResult(),
1095                         "[%s] Failed to get valid buffer length for (%d x %d), pixel format %d.",
1096                         GetErrorMessage(GetLastResult()), width, height, __pixelFormat);
1097
1098                 pDataResized.reset(new (std::nothrow) byte[dstLength]);
1099                 SysTryReturn(NID_MEDIA, pDataResized.get() != null, pImgBuffer.get(), E_OUT_OF_MEMORY,
1100                         "[E_OUT_OF_MEMORY] Failed to allocate %d bytes.", dstLength);
1101
1102                 r = const_cast<_ImageBufferImpl *>(this)->Lock(pData, length, pixFmt);
1103                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r,
1104                         "[%s] Lock failed. Propagated.", GetErrorMessage(r));
1105
1106                 r = _ImageUtil::ResizeBuffer(pData, __pixelFormat, __width, __height,
1107                         pDataResized.get(), width, height);
1108                 SysTryCatch(NID_MEDIA, (r == E_SUCCESS) && (pDataResized.get() != null), , r,
1109                         "[%s] Could not resize buffer.", GetErrorMessage(r));
1110
1111                 const_cast<_ImageBufferImpl *>(this)->Unlock();
1112
1113                 pImgBuffer.reset(new (std::nothrow) ImageBuffer);
1114                 SysTryCatch(NID_MEDIA, pImgBuffer.get() != null, , E_OUT_OF_MEMORY,
1115                         "[E_OUT_OF_MEMORY] Could not create new instance.")
1116
1117                 r = pImgBuffer->Construct(width, height, __pixelFormat, pDataResized.get(), dstLength);
1118                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
1119                         "[%s] Failed to construct the resized ImageBuffer.", GetErrorMessage(r));
1120
1121                 pResizedImpl = GetInstance(*pImgBuffer);
1122                 SysTryReturn(NID_MEDIA, pResizedImpl != null, null, r,
1123                         "[%s] Failed to GetInstance.", GetErrorMessage(r));
1124                 pResizedImpl->__maskColor = __maskColor;
1125                 pResizedImpl->__transparent = __transparent;
1126         }
1127         else
1128         {
1129                 pImgBuffer.reset(CloneN());
1130         }
1131
1132         SetLastResult(r);
1133         return pImgBuffer.release();
1134
1135 CATCH:
1136
1137         const_cast<_ImageBufferImpl *>(this)->Unlock();
1138         SetLastResult(r);
1139         return null;
1140 }
1141
1142 ImageBuffer*
1143 _ImageBufferImpl::FlipN(ImageFlipType flipType) const
1144 {
1145         std::unique_ptr<ImageBuffer> pImgBuffer;
1146         result r = E_SUCCESS;
1147         byte* pData = null;
1148         std::unique_ptr<byte[]> pDataFlip;
1149         int length = 0;
1150         MediaPixelFormat pixFmt = MEDIA_PIXEL_FORMAT_NONE;
1151         _ImageBufferImpl* pFlippedImpl = null;
1152
1153         SysTryReturn(NID_MEDIA, (flipType >= IMAGE_FLIP_NONE) && (flipType <= IMAGE_FLIP_VERTICAL),
1154                 pImgBuffer.get(), E_INVALID_ARG, "[E_INVALID_ARG] Flip type is not valid: %d.", flipType);
1155
1156         if (flipType != IMAGE_FLIP_NONE)
1157         {
1158                 r = const_cast<_ImageBufferImpl *>(this)->Lock(pData, length, pixFmt);
1159                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, pImgBuffer.get(), r,
1160                         "[%s] Lock failed. Propagated.", GetErrorMessage(r));
1161
1162                 pDataFlip.reset(new (std::nothrow) byte[length]);
1163                 SysTryCatch(NID_MEDIA, pDataFlip.get() != null, , E_OUT_OF_MEMORY,
1164                         "[E_OUT_OF_MEMORY] Could not allocate %d bytes for flipped output.", length);
1165
1166                 r = _ImageUtil::FlipBuffer(pData, __pixelFormat, __width, __height, pDataFlip.get(), flipType);
1167                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r,
1168                         "[%s] Could not flip the data.", GetErrorMessage(r));
1169                 
1170                 const_cast<_ImageBufferImpl *>(this)->Unlock();
1171
1172                 pImgBuffer.reset(new (std::nothrow) ImageBuffer);
1173                 SysTryCatch(NID_MEDIA, pImgBuffer.get() != null, , E_OUT_OF_MEMORY,
1174                         "[E_OUT_OF_MEMORY] Could not create new instance.")
1175
1176                 r = pImgBuffer->Construct(__width, __height, __pixelFormat, pDataFlip.get(), length);
1177                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r,
1178                         "[%s] Failed to construct the fliped ImageBuffer.", GetErrorMessage(r));
1179
1180                 pFlippedImpl = GetInstance(*pImgBuffer);
1181                 SysTryReturn(NID_MEDIA, pFlippedImpl != null, null, r,
1182                         "[%s] Failed to GetInstance.", GetErrorMessage(r));
1183                 pFlippedImpl->__maskColor = __maskColor;
1184                 pFlippedImpl->__transparent = __transparent;
1185         }
1186         else
1187         {
1188                 pImgBuffer.reset(CloneN());
1189         }
1190
1191         SetLastResult(r);
1192         return pImgBuffer.release();
1193
1194 CATCH:
1195
1196         const_cast<_ImageBufferImpl *>(this)->Unlock();
1197
1198         SetLastResult(r);
1199         return null;
1200 }
1201
1202 ImageBuffer*
1203 _ImageBufferImpl::RotateN(ImageRotationType rotationType) const
1204 {
1205         std::unique_ptr<ImageBuffer> pImgBuffer;
1206         result r = E_SUCCESS;
1207         byte* pData = null;
1208         std::unique_ptr<byte[]> pDataRotate;
1209         int length = 0;
1210         int rotatedWidth= 0;
1211         int rotatedHeight = 0;
1212         MediaPixelFormat pixFmt = MEDIA_PIXEL_FORMAT_NONE;
1213         _ImageBufferImpl* pRotatedImpl = null;
1214
1215         SysTryReturn(NID_MEDIA, (rotationType >= IMAGE_ROTATION_0) && (rotationType <= IMAGE_ROTATION_270),
1216                 pImgBuffer.get(), E_INVALID_ARG, "[E_INVALID_ARG] Rotation type is not valid: %d.", rotationType);
1217
1218         if (rotationType != IMAGE_ROTATION_0)
1219         {
1220                 r = const_cast<_ImageBufferImpl *>(this)->Lock(pData, length, pixFmt);
1221                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, pImgBuffer.get(), r,
1222                         "[%s] Lock failed. Propagated.", GetErrorMessage(r));
1223
1224                 pDataRotate.reset(new (std::nothrow) byte[length]);
1225                 SysTryCatch(NID_MEDIA, pDataRotate.get() != null, , E_OUT_OF_MEMORY,
1226                         "[E_OUT_OF_MEMORY] Could not allocate %d bytes for rotated output.", length);
1227
1228                 r = _ImageUtil::RotateBuffer(pData, __pixelFormat, __width, __height, pDataRotate.get(),
1229                         rotatedWidth, rotatedHeight, rotationType);
1230                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r,
1231                         "[%s] Could not rotate the data.", GetErrorMessage(r));
1232
1233                 const_cast<_ImageBufferImpl *>(this)->Unlock();
1234
1235                 pImgBuffer.reset(new (std::nothrow) ImageBuffer);
1236                 SysTryCatch(NID_MEDIA, pImgBuffer.get() != null, , E_OUT_OF_MEMORY,
1237                         "[E_OUT_OF_MEMORY] Could not create new instance.")
1238
1239                 r = pImgBuffer->Construct(rotatedWidth, rotatedHeight, __pixelFormat, pDataRotate.get(), length);
1240                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
1241                         "[%s] Failed to construct the rotated ImageBuffer.", GetErrorMessage(r));
1242
1243                 pRotatedImpl = GetInstance(*pImgBuffer);
1244                 SysTryReturn(NID_MEDIA, pRotatedImpl != null, null, r,
1245                         "[%s] Failed to GetInstance.", GetErrorMessage(r));
1246                 pRotatedImpl->__maskColor = __maskColor;
1247                 pRotatedImpl->__transparent = __transparent;
1248         }
1249         else
1250         {
1251                 pImgBuffer.reset(CloneN());
1252         }
1253
1254         SetLastResult(r);
1255         return pImgBuffer.release();
1256
1257 CATCH:
1258
1259         const_cast<_ImageBufferImpl *>(this)->Unlock();
1260
1261         SetLastResult(r);
1262         return null;
1263 }
1264
1265 ImageBuffer*
1266 _ImageBufferImpl::CropN(int x, int y, int width, int height) const
1267 {
1268         std::unique_ptr<ImageBuffer> pImgBuffer;
1269         result r = E_SUCCESS;
1270         byte* pData = null;
1271         std::unique_ptr<byte[]> pDataCropped;
1272         int length = 0;
1273         int dstLength = 0;
1274         MediaPixelFormat pixFmt = MEDIA_PIXEL_FORMAT_NONE;
1275         _ImageBufferImpl *pCroppedImpl = null;
1276
1277         SysTryReturn(NID_MEDIA, (x >= 0) && (y >= 0) && (x <= __width) && (y <= __height),
1278                 pImgBuffer.get(), E_INVALID_ARG,
1279                 "[E_INVALID_ARG] Origin should lie within image: (%d, %d) is outside (0, 0) - (%d, %d).",
1280                 x, y, __width, __height);
1281
1282         SysTryReturn(NID_MEDIA, (width > 0) && (height > 0),
1283                 pImgBuffer.get(), E_INVALID_ARG,
1284                 "[E_INVALID_ARG] Dimensions of cropped region should greater than zero: (%d, %d).",
1285                 width, height);
1286
1287         SysTryReturn(NID_MEDIA, (x + width <= __width) && (y + height <= __height),
1288                 pImgBuffer.get(), E_INVALID_ARG,
1289                 "[E_INVALID_ARG] End of cropped region should lie within image: (%d, %d) is outside (0, 0) - (%d, %d).",
1290                 x + width, y + height, __width, __height);
1291
1292         SysTryReturn(NID_MEDIA, _ImageUtil::IsValidDimension(__pixelFormat, width, height) == true,
1293                 pImgBuffer.get(), E_INVALID_ARG,
1294                 "[E_INVALID_ARG] Current pixel format does not support odd dimensions (%d, %d).",
1295                 width, height);
1296
1297         if ((x != 0) || (y != 0) || (width != __width) || (height != __height))
1298         {
1299                 r = const_cast<_ImageBufferImpl *>(this)->Lock(pData, length, pixFmt);
1300                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, pImgBuffer.get(), r,
1301                         "[%s] Lock failed. Propagated.", GetErrorMessage(r));
1302
1303                 dstLength = _ImageUtil::GetBufferSize(__pixelFormat, width, height);
1304                 SysTryCatch(NID_MEDIA, dstLength > 0, , GetLastResult(),
1305                         "[%s] Could not get output buffer size.", GetErrorMessage(GetLastResult()));
1306
1307                 pDataCropped.reset(new (std::nothrow) byte[dstLength]);
1308                 SysTryCatch(NID_MEDIA, pDataCropped.get() != null, , E_OUT_OF_MEMORY,
1309                         "[E_OUT_OF_MEMORY] Could not allocate %d bytes for cropped output.", dstLength);
1310
1311                 r = _ImageUtil::CropBuffer(pData, __pixelFormat, __width, __height,
1312                         pDataCropped.get(), x, y, width, height);
1313                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r,
1314                         "[%s] Could not Crop the data.", GetErrorMessage(r));
1315
1316                 const_cast<_ImageBufferImpl *>(this)->Unlock();
1317
1318                 pImgBuffer.reset(new (std::nothrow) ImageBuffer);
1319                 SysTryCatch(NID_MEDIA, pImgBuffer.get() != null, , E_OUT_OF_MEMORY,
1320                         "[E_OUT_OF_MEMORY] Could not create new instance.")
1321
1322                 r = pImgBuffer->Construct(width, height, __pixelFormat, pDataCropped.get(), dstLength);
1323                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
1324                         "[%s] Failed to construct the croped ImageBuffer.", GetErrorMessage(r));
1325
1326                 pCroppedImpl = GetInstance(*pImgBuffer);
1327                 SysTryReturn(NID_MEDIA, pCroppedImpl != null, null, r,
1328                         "[%s] Failed to GetInstance.", GetErrorMessage(r));
1329                 pCroppedImpl->__maskColor = __maskColor;
1330                 pCroppedImpl->__transparent = __transparent;
1331         }
1332         else
1333         {
1334                 pImgBuffer.reset(CloneN());
1335         }
1336
1337         SetLastResult(r);
1338         return pImgBuffer.release();
1339
1340 CATCH:
1341
1342         const_cast<_ImageBufferImpl *>(this)->Unlock();
1343
1344         SetLastResult(r);
1345         return null;
1346 }
1347
1348 result
1349 _ImageBufferImpl::GetImageInfo(const String& srcImagePath, ImageFormat& imageFormat,
1350         int &width, int &height)
1351 {
1352         result r = E_SUCCESS;
1353
1354         std::unique_ptr<ByteBuffer> pSrcBuf(_MediaUtil::FileToBufferN(srcImagePath, 0));
1355         SysTryReturn(NID_MEDIA, pSrcBuf.get() != null, GetLastResult(), GetLastResult(),
1356                 "[%s] Propagated.", GetErrorMessage(GetLastResult()));
1357
1358         r = GetImageInfo(*pSrcBuf.get(), imageFormat, width, height);
1359
1360         return r;
1361 }
1362
1363 result
1364 _ImageBufferImpl::GetImageInfo(const ByteBuffer& srcImageBuf, ImageFormat& imageFormat,
1365         int &width, int &height)
1366 {
1367         result r = E_SUCCESS;
1368         _ImageDecoder dec;
1369
1370         r = dec.Construct(srcImageBuf, MEDIA_PIXEL_FORMAT_RGB565LE);
1371         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] dec.Construct", GetErrorMessage(r));
1372         imageFormat = dec.GetImageFormat();
1373         r = dec.GetDimension(width, height);
1374         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] dec.GetDimension", GetErrorMessage(r));
1375
1376         return r;
1377 }
1378
1379 bool
1380 _ImageBufferImpl::IsSupportedPixelFormat(MediaPixelFormat pixelFormat)
1381 {
1382         for (unsigned int i = 0; i < sizeof(_IMAGE_BUFFER_PIXEL_FORMATS)/sizeof(_IMAGE_BUFFER_PIXEL_FORMATS[0]) ; i++)
1383         {
1384                 if(pixelFormat == _IMAGE_BUFFER_PIXEL_FORMATS[i])
1385                 {
1386                         return true;
1387                 }
1388         }
1389         return false;
1390 }
1391
1392 IListT<MediaPixelFormat>*
1393 _ImageBufferImpl::GetSupportedPixelFormatListN()
1394 {
1395         result r = E_SUCCESS;
1396         std::unique_ptr<ArrayListT<MediaPixelFormat> > pList(new (std::nothrow) ArrayListT<MediaPixelFormat>());
1397         SysTryReturn(NID_MEDIA, pList.get() != null, null, E_OUT_OF_MEMORY,
1398                 "[E_OUT_OF_MEMORY] Could not allocate memory for output.");
1399
1400         // TODO update list later for supported color formats in color converter?.
1401         for (unsigned int i=0; i<sizeof(_IMAGE_BUFFER_PIXEL_FORMATS)/sizeof(_IMAGE_BUFFER_PIXEL_FORMATS[0]); i++)
1402         {
1403                 r = pList->Add(_IMAGE_BUFFER_PIXEL_FORMATS[i]);
1404                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
1405                                         "[%s] Adding elements to list failed. List is not complete.", GetErrorMessage(r));
1406         }
1407
1408         SetLastResult(r);
1409         return pList.release();
1410 }
1411
1412 _ImageBufferImpl*
1413 _ImageBufferImpl::GetInstance(ImageBuffer& a)
1414 {
1415         return a.__pImpl;
1416 }
1417
1418 const _ImageBufferImpl*
1419 _ImageBufferImpl::GetInstance(const ImageBuffer& a)
1420 {
1421         return a.__pImpl;
1422 }
1423
1424 }} // Tizen::Media
1425