Init Tizen 2.2.1
[framework/osp/image-core.git] / src / FMedia_JpegDecoder.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_JpegDecoder.cpp
20  * @brief This file contains the implementation of _JpegDecoder class.
21  */
22 #include <stdio.h>
23 #include <setjmp.h>
24 #include <jpeglib.h>
25 #include <stdlib.h>
26 #include <FMediaImageTypes.h>
27 #include <FBaseSysLog.h>
28 #include "FMedia_JpegDecoder.h"
29
30 namespace Tizen { namespace Media
31 {
32
33 _JpegDecoder::_JpegDecoder(void)
34 {
35         __pSrcBuf = null;
36         __srcBufSize = 0;
37         __srcWidth = 0;
38         __srcHeight = 0;
39         __decodingRectX = 0;
40         __decodingRectY = 0;
41         __decodingRectWidth = 0;
42         __decodingRectHeight = 0;
43         __isDecodeRegionEnabled = false;
44         __scale = 0;
45         __pDec = null;
46         __pErr = null;
47         __pJmp = null;
48 }
49
50 _JpegDecoder::~_JpegDecoder(void)
51 {
52         // SAFE_DELETE_ARRAY(__pSrcBuf);
53         if (__pDec != null)
54         {
55                 jpeg_destroy_decompress(__pDec);
56         }
57
58         if (__pDec)
59         {
60                 delete __pDec;
61         }
62         if (__pErr)
63         {
64                 delete __pErr;
65         }
66         if (__pJmp)
67         {
68                 delete __pJmp;
69         }
70 }
71
72 void
73 _JpegDecoder::JpegErrorExitStatic(struct jpeg_common_struct * pDecInfo)
74 {
75         if (pDecInfo != null)
76         {
77                 _JpegDecoder *pDec = (_JpegDecoder*)pDecInfo->client_data;
78                 if (pDec)
79                 {
80                         pDec->JpegErrorExit();
81                 }
82         }
83 }
84
85 void
86 _JpegDecoder::JpegErrorExit(void)
87 {
88         longjmp(__pJmp, 1);
89 }
90
91 result
92 _JpegDecoder::Construct(const byte* buffer, int length, MediaPixelFormat pixelFormat)
93 {
94         result r = E_SUCCESS;
95
96         SysTryReturnResult(NID_MEDIA, __pDec == null, E_INVALID_STATE, "Already constructed");
97
98         // TODO: do not copy the source data
99         //__pSrcBuf = new (std::nothrow) byte[length];
100         //SysTryCatch(NID_MEDIA, __pSrcBuf != null, r = E_SYSTEM, E_SYSTEM,
101         //                 "[E_SYSTEM] new byte:%d", length);
102         // memcpy(__pSrcBuf, buffer, length);
103         __pSrcBuf = (byte*)buffer;
104         __srcBufSize = length;
105
106         __pDec = new (std::nothrow) jpeg_decompress_struct;
107         SysTryCatch(NID_MEDIA, __pDec != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
108                            "[E_OUT_OF_MEMORY] new ", sizeof(jpeg_decompress_struct));
109         __pErr = new (std::nothrow) jpeg_error_mgr;
110         SysTryCatch(NID_MEDIA, __pErr != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
111                            "[E_OUT_OF_MEMORY] new ", sizeof(jpeg_error_mgr));
112         __pJmp = new (std::nothrow) __jmp_buf_tag;
113         SysTryCatch(NID_MEDIA, __pJmp != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
114                            "[E_OUT_OF_MEMORY] new ", sizeof(__jmp_buf_tag));
115
116         memset(__pDec, 0, sizeof(jpeg_decompress_struct));
117         memset(__pErr, 0, sizeof(jpeg_error_mgr));
118         memset(__pJmp, 0, sizeof(__jmp_buf_tag));
119
120         // Initialize
121         __pDec->err = jpeg_std_error(__pErr);
122         __pErr->error_exit = JpegErrorExitStatic;
123         __pDec->client_data = this;
124
125         SysTryCatch(NID_MEDIA, !setjmp(__pJmp), r = E_INVALID_DATA, E_INVALID_DATA,
126                            "[E_INVALID_DATA] error jump");
127
128         jpeg_create_decompress(__pDec);
129
130         // Specify data source for decompression
131         jpeg_mem_src(__pDec, (JOCTET*) __pSrcBuf, __srcBufSize);
132
133         // Read file header, set default decompression parameters
134         jpeg_read_header(__pDec, TRUE);
135
136         __srcWidth = __pDec->image_width;
137         __srcHeight = __pDec->image_height;
138
139         return E_SUCCESS;
140
141 CATCH:
142         //SAFE_DELETE_ARRAY(__pSrcBuf);
143         if (__pDec)
144         {
145                 jpeg_destroy_decompress(__pDec);
146         }
147         return r;
148 }
149
150 byte*
151 _JpegDecoder::DecodeN(int& length)
152 {
153         int buffSize = 0;
154         int planarSize = 0;
155         int h = 0;
156         byte* pReturnBuf = null;
157         int outY = 0;
158         int outX = 0;
159         byte* outBuf = null;
160         result r = E_SUCCESS;
161
162         SysTryCatch(NID_MEDIA, !setjmp(__pJmp), r = E_INVALID_DATA, E_INVALID_DATA,
163                            "[E_INVALID_DATA] error jump");
164
165         // Set decoding option
166         if (__pDec->jpeg_color_space == JCS_GRAYSCALE)
167         {
168                 __pDec->out_color_space = JCS_GRAYSCALE;
169         }
170         else if (__pDec->jpeg_color_space == JCS_YCCK) // YCCK
171         {
172                 __pDec->out_color_space = JCS_YCCK;
173         }
174         else // YUV444
175         {
176                 __pDec->out_color_space = JCS_YCbCr;
177         }
178
179         // Start decompressor
180         jpeg_start_decompress(__pDec);
181
182         // Write output buffer
183         __srcWidth = __pDec->output_width;
184         __srcHeight = __pDec->output_height;
185
186         if (__pDec->output_components == 1)  // for grayscale
187         {
188                 if (__isDecodeRegionEnabled == true)
189                 {
190                         int row_stride = __pDec->output_width;
191                         buffSize = __decodingRectWidth * __decodingRectHeight * 3;
192                         length = buffSize;
193                         JSAMPARRAY buffer = (*__pDec->mem->alloc_sarray)((struct jpeg_common_struct *) __pDec, JPOOL_IMAGE, row_stride, 1);
194
195                         pReturnBuf = new (std::nothrow) byte[buffSize];
196                         SysTryCatch(NID_MEDIA, pReturnBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
197                            "[E_OUT_OF_MEMORY] Could not allocate %d bytes for output.", buffSize);
198
199                         // Initialize cb and cr to 128, since they need not be considered for gray scale image.
200                         memset(pReturnBuf, 128, buffSize);
201                         outBuf = pReturnBuf;
202
203                         while (__pDec->output_scanline < (__decodingRectY + __decodingRectHeight))
204                         {
205                                 jpeg_read_scanlines(__pDec, buffer, 1);
206                                 if (h >= __decodingRectY)
207                                 {
208                                         outX = 0;
209                                         for (int x = __decodingRectX; x < __decodingRectX + __decodingRectWidth; x++)
210                                         {
211                                                 JSAMPLE* p = buffer[0] + x;
212
213                                                 // YUV444  -> YUV444p
214                                                 pReturnBuf[(__decodingRectWidth * outY) + outX] = p[0]; // Y
215                                                 outX++;
216                                         }
217                                         outY++;
218                                 }
219                         }
220                 }
221                 else // if not decoding a region
222                 {
223                         int row_stride = __pDec->output_width;
224                         buffSize = __pDec->output_width * __pDec->output_height * 3;
225                         length = buffSize;
226                         JSAMPARRAY buffer = (*__pDec->mem->alloc_sarray)((struct jpeg_common_struct *) __pDec, JPOOL_IMAGE, row_stride, 1);
227
228                         pReturnBuf = new (std::nothrow) byte[buffSize];
229                         SysTryCatch(NID_MEDIA, pReturnBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
230                            "[E_OUT_OF_MEMORY] Could not allocate %d bytes for output.", buffSize);
231
232                         // Initialize cb and cr to 128, since they need not be considered for gray scale image.
233                         memset(pReturnBuf, 128, buffSize);
234                         outBuf = pReturnBuf;
235
236                         while (__pDec->output_scanline < __pDec->output_height)
237                         {
238                                 jpeg_read_scanlines(__pDec, buffer, 1);
239
240                                 for (unsigned int x = 0; x < __pDec->output_width; x++)
241                                 {
242                                                 JSAMPLE* p = buffer[0] + x;
243                                         // YUV444  -> YUV444p
244                                         pReturnBuf[(__pDec->output_width * h) + x] = p[0]; // Y
245                                 }
246                                 h++;
247                         }
248                 }
249         }
250         else if (__pDec->output_components == 4) // YCCK. Need to handle CMYK also.
251         {
252                 if (__isDecodeRegionEnabled == true)
253                 {
254                         buffSize = __decodingRectWidth * __decodingRectHeight * 3;
255                         planarSize = (__decodingRectWidth * __decodingRectHeight);
256                         length = buffSize;
257                         int row_stride = __pDec->output_width * __pDec->output_components;
258                         JSAMPARRAY buffer = (*__pDec->mem->alloc_sarray)((struct jpeg_common_struct *) __pDec, JPOOL_IMAGE, row_stride, 1);
259
260                         pReturnBuf = new (std::nothrow) byte[buffSize];
261                         SysTryCatch(NID_MEDIA, pReturnBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
262                            "[E_OUT_OF_MEMORY] Could not allocate %d bytes for output.", buffSize);
263
264                         memset(pReturnBuf, 0, buffSize);
265                         outBuf = pReturnBuf;
266
267                         while (__pDec->output_scanline < (__decodingRectY + __decodingRectHeight))
268                         {
269                                 jpeg_read_scanlines(__pDec, buffer, 1);
270                                 if (h >= __decodingRectY)
271                                 {
272                                         outX = 0;
273                                         for (int x = __decodingRectX; x < __decodingRectX + __decodingRectWidth; x++)
274                                         {
275                                                 JSAMPLE* p = buffer[0] + (__pDec->output_components * x);
276
277                                                 // YCCK -> YUV444p
278                                                 pReturnBuf[(__decodingRectWidth * outY) + outX] = 255 - p[0];                                   // Y
279                                                 pReturnBuf[(__decodingRectWidth * outY) + planarSize + outX] = 255 - p[1];              // Cb
280                                                 pReturnBuf[(__decodingRectWidth * outY) + (planarSize * 2) + outX] = 255 - p[2];// Cr
281                                                 outX++;
282                                         }
283                                         outY++;
284                                 }
285                                 h++;
286                         }
287                 }
288                 else
289                 {
290                         buffSize = __pDec->output_width * __pDec->output_height * 3;
291                         planarSize = __pDec->output_width * __pDec->output_height;
292                         length = buffSize;
293                         int row_stride = __pDec->output_width * __pDec->output_components;
294                         JSAMPARRAY buffer = (*__pDec->mem->alloc_sarray)((struct jpeg_common_struct *) __pDec, JPOOL_IMAGE, row_stride, 1);
295
296                         pReturnBuf = new (std::nothrow) byte[buffSize];
297                         SysTryCatch(NID_MEDIA, pReturnBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
298                            "[E_OUT_OF_MEMORY] Could not allocate %d bytes for output.", buffSize);
299
300                         memset(pReturnBuf, 0, buffSize);
301                         outBuf = pReturnBuf;
302
303                         while (__pDec->output_scanline < __pDec->output_height)
304                         {
305                                 jpeg_read_scanlines(__pDec, buffer, 1);
306
307                                 for (unsigned int x = 0; x < __pDec->output_width; x++)
308                                 {
309                                         JSAMPLE* p = buffer[0] + (__pDec->output_components * x);
310
311                                         // YCCK -> YUV444p
312                                         pReturnBuf[(__pDec->output_width * h) + x] = 255 - p[0];                                                // Y
313                                         pReturnBuf[(__pDec->output_width * h) + planarSize + x] = 255 - p[1];                   // Cb
314                                         pReturnBuf[(__pDec->output_width * h) + (planarSize * 2) + x] = 255 - p[2];             // Cr
315                                 }
316                                 h++;
317                         }
318                 }
319         }
320         else // (__pDec->output_components == 3) YUV444
321         {
322                 if (__isDecodeRegionEnabled == true)
323                 {
324                         buffSize = __decodingRectWidth * __decodingRectHeight * __pDec->output_components;
325                         planarSize = (__decodingRectWidth * __decodingRectHeight);
326                         length = buffSize;
327                         int row_stride = __pDec->output_width * __pDec->output_components;
328                         JSAMPARRAY buffer = (*__pDec->mem->alloc_sarray)((struct jpeg_common_struct *) __pDec, JPOOL_IMAGE, row_stride, 1);
329
330                         pReturnBuf = new (std::nothrow) byte[buffSize];
331                         SysTryCatch(NID_MEDIA, pReturnBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
332                            "[E_OUT_OF_MEMORY] Could not allocate %d bytes for output.", buffSize);
333
334                         memset(pReturnBuf, 0, buffSize);
335                         outBuf = pReturnBuf;
336
337                         while (__pDec->output_scanline < (__decodingRectY + __decodingRectHeight))
338                         {
339                                 jpeg_read_scanlines(__pDec, buffer, 1);
340                                 if (h >= __decodingRectY)
341                                 {
342                                         outX = 0;
343                                         for (int x = __decodingRectX; x < __decodingRectX + __decodingRectWidth; x++)
344                                         {
345                                                 JSAMPLE* p = buffer[0] + 3 * x;
346
347                                                 // YUV444  -> YUV444p
348                                                 pReturnBuf[(__decodingRectWidth * outY) + outX] = p[0];                                         // Y
349                                                 pReturnBuf[(__decodingRectWidth * outY) + planarSize + outX] = p[1];            // Cb
350                                                 pReturnBuf[(__decodingRectWidth * outY) + (planarSize * 2) + outX] = p[2];      // Cr
351                                                 outX++;
352                                         }
353                                         outY++;
354                                 }
355                                 h++;
356                         }
357                 }
358                 else
359                 {
360                         buffSize = __pDec->output_width * __pDec->output_height * __pDec->output_components;
361                         planarSize = __pDec->output_width * __pDec->output_height;
362                         length = buffSize;
363                         int row_stride = __pDec->output_width * __pDec->output_components;
364                         JSAMPARRAY buffer = (*__pDec->mem->alloc_sarray)((struct jpeg_common_struct *) __pDec, JPOOL_IMAGE, row_stride, 1);
365
366                         pReturnBuf = new (std::nothrow) byte[buffSize];
367                         SysTryCatch(NID_MEDIA, pReturnBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
368                            "[E_OUT_OF_MEMORY] Could not allocate %d bytes for output.", buffSize);
369
370                         memset(pReturnBuf, 0, buffSize);
371                         outBuf = pReturnBuf;
372
373                         while (__pDec->output_scanline < __pDec->output_height)
374                         {
375                                 jpeg_read_scanlines(__pDec, buffer, 1);
376
377                                 for (unsigned int x = 0; x < __pDec->output_width; x++)
378                                 {
379                                         JSAMPLE* p = buffer[0] + 3 * x;
380
381                                         // YUV444  -> YUV444p
382                                         pReturnBuf[(__pDec->output_width * h) + x] = p[0];                                              // Y
383                                         pReturnBuf[(__pDec->output_width * h) + planarSize + x] = p[1];                 // Cb
384                                         pReturnBuf[(__pDec->output_width * h) + (planarSize * 2) + x] = p[2];   // Cr
385                                 }
386                                 h++;
387                         }
388                 }
389         }
390
391         pReturnBuf = null;
392         SetLastResult(E_SUCCESS);
393 CATCH:
394         return outBuf;
395 }
396
397 result
398 _JpegDecoder::SetDecodingRegion(int x, int y, int width, int height)
399 {
400         SysTryReturnResult(NID_MEDIA, ((x >= 0) && (y >= 0) && ((x + width) <= __srcWidth) && ((y + height) <= __srcHeight)), E_INVALID_ARG,
401                         "Invalid Input - %d %d %d %d src_width - %d src_height - %d", x, y, width, height, __srcWidth, __srcHeight);
402         __decodingRectX = x;
403         __decodingRectY = y;
404         __decodingRectWidth = width;
405         __decodingRectHeight = height;
406         __isDecodeRegionEnabled = true;
407         return E_SUCCESS;
408 }
409
410 result
411 _JpegDecoder::GetDimension(int& width, int& height)
412 {
413         width = __srcWidth;
414         height = __srcHeight;
415
416         return E_SUCCESS;
417 }
418
419 MediaPixelFormat
420 _JpegDecoder::GetPixelFormat(void)
421 {
422         return MEDIA_PIXEL_FORMAT_YUV444P;
423 }
424
425 result
426 _JpegDecoder::SetScaleDown(int scaleDown)
427 {
428         __scale = scaleDown;
429         return E_SUCCESS;
430 }
431
432 result
433 _JpegDecoder::GetValue(const Tizen::Base::String& key, Tizen::Base::Object &value)
434 {
435         return E_UNSUPPORTED_OPERATION;
436 }
437
438 }} // Tizen::Media