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