Added transparency support in RGB565 bitmap outputs, for gif decoder.
[framework/osp/image-core.git] / src / FMedia_TiffDecoder.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_TiffDecoder.c
20  * @brief  This file contains the implementation of _TiffDecoder class.
21  */
22 #include <unique_ptr.h>
23 #include <FMediaImageTypes.h>
24 #include <FBaseSysLog.h>
25 #include "FMedia_TiffDecoder.h"
26
27 using namespace Tizen::Io;
28 using namespace Tizen::Base::Collection;
29
30 namespace Tizen { namespace Media
31 {
32
33 _TiffDecoder::_TiffDecoder(void)
34         : __pTiffMemory(null)
35         , __pTiffHandle(null)
36         , __width(0)
37         , __height(0)
38 {
39 }
40
41 _TiffDecoder::~_TiffDecoder(void)
42 {
43         if (__pTiffMemory->pData != null)
44         {
45                 delete[] __pTiffMemory->pData;
46                 __pTiffMemory->pData = null;
47         }
48
49         if (__pTiffHandle != null)
50         {
51                 TIFFClose(__pTiffHandle);
52                 __pTiffHandle = null;
53         }
54 }
55
56 // Tiff call back functions for buffer handling.
57 tsize_t
58 _TiffDecoder::TiffCbReadData(thandle_t handle, tdata_t pData, tsize_t size)
59 {
60         _TiffMemory *pTiffMem = (_TiffMemory*)handle;
61         if (size <= pTiffMem->left)
62         {
63                 unsigned char *pFrom = pTiffMem->pData + pTiffMem->point;
64                 memcpy(pData, pFrom, size);
65                 pTiffMem->left = pTiffMem->left - size;
66                 pTiffMem->point = pTiffMem->point + size;
67                 return size;
68         }
69         return 0L;
70 }
71
72 toff_t
73 _TiffDecoder::TiffCbSeekData(thandle_t handle, toff_t amount, int indication)
74 {
75         _TiffMemory *pTiffMem = (_TiffMemory*)handle;
76         switch (indication)
77         {
78         case SEEK_SET:
79                 if (amount <= pTiffMem->size)
80                 {
81                         pTiffMem->point = amount;
82                         pTiffMem->left = pTiffMem->size - amount;
83                         return amount;
84                 }
85                 else
86                 {
87                         return 0ULL;
88                 }
89                 break;
90         case SEEK_CUR:
91                 if (pTiffMem->left - amount <= (signed int)pTiffMem->size || pTiffMem->left >= amount)
92                 {
93                         pTiffMem->point = pTiffMem->point + amount;
94                         pTiffMem->left = pTiffMem->left - amount;
95                         return amount;
96                 }
97                 else
98                 {
99                         return 0ULL;
100                 }
101                 break;
102         case SEEK_END:
103                 if (amount >= -pTiffMem->size && amount <= 0)
104                 {
105                         pTiffMem->point = pTiffMem->size - amount;
106                         pTiffMem->left = amount;
107                         return amount;
108                 }
109                 else
110                 {
111                         return 0ULL;
112                 }
113                 break;
114         default:
115                 return 0ULL;
116                 break;
117         }
118
119 }
120
121 toff_t
122 _TiffDecoder::TiffCbGetSize(thandle_t handle)
123 {
124         _TiffMemory *pTiffMem = (_TiffMemory*)handle;
125         return pTiffMem->size;
126 }
127
128 int
129 _TiffDecoder::TiffCbMemClose(thandle_t)
130 {
131         // Unhandled.
132         return 0;
133 }
134
135 int
136 _TiffDecoder::TiffCbMemMapFileproc(thandle_t, tdata_t*, toff_t*)
137 {
138         // Unhandled.
139         return 0;
140 }
141
142 void
143 _TiffDecoder::TiffCbMemUnMapFileProc(thandle_t, tdata_t, toff_t)
144 {
145         // Unhandled.
146         return;
147 }
148
149 // _TiffDecoder functions.
150 result
151 _TiffDecoder::Construct(const byte* buffer, int length, MediaPixelFormat pixelFormat)
152 {
153         result r = E_SUCCESS;
154
155         SysTryReturnResult(NID_MEDIA, buffer != null, E_INVALID_ARG,
156                 "Input buffer is null");
157
158         __pTiffMemory = std::unique_ptr<_TiffMemory> (new (std::nothrow)_TiffMemory);
159         SysTryReturnResult(NID_MEDIA, __pTiffMemory.get() != null, E_OUT_OF_MEMORY,
160                 "Failed to create _TiffMemory structure.");
161
162         __pTiffMemory->pData = new (std::nothrow) byte[length];
163         SysTryCatch(NID_MEDIA, __pTiffMemory->pData != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
164                 "[E_OUT_OF_MEMORY] Failed to allocate _TiffMemory->pData: %d bytes.", length);
165
166         memcpy(__pTiffMemory->pData, buffer, length);
167
168         __pTiffMemory->size = length;
169         __pTiffMemory->left = length;
170         __pTiffMemory->point = 0;
171
172         __pTiffHandle = TIFFClientOpen("dummy", "r", (void *)__pTiffMemory.get(),
173                         TiffCbReadData, TiffCbReadData,
174                         TiffCbSeekData, TiffCbMemClose,
175                         TiffCbGetSize,
176                         TiffCbMemMapFileproc, TiffCbMemUnMapFileProc);
177         SysTryCatch(NID_MEDIA, __pTiffHandle != null, r = E_SYSTEM, E_SYSTEM,
178                 "[E_SYSTEM] TIFFClientOpen failed.");
179
180         TIFFGetField(__pTiffHandle, TIFFTAG_IMAGEWIDTH, &__width);
181         SysTryCatch(NID_MEDIA, __width > 0, r = E_SYSTEM, E_SYSTEM,
182                 "[E_SYSTEM] Check image, width is zero.");
183         TIFFGetField(__pTiffHandle, TIFFTAG_IMAGELENGTH, &__height);
184         SysTryCatch(NID_MEDIA, __height > 0, r = E_SYSTEM, E_SYSTEM,
185                 "[E_SYSTEM] Check image, height is zero.");
186
187         return r;
188
189 CATCH:
190
191                 if (__pTiffMemory->pData != null)
192                 {
193                         delete[] __pTiffMemory->pData;
194                         __pTiffMemory->pData = null;
195                 }
196         return r;
197 }
198
199 byte*
200 _TiffDecoder::DecodeN(int& outLength)
201 {
202         int tiffRet = 0;
203         int row = 0;
204         int rowSize = 0;
205         byte* pTempDstPtr = null;
206         byte* pTempSrcPtr = null;
207         
208         std::unique_ptr<byte[]> pTempDecodeBuf;
209         std::unique_ptr<byte[]> pOutBuf;
210         SysTryReturn(NID_MEDIA, __pTiffHandle != null, null, E_INVALID_STATE,
211                 "Instance is not constructed.");
212
213         outLength = __width * __height * BYTES_PER_PIXEL_RGBA;
214         pTempDecodeBuf.reset(new (std::nothrow) byte[outLength]);
215         SysTryReturn(NID_MEDIA, pTempDecodeBuf.get() != null, null, E_OUT_OF_MEMORY,
216                 "[E_OUT_OF_MEMORY] Could not allocate %d bytes for temp buffer!", outLength);
217
218         pOutBuf.reset(new (std::nothrow) byte[outLength]);
219         SysTryReturn(NID_MEDIA, pOutBuf.get() != null, null, E_OUT_OF_MEMORY,
220                 "[E_OUT_OF_MEMORY] Could not allocate %d bytes for temp buffer!", outLength);
221
222         tiffRet = TIFFReadRGBAImage(__pTiffHandle, __width, __height, (uint32*)pTempDecodeBuf.get(), 0);
223         SysTryReturn(NID_MEDIA, tiffRet == 1, null, E_SYSTEM,
224                 "[E_SYSTEM] TIFFReadRGBAImage failed.");
225
226         rowSize = __width * BYTES_PER_PIXEL_RGBA;
227         pTempDstPtr = pOutBuf.get() + ((__height - 1) * rowSize);
228         pTempSrcPtr = pTempDecodeBuf.get();
229
230         // libtiff returns a vertically flipped image.
231         for (row = 0; row < __height; row++)
232         {
233                 memcpy(pTempDstPtr, pTempSrcPtr, rowSize);
234                 pTempDstPtr -= rowSize;
235                 pTempSrcPtr += rowSize;
236         }
237         SetLastResult(E_SUCCESS);
238         return pOutBuf.release();
239 }
240
241 result
242 _TiffDecoder::SetDecodingRegion(int x, int y, int width, int height)
243 {
244         return E_UNSUPPORTED_OPERATION;
245 }
246
247 result
248 _TiffDecoder::GetDimension(int& width, int& height)
249 {
250         SysTryReturnResult(NID_MEDIA, __pTiffHandle != null, E_INVALID_STATE, "Instance is not constructed.");
251
252         width = __width;
253         height = __height;
254
255         SetLastResult(E_SUCCESS);
256         return E_SUCCESS;
257 }
258
259 MediaPixelFormat
260 _TiffDecoder::GetPixelFormat(void)
261 {
262         MediaPixelFormat pixelFormat = MEDIA_PIXEL_FORMAT_NONE;
263
264         pixelFormat = MEDIA_PIXEL_FORMAT_RGBA8888;
265
266         SetLastResult(E_SUCCESS);
267         return pixelFormat;
268 }
269 }} // Tizen::Media