merge with master
[framework/osp/image-core.git] / src / FMedia_JpegTurboDecoder.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_JpegTurboDecoder.cpp
20 * @brief This file contains the implementation of _JpegTurboDecoder class.
21 */
22 #include <unique_ptr.h>
23 #include <turbojpeg.h>
24 #include <FMediaImageTypes.h>
25 #include <FBaseSysLog.h>
26 #include "FMedia_JpegTurboDecoder.h"
27
28 namespace Tizen { namespace Media
29 {
30
31 _JpegTurboDecoder::_JpegTurboDecoder(void)
32 {
33         __pSrcBuf = null;
34         __srcBufSize = 0;
35         __srcWidth = 0;
36         __srcHeight = 0;
37         __decodingRectX = 0;
38         __decodingRectY = 0;
39         __decodingRectWidth = 0;
40         __decodingRectHeight = 0;
41         __isDecodeRegionEnabled = false;
42         __tjDecodingHandle = null;
43         __tjTransformHandle = null;
44         __scale = 0;
45         __subSamp = TJSAMP_444;
46         __requestPixelFormat = MEDIA_PIXEL_FORMAT_NONE;
47 }
48
49 _JpegTurboDecoder::~_JpegTurboDecoder(void)
50 {
51         if(__tjDecodingHandle)
52         {
53                 tjDestroy(__tjDecodingHandle);
54         }
55         if(__tjTransformHandle)
56         {
57                 tjDestroy(__tjTransformHandle);
58         }
59 }
60
61 result
62 _JpegTurboDecoder::Construct(const byte* buffer, int length, MediaPixelFormat pixelFormat)
63 {
64         result r = E_SUCCESS;
65         int ret;
66
67         __pSrcBuf = const_cast<byte*>(buffer);
68         __srcBufSize = length;
69
70         __requestPixelFormat = pixelFormat;
71
72         __tjDecodingHandle = tjInitDecompress();
73         SysTryCatch(NID_MEDIA, __tjDecodingHandle != null, r = E_SYSTEM, E_SYSTEM,
74                 "[E_SYSTEM] Turbo JPEG InitDecompress failed : %s", tjGetErrorStr());
75
76         ret = tjDecompressHeader2(__tjDecodingHandle, __pSrcBuf, __srcBufSize, &__srcWidth, &__srcHeight, &__subSamp);
77         SysTryCatch(NID_MEDIA, ret == 0 , r = E_SYSTEM, E_SYSTEM,
78                 "[E_SYSTEM] Turbo JPEG DecompressHeader2 failed : %s", tjGetErrorStr());
79
80         __tjTransformHandle = tjInitTransform();
81         SysTryCatch(NID_MEDIA, __tjDecodingHandle != null, r = E_SYSTEM, E_SYSTEM,
82                 "[E_SYSTEM] Turbo JPEG InitTransform failed : %s", tjGetErrorStr());
83
84         return E_SUCCESS;
85
86 CATCH:
87         if ( __tjDecodingHandle )
88         {
89                 tjDestroy(__tjDecodingHandle);
90                 __tjDecodingHandle = null;
91         }
92         if ( __tjTransformHandle )
93         {
94                 tjDestroy(__tjTransformHandle);
95                 __tjTransformHandle = null;
96         }
97         return r;
98 }
99
100 byte*
101 _JpegTurboDecoder::DecodeN(int& outLength)
102 {
103         int buffSize = 0;
104         int ret = 0;
105         int tjPixelFormat = 0;
106         byte* pTransBuf = null;
107         tjtransform cropInfo = {};
108         unsigned long dstSize;
109         std::unique_ptr<byte[]> pOutBuf;
110
111         buffSize = tjBufSize(__srcWidth, __srcHeight, TJSAMP_444);
112         SysTryReturn(NID_MEDIA, buffSize > 0, null, E_INVALID_DATA,
113                 "[E_INVALID_DATA] Decoder returned buffer size (%d).", buffSize);
114
115         pOutBuf.reset(new (std::nothrow) byte[buffSize]);
116         SysTryReturn(NID_MEDIA, pOutBuf.get() != null, null, E_OUT_OF_MEMORY,
117                 "[E_OUT_OF_MEMORY] Could not allocate %d bytes.", buffSize);
118
119         if ( __requestPixelFormat == MEDIA_PIXEL_FORMAT_RGBA8888)
120         {
121                 tjPixelFormat = TJPF_RGBA;
122         }
123         else
124         {
125                 tjPixelFormat = TJPF_BGRA;
126         }
127         if (__isDecodeRegionEnabled == true)
128         {
129                 cropInfo.r.x = __decodingRectX;
130                 cropInfo.r.y = __decodingRectY;
131                 cropInfo.r.w = __decodingRectWidth;
132                 cropInfo.r.h = __decodingRectHeight;
133                 cropInfo.op =  TJXOP_NONE;
134                 cropInfo.options = TJXOPT_CROP;
135
136                 ret = tjTransform(__tjTransformHandle, __pSrcBuf,__srcBufSize, 1, &pTransBuf, &dstSize, &cropInfo, 0);
137                 SysTryReturn(NID_MEDIA, ret == 0, null, E_INVALID_DATA,
138                         "[E_INVALID_DATA] Turbo JPEG Crop Failed : %s", tjGetErrorStr());
139
140                 ret = tjDecompress2(__tjDecodingHandle, pTransBuf, __srcBufSize, pOutBuf.get(), __decodingRectWidth, __decodingRectWidth* tjPixelSize[tjPixelFormat], __decodingRectHeight, tjPixelFormat, 0);
141                 SysTryReturn(NID_MEDIA, ret == 0, null, E_INVALID_DATA,
142                         "[E_INVALID_DATA] Turbo JPEG Decompress Failed : %s", tjGetErrorStr());
143
144                 outLength = __decodingRectWidth * __decodingRectHeight * tjPixelSize[tjPixelFormat];
145         }
146         else
147         {
148                 ret = tjDecompress2(__tjDecodingHandle, __pSrcBuf, __srcBufSize, pOutBuf.get(), __srcWidth, __srcWidth* tjPixelSize[tjPixelFormat], __srcHeight, tjPixelFormat, 0);
149                 SysTryReturn(NID_MEDIA, ret == 0, null, E_INVALID_DATA,
150                         "[E_INVALID_DATA] Turbo JPEG Decompress Failed : %s", tjGetErrorStr());
151                 outLength = __srcWidth * __srcHeight * tjPixelSize[tjPixelFormat];
152         }
153
154         SetLastResult(E_SUCCESS);
155         return pOutBuf.release();
156 }
157
158 result
159 _JpegTurboDecoder::SetDecodingRegion(int x, int y, int width, int height)
160 {
161         SysTryReturnResult(NID_MEDIA, ((x >= 0) && (y >= 0) && ((x + width) <= __srcWidth) && ((y + height) <= __srcHeight)),
162                 E_INVALID_ARG,
163                 "Invalid Input - Check dimensions and coordinates (x, y) = (%d, %d), width (%d), height (%d), Image dimensions (%d x %d)",
164                 x, y, width, height, __srcWidth, __srcHeight);
165         SysTryReturnResult(NID_MEDIA, (!(x%tjMCUWidth[__subSamp]) && !(y%tjMCUHeight[__subSamp])), E_UNSUPPORTED_OPERATION,
166                 "To crop this JPEG image using JpegTurbo decoder, x must be a multiple of %d and y must be a multiple of %d",
167                 tjMCUWidth[__subSamp], tjMCUHeight[__subSamp]);
168         __decodingRectX = x;
169         __decodingRectY = y;
170         __decodingRectWidth = width;
171         __decodingRectHeight = height;
172         __isDecodeRegionEnabled = true;
173         return E_SUCCESS;
174 }
175
176 result
177 _JpegTurboDecoder::GetDimension(int& width, int& height)
178 {
179         width = __srcWidth;
180         height = __srcHeight;
181
182         return E_SUCCESS;
183 }
184
185 MediaPixelFormat
186 _JpegTurboDecoder::GetPixelFormat(void)
187 {
188         if ( __requestPixelFormat == MEDIA_PIXEL_FORMAT_RGBA8888)
189         {
190                 return MEDIA_PIXEL_FORMAT_RGBA8888;
191         }
192         else
193         {
194                 return MEDIA_PIXEL_FORMAT_BGRA8888;
195         }
196 }
197
198 result
199 _JpegTurboDecoder::SetScaleDown(int scaleDown)
200 {
201         __scale = scaleDown;
202         return E_SUCCESS;
203 }
204
205 result
206 _JpegTurboDecoder::GetValue(const Tizen::Base::String& key, Tizen::Base::Object &value)
207 {
208         return E_UNSUPPORTED_OPERATION;
209 }
210
211 }} // Tizen::Media
212