Tizen 2.1 base
[framework/osp/uifw.git] / src / graphics / util / FGrp_UtilPixmap.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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        FGrp_UtilPixmap.cpp
20  * @brief       This is the implementation file for internal util class.
21  *
22  */
23
24 #include <new>
25 #include <memory>
26 #include <cstring>
27
28 #include <unique_ptr.h>
29
30 #include <FBaseDataType.h>
31 #include <FBaseSysLog.h>
32
33 #include "FGrp_UtilTemplate.h"
34 #include "FGrp_UtilPixmap.h"
35
36 using namespace Tizen::Graphics;
37
38 ////////////////////////////////////////////////////////////////////////////////
39 // image manipulation
40
41 _Util::Pixmap::Pixmap()
42 {
43         type = 0;
44         width = 0;
45         height = 0;
46         depth = 0;
47         bytesPerLine = 0,
48         enableColorKey = false;
49         colorKey = 0;
50         enableReplaceColor = false;
51         replaceColor = 0;
52         isOpaque = 0;
53         isPremultiplied = 0;
54         pBitmap = 0;
55         reserved = 0;
56 }
57
58 _Util::Pixmap::Pixmap(int _width, int _height, int _depth, int _bytesPerLine)
59 {
60         type = 0;
61         width = _width;
62         height = _height;
63         depth = _depth;
64         bytesPerLine = _bytesPerLine,
65         enableColorKey = false;
66         colorKey = 0;
67         enableReplaceColor = false;
68         replaceColor = 0;
69         isOpaque = 0;
70         isPremultiplied = 0;
71         pBitmap = 0;
72         reserved = 0;
73
74         if (bytesPerLine == 0)
75         {
76                 bytesPerLine = width * depth / 8;
77         }
78
79         pBitmap = new (std::nothrow) unsigned char[bytesPerLine * height];
80
81         SysTryReturnVoidResult(NID_GRP, pBitmap, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
82
83         // ¸ðµç °ÍÀÌ ¼º°øÇßÀ» ¶§¸¸ 1ÀÇ °ªÀ» °¡Áö°Ô µÈ´Ù.
84         reserved = 1;
85 }
86
87 _Util::Pixmap::Pixmap(int _width, int _height, int _depth, void* _pBitmap, int _bytesPerLine)
88 {
89         type = 0;
90         width = _width;
91         height = _height;
92         depth = _depth;
93         bytesPerLine = _bytesPerLine,
94         enableColorKey = false;
95         colorKey = 0;
96         enableReplaceColor = false;
97         replaceColor = 0;
98         isOpaque = 0;
99         isPremultiplied = 0;
100         pBitmap = (unsigned char*) _pBitmap;
101         reserved = 0;
102
103         if (bytesPerLine == 0)
104         {
105                 bytesPerLine = width * depth / 8;
106         }
107 }
108
109 _Util::Pixmap::Pixmap(PixmapBase& refImage)
110 {
111         memcpy(this, &refImage, sizeof(*this));
112         refImage.reserved = 0;
113 }
114
115 _Util::Pixmap::Pixmap(const PixmapBase& refImage)
116 {
117         memcpy(this, &refImage, sizeof(*this));
118         this->reserved = 0;
119 }
120
121 _Util::Pixmap::Pixmap(const Pixmap& refImage)
122 {
123         memcpy(this, &refImage, sizeof(*this));
124         this->reserved = 0;
125 }
126
127 _Util::Pixmap::~Pixmap()
128 {
129         if (reserved)
130         {
131                 delete[] pBitmap;
132         }
133 }
134
135 _Util::Pixmap&
136 _Util::Pixmap::operator =(const Pixmap& refImage)
137 {
138         if (this == &refImage)
139         {
140                 return *this;
141         }
142
143         PixmapBase::operator =(refImage);
144
145         refImage.reserved = 0;
146
147         return *this;
148 }
149
150 _Util::PixmapBase
151 _Util::Pixmap::GetSubBitmap(long x, long y, long w, long h) const
152 {
153         int x1 = x;
154         int y1 = y;
155         int x2 = x + w;
156         int y2 = y + h;
157
158         x1 = (x1 < 0) ? 0 : x1;
159         y1 = (y1 < 0) ? 0 : y1;
160         x2 = (x2 > width) ? width : x2;
161         y2 = (y2 > height) ? height : y2;
162
163         PixmapBase retImage((PixmapBase &) * this);
164         ((PixmapBase*) this)->reserved = retImage.reserved;
165         retImage.reserved = 0;
166
167         retImage.pBitmap += retImage.bytesPerLine * y1 + x1 * depth / 8;
168         retImage.width = x2 - x1;
169         retImage.height = y2 - y1;
170
171         return retImage;
172 }
173
174 _Util::PixmapBase
175 _Util::Pixmap::GetSubBitmapUnsafe(long x, long y, long w, long h) const
176 {
177         PixmapBase retImage((PixmapBase &) * this);
178         ((PixmapBase*) this)->reserved = retImage.reserved;
179         retImage.reserved = 0;
180
181         retImage.pBitmap += retImage.bytesPerLine * y + x * depth / 8;
182         retImage.width = w;
183         retImage.height = h;
184
185         return retImage;
186 }
187
188 namespace // unnamed
189 {
190
191 template<typename DestPixel, typename SourPixel>
192 inline DestPixel*
193 _ConvertColorFormat(DestPixel* pDest, SourPixel* pSour, int count)
194 {
195         DestPixel* pDestEnd = pDest + count;
196
197         while (pDest < pDestEnd)
198         {
199                 *pDest++ = *pSour++;
200         }
201
202         return pDestEnd;
203 }
204
205 template<>
206 inline unsigned long*
207 _ConvertColorFormat(unsigned long* pDest, unsigned short* pSour, int count)
208 {
209         typedef unsigned short SourPixel;
210         typedef unsigned long DestPixel;
211
212         DestPixel* pDestEnd = pDest + count;
213
214         while (pDest < pDestEnd)
215         {
216                 DestPixel r = (*pSour & 0xF800) >> 8;
217                 DestPixel g = (*pSour & 0x07E0) >> 3;
218                 DestPixel b = (*pSour & 0x001F) << 3;
219
220                 r += (r >> 5);
221                 g += (g >> 6);
222                 b += (b >> 5);
223
224                 *pDest++ = 0xFF000000 | (r << 16) | (g << 8) | (b);
225                 ++pSour;
226         }
227
228         return pDestEnd;
229 }
230
231 template<>
232 inline unsigned short*
233 _ConvertColorFormat(unsigned short* pDest, unsigned long* pSour, int count)
234 {
235         typedef unsigned long SourPixel;
236         typedef unsigned short DestPixel;
237
238         DestPixel* pDestEnd = pDest + count;
239
240         while (pDest < pDestEnd)
241         {
242                 DestPixel r = (DestPixel) ((*pSour & 0xF80000) >> 8);
243                 DestPixel g = (DestPixel) ((*pSour & 0x00FC00) >> 5);
244                 DestPixel b = (DestPixel) ((*pSour & 0x0000F8) >> 3);
245
246                 *pDest++ = r | g | b;
247                 ++pSour;
248         }
249
250         return pDestEnd;
251 }
252
253 template<typename DestPixel, typename SourPixel>
254 DestPixel*
255 ConvertBitmap(const _Util::Pixmap& srcBitmap)
256 {
257         std::unique_ptr<DestPixel[]> buffer(new (std::nothrow) DestPixel[srcBitmap.width * srcBitmap.height]);
258
259         SysTryReturn(NID_GRP, buffer, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
260
261         DestPixel* pDest = (DestPixel*) buffer.get();
262         SourPixel* pSour = (SourPixel*) srcBitmap.pBitmap;
263         long pitch = (srcBitmap.bytesPerLine / sizeof(SourPixel));
264
265         for (int y = 0; y < srcBitmap.height; y++)
266         {
267                 pDest = _ConvertColorFormat(pDest, pSour, srcBitmap.width);
268                 pSour += pitch;
269         }
270
271         return buffer.release();
272 }
273
274 unsigned char*
275 _CreatePremultipliedBuffer(const _Util::Pixmap& srcImage)
276 {
277         typedef unsigned long DestPixel;
278
279         if (srcImage.depth != 32)
280                 return null;
281
282         std::unique_ptr<unsigned char[]> destBuffer(new (std::nothrow) unsigned char[srcImage.width * srcImage.height * sizeof(DestPixel)]);
283
284         DestPixel* pDestBuffer = reinterpret_cast<DestPixel*>(destBuffer.get());
285
286         if (pDestBuffer)
287         {
288                 if (srcImage.bytesPerLine == int(srcImage.width * sizeof(DestPixel)))
289                 {
290                         memcpy(pDestBuffer, srcImage.pBitmap, srcImage.bytesPerLine * srcImage.height);
291                 }
292                 else
293                 {
294                         DestPixel* pSrc = (DestPixel*)srcImage.pBitmap;
295                         DestPixel* pDst = (DestPixel*)pDestBuffer;
296
297                         long srcPitch = (srcImage.bytesPerLine * 8 / srcImage.depth);
298                         long dstPitch = srcImage.width;
299
300                         for (int y = 0; y < srcImage.height; y++)
301                         {
302                                 memcpy(pDst, pSrc, srcImage.width * sizeof(DestPixel));
303                                 pSrc += srcPitch;
304                                 pDst += dstPitch;
305                         }
306                 }
307
308                 DestPixel* p = (DestPixel*)pDestBuffer;
309                 long padding = 0;
310
311                 for (int y = 0; y < srcImage.height; y++)
312                 {
313                         for (int x = 0; x < srcImage.width; x++)
314                         {
315                                 DestPixel a = (*p) & 0xFF000000;
316                                 DestPixel r = (*p >> 8) & 0x0000FF00;
317                                 DestPixel g = (*p >> 8) & 0x000000FF;
318                                 DestPixel b = (*p) & 0x000000FF;
319
320                                 DestPixel mul = (a >> 24) + (a >> 31);
321
322                                 r = (r * mul) & 0x00FF0000;
323                                 g = (g * mul) & 0x0000FF00;
324                                 b = (b * mul) & 0x0000FF00;
325
326                                 *p++ = a | r | g | (b >> 8);
327                         }
328
329                         p += padding;
330                 }
331         }
332
333         return destBuffer.release();
334 }
335
336 }
337
338 _Util::Pixmap*
339 _Util::Pixmap::GetClone(unsigned long depth) const
340 {
341         {
342                 if ((this->pBitmap == null) || (this->width <= 0) || (this->height <= 0))
343                 {
344                         return null;
345                 }
346         }
347
348         void* pConvertedBuffer = null;
349
350         if (depth == 32 && this->depth == 32)
351         {
352                 pConvertedBuffer = (void*) ConvertBitmap <unsigned long, unsigned long>(*this);
353         }
354         else if (depth == 32 && this->depth == 16)
355         {
356                 pConvertedBuffer = (void*) ConvertBitmap <unsigned long, unsigned short>(*this);
357         }
358         else if (depth == 16 && this->depth == 32)
359         {
360                 pConvertedBuffer = (void*) ConvertBitmap <unsigned short, unsigned long>(*this);
361         }
362         else if (depth == 16 && this->depth == 16)
363         {
364                 pConvertedBuffer = (void*) ConvertBitmap <unsigned short, unsigned short>(*this);
365         }
366
367         if (pConvertedBuffer == null)
368         {
369                 return null;
370         }
371
372         _Util::Pixmap* pImageEx = new (std::nothrow) _Util::Pixmap(this->width, this->height, depth, pConvertedBuffer, this->width * depth / 8);
373
374         SysTryReturn(NID_GRP, pImageEx, pImageEx, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
375
376         pImageEx->reserved = 1;
377
378         return pImageEx;
379 }
380
381 _Util::Pixmap*
382 _Util::Pixmap::GetPremultipliedPixmap(void) const
383 {
384         {
385                 if ((this->pBitmap == null) || (this->width <= 0) || (this->height <= 0))
386                 {
387                         return null;
388                 }
389         }
390
391         if (this->depth == 32)
392         {
393                 std::auto_ptr<_Util::Pixmap> temp(new (std::nothrow) _Util::Pixmap(*this));
394                 std::unique_ptr<unsigned char[]> buffer(_CreatePremultipliedBuffer(*this));
395
396                 if (temp.get() && buffer.get())
397                 {
398                         temp->pBitmap = buffer.release();
399                         temp->bytesPerLine = temp->width * temp->depth / 8;
400                         temp->reserved = 1;
401
402                         return temp.release();
403                 }
404                 else
405                 {
406                         return null;
407                 }
408         }
409         else
410         {
411                 return GetClone(this->depth);
412         }
413 }
414
415 void
416 _Util::Pixmap::ConvertPremultiplied(void)
417 {
418         if (this->pBitmap == null || this->depth != 32)
419                 return;
420
421         if (this->isPremultiplied)
422                 return;
423
424         typedef unsigned long DestPixel;
425
426         DestPixel* p = reinterpret_cast<DestPixel*>(this->pBitmap);
427         long paddingBytes = this->bytesPerLine - this->width * this->depth / 8;
428
429         for (int y = 0; y < this->height; y++)
430         {
431                 for (int x = 0; x < this->width; x++)
432                 {
433                         DestPixel a = (*p) & 0xFF000000;
434                         DestPixel r = (*p >> 8) & 0x0000FF00;
435                         DestPixel g = (*p >> 8) & 0x000000FF;
436                         DestPixel b = (*p) & 0x000000FF;
437
438                         DestPixel mul = (a >> 24) + (a >> 31);
439
440                         r = (r * mul) & 0x00FF0000;
441                         g = (g * mul) & 0x0000FF00;
442                         b = (b * mul) & 0x0000FF00;
443
444                         *p++ = a | r | g | (b >> 8);
445                 }
446
447                 p = reinterpret_cast<DestPixel*>(reinterpret_cast<unsigned char*>(p) + paddingBytes);
448         }
449 }