2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "loader-bmp.h"
20 #include <dali/public-api/common/vector-wrapper.h>
21 #include <dali/integration-api/debug.h>
22 #include <dali/integration-api/bitmap.h>
23 #include <dali/public-api/images/image-attributes.h>
27 using Integration::Bitmap;
28 using Dali::Integration::PixelBuffer;
34 const unsigned int FileHeaderOffsetOfBF32V4 = 0x7A;
35 const unsigned int MaskForBFRGB565 = 0x80;
36 const unsigned int FileHeaderOffsetOfRGB24V5 = 0x8A;
40 BMP_RGB1 = 14, //BI_RGB & bpp =1
41 BMP_RGB4, //BI_RGB & bpp = 4
42 BMP_RGB8, //BI_RGB & bpp = 8
43 BMP_RGB555, //BI_RGB & bpp = 16
44 BMP_BITFIELDS555, //BI_BITFIELDS & 16bit & R:G:B = 5:5:5
45 BMP_BITFIELDS32, //BI_BITFIELDS & 32bit & R:G:B:A = 8:8:8:8
48 BMP_BITFIELDS32V4,//BI_BITFIELDS & 32bit
49 BMP_RGB24V5, //BI_RGB & bpp = 24 & bmp version5
55 unsigned short signature; // Bitmap file signature
56 unsigned int fileSize; // Bitmap file size in bytes
57 unsigned short reserved1; // Reserved bits
58 unsigned short reserved2; // Reserved bits
59 unsigned int offset; // Offset from BMP file header to BMP bits
60 } __attribute__ ( (__packed__)); // Stops the structure from being aligned to every 4 bytes
64 unsigned int infoHeaderSize; // Specifies the number of bytes required by the info header
65 unsigned int width; // The Image Width
66 int height; // The Image Height (negative value represents image data is flipped)
67 unsigned short planes; // The number of color planes, must be 1
68 unsigned short bitsPerPixel; // The bits per pixel
69 unsigned int compression; // The type of compression used by the image
70 unsigned int imageSize; // The size of the image in bytes
71 unsigned int xPixelsPerMeter; // The number of pixels per meter in x axis
72 unsigned int yPixelsPerMeter; // The number of pixels per meter in y axis
73 unsigned int numberOfColors; // The number of colors in the color table
74 unsigned int importantColors; // The important color count
75 } __attribute__ ( (__packed__)); // Stops the structure from being aligned to every 4 bytes
78 * Template function to read from the file directly into our structure.
79 * @param[in] fp The file to read from
80 * @param[out] header The structure we want to store our information in
81 * @return true, if read successful, false otherwise
84 inline bool ReadHeader(FILE* fp, T& header)
86 unsigned int readLength = sizeof(T);
88 // Load the information directly into our structure
89 if (fread((void*)&header, 1, readLength, fp) != readLength)
97 bool LoadBmpHeader(FILE *fp, unsigned int &width, unsigned int &height, BmpFileHeader &fileHeader, BmpInfoHeader &infoHeader)
99 if (!ReadHeader(fp, fileHeader))
104 if (!ReadHeader(fp, infoHeader))
109 width = infoHeader.width;
110 height = infoHeader.height;
116 * function to decode format BI_RGB & bpp = 24 & bmp version5.
117 * @param[in] fp The file to read from
118 * @param[out] pixels The pointer that we want to store bmp data in
119 * @param[in] width bmp width
120 * @param[in] height bmp height
121 * @param[in] offset offset from bmp header to bmp image data
122 * @param[in] topDown indicate image data is read from bottom or from top
123 * @param[in] padding padded to a u_int32 boundary for each line
124 * @return true, if decode successful, false otherwise
126 bool DecodeRGB24V5(FILE *fp,
132 unsigned int rowStride,
133 unsigned int padding)
135 if(fp == NULL || pixels == NULL)
137 DALI_LOG_ERROR("Error decoding BMP_RGB24V5 format\n");
140 if ( fseek(fp, offset, SEEK_SET) )
142 DALI_LOG_ERROR("Error seeking BMP_RGB24V5 data\n");
146 for(unsigned int yPos = 0; yPos < height; yPos ++)
148 PixelBuffer *pixelsPtr = NULL;
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 if( fseek(fp, offset, SEEK_SET) )
209 DALI_LOG_ERROR("Error seeking BMP_BITFIELDS32V4 data\n");
213 for(unsigned int yPos = 0; yPos < height; yPos ++)
215 PixelBuffer *pixelsPtr = NULL;
218 pixelsPtr = pixels + ( yPos * rowStride);
222 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
224 if (fread(pixelsPtr, 1, rowStride, fp) != rowStride)
226 DALI_LOG_ERROR("Error reading the BMP image\n");
229 for(unsigned int i = 0; i < rowStride; i += 4)
231 unsigned char temp = pixelsPtr[i];
232 pixelsPtr[i] = pixelsPtr[i + 2];
233 pixelsPtr[i + 2] = temp;
237 // move past the padding.
238 if( fseek(fp, padding, SEEK_CUR) )
240 DALI_LOG_ERROR("Error moving past BMP_BITFIELDS32V4 padding\n");
249 * function to decode format BI_BITFIELDS & bpp = 32
250 * @param[in] fp The file to read from
251 * @param[out] pixels The pointer that we want to store bmp data in
252 * @param[in] width bmp width
253 * @param[in] height bmp height
254 * @param[in] offset offset from bmp header to bmp image data
255 * @param[in] topDown indicate image data is read from bottom or from top
256 * @param[in] rowStride bits span for each line
257 * @param[in] padding padded to a u_int32 boundary for each line
258 * @return true, if decode successful, false otherwise
260 bool DecodeBF32(FILE *fp,
266 unsigned int rowStride,
267 unsigned int padding)
269 if(fp == NULL || pixels == NULL)
271 DALI_LOG_ERROR("Error decoding BMP_BITFIELDS32 format\n");
274 if( fseek(fp, offset, SEEK_SET) )
276 DALI_LOG_ERROR("Error seeking BMP_BITFIELDS32 data\n");
280 for (unsigned int yPos = 0; yPos < height; yPos++)
282 PixelBuffer *pixelsPtr;
285 // the data in the file is top down, and we store the data top down
286 pixelsPtr = pixels + ( yPos * rowStride);
290 // the data in the file is bottom up, and we store the data top down
291 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
294 if (fread(pixelsPtr, 1, rowStride, fp) != rowStride)
296 DALI_LOG_ERROR("Error reading the BMP image\n");
299 for(unsigned int i = 0; i < rowStride; i += 4)
301 unsigned char temp = pixelsPtr[i];
302 pixelsPtr[i] = pixelsPtr[i + 2];
303 pixelsPtr[i + 2] = temp;
308 // move past the padding.
309 if( fseek(fp, padding, SEEK_CUR) )
311 DALI_LOG_ERROR("Error moving past BMP_BITFIELDS32 padding\n");
319 * function to decode format BI_BITFIELDS & bpp = 16 & R:G:B = 5:6:5
320 * @param[in] fp The file to read from
321 * @param[out] pixels The pointer that we want to store bmp data in
322 * @param[in] width bmp width
323 * @param[in] height bmp height
324 * @param[in] offset offset from bmp header to bmp image data
325 * @param[in] topDown indicate image data is read from bottom or from top
326 * @return true, if decode successful, false otherwise
328 bool DecodeBF565(FILE *fp,
335 if(fp == NULL || pixels == NULL)
337 DALI_LOG_ERROR("Error decoding RGB565 format\n");
340 if( fseek(fp, offset, SEEK_SET) )
342 DALI_LOG_ERROR("Error seeking RGB565 data\n");
346 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
347 unsigned int rowStride = width * 2;
349 for(unsigned int i = 0; i < height; i++)
351 PixelBuffer *pixelsPtr = NULL;
354 // the data in the file is top down, and we store the data top down
355 pixelsPtr = pixels + ( i * rowStride);
359 // the data in the file is bottom up, and we store the data top down
360 pixelsPtr = pixels + (((height - 1) - i) * rowStride);
362 if(fread(pixelsPtr, 1, rowStride, fp) != rowStride)
372 * function to decode format BI_BITFIELDS & bpp = 16 & R:G:B = 5:5:5
373 * @param[in] fp The file to read from
374 * @param[out] pixels The pointer that we want to store bmp data in
375 * @param[in] width bmp width
376 * @param[in] height bmp height
377 * @param[in] offset offset from bmp header to bmp image data
378 * @param[in] topDown indicate image data is read from bottom or from top
379 * @return true, if decode successful, false otherwise
381 bool DecodeBF555(FILE *fp,
388 if(fp == NULL || pixels == NULL)
390 DALI_LOG_ERROR("Error decoding BMP_BITFIELDS555 format\n");
394 if( fseek(fp, offset, SEEK_SET) )
396 DALI_LOG_ERROR("Error seeking BMP_BITFIELDS555 data\n");
400 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
402 std::vector<char> raw(width * height * 2);
403 unsigned int rawStride = width * 2;
404 unsigned int rowStride = width * 3;
407 for(unsigned int j = 0; j < height; j ++)
409 rawPtr = &raw[0] + ( j * rawStride);
410 if(fread(rawPtr, 1, rawStride, fp) != rawStride)
416 for (unsigned int yPos = 0; yPos < height; yPos++)
418 PixelBuffer *pixelsPtr = NULL;
421 // the data in the file is top down, and we store the data top down
422 pixelsPtr = pixels + ( yPos * rowStride);
426 // the data in the file is bottom up, and we store the data top down
427 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
430 for(unsigned int k = 0; k < width; k ++)
432 int index = yPos * rawStride + 2 * k;
433 pixelsPtr[3 * k] = ((raw[ index + 1] >> 2) & 0x1F) * 0xFF / 0x1F;
434 pixelsPtr[3 * k + 1] = (((raw[index + 1] & 0x03) << 3) | (raw[ index] >> 5)) * 0xFF/ 0x1F;
435 pixelsPtr[3 * k + 2] = (raw[ index] & 0x1F) * 0xFF / 0x1F;
442 * function to decode format BI_RGB & bpp = 16 & R:G:B = 5:5:5
443 * @param[in] fp The file to read from
444 * @param[out] pixels The pointer that we want to store bmp data in
445 * @param[in] width bmp width
446 * @param[in] height bmp height
447 * @param[in] offset offset from bmp header to bmp image data
448 * @param[in] topDown indicate image data is read from bottom or from top
449 * @return true, if decode successful, false otherwise
451 bool DecodeRGB555(FILE *fp,
458 if(fp == NULL || pixels == NULL)
460 DALI_LOG_ERROR("Error decoding BMP_RGB555 format\n");
463 if( fseek(fp, offset, SEEK_SET) )
465 DALI_LOG_ERROR("Error seeking BMP_RGB555 data\n");
469 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
470 std::vector<char> raw(width * height * 2);
471 unsigned int rawStride = width * 2;
472 unsigned int rowStride = width * 3;
475 for(unsigned int j = 0; j < height; j ++)
477 rawPtr = &raw[0] + ( j * rawStride);
478 if(fread(rawPtr, 1, rawStride, fp) != rawStride)
483 for(unsigned int i = 0; i < height; i++)
485 PixelBuffer *pixelsPtr = NULL;
488 // the data in the file is top down, and we store the data top down
489 pixelsPtr = pixels + ( i * rowStride);
493 // the data in the file is bottom up, and we store the data top down
494 pixelsPtr = pixels + (((height - 1) - i) * rowStride);
496 for(unsigned int k = 0; k < width; k ++)
498 int index = i * rawStride + 2 * k;
499 pixelsPtr[3 * k] = ((raw[ index + 1] >> 2) & 0x1F) * 0xFF / 0x1F;
500 pixelsPtr[3 * k + 1] = (((raw[index + 1] & 0x03) << 3) | (raw[ index] >> 5)) * 0xFF/ 0x1F;
501 pixelsPtr[3 * k + 2] = (raw[ index] & 0x1F) * 0xFF / 0x1F;
509 * function to decode format BI_RGB & bpp = 1
510 * @param[in] fp The file to read from
511 * @param[out] pixels The pointer that we want to store bmp data in
512 * @param[in] width bmp width
513 * @param[in] height bmp height
514 * @param[in] offset offset from bmp header to bmp palette data
515 * @param[in] topDown indicate image data is read from bottom or from top
516 * @return true, if decode successful, false otherwise
518 bool DecodeRGB1(FILE *fp,
525 if(fp == NULL || pixels == NULL)
527 DALI_LOG_ERROR("Error decoding BMP_RGB1 format\n");
530 if( fseek(fp, offset, SEEK_SET) )
532 DALI_LOG_ERROR("Error seeking BMP_RGB1 data\n");
536 unsigned char colorTable[8] = {0};
538 unsigned int fillw = ((width & 63) != 0) ? width + 64 - (width & 63) : width;
539 std::vector<char> colorIndex(fillw * height);
540 unsigned int rowStride = fillw * 3; // RGB
543 if(fread(colorTable, 1, 8, fp) != 8)
548 for(unsigned int i = 0; i < fillw * height; i += 8)
550 if(fread(&cmd, 1, 1, fp) != 1)
555 colorIndex[i] = (cmd >> 7) & 0x01;
556 colorIndex[i + 1] = (cmd >> 6) & 0x01;
557 colorIndex[i + 2] = (cmd >> 5) & 0x01;
558 colorIndex[i + 3] = (cmd >> 4) & 0x01;
559 colorIndex[i + 4] = (cmd >> 3) & 0x01;
560 colorIndex[i + 5] = (cmd >> 2) & 0x01;
561 colorIndex[i + 6] = (cmd >> 1) & 0x01;
562 colorIndex[i + 7] = (cmd & 0x01);
565 for(unsigned int index = 0; index < height; index = index + 1)
567 PixelBuffer *pixelsPtr = NULL;
570 // the data in the file is top down, and we store the data top down
571 pixelsPtr = pixels + ( index * rowStride);
575 // the data in the file is bottom up, and we store the data top down
576 pixelsPtr = pixels + (((height - 1) - index) * rowStride);
578 for(unsigned int j = 0; j < fillw; j ++)
581 if((fillw * index + j ) < (fillw * height))
583 ctIndex = colorIndex[ fillw * index + j ];
589 // temp solution for PLM bug P130411-5268, there is one mono bmp that cause DecodeRGB1 API crash.
590 if( ((3 * j + 2) < height * fillw * 3) && (ctIndex < 2))
592 pixelsPtr[ 3 * j ] = colorTable[4 * ctIndex + 2];
593 pixelsPtr[3 * j + 1] = colorTable[4 * ctIndex + 1];
594 pixelsPtr[3 * j + 2] = colorTable[4 * ctIndex ];
602 * function to decode format BI_RGB & bpp = 4
603 * @param[in] fp The file to read from
604 * @param[out] pixels The pointer that we want to store bmp data in
605 * @param[in] width bmp width
606 * @param[in] height bmp height
607 * @param[in] offset offset from bmp header to bmp palette data
608 * @param[in] topDown indicate image data is read from bottom or from top
609 * @return true, if decode successful, false otherwise
611 bool DecodeRGB4(FILE *fp,
618 if(fp == NULL || pixels == NULL)
620 DALI_LOG_ERROR("Error decoding BMP_RGB4 format\n");
623 if( fseek(fp, offset, SEEK_SET) )
625 DALI_LOG_ERROR("Error seeking BMP_RGB4 data\n");
631 unsigned int fillw = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
632 std::vector<char> colorIndex(fillw * height);
633 unsigned int rowStride = fillw * 3;
635 if(fread(colorTable, 1, 64, fp) != 64)
640 for(unsigned int i = 0; i < fillw * height; i += 2)
642 if (fread(&cmd, 1, 1, fp) != 1)
647 colorIndex[i] = cmd >> 4;
648 colorIndex[i + 1] = cmd & (0x0F);
652 for(unsigned int index = 0; index < height; index = index + 1)
654 PixelBuffer *pixelsPtr = NULL;
657 // the data in the file is top down, and we store the data top down
658 pixelsPtr = pixels + ( index * rowStride);
662 // the data in the file is bottom up, and we store the data top down
663 pixelsPtr = pixels + (((height - 1) - index) * rowStride);
665 for(unsigned int j = 0; j < fillw; j ++)
667 ctIndex = colorIndex[ fillw * index + j ];
668 pixelsPtr[ 3 * j ] = colorTable[4 * ctIndex + 2];
669 pixelsPtr[(3 * j + 1)] = colorTable[4 * ctIndex + 1];
670 pixelsPtr[(3 * j + 2)] = colorTable[4 * ctIndex ];
678 * function to decode format BI_RGB & bpp = 8
679 * @param[in] fp The file to read from
680 * @param[out] pixels The pointer that we want to store bmp data in
681 * @param[in] width bmp width
682 * @param[in] height bmp height
683 * @param[in] offset offset from bmp header to bmp palette data
684 * @param[in] topDown indicate image data is read from bottom or from top
685 * @return true, if decode successful, false otherwise
687 bool DecodeRGB8(FILE *fp,
694 if(fp == NULL || pixels == NULL)
696 DALI_LOG_ERROR("Error decoding BMP_RGB8 format\n");
699 if( fseek(fp, offset, SEEK_SET) )
701 DALI_LOG_ERROR("Error seeking BMP_RGB8 data\n");
705 std::vector<char> colorTable(1024);
706 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
708 std::vector<char> colorIndex(width * height);
709 unsigned int rowStride = width * 3;//RGB8->RGB24
711 if(fread(&colorTable[0], 1, 1024, fp) != 1024)
715 for(unsigned int i = 0; i < width * height; i ++)
717 if (fread(&cmd, 1, 1, fp) != 1)
725 for(unsigned int index = 0; index < height; index = index + 1)
727 PixelBuffer *pixelsPtr = NULL;
730 // the data in the file is top down, and we store the data top down
731 pixelsPtr = pixels + ( index * rowStride);
735 // the data in the file is bottom up, and we store the data top down
736 pixelsPtr = pixels + (((height - 1) - index) * rowStride);
738 for(unsigned int j = 0; j < width; j ++)
740 ctIndex = colorIndex[ width * index + j ];
741 pixelsPtr[ 3 * j ] = colorTable[4 * ctIndex + 2];
742 pixelsPtr[(3 * j + 1)] = colorTable[4 * ctIndex + 1];
743 pixelsPtr[(3 * j + 2)] = colorTable[4 * ctIndex ];
750 * function to decode format BI_RLE4 & bpp = 4
751 * @param[in] fp The file to read from
752 * @param[out] pixels The pointer that we want to store bmp data in
753 * @param[in] width bmp width
754 * @param[in] height bmp height
755 * @param[in] offset offset from bmp header to bmp palette data
756 * @param[in] topDown indicate image data is read from bottom or from top
757 * @return true, if decode successful, false otherwise
759 bool DecodeRLE4(FILE *fp,
766 if(fp == NULL || pixels == NULL)
768 DALI_LOG_ERROR("Error decoding BMP_RLE4 format\n");
771 PixelBuffer *pixelsPtr = pixels;
772 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
774 unsigned int cmdStride = 2;
776 std::vector<char> colorIndex(width * height >> 1);
777 std::vector<char> run;
782 width += (width & 1);
787 if( fseek(fp, offset, SEEK_SET) )
789 DALI_LOG_ERROR("Error seeking BMP_RLE4 data\n");
793 if (fread(colorTable, 1, 64, fp) != 64)
798 while((x >> 1) + y * width < width * height)
804 if (fread(cmd, 1, cmdStride, fp) != cmdStride)
808 if(cmd[0] == 0) // ESCAPE
812 case 1: //end of bitmap
815 case 0: // end of line
820 if (fread(cmd, 1, cmdStride, fp) != cmdStride)
822 DALI_LOG_ERROR("Error reading the BMP image\n");
825 dx = cmd[0] & (0xFF);
826 dy = cmd[1] & (0xFF);
831 // decode a literal run
832 unsigned int length = cmd[1] & (0xFF);
833 //size of run, which is word aligned
834 unsigned int bytesize = length;
835 bytesize += (bytesize & 1);
837 bytesize += (bytesize & 1);
838 run.resize(bytesize);
839 if(fread(&run[0], 1, bytesize, fp) != bytesize)
841 DALI_LOG_ERROR("Error reading the BMP image\n");
846 length += (length & 1);
848 for(unsigned int i = 0; i < length; i += 1)
850 colorIndex[(x >> 1) + width * (height - y - 1) + i] = run[i];
855 for(unsigned int i = 0; i < length; i ++)
857 if((i & 1) == 0)//copy high to low
859 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((run[i >> 1] & 0xF0) >> 4);
861 else //copy low to high
863 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((run[i >> 1] & 0x0F) << 4);
867 x += cmd[1] & (0xFF);
873 unsigned int length = cmd[0] & (0xFF);
876 length += (length & 1);
878 for(unsigned int i = 0; i < length; i ++)
880 colorIndex[(height-y-1)*width + i + (x >> 1)] = cmd[1];
885 for(unsigned int i = 0; i < length; i ++)
889 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((cmd[1] & 0xF0) >> 4);
893 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((cmd[1] & 0x0F) << 4);
897 x += cmd[0] & (0xFF);
903 for(unsigned int index = 0; index < (width * height ); index = index + 1)
905 ctIndexHigh = colorIndex[ index] >> 4;
906 ctIndexLow = colorIndex[index] & (0x0F);
907 pixelsPtr[6 * index ] = colorTable[4 * ctIndexHigh + 2];
908 pixelsPtr[6 * index + 1] = colorTable[4 * ctIndexHigh + 1];
909 pixelsPtr[6 * index + 2] = colorTable[4 * ctIndexHigh ];
910 pixelsPtr[6 * index + 3] = colorTable[4 * ctIndexLow + 2];
911 pixelsPtr[6 * index + 4] = colorTable[4 * ctIndexLow + 1];
912 pixelsPtr[6 * index + 5] = colorTable[4 * ctIndexLow ];
918 * function to decode format BI_RLE8 & bpp = 8
919 * @param[in] fp The file to read from
920 * @param[out] pixels The pointer that we want to store bmp data in
921 * @param[in] width bmp width
922 * @param[in] height bmp height
923 * @param[in] offset offset from bmp header to bmp palette data
924 * @param[in] topDown indicate image data is read from bottom or from top
925 * @return true, if decode successful, false otherwise
927 bool DecodeRLE8(FILE *fp,
934 if(fp == NULL || pixels == NULL)
936 DALI_LOG_ERROR("Error decoding BMP_RLE8 format\n");
939 PixelBuffer *pixelsPtr = pixels;
942 unsigned int cmdStride = 2;
944 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
945 std::vector<char> colorTable(1024);
947 std::vector<char> colorIndex(width * height);
949 if( fseek(fp, offset, SEEK_SET) )
951 DALI_LOG_ERROR("Error seeking BMP_RLE8 data\n");
955 if (fread(&colorTable[0], 1, 1024, fp) != 1024)
963 unsigned int length = 0;
964 unsigned int copylength = 0;
965 std::vector<char> run;
966 while((x + y * width) < width * height )
972 if (fread(cmd, 1, cmdStride, fp) != cmdStride)
977 if(cmd[0] == 0)//ESCAPE
981 case 1: // end of bitmap
984 case 0: // end of line
989 if (fread(cmd, 1, cmdStride, fp) != cmdStride)
991 DALI_LOG_ERROR("Error reading the BMP image\n");
994 dx = cmd[0] & (0xFF);
995 dy = cmd[1] & (0xFF);
1000 //decode a literal run
1001 length = cmd[1] & (0xFF);
1002 copylength = length;
1003 //absolute mode must be word-aligned
1004 length += (length & 1);
1006 if(fread(&run[0], 1, length, fp) != length)
1008 DALI_LOG_ERROR("Error reading the BMP image\n");
1012 for(unsigned int i = 0; i < length; i += 1)
1014 colorIndex[x + width * (height - y - 1) + i] = run[i];
1019 }// end if cmd[0] ==
1022 length = cmd[0] & (0xFF);
1023 for(unsigned int i = 0; i < length; i ++)
1025 colorIndex[(height - y - 1) * width + x] = cmd[1];
1031 for(unsigned int index = 0; index < width * height; index = index + 1)
1033 ctIndex = colorIndex[ index];
1034 pixelsPtr[3 * index ] = colorTable[4 * ctIndex + 2];
1035 pixelsPtr[3 * index + 1] = colorTable[4 * ctIndex + 1];
1036 pixelsPtr[3 * index + 2] = colorTable[4 * ctIndex ];
1041 } // unnamed namespace
1043 bool LoadBmpHeader(FILE *fp, const ImageAttributes& attributes, unsigned int &width, unsigned int &height)
1045 BmpFileHeader fileHeader;
1046 BmpInfoHeader infoHeader;
1048 bool ret = LoadBmpHeader(fp, width, height, fileHeader, infoHeader);
1053 bool LoadBitmapFromBmp( FILE *fp, Bitmap& bitmap, ImageAttributes& attributes, const ResourceLoadingClient& client )
1055 DALI_ASSERT_DEBUG(bitmap.GetPackedPixelsProfile() != 0 && "Need a packed pixel bitmap to load into.");
1058 DALI_LOG_ERROR("Error loading bitmap\n");
1061 BmpFormat customizedFormat = BMP_NOTEXIST;
1062 BmpFileHeader fileHeader;
1063 BmpInfoHeader infoHeader;
1065 // Load the header info
1066 unsigned int width, height;
1068 if (!LoadBmpHeader(fp, width, height, fileHeader, infoHeader))
1073 Pixel::Format pixelFormat = Pixel::RGB888;
1074 switch(infoHeader.compression)
1077 switch (infoHeader.bitsPerPixel)
1080 pixelFormat = Pixel::BGR8888;
1084 if(fileHeader.offset == FileHeaderOffsetOfRGB24V5)//0x8A
1086 customizedFormat = BMP_RGB24V5;
1090 pixelFormat = Pixel::RGB888;
1095 customizedFormat = BMP_RGB555;
1099 customizedFormat = BMP_RGB8;
1103 customizedFormat = BMP_RGB4;
1107 customizedFormat = BMP_RGB1;
1110 DALI_LOG_WARNING("%d bits per pixel not supported for BMP files\n", infoHeader.bitsPerPixel);
1116 if(infoHeader.bitsPerPixel == 8)
1118 customizedFormat = BMP_RLE8;
1124 if(infoHeader.bitsPerPixel == 4)
1126 customizedFormat = BMP_RLE4;
1130 case 3: // // BI_BITFIELDS
1132 if(infoHeader.bitsPerPixel == 16)
1134 if( fseek(fp, 14 + infoHeader.infoHeaderSize + 1, SEEK_SET) )
1140 if(fread(&mask, 1, 1, fp) != 1)
1145 if((mask & 0x80) == MaskForBFRGB565) // mask is 0xF8
1147 pixelFormat = Pixel::RGB565;
1149 else if((mask & 0x80) == 0)// mask is 0x 7C
1151 customizedFormat = BMP_BITFIELDS555;
1158 else if(infoHeader.bitsPerPixel == 32)
1160 if(fileHeader.offset == FileHeaderOffsetOfBF32V4)// 0x7A
1162 customizedFormat = BMP_BITFIELDS32V4;
1166 customizedFormat = BMP_BITFIELDS32;
1172 DALI_LOG_WARNING("Compression not supported for BMP files\n");
1176 bool topDown = false;
1178 // if height is negative, bitmap data is top down
1179 if (infoHeader.height<0)
1181 infoHeader.height = abs(infoHeader.height);
1182 height = infoHeader.height;
1186 unsigned int rowStride = infoHeader.width * (infoHeader.bitsPerPixel >>3);
1188 // bitmaps row stride is padded to 4 bytes
1189 unsigned int padding = (rowStride % 4);
1192 padding = 4 - padding;
1195 PixelBuffer *pixels = NULL;
1196 int imageW = infoHeader.width;
1197 int pixelBufferW = 0;
1198 switch(customizedFormat)
1205 case BMP_BITFIELDS555:
1207 pixelBufferW = ((imageW & 3) != 0) ? imageW + 4 - (imageW & 3) : imageW;
1208 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB888, pixelBufferW, abs(infoHeader.height));
1213 pixelBufferW = ((imageW & 63) != 0) ? imageW + 64 - (imageW & 63) : imageW;
1214 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB888, pixelBufferW, abs(infoHeader.height));
1217 case BMP_BITFIELDS32:
1218 case BMP_BITFIELDS32V4:
1220 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB8888, infoHeader.width, abs(infoHeader.height));
1225 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB888, infoHeader.width, infoHeader.height);
1229 if(pixelFormat == Pixel::RGB565 )
1231 pixelBufferW = ((imageW & 3) != 0) ? imageW + 4 - (imageW & 3) : imageW;
1232 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB565, pixelBufferW, abs(infoHeader.height));
1236 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(pixelFormat, infoHeader.width, infoHeader.height);
1241 // TODO: Add scaling support
1243 // Read the raw bitmap data
1244 PixelBuffer *pixelsPtr;
1245 bool decodeResult(false);
1246 switch(customizedFormat)
1250 decodeResult = DecodeRGB1( fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1255 decodeResult = DecodeRGB4(fp, pixels, infoHeader.width, infoHeader.height, 14 + infoHeader.infoHeaderSize, topDown);
1260 decodeResult = DecodeRLE4( fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1263 case BMP_BITFIELDS32:
1265 decodeResult = DecodeBF32(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown, rowStride, padding);
1268 case BMP_BITFIELDS555:
1270 decodeResult = DecodeBF555(fp, pixels,infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown);
1275 decodeResult = DecodeRGB555(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown);
1280 decodeResult = DecodeRGB8(fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1285 decodeResult = DecodeRLE8(fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1290 decodeResult = DecodeRGB24V5(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown, rowStride, padding);
1293 case BMP_BITFIELDS32V4:
1295 decodeResult = DecodeBF32V4(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown, rowStride, padding);
1300 if(pixelFormat == Pixel::RGB565)
1302 decodeResult = DecodeBF565(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown);
1306 for (unsigned int yPos = 0; yPos < height; yPos++)
1310 // the data in the file is top down, and we store the data top down
1311 pixelsPtr = pixels + ( yPos * rowStride);
1315 // the data in the file is bottom up, and we store the data top down
1316 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
1319 if (fread(pixelsPtr, 1, rowStride, fp) != rowStride)
1321 DALI_LOG_ERROR("Error reading the BMP image\n");
1325 // If 24 bit mode then swap Blue and Red pixels
1326 // BGR888 doesn't seem to be supported by dali-core
1327 if (infoHeader.bitsPerPixel == 24 )
1329 for(unsigned int i = 0; i < rowStride; i += 3)
1331 unsigned char temp = pixelsPtr[i];
1332 pixelsPtr[i] = pixelsPtr[i+2];
1333 pixelsPtr[i+2] = temp;
1339 if( fseek(fp, padding, SEEK_CUR) ) // move past the padding.
1341 DALI_LOG_ERROR("Error moving past BMP padding\n");
1345 decodeResult = true;
1356 attributes.SetSize(infoHeader.width, infoHeader.height);
1357 attributes.SetPixelFormat(pixelFormat);
1359 switch(customizedFormat)
1367 case BMP_BITFIELDS555:
1369 attributes.SetPixelFormat(Pixel::RGB888);
1371 case BMP_BITFIELDS32:
1372 case BMP_BITFIELDS32V4:
1373 attributes.SetPixelFormat(Pixel::RGB8888);
1381 } // namespace SlpPlatform