Minor optimization on image loading
[platform/core/uifw/dali-adaptor.git] / dali / internal / imaging / common / loader-ico.cpp
1 /*
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*
18  * Derived from Enlightenment file evas_image_load_ico.c[1]  which is licensed
19  * under the BSD 2-clause license[2] reproduced below.
20  *
21  * [1][http://web.archive.org/web/20141201151111/http://git.enlightenment.org/core/efl.git/tree/src/modules/evas/loaders/ico/evas_image_load_ico.c]
22  * [2][http://web.archive.org/web/20140717012400/https://git.enlightenment.org/core/efl.git/about/]
23  *
24  * Copyright (C) 2002-2012 Carsten Haitzler, Dan Sinclair, Mike Blumenkrantz,
25  * Samsung Electronics and various contributors (see AUTHORS)
26  *
27  * All rights reserved.
28  *
29  * Redistribution and use in source and binary forms, with or without
30  * modification, are permitted provided that the following conditions are met:
31  *
32  *    1. Redistributions of source code must retain the above copyright
33  *       notice, this list of conditions and the following disclaimer.
34  *    2. Redistributions in binary form must reproduce the above copyright
35  *       notice, this list of conditions and the following disclaimer in the
36  *       documentation and/or other materials provided with the distribution.
37  *
38  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
39  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
40  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
41  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
42  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
44  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
45  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
46  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
47  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  */
49
50 // HEADER
51 #include <dali/internal/imaging/common/loader-ico.h>
52
53 // EXTERNAL INCLUDES
54 #include <dali/public-api/common/dali-vector.h>
55 #include <cstring>
56
57 // INTERNAL INCLUDES
58 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
59 #include <dali/integration-api/debug.h>
60
61 namespace Dali
62 {
63 namespace TizenPlatform
64 {
65 namespace
66 {
67 // Reserved 2 bytes + type 2 bytes + count 2 bytes + count * 16 bytes
68 const unsigned char ICO_FILE_HEADER = 22;
69 // Info header 40 bytes = size 4 bytes + width 4 bytes + height 4 bytes + planes 2 bytes + bitcount 2 bytes
70 // + compression 4 bytes + imagesize 4 bytes + xpixelsPerM 4 bytes + ypixelsPerM 4 bytes + colorsUsed 4 bytes + colorImportant 4 bytes
71 // besides, there are rgba color data = numberOfColors * 4 bytes
72 const unsigned char ICO_IMAGE_INFO_HEADER = 40;
73
74 typedef unsigned char DATA8;
75 #define A_VAL(p) (reinterpret_cast<DATA8*>(p)[3])
76
77 #define RGB_JOIN(r, g, b) \
78   (((r) << 16) + ((g) << 8) + (b))
79
80 #define ARGB_JOIN(a, r, g, b) \
81   (((a) << 24) + ((r) << 16) + ((g) << 8) + (b))
82
83 bool read_ushort(const unsigned char* const& map, size_t length, size_t* position, unsigned short* ret)
84 {
85   unsigned char b[2];
86
87   if(DALI_UNLIKELY(*position + 2 > length))
88   {
89     return false;
90   }
91   b[0] = map[(*position)++];
92   b[1] = map[(*position)++];
93   *ret = (b[1] << 8) | b[0];
94   return true;
95 }
96
97 bool read_uint(const unsigned char* const& map, size_t length, size_t* position, unsigned int* ret)
98 {
99   unsigned char b[4];
100   unsigned int  i;
101
102   if(DALI_UNLIKELY(*position + 4 > length))
103   {
104     return false;
105   }
106   for(i = 0; i < 4; i++)
107   {
108     b[i] = map[(*position)++];
109   }
110   *ret = ARGB_JOIN(b[3], b[2], b[1], b[0]);
111   return true;
112 }
113
114 bool read_uchar(const unsigned char* const& map, size_t length, size_t* position, unsigned char* ret)
115 {
116   if(DALI_UNLIKELY(*position + 1 > length))
117   {
118     return false;
119   }
120   *ret = map[(*position)++];
121   return true;
122 }
123
124 bool read_mem(const unsigned char* const& map, size_t length, size_t* position, void* buffer, int size)
125 {
126   if(DALI_UNLIKELY(*position + size > length))
127   {
128     return false;
129   }
130   memcpy(buffer, map + *position, size);
131   *position += size;
132   return true;
133 }
134
135 enum
136 {
137   SMALLEST,
138   BIGGEST,
139   SMALLER,
140   BIGGER
141 };
142
143 enum
144 {
145   ICON   = 1,
146   CURSOR = 2
147 };
148
149 struct IcoData
150 {
151   int          pdelta;
152   int          w, h;
153   int          cols;
154   int          bpp, planes;
155   int          hot_x, hot_y;
156   unsigned int bmoffset, bmsize;
157 };
158
159 bool LoadIcoHeaderHelper(FILE*                        fp,
160                          IcoData&                     chosen,
161                          Dali::Vector<unsigned char>& map,
162                          unsigned int&                fsize)
163 {
164   memset(&chosen, 0, sizeof(chosen));
165
166   if(DALI_UNLIKELY(fp == NULL))
167   {
168     DALI_LOG_ERROR("Error loading bitmap\n");
169     return false;
170   }
171   size_t         position = 0;
172   unsigned short word;
173   unsigned char  byte;
174
175   if(DALI_UNLIKELY(fseek(fp, 0, SEEK_END)))
176   {
177     DALI_LOG_ERROR("Error seeking ICO data\n");
178     return false;
179   }
180
181   long positionIndicator = ftell(fp);
182   fsize                  = 0u;
183
184   if(positionIndicator > -1L)
185   {
186     fsize = static_cast<unsigned int>(positionIndicator);
187   }
188
189   if(DALI_UNLIKELY(0u == fsize))
190   {
191     return false;
192   }
193
194   if(DALI_UNLIKELY(fseek(fp, 0, SEEK_SET)))
195   {
196     DALI_LOG_ERROR("Error seeking ICO data\n");
197     return false;
198   }
199
200   if(DALI_UNLIKELY(fsize < (ICO_FILE_HEADER + ICO_IMAGE_INFO_HEADER))) //6 + 16 + 40
201   {
202     return false;
203   }
204   map.ResizeUninitialized(fsize);
205   if(DALI_UNLIKELY(fread(&map[0], 1, fsize, fp) != fsize))
206   {
207     DALI_LOG_WARNING("image file read opeation error!\n");
208     return false;
209   }
210
211   const std::uint8_t* const inputBufferPtr = &map[0];
212
213   int            search = BIGGEST;
214   unsigned short reserved, type, count;
215   if(DALI_UNLIKELY(!read_ushort(inputBufferPtr, fsize, &position, &reserved)))
216   {
217     return false;
218   }
219   if(DALI_UNLIKELY(!read_ushort(inputBufferPtr, fsize, &position, &type)))
220   {
221     return false;
222   }
223   if(DALI_UNLIKELY(!read_ushort(inputBufferPtr, fsize, &position, &count)))
224   {
225     return false;
226   }
227   if(DALI_UNLIKELY(!((reserved == 0) &&
228                      ((type == ICON) || (type == CURSOR)) && (count != 0))))
229   {
230     return false;
231   }
232   search           = BIGGEST;
233   chosen.pdelta    = 0;
234   bool have_choice = false;
235
236   for(unsigned short i = 0; i < count; i++)
237   {
238     unsigned char tw = 0, th = 0, tcols = 0;
239     if(DALI_UNLIKELY(!read_uchar(inputBufferPtr, fsize, &position, &tw)))
240     {
241       return false;
242     }
243     int w = tw;
244     if(w <= 0)
245     {
246       w = 256;
247     }
248     if(DALI_UNLIKELY(!read_uchar(inputBufferPtr, fsize, &position, &th)))
249     {
250       return false;
251     }
252     int h = th;
253     if(h <= 0)
254     {
255       h = 256;
256     }
257     if(DALI_UNLIKELY(!read_uchar(inputBufferPtr, fsize, &position, &tcols)))
258     {
259       return false;
260     }
261     int cols = tcols;
262     if(DALI_UNLIKELY(!read_uchar(inputBufferPtr, fsize, &position, &byte)))
263     {
264       return false;
265     }
266     if(DALI_UNLIKELY(!read_ushort(inputBufferPtr, fsize, &position, &word)))
267     {
268       return false;
269     }
270     int planes = 0;
271     if(type == 1)
272     {
273       planes = word;
274     }
275     //else hot_x = word;
276     if(DALI_UNLIKELY(!read_ushort(inputBufferPtr, fsize, &position, &word)))
277     {
278       return false;
279     }
280     int bpp = 0;
281     if(type == 1)
282     {
283       bpp = word;
284     }
285
286     // 0 colors means 256 for paletized modes.
287     // Note: We must not do this conversion for bpp greater than 8, as there is no palette.
288     if(bpp <= 8 && cols == 0)
289     {
290       cols = 256;
291     }
292
293     //else hot_y = word;
294     unsigned int bmoffset, bmsize;
295     if(DALI_UNLIKELY(!read_uint(inputBufferPtr, fsize, &position, &bmsize)))
296     {
297       return false;
298     }
299     if(DALI_UNLIKELY(!read_uint(inputBufferPtr, fsize, &position, &bmoffset)))
300     {
301       return false;
302     }
303     if(DALI_UNLIKELY((bmsize <= 0) || (bmoffset <= 0) || (bmoffset >= fsize)))
304     {
305       return false;
306     }
307     if(search == BIGGEST)
308     {
309       int pdelta = w * h;
310       if((!have_choice) ||
311          ((pdelta >= chosen.pdelta) &&
312           (((bpp >= 3) && (bpp >= chosen.bpp)) ||
313            ((bpp < 3) && (cols >= chosen.cols)))))
314       {
315         have_choice     = true;
316         chosen.pdelta   = pdelta;
317         chosen.w        = w;
318         chosen.h        = h;
319         chosen.cols     = cols;
320         chosen.bpp      = bpp;
321         chosen.planes   = planes;
322         chosen.bmsize   = bmsize;
323         chosen.bmoffset = bmoffset;
324       }
325     }
326   }
327
328   if(DALI_UNLIKELY(chosen.bmoffset == 0))
329   {
330     return false;
331   }
332
333   return true;
334 }
335
336 /**
337  * @brief Handle the different bits per pixel
338  * @param[in] bitcount The bit count
339  * @param[in] inputBufferPtr The map to use
340  * @param[in/out] pix A reference to the pointer to the pix buffer
341  * @param[in/out] outputBufferPtr A reference to the surface buffer
342  * @param[in] width The width
343  * @param[in] height The height
344  * @param[in] fsize The file size
345  * @param[in/out] position The position in the file
346  * @param[/outin] pixbuf A reference to the pixbuf
347  * @param[in] stride The stride to use
348  * @param[in] palette The palette
349  */
350 bool HandleBitsPerPixel(
351   const unsigned int                bitcount,
352   const std::uint8_t* const&        inputBufferPtr,
353   unsigned int*&                    pix,
354   std::uint32_t* const&             outputBufferPtr,
355   const unsigned int                width,
356   const unsigned int                height,
357   const unsigned int                fsize,
358   size_t&                           position,
359   const unsigned int                stride,
360   const Dali::Vector<unsigned int>& palette)
361 {
362   // Pixbuf only ever contains one scanline worth of data.
363   Dali::Vector<std::uint8_t> pixbuf;
364   pixbuf.ResizeUninitialized(stride);
365   std::uint8_t* lineBufferPtr = &pixbuf[0];
366
367   // Note: Switch is in order of most common format first.
368   switch(bitcount)
369   {
370     case 32:
371     {
372       const std::uint8_t* p = inputBufferPtr + position;
373       pix                   = outputBufferPtr + ((height - 1) * width);
374
375       for(unsigned int i = 0; i < height; i++)
376       {
377         for(unsigned int j = 0; j < width; j++)
378         {
379           *pix++ = ARGB_JOIN(p[3], p[0], p[1], p[2]);
380           p += 4;
381         }
382         // Move the output up 1 line (we subtract 2 lines because we moved forward one line while copying).
383         pix -= (width * 2);
384       }
385       break;
386     }
387
388     case 24:
389     {
390       for(unsigned int i = 0; i < height; i++)
391       {
392         pix = outputBufferPtr + ((height - 1 - i) * width);
393         if(DALI_UNLIKELY(!read_mem(inputBufferPtr, fsize, &position, lineBufferPtr, stride)))
394         {
395           return false;
396         }
397         const std::uint8_t* p = lineBufferPtr;
398         for(unsigned int j = 0; j < width; j++)
399         {
400           *pix++ = ARGB_JOIN(0xff, p[0], p[1], p[2]);
401           p += 3;
402         }
403       }
404       break;
405     }
406
407     case 8:
408     {
409       for(unsigned int i = 0; i < height; i++)
410       {
411         pix = outputBufferPtr + ((height - 1 - i) * width);
412         if(DALI_UNLIKELY(!read_mem(inputBufferPtr, fsize, &position, lineBufferPtr, stride)))
413         {
414           return false;
415         }
416         const std::uint8_t* p = lineBufferPtr;
417         for(unsigned int j = 0; j < width; j++)
418         {
419           *pix++ = palette[*p++];
420         }
421       }
422       break;
423     }
424
425     case 4:
426     {
427       for(unsigned int i = 0; i < height; i++)
428       {
429         pix = outputBufferPtr + ((height - 1 - i) * width);
430         if(DALI_UNLIKELY(!read_mem(inputBufferPtr, fsize, &position, lineBufferPtr, stride)))
431         {
432           return false;
433         }
434         const std::uint8_t* p = lineBufferPtr;
435         for(unsigned int j = 0; j < width; j++)
436         {
437           if(j & 0x1)
438           {
439             *pix = palette[*p & 0x0f];
440             p++;
441           }
442           else
443           {
444             *pix = palette[*p >> 4];
445           }
446           pix++;
447         }
448       }
449       break;
450     }
451
452     case 1:
453     {
454       const std::uint32_t bytesPerWidth          = width / 8;
455       const std::uint32_t bytesRemainingPerWidth = width & 7;
456       for(unsigned int i = 0; i < height; i++)
457       {
458         pix = outputBufferPtr + ((height - 1 - i) * width);
459         if(DALI_UNLIKELY(!read_mem(inputBufferPtr, fsize, &position, lineBufferPtr, stride)))
460         {
461           return false;
462         }
463
464         const std::uint8_t* p = lineBufferPtr;
465         for(unsigned int j = 0; j < bytesPerWidth; ++j)
466         {
467           *pix++ = palette[*p >> 7];
468           *pix++ = palette[*p >> 6 & 0x01];
469           *pix++ = palette[*p >> 5 & 0x01];
470           *pix++ = palette[*p >> 4 & 0x01];
471           *pix++ = palette[*p >> 3 & 0x01];
472           *pix++ = palette[*p >> 2 & 0x01];
473           *pix++ = palette[*p >> 1 & 0x01];
474           *pix++ = palette[*p >> 0 & 0x01];
475
476           ++p;
477         }
478         if(bytesRemainingPerWidth > 0)
479         {
480           for(std::uint32_t j = 0; j < bytesRemainingPerWidth; ++j)
481           {
482             *pix++ = palette[(*p >> (7 - j)) & 0x01];
483           }
484           ++p;
485         }
486       }
487       break;
488     }
489
490     default:
491     {
492       DALI_LOG_WARNING("Image file contains unsupported bits-per-pixel %d\n", bitcount);
493       return false;
494     }
495   }
496
497   return true;
498 }
499
500 /**
501  * @brief Apply the mask if required
502  * @param[in] inputBufferPtr The map to use
503  * @param[in] fsize The file size
504  * @param[in/out] position The position in the file
505  * @param[in] bitStride The stride
506  * @param[in] width The width
507  * @param[in] height The height
508  * @param[in/out] pix A reference to the pointer to the pix buffer
509  * @param[in/out] outputBufferPtr A reference to the surface buffer
510  */
511 bool ApplyMask(
512   const std::uint8_t* const& inputBufferPtr,
513   const unsigned int         fsize,
514   size_t&                    position,
515   const unsigned int         bitStride,
516   const unsigned int         width,
517   const unsigned int         height,
518   unsigned int*&             pix,
519   std::uint32_t* const&      outputBufferPtr)
520 {
521   Dali::Vector<std::uint8_t> maskbuf;
522   maskbuf.ResizeUninitialized(bitStride);
523   std::uint8_t* lineBufferPtr = &maskbuf[0];
524
525   // Apply mask.
526   // Precalc to save time in the loops.
527   unsigned int bytesPerWidth          = width / 8;
528   unsigned int bytesRemainingPerWidth = width - (bytesPerWidth << 3);
529
530   // Loop for each line of the image.
531   for(unsigned int i = 0; i < height; ++i)
532   {
533     pix = outputBufferPtr + ((height - 1 - i) * width);
534     if(DALI_UNLIKELY(!read_mem(inputBufferPtr, fsize, &position, lineBufferPtr, bitStride)))
535     {
536       return false;
537     }
538     const std::uint8_t* m = lineBufferPtr;
539
540     // Do chunks of 8 pixels first so mask operations can be unrolled.
541     for(unsigned int j = 0; j < bytesPerWidth; ++j)
542     {
543       // Unrolled 8 bits of the mask to avoid many conditions and branches.
544       A_VAL(pix++) = (*m & (1 << 7)) ? 0x00 : 0xff;
545       A_VAL(pix++) = (*m & (1 << 6)) ? 0x00 : 0xff;
546       A_VAL(pix++) = (*m & (1 << 5)) ? 0x00 : 0xff;
547       A_VAL(pix++) = (*m & (1 << 4)) ? 0x00 : 0xff;
548       A_VAL(pix++) = (*m & (1 << 3)) ? 0x00 : 0xff;
549       A_VAL(pix++) = (*m & (1 << 2)) ? 0x00 : 0xff;
550       A_VAL(pix++) = (*m & (1 << 1)) ? 0x00 : 0xff;
551       A_VAL(pix++) = (*m & (1 << 0)) ? 0x00 : 0xff;
552       m++;
553     }
554
555     // Handle any remaining width ( < 8 ) or images that are < 8 wide.
556     if(bytesRemainingPerWidth > 0)
557     {
558       for(unsigned int j = 0; j < bytesRemainingPerWidth; ++j)
559       {
560         // Note: Although we are doing less that a bytes worth of mask, we still always start on the first bit.
561         // If the image is smaller than 8 pixels wide, each mask will still start on a new byte.
562         A_VAL(pix++) = (*m & (1 << (7 - j))) ? 0x00 : 0xff;
563       }
564       m++;
565     }
566   }
567
568   return true;
569 }
570
571 } //unnamed namespace
572
573 bool LoadIcoHeader(const Dali::ImageLoader::Input& input, unsigned int& width, unsigned int& height)
574 {
575   IcoData                     chosen;
576   Dali::Vector<unsigned char> map;
577   unsigned int                fsize;
578   FILE* const                 fp = input.file;
579
580   if(DALI_UNLIKELY(false == LoadIcoHeaderHelper(fp, chosen, map, fsize)))
581   {
582     return false;
583   }
584
585   width  = chosen.w;
586   height = chosen.h;
587
588   return true;
589 }
590
591 bool LoadBitmapFromIco(const Dali::ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap)
592 {
593   IcoData                     chosen;
594   Dali::Vector<unsigned char> map;
595   unsigned int                fsize;
596   FILE* const                 fp = input.file;
597
598   if(DALI_UNLIKELY(false == LoadIcoHeaderHelper(fp, chosen, map, fsize)))
599   {
600     return false;
601   }
602
603   unsigned int   dword;
604   unsigned short word;
605
606   int           diff_size = 0;
607   unsigned int* pix;
608
609   size_t position = chosen.bmoffset; //22 == position
610
611   unsigned int w    = chosen.w;
612   unsigned int h    = chosen.h;
613   unsigned int cols = chosen.cols;
614
615   const std::uint8_t* const inputBufferPtr = &map[0];
616
617   // read bmp header time... let's do some checking
618   if(DALI_UNLIKELY(!read_uint(inputBufferPtr, fsize, &position, &dword)))
619   {
620     return false; // headersize - dont care
621   }
622   if(DALI_UNLIKELY(!read_uint(inputBufferPtr, fsize, &position, &dword)))
623   {
624     return false; // width
625   }
626   if(dword > 0)
627   {
628     if(dword != w)
629     {
630       w         = dword;
631       diff_size = 1;
632     }
633   }
634   if(DALI_UNLIKELY(!read_uint(inputBufferPtr, fsize, &position, &dword)))
635   {
636     return false; // height
637   }
638   if(dword > 0)
639   {
640     if(dword != (h * 2))
641     {
642       h         = dword / 2;
643       diff_size = 1;
644     }
645   }
646   if(diff_size)
647   {
648     DALI_LOG_WARNING("Broken ICO file!\n");
649   }
650
651   if(DALI_UNLIKELY(!read_ushort(inputBufferPtr, fsize, &position, &word)))
652   {
653     return false; // planes
654   }
655   //planes2 = word;
656   if(DALI_UNLIKELY(!read_ushort(inputBufferPtr, fsize, &position, &word)))
657   {
658     return false; // bitcount
659   }
660   unsigned int bitcount = word;
661   if(DALI_UNLIKELY(!read_uint(inputBufferPtr, fsize, &position, &dword)))
662   {
663     return false; // compression
664   }
665   //compression = dword;
666   if(DALI_UNLIKELY(!read_uint(inputBufferPtr, fsize, &position, &dword)))
667   {
668     return false; // imagesize
669   }
670   //imagesize = dword;
671   if(DALI_UNLIKELY(!read_uint(inputBufferPtr, fsize, &position, &dword)))
672   {
673     return false; // z pixels per m
674   }
675   if(DALI_UNLIKELY(!read_uint(inputBufferPtr, fsize, &position, &dword)))
676   {
677     return false; // y pizels per m
678   }
679   if(DALI_UNLIKELY(!read_uint(inputBufferPtr, fsize, &position, &dword)))
680   {
681     return false; // colors used
682   }
683   //colorsused = dword;
684   if(DALI_UNLIKELY(!read_uint(inputBufferPtr, fsize, &position, &dword)))
685   {
686     return false; // colors important
687   }
688
689   Dali::Vector<unsigned int> pal;
690   pal.Resize(256 * 4);
691   for(unsigned int i = 0; i < cols; i++)
692   {
693     unsigned char a, r, g, b;
694
695     if(DALI_UNLIKELY(!read_uchar(inputBufferPtr, fsize, &position, &b)))
696     {
697       return false;
698     }
699     if(DALI_UNLIKELY(!read_uchar(inputBufferPtr, fsize, &position, &g)))
700     {
701       return false;
702     }
703     if(DALI_UNLIKELY(!read_uchar(inputBufferPtr, fsize, &position, &r)))
704     {
705       return false;
706     }
707     if(DALI_UNLIKELY(!read_uchar(inputBufferPtr, fsize, &position, &a)))
708     {
709       return false;
710     }
711     pal[i] = ARGB_JOIN(0xff, b, g, r);
712   }
713
714   Dali::Vector<std::uint32_t> surface;
715
716   // This is the reference way of calculating the total number of bytes necessary to store one row of pixels.
717   unsigned int stride    = (((bitcount * w) + 31) / 32) * 4;
718   unsigned int bitStride = ((w + 31) / 32) * 4;
719   // Set up the surface as soon as we have the width and height.
720   surface.ResizeUninitialized(w * h);
721
722   std::uint32_t* const outputBufferPtr = &surface[0];
723
724   // Handle different bits-per-pixel.
725   if(DALI_UNLIKELY(!HandleBitsPerPixel(bitcount, inputBufferPtr, pix, outputBufferPtr, w, h, fsize, position, stride, pal)))
726   {
727     return false;
728   }
729
730   // From the spec: If bpp is less than 32, there will be a 1bpp mask bitmap also.
731   if(bitcount < 32)
732   {
733     if(DALI_UNLIKELY(!ApplyMask(inputBufferPtr, fsize, position, bitStride, w, h, pix, outputBufferPtr)))
734     {
735       // Return false if not able to apply mask when the bpp is less than 32
736       return false;
737     }
738   }
739
740   bitmap      = Dali::Devel::PixelBuffer::New(w, h, Pixel::Format::RGBA8888);
741   auto pixels = bitmap.GetBuffer();
742   memcpy(pixels, outputBufferPtr, w * h * 4);
743
744   return true;
745 }
746
747 } // namespace TizenPlatform
748
749 } // namespace Dali