[Tizen] Fix bitfield BMP file error
[platform/core/uifw/dali-adaptor.git] / dali / internal / imaging / common / loader-bmp.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 #include <dali/internal/imaging/common/loader-bmp.h>
19
20 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
21 #include <dali/integration-api/debug.h>
22 #include <dali/public-api/common/vector-wrapper.h>
23
24 namespace Dali
25 {
26 namespace TizenPlatform
27 {
28 namespace
29 {
30 const unsigned int FileHeaderOffsetOfBF32V4  = 0x7A;
31 const unsigned int MaskForBFRGB565           = 0x80;
32 const unsigned int FileHeaderOffsetOfRGB24V5 = 0x8A;
33
34 enum BmpFormat
35 {
36   BMP_RGB1 = 14,     //BI_RGB & bpp =1
37   BMP_RGB4,          //BI_RGB & bpp = 4
38   BMP_RGB8,          //BI_RGB & bpp = 8
39   BMP_RGB555,        //BI_RGB & bpp = 16
40   BMP_BITFIELDS555,  //BI_BITFIELDS & 16bit & R:G:B = 5:5:5
41   BMP_BITFIELDS32,   //BI_BITFIELDS & 32bit & R:G:B:A = 8:8:8:8
42   BMP_RLE8,          //BI_RLE8
43   BMP_RLE4,          //BI_RLE4
44   BMP_BITFIELDS32V4, //BI_BITFIELDS & 32bit
45   BMP_RGB24V5,       //BI_RGB & bpp = 24 & bmp version5
46   BMP_NOTEXIST
47 };
48
49 struct BmpFileHeader
50 {
51   unsigned short signature;    // Bitmap file signature
52   unsigned int   fileSize;     // Bitmap file size in bytes
53   unsigned short reserved1;    // Reserved bits
54   unsigned short reserved2;    // Reserved bits
55   unsigned int   offset;       // Offset from BMP file header to BMP bits
56 } __attribute__((__packed__)); // Stops the structure from being aligned to every 4 bytes
57
58 struct BmpInfoHeader
59 {
60   unsigned int   infoHeaderSize;  // Specifies the number of bytes required by the info header
61   unsigned int   width;           // The Image Width
62   int            height;          // The Image Height (negative value represents image data is flipped)
63   unsigned short planes;          // The number of color planes, must be 1
64   unsigned short bitsPerPixel;    // The bits per pixel
65   unsigned int   compression;     // The type of compression used by the image
66   unsigned int   imageSize;       // The size of the image in bytes
67   unsigned int   xPixelsPerMeter; // The number of pixels per meter in x axis
68   unsigned int   yPixelsPerMeter; // The number of pixels per meter in y axis
69   unsigned int   numberOfColors;  // The number of colors in the color table
70   unsigned int   importantColors; // The important color count
71 } __attribute__((__packed__));    // Stops the structure from being aligned to every 4 bytes
72
73 /**
74  * Template function to read from the file directly into our structure.
75  * @param[in]  fp     The file to read from
76  * @param[out] header The structure we want to store our information in
77  * @return true, if read successful, false otherwise
78  */
79 template<typename T>
80 inline bool ReadHeader(FILE* fp, T& header)
81 {
82   const unsigned int readLength = sizeof(T);
83
84   // Load the information directly into our structure
85   if(DALI_UNLIKELY(fread(&header, 1, readLength, fp) != readLength))
86   {
87     return false;
88   }
89
90   return true;
91 }
92
93 bool LoadBmpHeader(FILE* fp, unsigned int& width, unsigned int& height, BmpFileHeader& fileHeader, BmpInfoHeader& infoHeader)
94 {
95   if(DALI_UNLIKELY(!ReadHeader(fp, fileHeader)))
96   {
97     DALI_LOG_ERROR("File header read failed\n");
98     return false;
99   }
100
101   if(DALI_UNLIKELY(!ReadHeader(fp, infoHeader)))
102   {
103     DALI_LOG_ERROR("Info header read failed\n");
104     return false;
105   }
106
107   width  = infoHeader.width;
108   height = abs(infoHeader.height);
109
110   if(DALI_UNLIKELY(infoHeader.width == 0))
111   {
112     DALI_LOG_ERROR("Invalid header size\n");
113     return false;
114   }
115
116   return true;
117 }
118
119 /**
120  * function to decode format BI_RGB & bpp = 24 & bmp version5.
121  * @param[in]  fp      The file to read from
122  * @param[out] pixels  The pointer that  we want to store bmp data  in
123  * @param[in]  width   bmp width
124  * @param[in]  height  bmp height
125  * @param[in]  offset  offset from bmp header to bmp image data
126  * @param[in]  topDown indicate image data is read from bottom or from top
127  * @param[in]  padding padded to a u_int32 boundary for each line
128  * @return true, if decode successful, false otherwise
129  */
130 bool DecodeRGB24V5(FILE*          fp,
131                    unsigned char* pixels,
132                    unsigned int   width,
133                    unsigned int   height,
134                    unsigned int   offset,
135                    bool           topDown,
136                    unsigned int   rowStride,
137                    unsigned int   padding)
138 {
139   if(DALI_UNLIKELY(fp == NULL || pixels == NULL))
140   {
141     DALI_LOG_ERROR("Error decoding BMP_RGB24V5 format\n");
142     return false;
143   }
144   if(DALI_UNLIKELY(fseek(fp, offset, SEEK_SET)))
145   {
146     DALI_LOG_ERROR("Error seeking BMP_RGB24V5 data\n");
147     return false;
148   }
149
150   for(std::uint32_t yPos = 0; yPos < height; ++yPos)
151   {
152     std::uint8_t* pixelsPtr = NULL;
153     if(topDown)
154     {
155       pixelsPtr = pixels + (yPos * rowStride);
156     }
157     else
158     {
159       pixelsPtr = pixels + (((height - 1) - yPos) * rowStride);
160     }
161     if(DALI_UNLIKELY(fread(pixelsPtr, 1, rowStride, fp) != rowStride))
162     {
163       DALI_LOG_ERROR("Error reading the BMP image\n");
164       return false;
165     }
166     for(std::uint32_t i = 0; i < rowStride; i += 3)
167     {
168       std::uint8_t temp = pixelsPtr[i];
169       pixelsPtr[i]      = pixelsPtr[i + 2];
170       pixelsPtr[i + 2]  = temp;
171     }
172
173     if(padding)
174     {
175       // move past the padding.
176       if(DALI_UNLIKELY(fseek(fp, padding, SEEK_CUR)))
177       {
178         DALI_LOG_ERROR("Error moving past BMP_RGB24V5 padding\n");
179       }
180     }
181   }
182   return true;
183 }
184
185 /**
186  * function to decode format BI_BITFIELDS & bpp = 32 & bmp version4.
187  * @param[in]  fp        The file to read from
188  * @param[out] pixels    The pointer that  we want to store bmp data  in
189  * @param[in]  width     bmp width
190  * @param[in]  height    bmp height
191  * @param[in]  offset    offset from bmp header to bmp image data
192  * @param[in]  topDown   indicate image data is read from bottom or from top
193  * @param[in]  rowStride bits span for each line
194  * @param[in]  padding   padded to a u_int32 boundary for each line
195  * @return true, if decode successful, false otherwise
196  */
197 bool DecodeBF32V4(FILE*          fp,
198                   unsigned char* pixels,
199                   unsigned int   width,
200                   unsigned int   height,
201                   unsigned int   offset,
202                   bool           topDown,
203                   unsigned int   rowStride,
204                   unsigned int   padding)
205 {
206   if(DALI_UNLIKELY(fp == NULL || pixels == NULL))
207   {
208     DALI_LOG_ERROR("Error decoding BMP_BITFIELDS32V4 format\n");
209     return false;
210   }
211   if(DALI_UNLIKELY(fseek(fp, offset, SEEK_SET)))
212   {
213     DALI_LOG_ERROR("Error seeking BMP_BITFIELDS32V4 data\n");
214     return false;
215   }
216
217   for(std::uint32_t yPos = 0; yPos < height; ++yPos)
218   {
219     std::uint8_t* pixelsPtr = NULL;
220     if(topDown)
221     {
222       pixelsPtr = pixels + (yPos * rowStride);
223     }
224     else
225     {
226       pixelsPtr = pixels + (((height - 1) - yPos) * rowStride);
227     }
228     if(DALI_UNLIKELY(fread(pixelsPtr, 1, rowStride, fp) != rowStride))
229     {
230       DALI_LOG_ERROR("Error reading the BMP image\n");
231       return false;
232     }
233     for(std::uint32_t i = 0; i < rowStride; i += 4)
234     {
235       std::uint8_t temp = pixelsPtr[i];
236       pixelsPtr[i]      = pixelsPtr[i + 2];
237       pixelsPtr[i + 2]  = temp;
238     }
239     if(padding)
240     {
241       // move past the padding.
242       if(DALI_UNLIKELY(fseek(fp, padding, SEEK_CUR)))
243       {
244         DALI_LOG_ERROR("Error moving past BMP_BITFIELDS32V4 padding\n");
245       }
246     }
247   }
248   return true;
249 }
250
251 /**
252  * function to decode format BI_BITFIELDS & bpp = 32
253  * @param[in]  fp        The file to read from
254  * @param[out] pixels    The pointer that  we want to store bmp data  in
255  * @param[in]  width     bmp width
256  * @param[in]  height    bmp height
257  * @param[in]  offset    offset from bmp header to bmp image data
258  * @param[in]  topDown   indicate image data is read from bottom or from top
259  * @param[in]  rowStride bits span for each line
260  * @param[in]  padding   padded to a u_int32 boundary for each line
261  * @return true, if decode successful, false otherwise
262  */
263 bool DecodeBF32(FILE*          fp,
264                 unsigned char* pixels,
265                 unsigned int   width,
266                 unsigned int   height,
267                 unsigned int   offset,
268                 bool           topDown,
269                 unsigned int   rowStride,
270                 unsigned int   padding)
271 {
272   if(DALI_UNLIKELY(fp == NULL || pixels == NULL))
273   {
274     DALI_LOG_ERROR("Error decoding BMP_BITFIELDS32 format\n");
275     return false;
276   }
277   if(DALI_UNLIKELY(fseek(fp, offset, SEEK_SET)))
278   {
279     DALI_LOG_ERROR("Error seeking BMP_BITFIELDS32 data\n");
280     return false;
281   }
282
283   for(std::uint32_t yPos = 0; yPos < height; ++yPos)
284   {
285     std::uint8_t* pixelsPtr;
286     if(topDown)
287     {
288       // the data in the file is top down, and we store the data top down
289       pixelsPtr = pixels + (yPos * rowStride);
290     }
291     else
292     {
293       // the data in the file is bottom up, and we store the data top down
294       pixelsPtr = pixels + (((height - 1) - yPos) * rowStride);
295     }
296
297     if(DALI_UNLIKELY(fread(pixelsPtr, 1, rowStride, fp) != rowStride))
298     {
299       DALI_LOG_ERROR("Error reading the BMP image\n");
300       return false;
301     }
302     for(std::uint32_t i = 0; i < rowStride; i += 4)
303     {
304       std::uint8_t temp = pixelsPtr[i];
305       pixelsPtr[i]      = pixelsPtr[i + 2];
306       pixelsPtr[i + 2]  = temp;
307     }
308
309     if(padding)
310     {
311       // move past the padding.
312       if(DALI_UNLIKELY(fseek(fp, padding, SEEK_CUR)))
313       {
314         DALI_LOG_ERROR("Error moving past BMP_BITFIELDS32 padding\n");
315       }
316     }
317   }
318   return true;
319 }
320
321 /**
322  * function to decode format BI_BITFIELDS & bpp = 16 & R:G:B = 5:6:5
323  * @param[in]  fp      The file to read from
324  * @param[out] pixels  The pointer that  we want to store bmp data  in
325  * @param[in]  width   bmp width
326  * @param[in]  height  bmp height
327  * @param[in]  offset  offset from bmp header to bmp image data
328  * @param[in]  topDown indicate image data is read from bottom or from top
329  * @return true, if decode successful, false otherwise
330  */
331 bool DecodeBF565(FILE*          fp,
332                  unsigned char* pixels,
333                  unsigned int   width,
334                  unsigned int   height,
335                  unsigned int   offset,
336                  bool           topDown)
337 {
338   if(DALI_UNLIKELY(fp == NULL || pixels == NULL))
339   {
340     DALI_LOG_ERROR("Error decoding RGB565 format\n");
341     return false;
342   }
343   if(DALI_UNLIKELY(fseek(fp, offset, SEEK_SET)))
344   {
345     DALI_LOG_ERROR("Error seeking RGB565 data\n");
346     return false;
347   }
348
349   width                   = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
350   std::uint32_t rowStride = width * 2;
351
352   for(std::uint32_t i = 0; i < height; ++i)
353   {
354     std::uint8_t* pixelsPtr = NULL;
355     if(topDown)
356     {
357       // the data in the file is top down, and we store the data top down
358       pixelsPtr = pixels + (i * rowStride);
359     }
360     else
361     {
362       // the data in the file is bottom up, and we store the data top down
363       pixelsPtr = pixels + (((height - 1) - i) * rowStride);
364     }
365     if(DALI_UNLIKELY(fread(pixelsPtr, 1, rowStride, fp) != rowStride))
366     {
367       return false;
368     }
369   }
370
371   return true;
372 }
373
374 /**
375  * function to decode format BI_BITFIELDS & bpp = 16 & R:G:B = 5:5:5
376  * @param[in]  fp      The file to read from
377  * @param[out] pixels  The pointer that  we want to store bmp data  in
378  * @param[in]  width   bmp width
379  * @param[in]  height  bmp height
380  * @param[in]  offset  offset from bmp header to bmp image data
381  * @param[in]  topDown indicate image data is read from bottom or from top
382  * @return true, if decode successful, false otherwise
383  */
384 bool DecodeBF555(FILE*          fp,
385                  unsigned char* pixels,
386                  unsigned int   width,
387                  unsigned int   height,
388                  unsigned int   offset,
389                  bool           topDown)
390 {
391   if(DALI_UNLIKELY(fp == NULL || pixels == NULL))
392   {
393     DALI_LOG_ERROR("Error decoding BMP_BITFIELDS555 format\n");
394     return false;
395   }
396
397   if(DALI_UNLIKELY(fseek(fp, offset, SEEK_SET)))
398   {
399     DALI_LOG_ERROR("Error seeking BMP_BITFIELDS555 data\n");
400     return false;
401   }
402
403   width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
404
405   std::vector<std::uint8_t> raw(width * height * 2);
406   std::uint32_t             rawStride = width * 2;
407   std::uint32_t             rowStride = width * 3;
408
409   std::uint8_t* rawPtr = NULL;
410   for(std::uint32_t j = 0; j < height; ++j)
411   {
412     rawPtr = &raw[0] + (j * rawStride);
413     if(DALI_UNLIKELY(fread(rawPtr, 1, rawStride, fp) != rawStride))
414     {
415       return false;
416     }
417   }
418
419   for(std::uint32_t yPos = 0; yPos < height; ++yPos)
420   {
421     std::uint8_t* pixelsPtr = NULL;
422     if(topDown)
423     {
424       // the data in the file is top down, and we store the data top down
425       pixelsPtr = pixels + (yPos * rowStride);
426     }
427     else
428     {
429       // the data in the file is bottom up, and we store the data top down
430       pixelsPtr = pixels + (((height - 1) - yPos) * rowStride);
431     }
432
433     for(std::uint32_t k = 0; k < width; ++k)
434     {
435       std::uint32_t index  = yPos * rawStride + 2 * k;
436       pixelsPtr[3 * k]     = ((raw[index + 1] >> 2) & 0x1F) * 0xFF / 0x1F;
437       pixelsPtr[3 * k + 1] = (((raw[index + 1] & 0x03) << 3) | (raw[index] >> 5)) * 0xFF / 0x1F;
438       pixelsPtr[3 * k + 2] = (raw[index] & 0x1F) * 0xFF / 0x1F;
439     }
440   }
441   return true;
442 }
443
444 /**
445  * function to decode format BI_RGB & bpp = 16 & R:G:B = 5:5:5
446  * @param[in]  fp      The file to read from
447  * @param[out] pixels  The pointer that  we want to store bmp data  in
448  * @param[in]  width   bmp width
449  * @param[in]  height  bmp height
450  * @param[in]  offset  offset from bmp header to bmp image data
451  * @param[in]  topDown indicate image data is read from bottom or from top
452  * @return true, if decode successful, false otherwise
453  */
454 bool DecodeRGB555(FILE*          fp,
455                   unsigned char* pixels,
456                   unsigned int   width,
457                   unsigned int   height,
458                   unsigned int   offset,
459                   bool           topDown)
460 {
461   if(DALI_UNLIKELY(fp == NULL || pixels == NULL))
462   {
463     DALI_LOG_ERROR("Error decoding BMP_RGB555 format\n");
464     return false;
465   }
466   if(DALI_UNLIKELY(fseek(fp, offset, SEEK_SET)))
467   {
468     DALI_LOG_ERROR("Error seeking BMP_RGB555 data\n");
469     return false;
470   }
471
472   width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
473   std::vector<std::uint8_t> raw(width * height * 2);
474   std::uint32_t             rawStride = width * 2;
475   std::uint32_t             rowStride = width * 3;
476
477   std::uint8_t* rawPtr = NULL;
478   for(std::uint32_t j = 0; j < height; ++j)
479   {
480     rawPtr = &raw[0] + (j * rawStride);
481     if(DALI_UNLIKELY(fread(rawPtr, 1, rawStride, fp) != rawStride))
482     {
483       return false;
484     }
485   }
486   for(std::uint32_t i = 0; i < height; ++i)
487   {
488     std::uint8_t* pixelsPtr = NULL;
489     if(topDown)
490     {
491       // the data in the file is top down, and we store the data top down
492       pixelsPtr = pixels + (i * rowStride);
493     }
494     else
495     {
496       // the data in the file is bottom up, and we store the data top down
497       pixelsPtr = pixels + (((height - 1) - i) * rowStride);
498     }
499     for(std::uint32_t k = 0; k < width; ++k)
500     {
501       std::uint32_t index  = i * rawStride + 2 * k;
502       pixelsPtr[3 * k]     = ((raw[index + 1] >> 2) & 0x1F) * 0xFF / 0x1F;
503       pixelsPtr[3 * k + 1] = (((raw[index + 1] & 0x03) << 3) | (raw[index] >> 5)) * 0xFF / 0x1F;
504       pixelsPtr[3 * k + 2] = (raw[index] & 0x1F) * 0xFF / 0x1F;
505     }
506   }
507   return true;
508 }
509
510 /**
511  * function to decode format BI_RGB & bpp = 1
512  * @param[in]  fp      The file to read from
513  * @param[out] pixels  The pointer that  we want to store bmp data  in
514  * @param[in]  width   bmp width
515  * @param[in]  height  bmp height
516  * @param[in]  offset  offset from bmp header to bmp palette data
517  * @param[in]  topDown indicate image data is read from bottom or from top
518  * @return true, if decode successful, false otherwise
519  */
520 bool DecodeRGB1(FILE*          fp,
521                 unsigned char* pixels,
522                 unsigned int   width,
523                 unsigned int   height,
524                 unsigned int   offset,
525                 bool           topDown)
526 {
527   if(DALI_UNLIKELY(fp == NULL || pixels == NULL))
528   {
529     DALI_LOG_ERROR("Error decoding BMP_RGB1 format\n");
530     return false;
531   }
532   if(DALI_UNLIKELY(fseek(fp, offset, SEEK_SET)))
533   {
534     DALI_LOG_ERROR("Error seeking BMP_RGB1 data\n");
535     return false;
536   }
537
538   std::uint8_t              colorTable[8] = {0};
539   std::uint8_t              cmd;
540   std::uint32_t             fillw = ((width & 63) != 0) ? width + 64 - (width & 63) : width;
541   std::vector<std::uint8_t> colorIndex(fillw * height);
542   std::uint32_t             rowStride = fillw * 3; // RGB
543
544   if(DALI_UNLIKELY(fread(colorTable, 1, 8, fp) != 8))
545   {
546     return false;
547   }
548
549   for(std::uint32_t i = 0; i < fillw * height; i += 8)
550   {
551     if(DALI_UNLIKELY(fread(&cmd, 1, 1, fp) != 1))
552     {
553       return false;
554     }
555
556     colorIndex[i]     = (cmd >> 7) & 0x01;
557     colorIndex[i + 1] = (cmd >> 6) & 0x01;
558     colorIndex[i + 2] = (cmd >> 5) & 0x01;
559     colorIndex[i + 3] = (cmd >> 4) & 0x01;
560     colorIndex[i + 4] = (cmd >> 3) & 0x01;
561     colorIndex[i + 5] = (cmd >> 2) & 0x01;
562     colorIndex[i + 6] = (cmd >> 1) & 0x01;
563     colorIndex[i + 7] = (cmd & 0x01);
564   }
565
566   for(std::uint32_t index = 0; index < height; ++index)
567   {
568     std::uint8_t* pixelsPtr = NULL;
569     if(topDown)
570     {
571       // the data in the file is top down, and we store the data top down
572       pixelsPtr = pixels + (index * rowStride);
573     }
574     else
575     {
576       // the data in the file is bottom up, and we store the data top down
577       pixelsPtr = pixels + (((height - 1) - index) * rowStride);
578     }
579     for(std::uint32_t j = 0; j < fillw; ++j)
580     {
581       std::uint32_t ctIndex = 0;
582       if((fillw * index + j) < (fillw * height))
583       {
584         ctIndex = colorIndex[fillw * index + j];
585       }
586       else
587       {
588         break;
589       }
590       // temp solution for PLM bug P130411-5268, there is one mono bmp that cause DecodeRGB1 API crash.
591       if(((3 * j + 2) < height * fillw * 3) && (ctIndex < 2))
592       {
593         pixelsPtr[3 * j]     = colorTable[4 * ctIndex + 2];
594         pixelsPtr[3 * j + 1] = colorTable[4 * ctIndex + 1];
595         pixelsPtr[3 * j + 2] = colorTable[4 * ctIndex];
596       }
597     }
598   }
599   return true;
600 }
601
602 /**
603  * function to decode format BI_RGB & bpp = 4
604  * @param[in]  fp      The file to read from
605  * @param[out] pixels  The pointer that  we want to store bmp data  in
606  * @param[in]  width   bmp width
607  * @param[in]  height  bmp height
608  * @param[in]  offset  offset from bmp header to bmp palette data
609  * @param[in]  topDown indicate image data is read from bottom or from top
610  * @return true, if decode successful, false otherwise
611  */
612 bool DecodeRGB4(FILE*          fp,
613                 unsigned char* pixels,
614                 unsigned int   width,
615                 unsigned int   height,
616                 unsigned int   offset,
617                 bool           topDown)
618 {
619   if(DALI_UNLIKELY(fp == NULL || pixels == NULL))
620   {
621     DALI_LOG_ERROR("Error decoding BMP_RGB4 format\n");
622     return false;
623   }
624   if(DALI_UNLIKELY(fseek(fp, offset, SEEK_SET)))
625   {
626     DALI_LOG_ERROR("Error seeking BMP_RGB4 data\n");
627     return false;
628   }
629
630   std::uint8_t              colorTable[64];
631   std::uint8_t              cmd;
632   std::uint32_t             fillw = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
633   std::vector<std::uint8_t> colorIndex(fillw * height);
634   std::uint32_t             rowStride = fillw * 3;
635
636   if(DALI_UNLIKELY(fread(colorTable, 1, 64, fp) != 64))
637   {
638     return false;
639   }
640
641   for(std::uint32_t i = 0; i < fillw * height; i += 2)
642   {
643     if(DALI_UNLIKELY(fread(&cmd, 1, 1, fp) != 1))
644     {
645       return false;
646     }
647
648     colorIndex[i]     = cmd >> 4;
649     colorIndex[i + 1] = cmd & (0x0F);
650   }
651   std::uint32_t ctIndex = 0;
652
653   for(std::uint32_t index = 0; index < height; ++index)
654   {
655     std::uint8_t* pixelsPtr = NULL;
656     if(topDown)
657     {
658       // the data in the file is top down, and we store the data top down
659       pixelsPtr = pixels + (index * rowStride);
660     }
661     else
662     {
663       // the data in the file is bottom up, and we store the data top down
664       pixelsPtr = pixels + (((height - 1) - index) * rowStride);
665     }
666     for(std::uint32_t j = 0; j < fillw; ++j)
667     {
668       ctIndex                = colorIndex[fillw * index + j];
669       pixelsPtr[3 * j]       = colorTable[4 * ctIndex + 2];
670       pixelsPtr[(3 * j + 1)] = colorTable[4 * ctIndex + 1];
671       pixelsPtr[(3 * j + 2)] = colorTable[4 * ctIndex];
672     }
673   }
674
675   return true;
676 }
677
678 /**
679  * function to decode format BI_RGB & bpp = 8
680  * @param[in]  fp      The file to read from
681  * @param[out] pixels  The pointer that  we want to store bmp data  in
682  * @param[in]  width   bmp width
683  * @param[in]  height  bmp height
684  * @param[in]  offset  offset from bmp header to bmp palette data
685  * @param[in]  topDown indicate image data is read from bottom or from top
686  * @return true, if decode successful, false otherwise
687  */
688 bool DecodeRGB8(FILE*          fp,
689                 unsigned char* pixels,
690                 unsigned int   width,
691                 unsigned int   height,
692                 unsigned int   offset,
693                 bool           topDown)
694 {
695   if(DALI_UNLIKELY(fp == NULL || pixels == NULL))
696   {
697     DALI_LOG_ERROR("Error decoding BMP_RGB8 format\n");
698     return false;
699   }
700   if(DALI_UNLIKELY(fseek(fp, offset, SEEK_SET)))
701   {
702     DALI_LOG_ERROR("Error seeking BMP_RGB8 data\n");
703     return false;
704   }
705
706   std::vector<std::uint8_t> colorTable(1024);
707   width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
708   std::vector<std::uint8_t> colorIndex(width * height);
709   std::uint32_t             rowStride = width * 3; //RGB8->RGB24
710
711   if(DALI_UNLIKELY(fread(&colorTable[0], 1, 1024, fp) != 1024))
712   {
713     return false;
714   }
715   if(DALI_UNLIKELY(fread(&colorIndex[0], 1, width * height, fp) != width * height))
716   {
717     return false;
718   }
719   std::uint8_t ctIndex = 0;
720   for(std::uint32_t index = 0; index < height; ++index)
721   {
722     std::uint8_t* pixelsPtr = NULL;
723     if(topDown)
724     {
725       // the data in the file is top down, and we store the data top down
726       pixelsPtr = pixels + (index * rowStride);
727     }
728     else
729     {
730       // the data in the file is bottom up, and we store the data top down
731       pixelsPtr = pixels + (((height - 1) - index) * rowStride);
732     }
733     for(std::uint32_t j = 0; j < width; ++j)
734     {
735       ctIndex                = colorIndex[width * index + j];
736       pixelsPtr[3 * j]       = colorTable[4 * ctIndex + 2];
737       pixelsPtr[(3 * j + 1)] = colorTable[4 * ctIndex + 1];
738       pixelsPtr[(3 * j + 2)] = colorTable[4 * ctIndex];
739     }
740   }
741   return true;
742 }
743
744 /**
745  * function to decode format BI_RLE4 & bpp = 4
746  * @param[in]  fp      The file to read from
747  * @param[out] pixels  The pointer that  we want to store bmp data  in
748  * @param[in]  width   bmp width
749  * @param[in]  height  bmp height
750  * @param[in]  offset  offset from bmp header to bmp palette data
751  * @param[in]  topDown indicate image data is read from bottom or from top
752  * @return true, if decode successful, false otherwise
753  */
754 bool DecodeRLE4(FILE*          fp,
755                 unsigned char* pixels,
756                 unsigned int   width,
757                 unsigned int   height,
758                 unsigned int   offset,
759                 bool           topDown)
760 {
761   if(DALI_UNLIKELY(fp == NULL || pixels == NULL))
762   {
763     DALI_LOG_ERROR("Error decoding BMP_RLE4 format\n");
764     return false;
765   }
766   std::uint8_t* pixelsPtr = pixels;
767   width                   = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
768   std::uint8_t              cmd[2];
769   std::uint32_t             cmdStride = 2;
770   std::uint8_t              colorTable[64];
771   std::vector<std::uint8_t> colorIndex(width * height >> 1);
772   std::vector<std::uint8_t> run;
773   std::uint32_t             x  = 0;
774   std::uint32_t             y  = 0;
775   std::uint32_t             dx = 0;
776   std::uint32_t             dy = 0;
777   width += (width & 1);
778   width = width >> 1;
779
780   bool finish = false;
781
782   if(DALI_UNLIKELY(fseek(fp, offset, SEEK_SET)))
783   {
784     DALI_LOG_ERROR("Error seeking BMP_RLE4 data\n");
785     return false;
786   }
787
788   if(DALI_UNLIKELY(fread(colorTable, 1, 64, fp) != 64))
789   {
790     return false;
791   }
792
793   while((x >> 1) + y * width < width * height)
794   {
795     if(finish)
796     {
797       break;
798     }
799     if(DALI_UNLIKELY(fread(cmd, 1, cmdStride, fp) != cmdStride))
800     {
801       return false;
802     }
803     if(cmd[0] == 0) // ESCAPE
804     {
805       switch(cmd[1])
806       {
807         case 1: //end of bitmap
808           finish = true;
809           break;
810         case 0: // end of line
811           x = 0;
812           y++;
813           break;
814         case 2: // delta
815           if(DALI_UNLIKELY(fread(cmd, 1, cmdStride, fp) != cmdStride))
816           {
817             DALI_LOG_ERROR("Error reading the BMP image\n");
818             return false;
819           }
820           dx = cmd[0] & (0xFF);
821           dy = cmd[1] & (0xFF);
822           x += dx;
823           y += dy;
824           break;
825         default:
826           // decode a literal run
827           std::uint32_t length = cmd[1] & (0xFF);
828           //size of run, which is word aligned
829           std::uint32_t bytesize = length;
830           bytesize += (bytesize & 1);
831           bytesize >>= 1;
832           bytesize += (bytesize & 1);
833           run.resize(bytesize);
834           if(DALI_UNLIKELY(fread(&run[0], 1, bytesize, fp) != bytesize))
835           {
836             DALI_LOG_ERROR("Error reading the BMP image\n");
837             return false;
838           }
839           if((x & 1) == 0)
840           {
841             length += (length & 1);
842             length >>= 1;
843             for(std::uint32_t i = 0; i < length; ++i)
844             {
845               colorIndex[(x >> 1) + width * (height - y - 1) + i] = run[i];
846             }
847           }
848           else
849           {
850             for(std::uint32_t i = 0; i < length; ++i)
851             {
852               if((i & 1) == 0) //copy high to low
853               {
854                 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((run[i >> 1] & 0xF0) >> 4);
855               }
856               else //copy low to high
857               {
858                 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((run[i >> 1] & 0x0F) << 4);
859               }
860             }
861           }
862           x += cmd[1] & (0xFF);
863           break;
864       }
865     }
866     else
867     {
868       std::uint32_t length = cmd[0] & (0xFF);
869       if((x & 1) == 0)
870       {
871         length += (length & 1);
872         length >>= 1;
873         for(std::uint32_t i = 0; i < length; ++i)
874         {
875           colorIndex[(height - y - 1) * width + i + (x >> 1)] = cmd[1];
876         }
877       }
878       else
879       {
880         for(std::uint32_t i = 0; i < length; ++i)
881         {
882           if((i & 1) == 0)
883           {
884             colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((cmd[1] & 0xF0) >> 4);
885           }
886           else
887           {
888             colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((cmd[1] & 0x0F) << 4);
889           }
890         }
891       }
892       x += cmd[0] & (0xFF);
893     }
894   }
895
896   std::uint32_t ctIndexHigh = 0;
897   std::uint32_t ctIndexLow  = 0;
898   for(std::uint32_t index = 0; index < (width * height); ++index)
899   {
900     ctIndexHigh              = colorIndex[index] >> 4;
901     ctIndexLow               = colorIndex[index] & (0x0F);
902     pixelsPtr[6 * index]     = colorTable[4 * ctIndexHigh + 2];
903     pixelsPtr[6 * index + 1] = colorTable[4 * ctIndexHigh + 1];
904     pixelsPtr[6 * index + 2] = colorTable[4 * ctIndexHigh];
905     pixelsPtr[6 * index + 3] = colorTable[4 * ctIndexLow + 2];
906     pixelsPtr[6 * index + 4] = colorTable[4 * ctIndexLow + 1];
907     pixelsPtr[6 * index + 5] = colorTable[4 * ctIndexLow];
908   }
909   return true;
910 }
911
912 /**
913  * function to decode format BI_RLE8 & bpp = 8
914  * @param[in]  fp      The file to read from
915  * @param[out] pixels  The pointer that  we want to store bmp data  in
916  * @param[in]  width   bmp width
917  * @param[in]  height  bmp height
918  * @param[in]  offset  offset from bmp header to bmp palette data
919  * @param[in]  topDown indicate image data is read from bottom or from top
920  * @return true, if decode successful, false otherwise
921  */
922 bool DecodeRLE8(FILE*          fp,
923                 unsigned char* pixels,
924                 unsigned int   width,
925                 unsigned int   height,
926                 unsigned int   offset,
927                 bool           topDown)
928 {
929   if(DALI_UNLIKELY(fp == NULL || pixels == NULL))
930   {
931     DALI_LOG_ERROR("Error decoding BMP_RLE8 format\n");
932     return false;
933   }
934   std::uint8_t* pixelsPtr = pixels;
935   std::uint32_t x         = 0;
936   std::uint32_t y         = 0;
937   std::uint32_t cmdStride = 2;
938
939   width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
940   std::vector<std::uint8_t> colorTable(1024);
941   std::uint8_t              cmd[2];
942   std::vector<std::uint8_t> colorIndex(width * height);
943
944   if(DALI_UNLIKELY(fseek(fp, offset, SEEK_SET)))
945   {
946     DALI_LOG_ERROR("Error seeking BMP_RLE8 data\n");
947     return false;
948   }
949
950   if(DALI_UNLIKELY(fread(&colorTable[0], 1, 1024, fp) != 1024))
951   {
952     return false;
953   }
954
955   std::uint32_t             dx         = 0;
956   std::uint32_t             dy         = 0;
957   bool                      finish     = false;
958   std::uint32_t             length     = 0;
959   std::uint32_t             copylength = 0;
960   std::vector<std::uint8_t> run;
961   while((x + y * width) < width * height)
962   {
963     if(DALI_UNLIKELY(finish))
964     {
965       break;
966     }
967     if(DALI_UNLIKELY(fread(cmd, 1, cmdStride, fp) != cmdStride))
968     {
969       return false;
970     }
971
972     if(cmd[0] == 0) //ESCAPE
973     {
974       switch(cmd[1])
975       {
976         case 1: // end of bitmap
977           finish = true;
978           break;
979         case 0: // end of line
980           x = 0;
981           y++;
982           break;
983         case 2: // delta
984           if(DALI_UNLIKELY(fread(cmd, 1, cmdStride, fp) != cmdStride))
985           {
986             DALI_LOG_ERROR("Error reading the BMP image\n");
987             return false;
988           }
989           dx = cmd[0] & (0xFF);
990           dy = cmd[1] & (0xFF);
991           x += dx;
992           y += dy;
993           break;
994         default:
995           //decode a literal run
996           length     = cmd[1] & (0xFF);
997           copylength = length;
998           //absolute mode must be word-aligned
999           length += (length & 1);
1000           run.resize(length);
1001           if(DALI_UNLIKELY(fread(&run[0], 1, length, fp) != length))
1002           {
1003             DALI_LOG_ERROR("Error reading the BMP image\n");
1004             return false;
1005           }
1006
1007           for(std::uint32_t i = 0; i < length; ++i)
1008           {
1009             colorIndex[x + width * (height - y - 1) + i] = run[i];
1010           }
1011           x += copylength;
1012           break;
1013       }
1014     } // end if cmd[0] ==
1015     else
1016     {
1017       length = cmd[0] & (0xFF);
1018       for(std::uint32_t i = 0; i < length; ++i)
1019       {
1020         colorIndex[(height - y - 1) * width + x] = cmd[1];
1021         x++;
1022       }
1023     }
1024   }
1025   std::uint32_t ctIndex = 0;
1026   for(std::uint32_t index = 0; index < width * height; ++index)
1027   {
1028     ctIndex                  = colorIndex[index];
1029     pixelsPtr[3 * index]     = colorTable[4 * ctIndex + 2];
1030     pixelsPtr[3 * index + 1] = colorTable[4 * ctIndex + 1];
1031     pixelsPtr[3 * index + 2] = colorTable[4 * ctIndex];
1032   }
1033   return true;
1034 }
1035
1036 } // unnamed namespace
1037
1038 bool LoadBmpHeader(const Dali::ImageLoader::Input& input, unsigned int& width, unsigned int& height)
1039 {
1040   BmpFileHeader fileHeader;
1041   BmpInfoHeader infoHeader;
1042
1043   bool ret = LoadBmpHeader(input.file, width, height, fileHeader, infoHeader);
1044
1045   return ret;
1046 }
1047
1048 bool LoadBitmapFromBmp(const Dali::ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap)
1049 {
1050   //DALI_ASSERT_DEBUG( bitmap.GetPackedPixelsProfile() != 0 && "Need a packed pixel bitmap to load into." );
1051   FILE* const fp = input.file;
1052   if(DALI_UNLIKELY(fp == NULL))
1053   {
1054     DALI_LOG_ERROR("Error loading bitmap\n");
1055     return false;
1056   }
1057   BmpFormat     customizedFormat = BMP_NOTEXIST;
1058   BmpFileHeader fileHeader;
1059   BmpInfoHeader infoHeader;
1060
1061   // Load the header info
1062   unsigned int width, height;
1063
1064   if(DALI_UNLIKELY(!LoadBmpHeader(fp, width, height, fileHeader, infoHeader)))
1065   {
1066     return false;
1067   }
1068
1069   Pixel::Format pixelFormat = Pixel::RGB888;
1070   switch(infoHeader.compression)
1071   {
1072     case 0:
1073     {
1074       switch(infoHeader.bitsPerPixel)
1075       {
1076         case 32:
1077         {
1078           pixelFormat = Pixel::RGBA8888;
1079           break;
1080         }
1081
1082         case 24:
1083         {
1084           if(fileHeader.offset == FileHeaderOffsetOfRGB24V5) //0x8A
1085           {
1086             customizedFormat = BMP_RGB24V5;
1087           }
1088           else
1089           {
1090             pixelFormat = Pixel::RGB888;
1091           }
1092           break;
1093         }
1094
1095         case 16:
1096         {
1097           customizedFormat = BMP_RGB555;
1098           break;
1099         }
1100
1101         case 8:
1102         {
1103           customizedFormat = BMP_RGB8;
1104           break;
1105         }
1106
1107         case 4: // RGB4
1108         {
1109           customizedFormat = BMP_RGB4;
1110           break;
1111         }
1112
1113         case 1: //RGB1
1114         {
1115           customizedFormat = BMP_RGB1;
1116           break;
1117         }
1118
1119         default:
1120         {
1121           DALI_LOG_ERROR("%d bits per pixel not supported for BMP files\n", infoHeader.bitsPerPixel);
1122           return false;
1123         }
1124       }
1125       break;
1126     }
1127     case 1: //// RLE8
1128     {
1129       if(infoHeader.bitsPerPixel == 8)
1130       {
1131         customizedFormat = BMP_RLE8;
1132       }
1133       break;
1134     }
1135     case 2: // RLE4
1136     {
1137       if(infoHeader.bitsPerPixel == 4)
1138       {
1139         customizedFormat = BMP_RLE4;
1140       }
1141       break;
1142     }
1143     case 3: // // BI_BITFIELDS
1144     {
1145       if(infoHeader.bitsPerPixel == 16)
1146       {
1147         if(DALI_UNLIKELY(fseek(fp, 14 + infoHeader.infoHeaderSize + 1, SEEK_SET)))
1148         {
1149           return false;
1150         }
1151
1152         char mask;
1153         if(DALI_UNLIKELY(fread(&mask, 1, 1, fp) != 1))
1154         {
1155           return false;
1156         }
1157
1158         if((mask & 0x80) == MaskForBFRGB565) // mask is 0xF8
1159         {
1160           pixelFormat = Pixel::RGB565;
1161         }
1162         else if((mask & 0x80) == 0) // mask is 0x 7C
1163         {
1164           customizedFormat = BMP_BITFIELDS555;
1165         }
1166         else
1167         {
1168           return false;
1169         }
1170       }
1171       else if(infoHeader.bitsPerPixel == 32)
1172       {
1173         if(fileHeader.offset == FileHeaderOffsetOfBF32V4) // 0x7A
1174         {
1175           customizedFormat = BMP_BITFIELDS32V4;
1176         }
1177         else
1178         {
1179           customizedFormat = BMP_BITFIELDS32;
1180         }
1181       }
1182       break;
1183     }
1184     default:
1185     {
1186       DALI_LOG_ERROR("Compression not supported for BMP files\n");
1187       return false;
1188     }
1189   }
1190
1191   bool topDown = false;
1192
1193   // if height is negative, bitmap data is top down
1194   if(infoHeader.height < 0)
1195   {
1196     infoHeader.height = abs(infoHeader.height);
1197     height            = infoHeader.height;
1198     topDown           = true;
1199   }
1200
1201   unsigned int rowStride = infoHeader.width * (infoHeader.bitsPerPixel >> 3);
1202
1203   // bitmaps row stride is padded to 4 bytes
1204   unsigned int padding = (rowStride % 4);
1205   if(padding)
1206   {
1207     padding = 4 - padding;
1208   }
1209
1210   int  imageW         = infoHeader.width;
1211   int  pixelBufferW   = infoHeader.width;
1212   int  pixelBufferH   = infoHeader.height;
1213   auto newPixelFormat = Pixel::Format::INVALID;
1214
1215   switch(customizedFormat)
1216   {
1217     case BMP_RLE8:
1218     case BMP_RGB8:
1219     case BMP_RGB4:
1220     case BMP_RLE4:
1221     case BMP_RGB555:
1222     case BMP_BITFIELDS555:
1223     {
1224       pixelBufferW   = ((imageW & 3) != 0) ? imageW + 4 - (imageW & 3) : imageW;
1225       pixelBufferH   = abs(infoHeader.height);
1226       newPixelFormat = Pixel::RGB888;
1227       break;
1228     }
1229     case BMP_RGB1:
1230     {
1231       pixelBufferW   = ((imageW & 63) != 0) ? imageW + 64 - (imageW & 63) : imageW;
1232       pixelBufferH   = abs(infoHeader.height);
1233       newPixelFormat = Pixel::RGB888;
1234       break;
1235     }
1236     case BMP_BITFIELDS32:
1237     case BMP_BITFIELDS32V4:
1238     {
1239       pixelBufferH   = abs(infoHeader.height);
1240       newPixelFormat = Pixel::RGBA8888;
1241       break;
1242     }
1243     case BMP_RGB24V5:
1244     {
1245       newPixelFormat = Pixel::RGB888;
1246       break;
1247     }
1248     default:
1249     {
1250       if(pixelFormat == Pixel::RGB565)
1251       {
1252         pixelBufferW   = ((imageW & 3) != 0) ? imageW + 4 - (imageW & 3) : imageW;
1253         pixelBufferH   = abs(infoHeader.height);
1254         newPixelFormat = Pixel::RGB565;
1255       }
1256       else
1257       {
1258         pixelBufferW   = infoHeader.width;
1259         pixelBufferH   = infoHeader.height;
1260         newPixelFormat = pixelFormat;
1261       }
1262       break;
1263     }
1264   }
1265
1266   bitmap      = Dali::Devel::PixelBuffer::New(pixelBufferW, pixelBufferH, newPixelFormat);
1267   auto pixels = bitmap.GetBuffer();
1268
1269   // Read the raw bitmap data
1270   decltype(pixels) pixelsIterator = nullptr;
1271
1272   bool decodeResult(false);
1273   switch(customizedFormat)
1274   {
1275     case BMP_RGB1:
1276     {
1277       decodeResult = DecodeRGB1(fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1278       break;
1279     }
1280     case BMP_RGB4:
1281     {
1282       decodeResult = DecodeRGB4(fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1283       break;
1284     }
1285     case BMP_RLE4:
1286     {
1287       decodeResult = DecodeRLE4(fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1288       break;
1289     }
1290     case BMP_BITFIELDS32:
1291     {
1292       decodeResult = DecodeBF32(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown, rowStride, padding);
1293       break;
1294     }
1295     case BMP_BITFIELDS555:
1296     {
1297       decodeResult = DecodeBF555(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown);
1298       break;
1299     }
1300     case BMP_RGB555:
1301     {
1302       decodeResult = DecodeRGB555(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown);
1303       break;
1304     }
1305     case BMP_RGB8:
1306     {
1307       decodeResult = DecodeRGB8(fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1308       break;
1309     }
1310     case BMP_RLE8:
1311     {
1312       decodeResult = DecodeRLE8(fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1313       break;
1314     }
1315     case BMP_RGB24V5:
1316     {
1317       decodeResult = DecodeRGB24V5(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown, rowStride, padding);
1318       break;
1319     }
1320     case BMP_BITFIELDS32V4:
1321     {
1322       decodeResult = DecodeBF32V4(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown, rowStride, padding);
1323       break;
1324     }
1325     default:
1326     {
1327       if(pixelFormat == Pixel::RGB565)
1328       {
1329         decodeResult = DecodeBF565(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown);
1330       }
1331       else
1332       {
1333         for(unsigned int yPos = 0; yPos < height; yPos++)
1334         {
1335           if(topDown)
1336           {
1337             // the data in the file is top down, and we store the data top down
1338             pixelsIterator = pixels + (yPos * rowStride);
1339           }
1340           else
1341           {
1342             // the data in the file is bottom up, and we store the data top down
1343             pixelsIterator = pixels + (((height - 1) - yPos) * rowStride);
1344           }
1345
1346           if(DALI_UNLIKELY(fread(pixelsIterator, 1, rowStride, fp) != rowStride))
1347           {
1348             DALI_LOG_ERROR("Error reading the BMP image\n");
1349             break;
1350           }
1351
1352           // If 32 bit mode then swap Blue and Red pixels. And Alpha pixels must be ignored.
1353           // Reference : https://users.cs.fiu.edu/~czhang/teaching/cop4225/project_files/bitmap_format.htm
1354           // ... if the compression field of the bitmap is set to bi_rgb, ... the high byte in each dword is not used.
1355           // RGB8888 format doesn't seem to be supported by graphics-api
1356           if(infoHeader.bitsPerPixel == 32)
1357           {
1358             for(uint32_t i = 0; i < rowStride; i += 4)
1359             {
1360               uint8_t temp          = pixelsIterator[i];
1361               pixelsIterator[i]     = pixelsIterator[i + 2];
1362               pixelsIterator[i + 2] = temp;
1363               pixelsIterator[i + 3] = 255u;
1364             }
1365           }
1366
1367           // If 24 bit mode then swap Blue and Red pixels
1368           // BGR888 doesn't seem to be supported by dali-core
1369           if(infoHeader.bitsPerPixel == 24)
1370           {
1371             for(uint32_t i = 0; i < rowStride; i += 3)
1372             {
1373               uint8_t temp          = pixelsIterator[i];
1374               pixelsIterator[i]     = pixelsIterator[i + 2];
1375               pixelsIterator[i + 2] = temp;
1376             }
1377           }
1378
1379           if(padding)
1380           {
1381             if(DALI_UNLIKELY(fseek(fp, padding, SEEK_CUR))) // move past the padding.
1382             {
1383               DALI_LOG_ERROR("Error moving past BMP padding\n");
1384             }
1385           }
1386         }
1387         decodeResult = true;
1388       }
1389       break;
1390     }
1391   } // switch
1392
1393   if(DALI_UNLIKELY(!decodeResult))
1394   {
1395     DALI_LOG_ERROR("Decoding failed\n");
1396     return false;
1397   }
1398
1399   return true;
1400 }
1401
1402 } // namespace TizenPlatform
1403
1404 } // namespace Dali