2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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
8 // http://floralicense.org/license/
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.
17 #include "loader-bmp.h"
19 #include <dali/public-api/common/vector-wrapper.h>
20 #include <dali/integration-api/debug.h>
21 #include <dali/integration-api/bitmap.h>
22 #include <dali/public-api/images/image-attributes.h>
26 using Integration::Bitmap;
27 using Dali::Integration::PixelBuffer;
33 const unsigned int FileHeaderOffsetOfBF32V4 = 0x7A;
34 const unsigned int MaskForBFRGB565 = 0x80;
35 const unsigned int FileHeaderOffsetOfRGB24V5 = 0x8A;
39 BMP_RGB1 = 14, //BI_RGB & bpp =1
40 BMP_RGB4, //BI_RGB & bpp = 4
41 BMP_RGB8, //BI_RGB & bpp = 8
42 BMP_RGB555, //BI_RGB & bpp = 16
43 BMP_BITFIELDS555, //BI_BITFIELDS & 16bit & R:G:B = 5:5:5
44 BMP_BITFIELDS32, //BI_BITFIELDS & 32bit & R:G:B:A = 8:8:8:8
47 BMP_BITFIELDS32V4,//BI_BITFIELDS & 32bit
48 BMP_RGB24V5, //BI_RGB & bpp = 24 & bmp version5
54 unsigned short signature; // Bitmap file signature
55 unsigned int fileSize; // Bitmap file size in bytes
56 unsigned short reserved1; // Reserved bits
57 unsigned short reserved2; // Reserved bits
58 unsigned int offset; // Offset from BMP file header to BMP bits
59 } __attribute__ ( (__packed__)); // Stops the structure from being aligned to every 4 bytes
63 unsigned int infoHeaderSize; // Specifies the number of bytes required by the info header
64 unsigned int width; // The Image Width
65 int height; // The Image Height (negative value represents image data is flipped)
66 unsigned short planes; // The number of color planes, must be 1
67 unsigned short bitsPerPixel; // The bits per pixel
68 unsigned int compression; // The type of compression used by the image
69 unsigned int imageSize; // The size of the image in bytes
70 unsigned int xPixelsPerMeter; // The number of pixels per meter in x axis
71 unsigned int yPixelsPerMeter; // The number of pixels per meter in y axis
72 unsigned int numberOfColors; // The number of colors in the color table
73 unsigned int importantColors; // The important color count
74 } __attribute__ ( (__packed__)); // Stops the structure from being aligned to every 4 bytes
77 * Template function to read from the file directly into our structure.
78 * @param[in] fp The file to read from
79 * @param[out] header The structure we want to store our information in
80 * @return true, if read successful, false otherwise
83 inline bool ReadHeader(FILE* fp, T& header)
85 unsigned int readLength = sizeof(T);
87 // Load the information directly into our structure
88 if (fread((void*)&header, 1, readLength, fp) != readLength)
96 bool LoadBmpHeader(FILE *fp, unsigned int &width, unsigned int &height, BmpFileHeader &fileHeader, BmpInfoHeader &infoHeader)
98 if (!ReadHeader(fp, fileHeader))
103 if (!ReadHeader(fp, infoHeader))
108 width = infoHeader.width;
109 height = infoHeader.height;
115 * function to decode format BI_RGB & bpp = 24 & bmp version5.
116 * @param[in] fp The file to read from
117 * @param[out] pixels The pointer that we want to store bmp data in
118 * @param[in] width bmp width
119 * @param[in] height bmp height
120 * @param[in] offset offset from bmp header to bmp image data
121 * @param[in] topDown indicate image data is read from bottom or from top
122 * @param[in] padding padded to a u_int32 boundary for each line
123 * @return true, if decode successful, false otherwise
125 bool DecodeRGB24V5(FILE *fp,
131 unsigned int rowStride,
132 unsigned int padding)
134 if(fp == NULL || pixels == NULL)
136 DALI_LOG_ERROR("Error decoding BMP_RGB24V5 format\n");
139 PixelBuffer *pixelsPtr = pixels;
141 if ( fseek(fp, offset, SEEK_SET) )
143 DALI_LOG_ERROR("Error seeking BMP_RGB24V5 data\n");
147 for(unsigned int yPos = 0; yPos < height; yPos ++)
151 pixelsPtr = pixels + ( yPos * rowStride);
155 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
157 if (fread(pixelsPtr, 1, rowStride, fp) != rowStride)
159 DALI_LOG_ERROR("Error reading the BMP image\n");
162 for(unsigned int i = 0; i < rowStride; i += 3)
164 unsigned char temp = pixelsPtr[i];
165 pixelsPtr[i] = pixelsPtr[i + 2];
166 pixelsPtr[i + 2] = temp;
171 // move past the padding.
172 if( fseek(fp, padding, SEEK_CUR) )
174 DALI_LOG_ERROR("Error moving past BMP_RGB24V5 padding\n");
182 * function to decode format BI_BITFIELDS & bpp = 32 & bmp version4.
183 * @param[in] fp The file to read from
184 * @param[out] pixels The pointer that we want to store bmp data in
185 * @param[in] width bmp width
186 * @param[in] height bmp height
187 * @param[in] offset offset from bmp header to bmp image data
188 * @param[in] topDown indicate image data is read from bottom or from top
189 * @param[in] rowStride bits span for each line
190 * @param[in] padding padded to a u_int32 boundary for each line
191 * @return true, if decode successful, false otherwise
193 bool DecodeBF32V4(FILE *fp,
199 unsigned int rowStride,
200 unsigned int padding)
202 if(fp == NULL || pixels == NULL)
204 DALI_LOG_ERROR("Error decoding BMP_BITFIELDS32V4 format\n");
207 PixelBuffer *pixelsPtr = pixels;
209 if( fseek(fp, offset, SEEK_SET) )
211 DALI_LOG_ERROR("Error seeking BMP_BITFIELDS32V4 data\n");
215 for(unsigned int yPos = 0; yPos < height; yPos ++)
219 pixelsPtr = pixels + ( yPos * rowStride);
223 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
225 if (fread(pixelsPtr, 1, rowStride, fp) != rowStride)
227 DALI_LOG_ERROR("Error reading the BMP image\n");
230 for(unsigned int i = 0; i < rowStride; i += 4)
232 unsigned char temp = pixelsPtr[i];
233 pixelsPtr[i] = pixelsPtr[i + 2];
234 pixelsPtr[i + 2] = temp;
238 // move past the padding.
239 if( fseek(fp, padding, SEEK_CUR) )
241 DALI_LOG_ERROR("Error moving past BMP_BITFIELDS32V4 padding\n");
250 * function to decode format BI_BITFIELDS & bpp = 32
251 * @param[in] fp The file to read from
252 * @param[out] pixels The pointer that we want to store bmp data in
253 * @param[in] width bmp width
254 * @param[in] height bmp height
255 * @param[in] offset offset from bmp header to bmp image data
256 * @param[in] topDown indicate image data is read from bottom or from top
257 * @param[in] rowStride bits span for each line
258 * @param[in] padding padded to a u_int32 boundary for each line
259 * @return true, if decode successful, false otherwise
261 bool DecodeBF32(FILE *fp,
267 unsigned int rowStride,
268 unsigned int padding)
270 if(fp == NULL || pixels == NULL)
272 DALI_LOG_ERROR("Error decoding BMP_BITFIELDS32 format\n");
275 PixelBuffer *pixelsPtr = pixels;
277 if( fseek(fp, offset, SEEK_SET) )
279 DALI_LOG_ERROR("Error seeking BMP_BITFIELDS32 data\n");
283 for (unsigned int yPos = 0; yPos < height; yPos++)
287 // the data in the file is top down, and we store the data top down
288 pixelsPtr = pixels + ( yPos * rowStride);
292 // the data in the file is bottom up, and we store the data top down
293 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
296 if (fread(pixelsPtr, 1, rowStride, fp) != rowStride)
298 DALI_LOG_ERROR("Error reading the BMP image\n");
301 for(unsigned int i = 0; i < rowStride; i += 4)
303 unsigned char temp = pixelsPtr[i];
304 pixelsPtr[i] = pixelsPtr[i + 2];
305 pixelsPtr[i + 2] = temp;
310 // move past the padding.
311 if( fseek(fp, padding, SEEK_CUR) )
313 DALI_LOG_ERROR("Error moving past BMP_BITFIELDS32 padding\n");
321 * function to decode format BI_BITFIELDS & bpp = 16 & R:G:B = 5:6:5
322 * @param[in] fp The file to read from
323 * @param[out] pixels The pointer that we want to store bmp data in
324 * @param[in] width bmp width
325 * @param[in] height bmp height
326 * @param[in] offset offset from bmp header to bmp image data
327 * @param[in] topDown indicate image data is read from bottom or from top
328 * @return true, if decode successful, false otherwise
330 bool DecodeBF565(FILE *fp,
337 if(fp == NULL || pixels == NULL)
339 DALI_LOG_ERROR("Error decoding RGB565 format\n");
342 PixelBuffer *pixelsPtr = pixels;
343 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
344 unsigned int rowStride = width * 2;
346 if( fseek(fp, offset, SEEK_SET) )
348 DALI_LOG_ERROR("Error seeking RGB565 data\n");
352 for(unsigned int i = 0; i < height; i++)
356 // the data in the file is top down, and we store the data top down
357 pixelsPtr = pixels + ( i * rowStride);
361 // the data in the file is bottom up, and we store the data top down
362 pixelsPtr = pixels + (((height - 1) - i) * rowStride);
364 if(fread(pixelsPtr, 1, rowStride, fp) != rowStride)
374 * function to decode format BI_BITFIELDS & bpp = 16 & R:G:B = 5:5:5
375 * @param[in] fp The file to read from
376 * @param[out] pixels The pointer that we want to store bmp data in
377 * @param[in] width bmp width
378 * @param[in] height bmp height
379 * @param[in] offset offset from bmp header to bmp image data
380 * @param[in] topDown indicate image data is read from bottom or from top
381 * @return true, if decode successful, false otherwise
383 bool DecodeBF555(FILE *fp,
390 if(fp == NULL || pixels == NULL)
392 DALI_LOG_ERROR("Error decoding BMP_BITFIELDS555 format\n");
395 PixelBuffer *pixelsPtr = pixels;
397 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
399 std::vector<char> raw(width * height * 2);
400 char *rawPtr = &raw[0];
401 unsigned int rawStride = width * 2;
402 unsigned int rowStride = width * 3;
404 if( fseek(fp, offset, SEEK_SET) )
406 DALI_LOG_ERROR("Error seeking BMP_BITFIELDS555 data\n");
410 for(unsigned int j = 0; j < height; j ++)
412 rawPtr = &raw[0] + ( j * rawStride);
413 if(fread(rawPtr, 1, rawStride, fp) != rawStride)
419 for (unsigned int yPos = 0; yPos < height; yPos++)
423 // the data in the file is top down, and we store the data top down
424 pixelsPtr = pixels + ( yPos * rowStride);
428 // the data in the file is bottom up, and we store the data top down
429 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
432 for(unsigned int k = 0; k < width; k ++)
434 int index = yPos * rawStride + 2 * k;
435 pixelsPtr[3 * k] = ((raw[ index + 1] >> 2) & 0x1F) * 0xFF / 0x1F;
436 pixelsPtr[3 * k + 1] = (((raw[index + 1] & 0x03) << 3) | (raw[ index] >> 5)) * 0xFF/ 0x1F;
437 pixelsPtr[3 * k + 2] = (raw[ index] & 0x1F) * 0xFF / 0x1F;
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
454 bool DecodeRGB555(FILE *fp,
461 if(fp == NULL || pixels == NULL)
463 DALI_LOG_ERROR("Error decoding BMP_RGB555 format\n");
466 PixelBuffer *pixelsPtr = pixels;
467 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
468 std::vector<char> raw(width * height * 2);
469 char *rawPtr = &raw[0];
470 unsigned int rawStride = width * 2;
471 unsigned int rowStride = width * 3;
473 if( fseek(fp, offset, SEEK_SET) )
475 DALI_LOG_ERROR("Error seeking BMP_RGB555 data\n");
479 for(unsigned int j = 0; j < height; j ++)
481 rawPtr = &raw[0] + ( j * rawStride);
482 if(fread(rawPtr, 1, rawStride, fp) != rawStride)
487 for(unsigned int i = 0; i < height; i++)
491 // the data in the file is top down, and we store the data top down
492 pixelsPtr = pixels + ( i * rowStride);
496 // the data in the file is bottom up, and we store the data top down
497 pixelsPtr = pixels + (((height - 1) - i) * rowStride);
499 for(unsigned int k = 0; k < width; k ++)
501 int 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;
512 * function to decode format BI_RGB & bpp = 1
513 * @param[in] fp The file to read from
514 * @param[out] pixels The pointer that we want to store bmp data in
515 * @param[in] width bmp width
516 * @param[in] height bmp height
517 * @param[in] offset offset from bmp header to bmp palette data
518 * @param[in] topDown indicate image data is read from bottom or from top
519 * @return true, if decode successful, false otherwise
521 bool DecodeRGB1(FILE *fp,
528 if(fp == NULL || pixels == NULL)
530 DALI_LOG_ERROR("Error decoding BMP_RGB1 format\n");
533 PixelBuffer *pixelsPtr = pixels;
534 unsigned char colorTable[8] = {0};
536 unsigned int fillw = ((width & 63) != 0) ? width + 64 - (width & 63) : width;
537 std::vector<char> colorIndex(fillw * height);
538 unsigned int rowStride = fillw * 3; // RGB
540 if( fseek(fp, offset, SEEK_SET) )
542 DALI_LOG_ERROR("Error seeking BMP_RGB1 data\n");
546 if(fread(colorTable, 1, 8, fp) != 8)
551 for(unsigned int i = 0; i < fillw * height; i += 8)
553 if(fread(&cmd, 1, 1, fp) != 1)
558 colorIndex[i] = (cmd >> 7) & 0x01;
559 colorIndex[i + 1] = (cmd >> 6) & 0x01;
560 colorIndex[i + 2] = (cmd >> 5) & 0x01;
561 colorIndex[i + 3] = (cmd >> 4) & 0x01;
562 colorIndex[i + 4] = (cmd >> 3) & 0x01;
563 colorIndex[i + 5] = (cmd >> 2) & 0x01;
564 colorIndex[i + 6] = (cmd >> 1) & 0x01;
565 colorIndex[i + 7] = (cmd & 0x01);
568 for(unsigned int index = 0; index < height; index = index + 1)
572 // the data in the file is top down, and we store the data top down
573 pixelsPtr = pixels + ( index * rowStride);
577 // the data in the file is bottom up, and we store the data top down
578 pixelsPtr = pixels + (((height - 1) - index) * rowStride);
580 for(unsigned int j = 0; j < fillw; j ++)
583 if((fillw * index + j ) < (fillw * height))
585 ctIndex = colorIndex[ fillw * index + j ];
591 // temp solution for PLM bug P130411-5268, there is one mono bmp that cause DecodeRGB1 API crash.
592 if( ((3 * j + 2) < height * fillw * 3) && (ctIndex < 2))
594 pixelsPtr[ 3 * j ] = colorTable[4 * ctIndex + 2];
595 pixelsPtr[3 * j + 1] = colorTable[4 * ctIndex + 1];
596 pixelsPtr[3 * j + 2] = colorTable[4 * ctIndex ];
604 * function to decode format BI_RGB & bpp = 4
605 * @param[in] fp The file to read from
606 * @param[out] pixels The pointer that we want to store bmp data in
607 * @param[in] width bmp width
608 * @param[in] height bmp height
609 * @param[in] offset offset from bmp header to bmp palette data
610 * @param[in] topDown indicate image data is read from bottom or from top
611 * @return true, if decode successful, false otherwise
613 bool DecodeRGB4(FILE *fp,
620 if(fp == NULL || pixels == NULL)
622 DALI_LOG_ERROR("Error decoding BMP_RGB4 format\n");
625 PixelBuffer *pixelsPtr = pixels;
628 unsigned int fillw = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
629 std::vector<char> colorIndex(fillw * height);
630 unsigned int rowStride = fillw * 3;
632 if( fseek(fp, offset, SEEK_SET) )
634 DALI_LOG_ERROR("Error seeking BMP_RGB4 data\n");
638 if(fread(colorTable, 1, 64, fp) != 64)
643 for(unsigned int i = 0; i < fillw * height; i += 2)
645 if (fread(&cmd, 1, 1, fp) != 1)
650 colorIndex[i] = cmd >> 4;
651 colorIndex[i + 1] = cmd & (0x0F);
655 for(unsigned int index = 0; index < height; index = index + 1)
659 // the data in the file is top down, and we store the data top down
660 pixelsPtr = pixels + ( index * rowStride);
664 // the data in the file is bottom up, and we store the data top down
665 pixelsPtr = pixels + (((height - 1) - index) * rowStride);
667 for(unsigned int j = 0; j < fillw; j ++)
669 ctIndex = colorIndex[ fillw * index + j ];
670 pixelsPtr[ 3 * j ] = colorTable[4 * ctIndex + 2];
671 pixelsPtr[(3 * j + 1)] = colorTable[4 * ctIndex + 1];
672 pixelsPtr[(3 * j + 2)] = colorTable[4 * ctIndex ];
680 * function to decode format BI_RGB & bpp = 8
681 * @param[in] fp The file to read from
682 * @param[out] pixels The pointer that we want to store bmp data in
683 * @param[in] width bmp width
684 * @param[in] height bmp height
685 * @param[in] offset offset from bmp header to bmp palette data
686 * @param[in] topDown indicate image data is read from bottom or from top
687 * @return true, if decode successful, false otherwise
689 bool DecodeRGB8(FILE *fp,
696 if(fp == NULL || pixels == NULL)
698 DALI_LOG_ERROR("Error decoding BMP_RGB8 format\n");
701 PixelBuffer *pixelsPtr = pixels;
702 std::vector<char> colorTable(1024);
703 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
705 std::vector<char> colorIndex(width * height);
706 unsigned int rowStride = width * 3;//RGB8->RGB24
708 if( fseek(fp, offset, SEEK_SET) )
710 DALI_LOG_ERROR("Error seeking BMP_RGB8 data\n");
714 if(fread(&colorTable[0], 1, 1024, fp) != 1024)
718 for(unsigned int i = 0; i < width * height; i ++)
720 if (fread(&cmd, 1, 1, fp) != 1)
728 for(unsigned int index = 0; index < height; index = index + 1)
732 // the data in the file is top down, and we store the data top down
733 pixelsPtr = pixels + ( index * rowStride);
737 // the data in the file is bottom up, and we store the data top down
738 pixelsPtr = pixels + (((height - 1) - index) * rowStride);
740 for(unsigned int j = 0; j < width; j ++)
742 ctIndex = colorIndex[ width * index + j ];
743 pixelsPtr[ 3 * j ] = colorTable[4 * ctIndex + 2];
744 pixelsPtr[(3 * j + 1)] = colorTable[4 * ctIndex + 1];
745 pixelsPtr[(3 * j + 2)] = colorTable[4 * ctIndex ];
752 * function to decode format BI_RLE4 & bpp = 4
753 * @param[in] fp The file to read from
754 * @param[out] pixels The pointer that we want to store bmp data in
755 * @param[in] width bmp width
756 * @param[in] height bmp height
757 * @param[in] offset offset from bmp header to bmp palette data
758 * @param[in] topDown indicate image data is read from bottom or from top
759 * @return true, if decode successful, false otherwise
761 bool DecodeRLE4(FILE *fp,
768 if(fp == NULL || pixels == NULL)
770 DALI_LOG_ERROR("Error decoding BMP_RLE4 format\n");
773 PixelBuffer *pixelsPtr = pixels;
774 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
776 unsigned int cmdStride = 2;
778 std::vector<char> colorIndex(width * height >> 1);
779 std::vector<char> run;
784 width += (width & 1);
789 if( fseek(fp, offset, SEEK_SET) )
791 DALI_LOG_ERROR("Error seeking BMP_RLE4 data\n");
795 if (fread(colorTable, 1, 64, fp) != 64)
800 while((x >> 1) + y * width < width * height)
806 if (fread(cmd, 1, cmdStride, fp) != cmdStride)
810 if(cmd[0] == 0) // ESCAPE
814 case 1: //end of bitmap
817 case 0: // end of line
822 if (fread(cmd, 1, cmdStride, fp) != cmdStride)
824 DALI_LOG_ERROR("Error reading the BMP image\n");
827 dx = cmd[0] & (0xFF);
828 dy = cmd[1] & (0xFF);
833 // decode a literal run
834 unsigned int length = cmd[1] & (0xFF);
835 //size of run, which is word aligned
836 unsigned int bytesize = length;
837 bytesize += (bytesize & 1);
839 bytesize += (bytesize & 1);
840 run.resize(bytesize);
841 if(fread(&run[0], 1, bytesize, fp) != bytesize)
843 DALI_LOG_ERROR("Error reading the BMP image\n");
848 length += (length & 1);
850 for(unsigned int i = 0; i < length; i += 1)
852 colorIndex[(x >> 1) + width * (height - y - 1) + i] = run[i];
857 for(unsigned int i = 0; i < length; i ++)
859 if((i & 1) == 0)//copy high to low
861 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((run[i >> 1] & 0xF0) >> 4);
863 else //copy low to high
865 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((run[i >> 1] & 0x0F) << 4);
869 x += cmd[1] & (0xFF);
875 unsigned int length = cmd[0] & (0xFF);
878 length += (length & 1);
880 for(unsigned int i = 0; i < length; i ++)
882 colorIndex[(height-y-1)*width + i + (x >> 1)] = cmd[1];
887 for(unsigned int i = 0; i < length; i ++)
891 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((cmd[1] & 0xF0) >> 4);
895 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((cmd[1] & 0x0F) << 4);
899 x += cmd[0] & (0xFF);
905 for(unsigned int index = 0; index < (width * height ); index = index + 1)
907 ctIndexHigh = colorIndex[ index] >> 4;
908 ctIndexLow = colorIndex[index] & (0x0F);
909 pixelsPtr[6 * index ] = colorTable[4 * ctIndexHigh + 2];
910 pixelsPtr[6 * index + 1] = colorTable[4 * ctIndexHigh + 1];
911 pixelsPtr[6 * index + 2] = colorTable[4 * ctIndexHigh ];
912 pixelsPtr[6 * index + 3] = colorTable[4 * ctIndexLow + 2];
913 pixelsPtr[6 * index + 4] = colorTable[4 * ctIndexLow + 1];
914 pixelsPtr[6 * index + 5] = colorTable[4 * ctIndexLow ];
920 * function to decode format BI_RLE8 & bpp = 8
921 * @param[in] fp The file to read from
922 * @param[out] pixels The pointer that we want to store bmp data in
923 * @param[in] width bmp width
924 * @param[in] height bmp height
925 * @param[in] offset offset from bmp header to bmp palette data
926 * @param[in] topDown indicate image data is read from bottom or from top
927 * @return true, if decode successful, false otherwise
929 bool DecodeRLE8(FILE *fp,
936 if(fp == NULL || pixels == NULL)
938 DALI_LOG_ERROR("Error decoding BMP_RLE8 format\n");
941 PixelBuffer *pixelsPtr = pixels;
944 unsigned int cmdStride = 2;
946 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
947 std::vector<char> colorTable(1024);
949 std::vector<char> colorIndex(width * height);
951 if( fseek(fp, offset, SEEK_SET) )
953 DALI_LOG_ERROR("Error seeking BMP_RLE8 data\n");
957 if (fread(&colorTable[0], 1, 1024, fp) != 1024)
965 unsigned int length = 0;
966 unsigned int copylength = 0;
967 std::vector<char> run;
968 while((x + y * width) < width * height )
974 if (fread(cmd, 1, cmdStride, fp) != cmdStride)
979 if(cmd[0] == 0)//ESCAPE
983 case 1: // end of bitmap
986 case 0: // end of line
991 if (fread(cmd, 1, cmdStride, fp) != cmdStride)
993 DALI_LOG_ERROR("Error reading the BMP image\n");
996 dx = cmd[0] & (0xFF);
997 dy = cmd[1] & (0xFF);
1002 //decode a literal run
1003 length = cmd[1] & (0xFF);
1004 copylength = length;
1005 //absolute mode must be word-aligned
1006 length += (length & 1);
1008 if(fread(&run[0], 1, length, fp) != length)
1010 DALI_LOG_ERROR("Error reading the BMP image\n");
1014 for(unsigned int i = 0; i < length; i += 1)
1016 colorIndex[x + width * (height - y - 1) + i] = run[i];
1021 }// end if cmd[0] ==
1024 length = cmd[0] & (0xFF);
1025 for(unsigned int i = 0; i < length; i ++)
1027 colorIndex[(height - y - 1) * width + x] = cmd[1];
1033 for(unsigned int index = 0; index < width * height; index = index + 1)
1035 ctIndex = colorIndex[ index];
1036 pixelsPtr[3 * index ] = colorTable[4 * ctIndex + 2];
1037 pixelsPtr[3 * index + 1] = colorTable[4 * ctIndex + 1];
1038 pixelsPtr[3 * index + 2] = colorTable[4 * ctIndex ];
1043 } // unnamed namespace
1045 bool LoadBmpHeader(FILE *fp, const ImageAttributes& attributes, unsigned int &width, unsigned int &height)
1047 BmpFileHeader fileHeader;
1048 BmpInfoHeader infoHeader;
1050 bool ret = LoadBmpHeader(fp, width, height, fileHeader, infoHeader);
1055 bool LoadBitmapFromBmp(FILE *fp, Bitmap& bitmap, ImageAttributes& attributes)
1057 DALI_ASSERT_DEBUG(bitmap.GetPackedPixelsProfile() != 0 && "Need a packed pixel bitmap to load into.");
1060 DALI_LOG_ERROR("Error loading bitmap\n");
1063 BmpFormat customizedFormat = BMP_NOTEXIST;
1064 BmpFileHeader fileHeader;
1065 BmpInfoHeader infoHeader;
1067 // Load the header info
1068 unsigned int width, height;
1070 if (!LoadBmpHeader(fp, width, height, fileHeader, infoHeader))
1075 Pixel::Format pixelFormat = Pixel::RGB888;
1076 switch(infoHeader.compression)
1079 switch (infoHeader.bitsPerPixel)
1082 pixelFormat = Pixel::BGR8888;
1086 if(fileHeader.offset == FileHeaderOffsetOfRGB24V5)//0x8A
1088 customizedFormat = BMP_RGB24V5;
1092 pixelFormat = Pixel::RGB888;
1097 customizedFormat = BMP_RGB555;
1101 customizedFormat = BMP_RGB8;
1105 customizedFormat = BMP_RGB4;
1109 customizedFormat = BMP_RGB1;
1112 DALI_LOG_WARNING("%d bits per pixel not supported for BMP files\n", infoHeader.bitsPerPixel);
1118 if(infoHeader.bitsPerPixel == 8)
1120 customizedFormat = BMP_RLE8;
1126 if(infoHeader.bitsPerPixel == 4)
1128 customizedFormat = BMP_RLE4;
1132 case 3: // // BI_BITFIELDS
1134 if(infoHeader.bitsPerPixel == 16)
1136 if( fseek(fp, 14 + infoHeader.infoHeaderSize + 1, SEEK_SET) )
1142 if(fread(&mask, 1, 1, fp) != 1)
1147 if((mask & 0x80) == MaskForBFRGB565) // mask is 0xF8
1149 pixelFormat = Pixel::RGB565;
1151 else if((mask & 0x80) == 0)// mask is 0x 7C
1153 customizedFormat = BMP_BITFIELDS555;
1160 else if(infoHeader.bitsPerPixel == 32)
1162 if(fileHeader.offset == FileHeaderOffsetOfBF32V4)// 0x7A
1164 customizedFormat = BMP_BITFIELDS32V4;
1168 customizedFormat = BMP_BITFIELDS32;
1174 DALI_LOG_WARNING("Compression not supported for BMP files\n");
1178 bool topDown = false;
1180 // if height is negative, bitmap data is top down
1181 if (infoHeader.height<0)
1183 infoHeader.height = abs(infoHeader.height);
1184 height = infoHeader.height;
1188 unsigned int rowStride = infoHeader.width * (infoHeader.bitsPerPixel >>3);
1190 // bitmaps row stride is padded to 4 bytes
1191 unsigned int padding = (rowStride % 4);
1194 padding = 4 - padding;
1197 PixelBuffer *pixels = NULL;
1198 int imageW = infoHeader.width;
1199 int pixelBufferW = 0;
1200 switch(customizedFormat)
1207 case BMP_BITFIELDS555:
1209 pixelBufferW = ((imageW & 3) != 0) ? imageW + 4 - (imageW & 3) : imageW;
1210 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB888, pixelBufferW, abs(infoHeader.height));
1215 pixelBufferW = ((imageW & 63) != 0) ? imageW + 64 - (imageW & 63) : imageW;
1216 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB888, pixelBufferW, abs(infoHeader.height));
1219 case BMP_BITFIELDS32:
1220 case BMP_BITFIELDS32V4:
1222 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB8888, infoHeader.width, abs(infoHeader.height));
1227 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB888, infoHeader.width, infoHeader.height);
1231 if(pixelFormat == Pixel::RGB565 )
1233 pixelBufferW = ((imageW & 3) != 0) ? imageW + 4 - (imageW & 3) : imageW;
1234 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB565, pixelBufferW, abs(infoHeader.height));
1238 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(pixelFormat, infoHeader.width, infoHeader.height);
1243 // TODO: Add scaling support
1245 // Read the raw bitmap data
1246 PixelBuffer *pixelsPtr;
1247 bool decodeResult(false);
1248 switch(customizedFormat)
1252 decodeResult = DecodeRGB1( fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1257 decodeResult = DecodeRGB4(fp, pixels, infoHeader.width, infoHeader.height, 14 + infoHeader.infoHeaderSize, topDown);
1262 decodeResult = DecodeRLE4( fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1265 case BMP_BITFIELDS32:
1267 decodeResult = DecodeBF32(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown, rowStride, padding);
1270 case BMP_BITFIELDS555:
1272 decodeResult = DecodeBF555(fp, pixels,infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown);
1277 decodeResult = DecodeRGB555(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown);
1282 decodeResult = DecodeRGB8(fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1287 decodeResult = DecodeRLE8(fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1292 decodeResult = DecodeRGB24V5(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown, rowStride, padding);
1295 case BMP_BITFIELDS32V4:
1297 decodeResult = DecodeBF32V4(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown, rowStride, padding);
1302 if(pixelFormat == Pixel::RGB565)
1304 decodeResult = DecodeBF565(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown);
1308 for (unsigned int yPos = 0; yPos < height; yPos++)
1312 // the data in the file is top down, and we store the data top down
1313 pixelsPtr = pixels + ( yPos * rowStride);
1317 // the data in the file is bottom up, and we store the data top down
1318 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
1321 if (fread(pixelsPtr, 1, rowStride, fp) != rowStride)
1323 DALI_LOG_ERROR("Error reading the BMP image\n");
1327 // If 24 bit mode then swap Blue and Red pixels
1328 // BGR888 doesn't seem to be supported by dali-core
1329 if (infoHeader.bitsPerPixel == 24 )
1331 for(unsigned int i = 0; i < rowStride; i += 3)
1333 unsigned char temp = pixelsPtr[i];
1334 pixelsPtr[i] = pixelsPtr[i+2];
1335 pixelsPtr[i+2] = temp;
1341 if( fseek(fp, padding, SEEK_CUR) ) // move past the padding.
1343 DALI_LOG_ERROR("Error moving past BMP padding\n");
1347 decodeResult = true;
1358 attributes.SetSize(infoHeader.width, infoHeader.height);
1359 attributes.SetPixelFormat(pixelFormat);
1361 switch(customizedFormat)
1369 case BMP_BITFIELDS555:
1371 attributes.SetPixelFormat(Pixel::RGB888);
1373 case BMP_BITFIELDS32:
1374 case BMP_BITFIELDS32V4:
1375 attributes.SetPixelFormat(Pixel::RGB8888);
1383 } // namespace SlpPlatform