f2118cb91e9f1cfc96091b87d1ffee82d32d6791
[platform/framework/native/image-core.git] / src / FMedia_ImageDecoder.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_ImageDecoder.cpp
20  * @brief  This is the implementation file for the _ImageDecoder.
21  */
22
23 #include <unique_ptr.h>
24 #include <FBaseColArrayListT.h>
25 #include <FBaseSysLog.h>
26 #include <FBaseInteger.h>
27 #include <FIoFile.h>
28 #include <FMediaImageTypes.h>
29 #include "FMedia_MediaUtil.h"
30 #include "FMedia_Ffmpeg.h"
31 #include "FMedia_ColorConverter.h"
32 #include "FMedia_ImageDecoder.h"
33 #include "FMedia_PngDecoder.h"
34 #include "FMedia_JpegDecoder.h"
35 #include "FMedia_JpegTurboDecoder.h"
36 #include "FMedia_GifDecoder.h"
37 #include "FMedia_BmpDecoder.h"
38 #include "FMedia_TiffDecoder.h"
39 #include "FMedia_WbmpDecoder.h"
40 #include "FMedia_ImageUtil.h"
41 #include "FMedia_ExifUtil.h"
42
43 using namespace Tizen::Base;
44 using namespace Tizen::Io;
45
46 namespace Tizen { namespace Media
47 {
48
49 #define IS_VALID_DEC_PIXEL(x)                              \
50         ((x == MEDIA_PIXEL_FORMAT_RGB565LE) || (x == MEDIA_PIXEL_FORMAT_BGRA8888) \
51          || (x == MEDIA_PIXEL_FORMAT_RGBA8888))
52
53 typedef struct {
54         ImageRotationType rotateType;
55         ImageFlipType flipType;
56         bool dimensionSwitch;
57 } _ImageExifInfo;
58
59 static const _ImageExifInfo _IMAGE_ROTATE_FLIP_MAP[] = {
60         { IMAGE_ROTATION_0,   IMAGE_FLIP_NONE,       false }, /* NONE         */
61         { IMAGE_ROTATION_0,   IMAGE_FLIP_NONE,       false }, /* TOP_LEFT     */
62         { IMAGE_ROTATION_0,   IMAGE_FLIP_VERTICAL,   false }, /* TOP_RIGHT    */
63         { IMAGE_ROTATION_180, IMAGE_FLIP_NONE,       false }, /* BOTTOM_RIGHT */
64         { IMAGE_ROTATION_0,   IMAGE_FLIP_HORIZONTAL, false }, /* BOTTOM_LEFT  */
65         { IMAGE_ROTATION_90,  IMAGE_FLIP_VERTICAL,   true  }, /* LEFT_TOP     */
66         { IMAGE_ROTATION_90,  IMAGE_FLIP_NONE,       true  }, /* RIGHT_TOP    */
67         { IMAGE_ROTATION_90,  IMAGE_FLIP_HORIZONTAL, true  }, /* RIGHT_BOTTOM */
68         { IMAGE_ROTATION_270, IMAGE_FLIP_NONE,       true  }  /* LEFT_BOTTOM  */
69 };
70
71 Tizen::Base::ByteBuffer*
72 _ImageDecoder::DecodeToBufferN(const Tizen::Base::String& filePath,
73                                 MediaPixelFormat pixelFormat, int &width, int &height, bool autoRotate)
74 {
75         result r = E_SUCCESS;
76
77         std::unique_ptr<ByteBuffer> pBuf;
78         _ImageDecoder dec;
79
80         SysTryReturn(NID_MEDIA, filePath.GetLength() > 0 && filePath.GetLength() <= PATH_MAX, null, E_INVALID_ARG,
81                                 "[E_INVALID_ARG] Given filePath length is zero or exceeds system limitations Length = %d.",filePath.GetLength());
82         SysSecureTryReturn(NID_MEDIA, File::IsFileExist(filePath), null, E_FILE_NOT_FOUND,
83                                 "[E_FILE_NOT_FOUND] filePath:%ls", filePath.GetPointer());
84
85         r = dec.Construct(filePath, pixelFormat, IMG_FORMAT_NONE, autoRotate);
86         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
87                 "[%s] Decoder construct failed.", GetErrorMessage(r));
88
89         // Reset decoder output demension
90         pBuf.reset(dec.DecodeN());
91         r = GetLastResult();
92         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
93
94         r = dec.GetDimension(width, height);
95         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
96
97         SetLastResult(E_SUCCESS);
98         return pBuf.release();
99 }
100
101 Tizen::Base::ByteBuffer*
102 _ImageDecoder::DecodeRegionToBufferN(const Tizen::Base::String& filePath,
103                                 MediaPixelFormat pixelFormat, int x, int y, int width, int height)
104 {
105         result r = E_SUCCESS;
106         _ImageDecoder dec;
107         int imgWidth = 0;
108         int imgHeight = 0;
109         std::unique_ptr<ByteBuffer> pBuf;
110
111         r = dec.Construct(filePath, pixelFormat);
112         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] dec.Construct", GetErrorMessage(r));
113         r = dec.GetDimension(imgWidth, imgHeight);
114         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] dec.GetDimension", GetErrorMessage(r));
115
116         SysTryReturn(NID_MEDIA, imgWidth >= (x + width) && imgHeight >= (y + height),
117                 null, E_INVALID_ARG,
118                 "[E_INVALID_ARG] Bottom left point of region (%d, %d) should lie within dimensions of image (%d x %d)",
119                 x, y, width, height, imgWidth, imgHeight);
120
121         r = dec.SetDecodingRegion(x, y, width, height);
122         SysTryReturn(NID_MEDIA, r == E_SUCCESS || r == E_UNSUPPORTED_OPERATION, null, r,
123                 "[%s] dec.SetDecodingRegion failed for region (%d, %d) (%d x %d)",
124                 GetErrorMessage(r), x, y, width, height);
125
126         if (r == E_SUCCESS)
127         {
128                 pBuf.reset(dec.DecodeN());
129                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
130         }
131         else // E_UNSUPPORTED_OPERATION
132         {
133                 // crop image
134                 ByteBuffer *pTmpBuf = null;
135
136                 pBuf.reset(dec.DecodeN());
137                 r = GetLastResult();
138                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
139                 pTmpBuf = _ImageUtil::CropN(*pBuf.get(), pixelFormat, imgWidth, imgHeight, x, y, width, height);
140                 SysTryReturn(NID_MEDIA, pTmpBuf != null, null, GetLastResult(),
141                         "[%s] Crop failed for buffer(%x), pixelFormat(%d), image size(%dx%d), region(%d,%d), (%dx%d)",
142                         GetErrorMessage(GetLastResult()), pBuf->GetPointer(), pixelFormat, imgWidth,
143                         imgHeight, x, y, width, height);
144                 pBuf.reset(pTmpBuf);
145         }
146
147         SetLastResult(E_SUCCESS);
148         return pBuf.release();
149 }
150
151 Tizen::Base::ByteBuffer*
152 _ImageDecoder::DecodeRegionToBufferN(const Tizen::Base::ByteBuffer& srcBuf, MediaPixelFormat pixelFormat,
153                                                                          int x, int y, int width, int height)
154 {
155         result r = E_SUCCESS;
156         _ImageDecoder dec;
157         int imgWidth = 0;
158         int imgHeight = 0;
159         std::unique_ptr<ByteBuffer> pBuf;
160
161         r = dec.Construct(srcBuf, pixelFormat);
162         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] dec.Construct", GetErrorMessage(r));
163         r = dec.GetDimension(imgWidth, imgHeight);
164         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] dec.GetDimension", GetErrorMessage(r));
165
166         SysTryReturn(NID_MEDIA, imgWidth >= (x + width) && imgHeight >= (y + height),
167                 null, E_INVALID_ARG,
168                 "[E_INVALID_ARG] Bottom left point of region (%d, %d) should lie within dimensions of image (%d x %d)",
169                 x, y, width, height, imgWidth, imgHeight);
170
171         r = dec.SetDecodingRegion(x, y, width, height);
172         SysTryReturn(NID_MEDIA, r == E_SUCCESS || r == E_UNSUPPORTED_OPERATION, null, r,
173                 "[%s] dec.SetDecodingRegion failed for region (%d, %d) (%d x %d)",
174                 GetErrorMessage(r), x, y, width, height);
175
176         if (r == E_SUCCESS)
177         {
178                 pBuf.reset(dec.DecodeN());
179                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
180         }
181         else // E_UNSUPPORTED_OPERATION
182         {
183                 // crop image
184                 ByteBuffer *pTmpBuf = null;
185                 pBuf.reset(dec.DecodeN());
186                 r = GetLastResult();
187                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
188                 pTmpBuf = _ImageUtil::CropN(*pBuf.get(), pixelFormat, imgWidth, imgHeight, x, y, width, height);
189                 SysTryReturn(NID_MEDIA, pTmpBuf != null, null, GetLastResult(),
190                         "[%s] Crop failed for buffer(%x), pixelFormat(%d), image size(%dx%d), region(%d,%d), (%dx%d)",
191                         GetErrorMessage(GetLastResult()), pBuf->GetPointer(), pixelFormat, imgWidth,
192                         imgHeight, x, y, width, height);
193                 pBuf.reset(pTmpBuf);
194         }
195
196         SetLastResult(E_SUCCESS);
197         return pBuf.release();
198 }
199
200 result
201 _ImageDecoder::GetImageInfo(const Tizen::Base::String& filePath, ImageFormat &imgFormat,
202                                                         int &width, int &height)
203 {
204         result r = E_SUCCESS;
205         _ImageDecoder dec;
206
207         r = dec.Construct(filePath);
208         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] dec.Construct", GetErrorMessage(r));
209         imgFormat = dec.GetImageFormat();
210         r = dec.GetDimension(width, height);
211         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] dec.GetDimension", GetErrorMessage(r));
212
213 CATCH:
214         return r;
215 }
216
217 _ImageDecoder::_ImageDecoder(void)
218 {
219         __pDec = null;
220         __imgFormat = IMG_FORMAT_NONE;
221         __pixelFormat = MEDIA_PIXEL_FORMAT_NONE;
222         __orgDim.width = 0;
223         __orgDim.height = 0;
224         __outDim.width = 0;
225         __outDim.height = 0;
226         __pSrcBuf = null;
227         __autoRotate = false;
228         __orientationInfo = 0;
229 }
230
231 _ImageDecoder::~_ImageDecoder(void)
232 {
233 }
234
235 _IImageDecoder*
236 _ImageDecoder::CreateDecoderN(ImageFormat srcFormat)
237 {
238         result r = E_SUCCESS;
239         std::unique_ptr<_IImageDecoder> pDec;
240
241         switch (srcFormat)
242         {
243         case IMG_FORMAT_JPG:
244                 pDec.reset( new (std::nothrow) _JpegTurboDecoder());
245                 break;
246
247         case IMG_FORMAT_PNG:
248                 pDec.reset( new (std::nothrow) _PngDecoder());
249                 break;
250
251         case IMG_FORMAT_GIF:
252                 pDec.reset( new (std::nothrow) _GifDecoder());
253                 break;
254
255         case IMG_FORMAT_BMP:
256                 pDec.reset( new (std::nothrow) _BmpDecoder());
257                 break;
258
259         case IMG_FORMAT_TIFF:
260                 pDec.reset( new (std::nothrow) _TiffDecoder());
261                 break;
262
263         case IMG_FORMAT_WBMP:
264                 pDec.reset( new (std::nothrow) _WbmpDecoder());
265                 break;
266
267         default:
268                 r = E_UNSUPPORTED_FORMAT;
269                 break;
270         }
271
272         //__imageFormat = srcFormat;
273         if (pDec.get() == null && r == E_SUCCESS)
274         {
275                 r = E_OUT_OF_MEMORY;
276         }
277         SetLastResult(r);
278         return pDec.release();
279 }
280
281
282 result
283 _ImageDecoder::Construct(const Tizen::Base::String& srcPath,
284                                                  MediaPixelFormat pixelFormat,
285                                                  ImageFormat imgFormat, bool autoRotate)
286 {
287         result r = E_SUCCESS;
288         std::unique_ptr<ByteBuffer> pBuf;
289
290         // File to Buffer
291         pBuf.reset(_MediaUtil::FileToBufferN(srcPath));
292         SysTryReturn(NID_MEDIA, pBuf.get() != null, GetLastResult(), GetLastResult(),
293                 "[%s] Propagated.", GetErrorMessage(GetLastResult()));
294
295         r = Construct(*pBuf.get(), pixelFormat, imgFormat);
296         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagated.", GetErrorMessage(r));
297
298         if (autoRotate == true)
299         {
300                 __autoRotate = true;
301                 _ExifUtil imgExif;
302                 imgExif.Construct(pBuf->GetPointer(), pBuf->GetCapacity());
303                 imgExif.GetValue(EXIF_TAG_IMAGE_ORIENTATION, __orientationInfo);
304                 // imgExif.GetValue() will return "r = E_OBJ_NOT_FOUND" if it could not be found exif infomation.
305                 // However, the result should be decided by result of construct in this function.
306                 SetLastResult(E_SUCCESS);
307         }
308         return r;
309 }
310
311 result
312 _ImageDecoder::Construct(const Tizen::Base::ByteBuffer& srcBuf,
313                                                  MediaPixelFormat pixelFormat,
314                                                  ImageFormat imgFormat)
315 {
316         result r = E_SUCCESS;
317
318         SysTryReturnResult(NID_MEDIA, __pDec.get() == null, E_INVALID_STATE, "Already constructed");
319         SysTryCatch(NID_MEDIA,
320                 (pixelFormat == MEDIA_PIXEL_FORMAT_RGB565LE)|| (pixelFormat == MEDIA_PIXEL_FORMAT_BGRA8888) ||
321                 (pixelFormat == MEDIA_PIXEL_FORMAT_RGBA8888), r = E_INVALID_ARG, E_INVALID_ARG,
322                 "[E_INVALID_ARG] pixelFormat:%d", pixelFormat);
323
324         SysTryCatch(NID_MEDIA, &srcBuf != null && srcBuf.GetCapacity() > 0,
325                 r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND,
326                 "[E_OBJ_NOT_FOUND] buf:0x%x, %d", &srcBuf, &srcBuf ? srcBuf.GetCapacity() : 0);
327
328         __pixelFormat = pixelFormat;
329
330         __pSrcBuf.reset(new (std::nothrow) ByteBuffer());
331         SysTryCatch(NID_MEDIA, __pSrcBuf.get() != null, , r, "[%s] Propagated.", GetErrorMessage(r));
332         r = __pSrcBuf->Construct(srcBuf);
333         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagated.", GetErrorMessage(r));
334
335         __imgFormat = _ImageUtil::GetImageFormat(srcBuf);
336
337         SysTryCatch(NID_MEDIA,
338                 (__imgFormat > IMG_FORMAT_NONE) && (__imgFormat <= IMG_FORMAT_WBMP),
339                 r = E_UNSUPPORTED_FORMAT, E_UNSUPPORTED_FORMAT, "[%s] Propagated.",
340                 GetErrorMessage(GetLastResult()));
341
342         // Create decoder
343         __pDec.reset(CreateDecoderN(__imgFormat));
344         SysTryCatch(NID_MEDIA, __pDec.get() != null, r = GetLastResult(), r,
345                 "[%s] Could not create decoder for image format %d.",
346                 GetErrorMessage(r), __imgFormat);
347
348         // Decoder construction
349         r = __pDec->Construct((byte*) __pSrcBuf->GetPointer(), __pSrcBuf->GetCapacity(), pixelFormat);
350         // TODO: enhance me. turbo jpeg construction failed.
351         if (IsFailed(r) && __imgFormat == IMG_FORMAT_JPG)
352         {
353                 __pDec.reset(new (std::nothrow) _JpegDecoder());
354                 SysTryCatch(NID_MEDIA, __pDec.get() != null, r = GetLastResult(), r,
355                         "[%s] Could not create decoder for image format %d.",
356                         GetErrorMessage(r), __imgFormat);
357
358                 // Decoder construction
359                 r = __pDec->Construct((byte*) __pSrcBuf->GetPointer(), __pSrcBuf->GetCapacity(), pixelFormat);
360         }
361         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagated.", GetErrorMessage(r));
362
363         // Get original dimension
364         r = __pDec->GetDimension(__orgDim.width, __orgDim.height);
365         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagated.", GetErrorMessage(r));
366         __outDim.width = __orgDim.width;
367         __outDim.height = __orgDim.height;
368
369 CATCH:
370         return r;
371 }
372
373 byte*
374 _ImageDecoder::DecodeN(int& outLength, ImageScalingMethod scalingMethod)
375 {
376         result r = E_SUCCESS;
377         int rawLength = 0;
378         std::unique_ptr<byte[]> pOutBuf;
379         std::unique_ptr<byte[]> pRawBuf;
380         std::unique_ptr<byte[]> pDstBuf;
381         SysTryReturn(NID_MEDIA, __pDec.get() != null, null, E_INVALID_STATE, "Not yet constructed");
382
383         // Decode
384         pRawBuf.reset(__pDec->DecodeN(rawLength));
385         SysTryReturn(NID_MEDIA, pRawBuf.get() != null, null, GetLastResult(),
386                 "[%s] buffer is null (%x), buffer length is %d.",
387                 GetErrorMessage(GetLastResult()),pRawBuf.get(), rawLength);
388
389         // Get working dimension
390         if ((__outDim.width == 0) && (__outDim.height == 0))
391         {
392                 __outDim.width = __orgDim.width;
393                 __outDim.height = __orgDim.height;
394         }
395
396         // if no need to convert.
397         if ((__pDec->GetPixelFormat() == __pixelFormat)
398                 && (__orgDim.width == __outDim.width)
399                 && (__orgDim.height == __outDim.height))
400         {
401                 pOutBuf.swap(pRawBuf);
402                 outLength = rawLength;
403         }
404         else
405         {
406                 _ColorConverter cvt;
407
408                 // Converter construction
409                 r = cvt.Construct(__pDec->GetPixelFormat(), __orgDim.width, __orgDim.height,
410                                                   __pixelFormat, __outDim.width, __outDim.height, scalingMethod);
411                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
412
413                 // Convert to output format
414                 pOutBuf.reset(cvt.ConvertN(pRawBuf.get(), rawLength, outLength));
415                 r = GetLastResult();
416                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
417         }
418
419         if (__autoRotate == true)
420         {
421                 int dstWidth = 0;
422                 int dstHeight = 0;
423
424                 if (__orientationInfo == EXIF_ORIENTATION_TOP_LEFT || __orientationInfo == 0)
425                 {
426                         SetLastResult(E_SUCCESS);
427                         return pOutBuf.release();
428                 }
429
430                 if (__orientationInfo > EXIF_ORIENTATION_LEFT_BOTTOM || __orientationInfo  < EXIF_ORIENTATION_TOP_LEFT)
431                 {
432                         SetLastResult(E_SUCCESS);
433                         return pOutBuf.release();
434                 }
435
436                 pDstBuf.reset(new (std::nothrow) byte[outLength]);
437                 SysTryReturn(NID_MEDIA, pDstBuf.get() != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY]");
438
439                 ImageRotationType rotateType = _IMAGE_ROTATE_FLIP_MAP[__orientationInfo].rotateType;
440                 ImageFlipType flipType = _IMAGE_ROTATE_FLIP_MAP[__orientationInfo].flipType;
441
442                 pDstBuf.reset(_ImageUtil::RotateN(pOutBuf.get(), __pixelFormat, __outDim.width, __outDim.height, rotateType, dstWidth, dstHeight));
443                 r = GetLastResult();
444                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] _ImageUtil:Resize", GetErrorMessage(r));
445
446                 __outDim.width = dstWidth;
447                 __outDim.height = dstHeight;
448
449                 pOutBuf.swap(pDstBuf);
450                 if (flipType != IMAGE_FLIP_NONE)
451                 {
452                         pDstBuf.reset(_ImageUtil::FlipN(pOutBuf.get(), __pixelFormat, __outDim.width, __outDim.height, flipType));
453                         r = GetLastResult();
454                         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] _ImageUtil:Flip", GetErrorMessage(r));
455
456                         pOutBuf.swap(pDstBuf);
457                 }
458         }
459         SetLastResult(E_SUCCESS);
460         return pOutBuf.release();
461 }
462
463 // TODO: Change return type to ByteBuffer*
464
465 Tizen::Base::ByteBuffer*
466 _ImageDecoder::DecodeN(void)
467 {
468         result r = E_SUCCESS;
469         int outLength = 0;
470         std::unique_ptr<byte[]> pTmpBuf;
471         std::unique_ptr<ByteBuffer> pByteBuf(new (std::nothrow) ByteBuffer());
472
473         SysTryReturn(NID_MEDIA, __pDec.get() != null, null, E_INVALID_STATE, "Not yet constructed");
474
475         pTmpBuf.reset(DecodeN(outLength));
476         SysTryReturn(NID_MEDIA, pTmpBuf.get() != null, null, GetLastResult(), "[%s] Propagated.", GetErrorMessage(GetLastResult()));
477
478         r = pByteBuf->Construct(outLength);
479         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r,
480                 "[%s] Propagated. Could not construct Bytebuffer of size %d",
481                 GetErrorMessage(r), outLength);
482
483         r = pByteBuf->SetArray((byte*) pTmpBuf.get(), 0, outLength);
484         SysTryReturn(NID_MEDIA, r == E_SUCCESS, null, r, "[%s] Propagated.", GetErrorMessage(r));
485         pByteBuf->Flip();
486
487         SetLastResult(E_SUCCESS);
488         return pByteBuf.release();
489 }
490
491 ImageFormat
492 _ImageDecoder::GetImageFormat(void) const
493 {
494         return __imgFormat;
495 }
496
497 result
498 _ImageDecoder::SetDecodingRegion(int x, int y, int width, int height)
499 {
500         SysTryReturnResult(NID_MEDIA, __pDec.get() != null, E_INVALID_STATE, "Not yet constructed");
501         result r = E_SUCCESS;
502
503         r = __pDec->SetDecodingRegion(x, y, width, height);
504         if (r == E_SUCCESS)
505         {
506                 __outDim.width = width;
507                 __outDim.height = height;
508                 __orgDim.width = width;
509                 __orgDim.height = height;
510         }
511         return r;
512 }
513
514 result
515 _ImageDecoder::GetDimension(int &width, int &height) const
516 {
517         SysTryReturnResult(NID_MEDIA, __pDec.get() != null, E_INVALID_STATE, "Not yet constructed");
518
519         width = __outDim.width;
520         height = __outDim.height;
521
522         return E_SUCCESS;
523 }
524
525 MediaPixelFormat
526 _ImageDecoder::GetPixelFormat(void) const
527 {
528         return __pixelFormat;
529 }
530
531 result
532 _ImageDecoder::GetValue(const Tizen::Base::String& key, Tizen::Base::Object &value)
533 {
534         SysTryReturnResult(NID_MEDIA, __pDec.get() != null, E_INVALID_STATE, "Not yet constructed");
535
536         return __pDec->GetValue(key, value);
537 }
538
539 result
540 _ImageDecoder::SetOutputDimension(int width, int height, bool keepAspectRatio)
541 {
542         if (width == 0 || height == 0 || __orgDim.width == 0 ||
543                 __orgDim.height == 0 || keepAspectRatio == false)
544         {
545                 __outDim.width = width;
546                 __outDim.height = height;
547         }
548         else    // keep aspect ratio
549         {
550                 double xRatio = Integer(width).ToDouble() / Integer(__orgDim.width).ToDouble();
551                 double yRatio = Integer(height).ToDouble() / Integer(__orgDim.height).ToDouble();
552                 if (xRatio >= 1.0 || yRatio >= 1.0)
553                 {
554                         __outDim.width = __orgDim.width;
555                         __outDim.height = __orgDim.height;
556                 }
557                 else if (xRatio < yRatio)
558                 {
559                         __outDim.width = (int)(__orgDim.width * yRatio);
560                         __outDim.height = height;
561                 }
562                 else
563                 {
564                         __outDim.width = width;
565                         __outDim.height = (int)(__orgDim.height*xRatio);
566                 }
567         }
568         return E_SUCCESS;
569 }
570
571 }} // Tizen::Media