2 * Copyright (c) 2017 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>
28 using Integration::Bitmap;
29 using Dali::Integration::PixelBuffer;
30 namespace TizenPlatform
35 const unsigned int FileHeaderOffsetOfBF32V4 = 0x7A;
36 const unsigned int MaskForBFRGB565 = 0x80;
37 const unsigned int FileHeaderOffsetOfRGB24V5 = 0x8A;
41 BMP_RGB1 = 14, //BI_RGB & bpp =1
42 BMP_RGB4, //BI_RGB & bpp = 4
43 BMP_RGB8, //BI_RGB & bpp = 8
44 BMP_RGB555, //BI_RGB & bpp = 16
45 BMP_BITFIELDS555, //BI_BITFIELDS & 16bit & R:G:B = 5:5:5
46 BMP_BITFIELDS32, //BI_BITFIELDS & 32bit & R:G:B:A = 8:8:8:8
49 BMP_BITFIELDS32V4,//BI_BITFIELDS & 32bit
50 BMP_RGB24V5, //BI_RGB & bpp = 24 & bmp version5
56 unsigned short signature; // Bitmap file signature
57 unsigned int fileSize; // Bitmap file size in bytes
58 unsigned short reserved1; // Reserved bits
59 unsigned short reserved2; // Reserved bits
60 unsigned int offset; // Offset from BMP file header to BMP bits
61 } __attribute__ ( (__packed__)); // Stops the structure from being aligned to every 4 bytes
65 unsigned int infoHeaderSize; // Specifies the number of bytes required by the info header
66 unsigned int width; // The Image Width
67 int height; // The Image Height (negative value represents image data is flipped)
68 unsigned short planes; // The number of color planes, must be 1
69 unsigned short bitsPerPixel; // The bits per pixel
70 unsigned int compression; // The type of compression used by the image
71 unsigned int imageSize; // The size of the image in bytes
72 unsigned int xPixelsPerMeter; // The number of pixels per meter in x axis
73 unsigned int yPixelsPerMeter; // The number of pixels per meter in y axis
74 unsigned int numberOfColors; // The number of colors in the color table
75 unsigned int importantColors; // The important color count
76 } __attribute__ ( (__packed__)); // Stops the structure from being aligned to every 4 bytes
79 * Template function to read from the file directly into our structure.
80 * @param[in] fp The file to read from
81 * @param[out] header The structure we want to store our information in
82 * @return true, if read successful, false otherwise
85 inline bool ReadHeader(FILE* fp, T& header)
87 const unsigned int readLength = sizeof(T);
89 // Load the information directly into our structure
90 if ( fread( &header, 1, readLength, fp ) != readLength )
98 bool LoadBmpHeader(FILE *fp, unsigned int &width, unsigned int &height, BmpFileHeader &fileHeader, BmpInfoHeader &infoHeader)
100 if (!ReadHeader(fp, fileHeader))
105 if (!ReadHeader(fp, infoHeader))
110 width = infoHeader.width;
111 height = abs(infoHeader.height);
113 if( infoHeader.width == 0 )
122 * function to decode format BI_RGB & bpp = 24 & bmp version5.
123 * @param[in] fp The file to read from
124 * @param[out] pixels The pointer that we want to store bmp data in
125 * @param[in] width bmp width
126 * @param[in] height bmp height
127 * @param[in] offset offset from bmp header to bmp image data
128 * @param[in] topDown indicate image data is read from bottom or from top
129 * @param[in] padding padded to a u_int32 boundary for each line
130 * @return true, if decode successful, false otherwise
132 bool DecodeRGB24V5(FILE *fp,
138 unsigned int rowStride,
139 unsigned int padding)
141 if(fp == NULL || pixels == NULL)
143 DALI_LOG_ERROR("Error decoding BMP_RGB24V5 format\n");
146 if ( fseek(fp, offset, SEEK_SET) )
148 DALI_LOG_ERROR("Error seeking BMP_RGB24V5 data\n");
152 for(unsigned int yPos = 0; yPos < height; yPos ++)
154 PixelBuffer *pixelsPtr = NULL;
157 pixelsPtr = pixels + ( yPos * rowStride);
161 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
163 if (fread(pixelsPtr, 1, rowStride, fp) != rowStride)
165 DALI_LOG_ERROR("Error reading the BMP image\n");
168 for(unsigned int i = 0; i < rowStride; i += 3)
170 unsigned char temp = pixelsPtr[i];
171 pixelsPtr[i] = pixelsPtr[i + 2];
172 pixelsPtr[i + 2] = temp;
177 // move past the padding.
178 if( fseek(fp, padding, SEEK_CUR) )
180 DALI_LOG_ERROR("Error moving past BMP_RGB24V5 padding\n");
188 * function to decode format BI_BITFIELDS & bpp = 32 & bmp version4.
189 * @param[in] fp The file to read from
190 * @param[out] pixels The pointer that we want to store bmp data in
191 * @param[in] width bmp width
192 * @param[in] height bmp height
193 * @param[in] offset offset from bmp header to bmp image data
194 * @param[in] topDown indicate image data is read from bottom or from top
195 * @param[in] rowStride bits span for each line
196 * @param[in] padding padded to a u_int32 boundary for each line
197 * @return true, if decode successful, false otherwise
199 bool DecodeBF32V4(FILE *fp,
205 unsigned int rowStride,
206 unsigned int padding)
208 if(fp == NULL || pixels == NULL)
210 DALI_LOG_ERROR("Error decoding BMP_BITFIELDS32V4 format\n");
213 if( fseek(fp, offset, SEEK_SET) )
215 DALI_LOG_ERROR("Error seeking BMP_BITFIELDS32V4 data\n");
219 for(unsigned int yPos = 0; yPos < height; yPos ++)
221 PixelBuffer *pixelsPtr = NULL;
224 pixelsPtr = pixels + ( yPos * rowStride);
228 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
230 if (fread(pixelsPtr, 1, rowStride, fp) != rowStride)
232 DALI_LOG_ERROR("Error reading the BMP image\n");
235 for(unsigned int i = 0; i < rowStride; i += 4)
237 unsigned char temp = pixelsPtr[i];
238 pixelsPtr[i] = pixelsPtr[i + 2];
239 pixelsPtr[i + 2] = temp;
243 // move past the padding.
244 if( fseek(fp, padding, SEEK_CUR) )
246 DALI_LOG_ERROR("Error moving past BMP_BITFIELDS32V4 padding\n");
255 * function to decode format BI_BITFIELDS & bpp = 32
256 * @param[in] fp The file to read from
257 * @param[out] pixels The pointer that we want to store bmp data in
258 * @param[in] width bmp width
259 * @param[in] height bmp height
260 * @param[in] offset offset from bmp header to bmp image data
261 * @param[in] topDown indicate image data is read from bottom or from top
262 * @param[in] rowStride bits span for each line
263 * @param[in] padding padded to a u_int32 boundary for each line
264 * @return true, if decode successful, false otherwise
266 bool DecodeBF32(FILE *fp,
272 unsigned int rowStride,
273 unsigned int padding)
275 if(fp == NULL || pixels == NULL)
277 DALI_LOG_ERROR("Error decoding BMP_BITFIELDS32 format\n");
280 if( fseek(fp, offset, SEEK_SET) )
282 DALI_LOG_ERROR("Error seeking BMP_BITFIELDS32 data\n");
286 for (unsigned int yPos = 0; yPos < height; yPos++)
288 PixelBuffer *pixelsPtr;
291 // the data in the file is top down, and we store the data top down
292 pixelsPtr = pixels + ( yPos * rowStride);
296 // the data in the file is bottom up, and we store the data top down
297 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
300 if (fread(pixelsPtr, 1, rowStride, fp) != rowStride)
302 DALI_LOG_ERROR("Error reading the BMP image\n");
305 for(unsigned int i = 0; i < rowStride; i += 4)
307 unsigned char temp = pixelsPtr[i];
308 pixelsPtr[i] = pixelsPtr[i + 2];
309 pixelsPtr[i + 2] = temp;
314 // move past the padding.
315 if( fseek(fp, padding, SEEK_CUR) )
317 DALI_LOG_ERROR("Error moving past BMP_BITFIELDS32 padding\n");
325 * function to decode format BI_BITFIELDS & bpp = 16 & R:G:B = 5:6:5
326 * @param[in] fp The file to read from
327 * @param[out] pixels The pointer that we want to store bmp data in
328 * @param[in] width bmp width
329 * @param[in] height bmp height
330 * @param[in] offset offset from bmp header to bmp image data
331 * @param[in] topDown indicate image data is read from bottom or from top
332 * @return true, if decode successful, false otherwise
334 bool DecodeBF565(FILE *fp,
341 if(fp == NULL || pixels == NULL)
343 DALI_LOG_ERROR("Error decoding RGB565 format\n");
346 if( fseek(fp, offset, SEEK_SET) )
348 DALI_LOG_ERROR("Error seeking RGB565 data\n");
352 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
353 unsigned int rowStride = width * 2;
355 for(unsigned int i = 0; i < height; i++)
357 PixelBuffer *pixelsPtr = NULL;
360 // the data in the file is top down, and we store the data top down
361 pixelsPtr = pixels + ( i * rowStride);
365 // the data in the file is bottom up, and we store the data top down
366 pixelsPtr = pixels + (((height - 1) - i) * rowStride);
368 if(fread(pixelsPtr, 1, rowStride, fp) != rowStride)
378 * function to decode format BI_BITFIELDS & bpp = 16 & R:G:B = 5:5:5
379 * @param[in] fp The file to read from
380 * @param[out] pixels The pointer that we want to store bmp data in
381 * @param[in] width bmp width
382 * @param[in] height bmp height
383 * @param[in] offset offset from bmp header to bmp image data
384 * @param[in] topDown indicate image data is read from bottom or from top
385 * @return true, if decode successful, false otherwise
387 bool DecodeBF555(FILE *fp,
394 if(fp == NULL || pixels == NULL)
396 DALI_LOG_ERROR("Error decoding BMP_BITFIELDS555 format\n");
400 if( fseek(fp, offset, SEEK_SET) )
402 DALI_LOG_ERROR("Error seeking BMP_BITFIELDS555 data\n");
406 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
408 std::vector<char> raw(width * height * 2);
409 unsigned int rawStride = width * 2;
410 unsigned int rowStride = width * 3;
413 for(unsigned int j = 0; j < height; j ++)
415 rawPtr = &raw[0] + ( j * rawStride);
416 if(fread(rawPtr, 1, rawStride, fp) != rawStride)
422 for (unsigned int yPos = 0; yPos < height; yPos++)
424 PixelBuffer *pixelsPtr = NULL;
427 // the data in the file is top down, and we store the data top down
428 pixelsPtr = pixels + ( yPos * rowStride);
432 // the data in the file is bottom up, and we store the data top down
433 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
436 for(unsigned int k = 0; k < width; k ++)
438 int index = yPos * rawStride + 2 * k;
439 pixelsPtr[3 * k] = ((raw[ index + 1] >> 2) & 0x1F) * 0xFF / 0x1F;
440 pixelsPtr[3 * k + 1] = (((raw[index + 1] & 0x03) << 3) | (raw[ index] >> 5)) * 0xFF/ 0x1F;
441 pixelsPtr[3 * k + 2] = (raw[ index] & 0x1F) * 0xFF / 0x1F;
448 * function to decode format BI_RGB & bpp = 16 & R:G:B = 5:5:5
449 * @param[in] fp The file to read from
450 * @param[out] pixels The pointer that we want to store bmp data in
451 * @param[in] width bmp width
452 * @param[in] height bmp height
453 * @param[in] offset offset from bmp header to bmp image data
454 * @param[in] topDown indicate image data is read from bottom or from top
455 * @return true, if decode successful, false otherwise
457 bool DecodeRGB555(FILE *fp,
464 if(fp == NULL || pixels == NULL)
466 DALI_LOG_ERROR("Error decoding BMP_RGB555 format\n");
469 if( fseek(fp, offset, SEEK_SET) )
471 DALI_LOG_ERROR("Error seeking BMP_RGB555 data\n");
475 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
476 std::vector<char> raw(width * height * 2);
477 unsigned int rawStride = width * 2;
478 unsigned int rowStride = width * 3;
481 for(unsigned int j = 0; j < height; j ++)
483 rawPtr = &raw[0] + ( j * rawStride);
484 if(fread(rawPtr, 1, rawStride, fp) != rawStride)
489 for(unsigned int i = 0; i < height; i++)
491 PixelBuffer *pixelsPtr = NULL;
494 // the data in the file is top down, and we store the data top down
495 pixelsPtr = pixels + ( i * rowStride);
499 // the data in the file is bottom up, and we store the data top down
500 pixelsPtr = pixels + (((height - 1) - i) * rowStride);
502 for(unsigned int k = 0; k < width; k ++)
504 int index = i * rawStride + 2 * k;
505 pixelsPtr[3 * k] = ((raw[ index + 1] >> 2) & 0x1F) * 0xFF / 0x1F;
506 pixelsPtr[3 * k + 1] = (((raw[index + 1] & 0x03) << 3) | (raw[ index] >> 5)) * 0xFF/ 0x1F;
507 pixelsPtr[3 * k + 2] = (raw[ index] & 0x1F) * 0xFF / 0x1F;
515 * function to decode format BI_RGB & bpp = 1
516 * @param[in] fp The file to read from
517 * @param[out] pixels The pointer that we want to store bmp data in
518 * @param[in] width bmp width
519 * @param[in] height bmp height
520 * @param[in] offset offset from bmp header to bmp palette data
521 * @param[in] topDown indicate image data is read from bottom or from top
522 * @return true, if decode successful, false otherwise
524 bool DecodeRGB1(FILE *fp,
531 if(fp == NULL || pixels == NULL)
533 DALI_LOG_ERROR("Error decoding BMP_RGB1 format\n");
536 if( fseek(fp, offset, SEEK_SET) )
538 DALI_LOG_ERROR("Error seeking BMP_RGB1 data\n");
542 unsigned char colorTable[8] = {0};
544 unsigned int fillw = ((width & 63) != 0) ? width + 64 - (width & 63) : width;
545 std::vector<char> colorIndex(fillw * height);
546 unsigned int rowStride = fillw * 3; // RGB
549 if(fread(colorTable, 1, 8, fp) != 8)
554 for(unsigned int i = 0; i < fillw * height; i += 8)
556 if(fread(&cmd, 1, 1, fp) != 1)
561 colorIndex[i] = (cmd >> 7) & 0x01;
562 colorIndex[i + 1] = (cmd >> 6) & 0x01;
563 colorIndex[i + 2] = (cmd >> 5) & 0x01;
564 colorIndex[i + 3] = (cmd >> 4) & 0x01;
565 colorIndex[i + 4] = (cmd >> 3) & 0x01;
566 colorIndex[i + 5] = (cmd >> 2) & 0x01;
567 colorIndex[i + 6] = (cmd >> 1) & 0x01;
568 colorIndex[i + 7] = (cmd & 0x01);
571 for(unsigned int index = 0; index < height; index = index + 1)
573 PixelBuffer *pixelsPtr = NULL;
576 // the data in the file is top down, and we store the data top down
577 pixelsPtr = pixels + ( index * rowStride);
581 // the data in the file is bottom up, and we store the data top down
582 pixelsPtr = pixels + (((height - 1) - index) * rowStride);
584 for(unsigned int j = 0; j < fillw; j ++)
586 unsigned int ctIndex = 0;
587 if((fillw * index + j ) < (fillw * height))
589 ctIndex = colorIndex[ fillw * index + j ];
595 // temp solution for PLM bug P130411-5268, there is one mono bmp that cause DecodeRGB1 API crash.
596 if( ((3 * j + 2) < height * fillw * 3) && (ctIndex < 2))
598 pixelsPtr[ 3 * j ] = colorTable[4 * ctIndex + 2];
599 pixelsPtr[3 * j + 1] = colorTable[4 * ctIndex + 1];
600 pixelsPtr[3 * j + 2] = colorTable[4 * ctIndex ];
608 * function to decode format BI_RGB & bpp = 4
609 * @param[in] fp The file to read from
610 * @param[out] pixels The pointer that we want to store bmp data in
611 * @param[in] width bmp width
612 * @param[in] height bmp height
613 * @param[in] offset offset from bmp header to bmp palette data
614 * @param[in] topDown indicate image data is read from bottom or from top
615 * @return true, if decode successful, false otherwise
617 bool DecodeRGB4(FILE *fp,
624 if(fp == NULL || pixels == NULL)
626 DALI_LOG_ERROR("Error decoding BMP_RGB4 format\n");
629 if( fseek(fp, offset, SEEK_SET) )
631 DALI_LOG_ERROR("Error seeking BMP_RGB4 data\n");
637 unsigned int fillw = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
638 std::vector<char> colorIndex(fillw * height);
639 unsigned int rowStride = fillw * 3;
641 if(fread(colorTable, 1, 64, fp) != 64)
646 for(unsigned int i = 0; i < fillw * height; i += 2)
648 if (fread(&cmd, 1, 1, fp) != 1)
653 colorIndex[i] = cmd >> 4;
654 colorIndex[i + 1] = cmd & (0x0F);
656 unsigned int ctIndex = 0;
658 for(unsigned int index = 0; index < height; index = index + 1)
660 PixelBuffer *pixelsPtr = NULL;
663 // the data in the file is top down, and we store the data top down
664 pixelsPtr = pixels + ( index * rowStride);
668 // the data in the file is bottom up, and we store the data top down
669 pixelsPtr = pixels + (((height - 1) - index) * rowStride);
671 for(unsigned int j = 0; j < fillw; j ++)
673 ctIndex = colorIndex[ fillw * index + j ];
674 pixelsPtr[ 3 * j ] = colorTable[4 * ctIndex + 2];
675 pixelsPtr[(3 * j + 1)] = colorTable[4 * ctIndex + 1];
676 pixelsPtr[(3 * j + 2)] = colorTable[4 * ctIndex ];
684 * function to decode format BI_RGB & bpp = 8
685 * @param[in] fp The file to read from
686 * @param[out] pixels The pointer that we want to store bmp data in
687 * @param[in] width bmp width
688 * @param[in] height bmp height
689 * @param[in] offset offset from bmp header to bmp palette data
690 * @param[in] topDown indicate image data is read from bottom or from top
691 * @return true, if decode successful, false otherwise
693 bool DecodeRGB8(FILE *fp,
700 if(fp == NULL || pixels == NULL)
702 DALI_LOG_ERROR("Error decoding BMP_RGB8 format\n");
705 if( fseek(fp, offset, SEEK_SET) )
707 DALI_LOG_ERROR("Error seeking BMP_RGB8 data\n");
711 std::vector<char> colorTable(1024);
712 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
714 std::vector<char> colorIndex(width * height);
715 unsigned int rowStride = width * 3;//RGB8->RGB24
717 if(fread(&colorTable[0], 1, 1024, fp) != 1024)
721 for(unsigned int i = 0; i < width * height; i ++)
723 if (fread(&cmd, 1, 1, fp) != 1)
730 unsigned int ctIndex = 0;
731 for(unsigned int index = 0; index < height; index = index + 1)
733 PixelBuffer *pixelsPtr = NULL;
736 // the data in the file is top down, and we store the data top down
737 pixelsPtr = pixels + ( index * rowStride);
741 // the data in the file is bottom up, and we store the data top down
742 pixelsPtr = pixels + (((height - 1) - index) * rowStride);
744 for(unsigned int j = 0; j < width; j ++)
746 ctIndex = colorIndex[ width * index + j ];
747 pixelsPtr[ 3 * j ] = colorTable[4 * ctIndex + 2];
748 pixelsPtr[(3 * j + 1)] = colorTable[4 * ctIndex + 1];
749 pixelsPtr[(3 * j + 2)] = colorTable[4 * ctIndex ];
756 * function to decode format BI_RLE4 & bpp = 4
757 * @param[in] fp The file to read from
758 * @param[out] pixels The pointer that we want to store bmp data in
759 * @param[in] width bmp width
760 * @param[in] height bmp height
761 * @param[in] offset offset from bmp header to bmp palette data
762 * @param[in] topDown indicate image data is read from bottom or from top
763 * @return true, if decode successful, false otherwise
765 bool DecodeRLE4(FILE *fp,
772 if(fp == NULL || pixels == NULL)
774 DALI_LOG_ERROR("Error decoding BMP_RLE4 format\n");
777 PixelBuffer *pixelsPtr = pixels;
778 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
780 unsigned int cmdStride = 2;
782 std::vector<char> colorIndex(width * height >> 1);
783 std::vector<char> run;
788 width += (width & 1);
793 if( fseek(fp, offset, SEEK_SET) )
795 DALI_LOG_ERROR("Error seeking BMP_RLE4 data\n");
799 if (fread(colorTable, 1, 64, fp) != 64)
804 while((x >> 1) + y * width < width * height)
810 if (fread(cmd, 1, cmdStride, fp) != cmdStride)
814 if(cmd[0] == 0) // ESCAPE
818 case 1: //end of bitmap
821 case 0: // end of line
826 if (fread(cmd, 1, cmdStride, fp) != cmdStride)
828 DALI_LOG_ERROR("Error reading the BMP image\n");
831 dx = cmd[0] & (0xFF);
832 dy = cmd[1] & (0xFF);
837 // decode a literal run
838 unsigned int length = cmd[1] & (0xFF);
839 //size of run, which is word aligned
840 unsigned int bytesize = length;
841 bytesize += (bytesize & 1);
843 bytesize += (bytesize & 1);
844 run.resize(bytesize);
845 if(fread(&run[0], 1, bytesize, fp) != bytesize)
847 DALI_LOG_ERROR("Error reading the BMP image\n");
852 length += (length & 1);
854 for(unsigned int i = 0; i < length; i += 1)
856 colorIndex[(x >> 1) + width * (height - y - 1) + i] = run[i];
861 for(unsigned int i = 0; i < length; i ++)
863 if((i & 1) == 0)//copy high to low
865 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((run[i >> 1] & 0xF0) >> 4);
867 else //copy low to high
869 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((run[i >> 1] & 0x0F) << 4);
873 x += cmd[1] & (0xFF);
879 unsigned int length = cmd[0] & (0xFF);
882 length += (length & 1);
884 for(unsigned int i = 0; i < length; i ++)
886 colorIndex[(height-y-1)*width + i + (x >> 1)] = cmd[1];
891 for(unsigned int i = 0; i < length; i ++)
895 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((cmd[1] & 0xF0) >> 4);
899 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((cmd[1] & 0x0F) << 4);
903 x += cmd[0] & (0xFF);
909 for(unsigned int index = 0; index < (width * height ); index = index + 1)
911 ctIndexHigh = colorIndex[ index] >> 4;
912 ctIndexLow = colorIndex[index] & (0x0F);
913 pixelsPtr[6 * index ] = colorTable[4 * ctIndexHigh + 2];
914 pixelsPtr[6 * index + 1] = colorTable[4 * ctIndexHigh + 1];
915 pixelsPtr[6 * index + 2] = colorTable[4 * ctIndexHigh ];
916 pixelsPtr[6 * index + 3] = colorTable[4 * ctIndexLow + 2];
917 pixelsPtr[6 * index + 4] = colorTable[4 * ctIndexLow + 1];
918 pixelsPtr[6 * index + 5] = colorTable[4 * ctIndexLow ];
924 * function to decode format BI_RLE8 & bpp = 8
925 * @param[in] fp The file to read from
926 * @param[out] pixels The pointer that we want to store bmp data in
927 * @param[in] width bmp width
928 * @param[in] height bmp height
929 * @param[in] offset offset from bmp header to bmp palette data
930 * @param[in] topDown indicate image data is read from bottom or from top
931 * @return true, if decode successful, false otherwise
933 bool DecodeRLE8(FILE *fp,
940 if(fp == NULL || pixels == NULL)
942 DALI_LOG_ERROR("Error decoding BMP_RLE8 format\n");
945 PixelBuffer *pixelsPtr = pixels;
948 unsigned int cmdStride = 2;
950 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
951 std::vector<char> colorTable(1024);
953 std::vector<char> colorIndex(width * height);
955 if( fseek(fp, offset, SEEK_SET) )
957 DALI_LOG_ERROR("Error seeking BMP_RLE8 data\n");
961 if (fread(&colorTable[0], 1, 1024, fp) != 1024)
969 unsigned int length = 0;
970 unsigned int copylength = 0;
971 std::vector<char> run;
972 while((x + y * width) < width * height )
978 if (fread(cmd, 1, cmdStride, fp) != cmdStride)
983 if(cmd[0] == 0)//ESCAPE
987 case 1: // end of bitmap
990 case 0: // end of line
995 if (fread(cmd, 1, cmdStride, fp) != cmdStride)
997 DALI_LOG_ERROR("Error reading the BMP image\n");
1000 dx = cmd[0] & (0xFF);
1001 dy = cmd[1] & (0xFF);
1006 //decode a literal run
1007 length = cmd[1] & (0xFF);
1008 copylength = length;
1009 //absolute mode must be word-aligned
1010 length += (length & 1);
1012 if(fread(&run[0], 1, length, fp) != length)
1014 DALI_LOG_ERROR("Error reading the BMP image\n");
1018 for(unsigned int i = 0; i < length; i += 1)
1020 colorIndex[x + width * (height - y - 1) + i] = run[i];
1025 }// end if cmd[0] ==
1028 length = cmd[0] & (0xFF);
1029 for(unsigned int i = 0; i < length; i ++)
1031 colorIndex[(height - y - 1) * width + x] = cmd[1];
1037 for(unsigned int index = 0; index < width * height; index = index + 1)
1039 ctIndex = colorIndex[ index];
1040 pixelsPtr[3 * index ] = colorTable[4 * ctIndex + 2];
1041 pixelsPtr[3 * index + 1] = colorTable[4 * ctIndex + 1];
1042 pixelsPtr[3 * index + 2] = colorTable[4 * ctIndex ];
1047 } // unnamed namespace
1049 bool LoadBmpHeader( const ImageLoader::Input& input, unsigned int& width, unsigned int& height )
1051 BmpFileHeader fileHeader;
1052 BmpInfoHeader infoHeader;
1054 bool ret = LoadBmpHeader( input.file, width, height, fileHeader, infoHeader );
1059 bool LoadBitmapFromBmp( const ImageLoader::Input& input, Integration::Bitmap& bitmap )
1061 DALI_ASSERT_DEBUG( bitmap.GetPackedPixelsProfile() != 0 && "Need a packed pixel bitmap to load into." );
1062 FILE* const fp = input.file;
1065 DALI_LOG_ERROR("Error loading bitmap\n");
1068 BmpFormat customizedFormat = BMP_NOTEXIST;
1069 BmpFileHeader fileHeader;
1070 BmpInfoHeader infoHeader;
1072 // Load the header info
1073 unsigned int width, height;
1075 if (!LoadBmpHeader(fp, width, height, fileHeader, infoHeader))
1080 Pixel::Format pixelFormat = Pixel::RGB888;
1081 switch(infoHeader.compression)
1084 switch (infoHeader.bitsPerPixel)
1087 pixelFormat = Pixel::BGR8888;
1091 if(fileHeader.offset == FileHeaderOffsetOfRGB24V5)//0x8A
1093 customizedFormat = BMP_RGB24V5;
1097 pixelFormat = Pixel::RGB888;
1102 customizedFormat = BMP_RGB555;
1106 customizedFormat = BMP_RGB8;
1110 customizedFormat = BMP_RGB4;
1114 customizedFormat = BMP_RGB1;
1117 DALI_LOG_WARNING("%d bits per pixel not supported for BMP files\n", infoHeader.bitsPerPixel);
1123 if(infoHeader.bitsPerPixel == 8)
1125 customizedFormat = BMP_RLE8;
1131 if(infoHeader.bitsPerPixel == 4)
1133 customizedFormat = BMP_RLE4;
1137 case 3: // // BI_BITFIELDS
1139 if(infoHeader.bitsPerPixel == 16)
1141 if( fseek(fp, 14 + infoHeader.infoHeaderSize + 1, SEEK_SET) )
1147 if(fread(&mask, 1, 1, fp) != 1)
1152 if((mask & 0x80) == MaskForBFRGB565) // mask is 0xF8
1154 pixelFormat = Pixel::RGB565;
1156 else if((mask & 0x80) == 0)// mask is 0x 7C
1158 customizedFormat = BMP_BITFIELDS555;
1165 else if(infoHeader.bitsPerPixel == 32)
1167 if(fileHeader.offset == FileHeaderOffsetOfBF32V4)// 0x7A
1169 customizedFormat = BMP_BITFIELDS32V4;
1173 customizedFormat = BMP_BITFIELDS32;
1179 DALI_LOG_WARNING("Compression not supported for BMP files\n");
1183 bool topDown = false;
1185 // if height is negative, bitmap data is top down
1186 if (infoHeader.height<0)
1188 infoHeader.height = abs(infoHeader.height);
1189 height = infoHeader.height;
1193 unsigned int rowStride = infoHeader.width * (infoHeader.bitsPerPixel >>3);
1195 // bitmaps row stride is padded to 4 bytes
1196 unsigned int padding = (rowStride % 4);
1199 padding = 4 - padding;
1202 PixelBuffer *pixels = NULL;
1203 int imageW = infoHeader.width;
1204 int pixelBufferW = 0;
1205 switch(customizedFormat)
1212 case BMP_BITFIELDS555:
1214 pixelBufferW = ((imageW & 3) != 0) ? imageW + 4 - (imageW & 3) : imageW;
1215 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB888, pixelBufferW, abs(infoHeader.height));
1220 pixelBufferW = ((imageW & 63) != 0) ? imageW + 64 - (imageW & 63) : imageW;
1221 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB888, pixelBufferW, abs(infoHeader.height));
1224 case BMP_BITFIELDS32:
1225 case BMP_BITFIELDS32V4:
1227 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB8888, infoHeader.width, abs(infoHeader.height));
1232 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB888, infoHeader.width, infoHeader.height);
1236 if(pixelFormat == Pixel::RGB565 )
1238 pixelBufferW = ((imageW & 3) != 0) ? imageW + 4 - (imageW & 3) : imageW;
1239 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGB565, pixelBufferW, abs(infoHeader.height));
1243 pixels = bitmap.GetPackedPixelsProfile()->ReserveBuffer(pixelFormat, infoHeader.width, infoHeader.height);
1247 pixelBufferW = infoHeader.width;
1248 pixelBufferH = infoHeader.height;
1249 newPixelFormat = pixelFormat;
1254 // TODO: Add scaling support
1256 // Read the raw bitmap data
1257 PixelBuffer *pixelsPtr;
1258 bool decodeResult(false);
1259 switch(customizedFormat)
1263 decodeResult = DecodeRGB1( fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1268 decodeResult = DecodeRGB4(fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1273 decodeResult = DecodeRLE4( fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1276 case BMP_BITFIELDS32:
1278 decodeResult = DecodeBF32(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown, rowStride, padding);
1281 case BMP_BITFIELDS555:
1283 decodeResult = DecodeBF555(fp, pixels,infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown);
1288 decodeResult = DecodeRGB555(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown);
1293 decodeResult = DecodeRGB8(fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1298 decodeResult = DecodeRLE8(fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1303 decodeResult = DecodeRGB24V5(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown, rowStride, padding);
1306 case BMP_BITFIELDS32V4:
1308 decodeResult = DecodeBF32V4(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown, rowStride, padding);
1313 if(pixelFormat == Pixel::RGB565)
1315 decodeResult = DecodeBF565(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown);
1319 for (unsigned int yPos = 0; yPos < height; yPos++)
1323 // the data in the file is top down, and we store the data top down
1324 pixelsPtr = pixels + ( yPos * rowStride);
1328 // the data in the file is bottom up, and we store the data top down
1329 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
1332 if (fread(pixelsPtr, 1, rowStride, fp) != rowStride)
1334 DALI_LOG_ERROR("Error reading the BMP image\n");
1338 // If 24 bit mode then swap Blue and Red pixels
1339 // BGR888 doesn't seem to be supported by dali-core
1340 if (infoHeader.bitsPerPixel == 24 )
1342 for(unsigned int i = 0; i < rowStride; i += 3)
1344 unsigned char temp = pixelsPtr[i];
1345 pixelsPtr[i] = pixelsPtr[i+2];
1346 pixelsPtr[i+2] = temp;
1352 if( fseek(fp, padding, SEEK_CUR) ) // move past the padding.
1354 DALI_LOG_ERROR("Error moving past BMP padding\n");
1358 decodeResult = true;
1372 } // namespace TizenPlatform