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 <dali/internal/imaging/common/loader-bmp.h>
20 #include <dali/public-api/common/vector-wrapper.h>
21 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
22 #include <dali/integration-api/debug.h>
27 namespace TizenPlatform
32 const unsigned int FileHeaderOffsetOfBF32V4 = 0x7A;
33 const unsigned int MaskForBFRGB565 = 0x80;
34 const unsigned int FileHeaderOffsetOfRGB24V5 = 0x8A;
38 BMP_RGB1 = 14, //BI_RGB & bpp =1
39 BMP_RGB4, //BI_RGB & bpp = 4
40 BMP_RGB8, //BI_RGB & bpp = 8
41 BMP_RGB555, //BI_RGB & bpp = 16
42 BMP_BITFIELDS555, //BI_BITFIELDS & 16bit & R:G:B = 5:5:5
43 BMP_BITFIELDS32, //BI_BITFIELDS & 32bit & R:G:B:A = 8:8:8:8
46 BMP_BITFIELDS32V4,//BI_BITFIELDS & 32bit
47 BMP_RGB24V5, //BI_RGB & bpp = 24 & bmp version5
53 unsigned short signature; // Bitmap file signature
54 unsigned int fileSize; // Bitmap file size in bytes
55 unsigned short reserved1; // Reserved bits
56 unsigned short reserved2; // Reserved bits
57 unsigned int offset; // Offset from BMP file header to BMP bits
58 } __attribute__ ( (__packed__)); // Stops the structure from being aligned to every 4 bytes
62 unsigned int infoHeaderSize; // Specifies the number of bytes required by the info header
63 unsigned int width; // The Image Width
64 int height; // The Image Height (negative value represents image data is flipped)
65 unsigned short planes; // The number of color planes, must be 1
66 unsigned short bitsPerPixel; // The bits per pixel
67 unsigned int compression; // The type of compression used by the image
68 unsigned int imageSize; // The size of the image in bytes
69 unsigned int xPixelsPerMeter; // The number of pixels per meter in x axis
70 unsigned int yPixelsPerMeter; // The number of pixels per meter in y axis
71 unsigned int numberOfColors; // The number of colors in the color table
72 unsigned int importantColors; // The important color count
73 } __attribute__ ( (__packed__)); // Stops the structure from being aligned to every 4 bytes
76 * Template function to read from the file directly into our structure.
77 * @param[in] fp The file to read from
78 * @param[out] header The structure we want to store our information in
79 * @return true, if read successful, false otherwise
82 inline bool ReadHeader(FILE* fp, T& header)
84 const unsigned int readLength = sizeof(T);
86 // Load the information directly into our structure
87 if ( fread( &header, 1, readLength, fp ) != readLength )
95 bool LoadBmpHeader(FILE *fp, unsigned int &width, unsigned int &height, BmpFileHeader &fileHeader, BmpInfoHeader &infoHeader)
97 if (!ReadHeader(fp, fileHeader))
102 if (!ReadHeader(fp, infoHeader))
107 width = infoHeader.width;
108 height = abs(infoHeader.height);
110 if( infoHeader.width == 0 )
119 * function to decode format BI_RGB & bpp = 24 & bmp version5.
120 * @param[in] fp The file to read from
121 * @param[out] pixels The pointer that we want to store bmp data in
122 * @param[in] width bmp width
123 * @param[in] height bmp height
124 * @param[in] offset offset from bmp header to bmp image data
125 * @param[in] topDown indicate image data is read from bottom or from top
126 * @param[in] padding padded to a u_int32 boundary for each line
127 * @return true, if decode successful, false otherwise
129 bool DecodeRGB24V5(FILE *fp,
130 unsigned char* pixels,
135 unsigned int rowStride,
136 unsigned int padding)
138 if(fp == NULL || pixels == NULL)
140 DALI_LOG_ERROR("Error decoding BMP_RGB24V5 format\n");
143 if ( fseek(fp, offset, SEEK_SET) )
145 DALI_LOG_ERROR("Error seeking BMP_RGB24V5 data\n");
149 for(unsigned int yPos = 0; yPos < height; yPos ++)
151 unsigned char* pixelsPtr = NULL;
154 pixelsPtr = pixels + ( yPos * rowStride);
158 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
160 if (fread(pixelsPtr, 1, rowStride, fp) != rowStride)
162 DALI_LOG_ERROR("Error reading the BMP image\n");
165 for(unsigned int i = 0; i < rowStride; i += 3)
167 unsigned char temp = pixelsPtr[i];
168 pixelsPtr[i] = pixelsPtr[i + 2];
169 pixelsPtr[i + 2] = temp;
174 // move past the padding.
175 if( fseek(fp, padding, SEEK_CUR) )
177 DALI_LOG_ERROR("Error moving past BMP_RGB24V5 padding\n");
185 * function to decode format BI_BITFIELDS & bpp = 32 & bmp version4.
186 * @param[in] fp The file to read from
187 * @param[out] pixels The pointer that we want to store bmp data in
188 * @param[in] width bmp width
189 * @param[in] height bmp height
190 * @param[in] offset offset from bmp header to bmp image data
191 * @param[in] topDown indicate image data is read from bottom or from top
192 * @param[in] rowStride bits span for each line
193 * @param[in] padding padded to a u_int32 boundary for each line
194 * @return true, if decode successful, false otherwise
196 bool DecodeBF32V4(FILE *fp,
197 unsigned char* pixels,
202 unsigned int rowStride,
203 unsigned int padding)
205 if(fp == NULL || pixels == NULL)
207 DALI_LOG_ERROR("Error decoding BMP_BITFIELDS32V4 format\n");
210 if( fseek(fp, offset, SEEK_SET) )
212 DALI_LOG_ERROR("Error seeking BMP_BITFIELDS32V4 data\n");
216 for(unsigned int yPos = 0; yPos < height; yPos ++)
218 unsigned char* pixelsPtr = NULL;
221 pixelsPtr = pixels + ( yPos * rowStride);
225 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
227 if (fread(pixelsPtr, 1, rowStride, fp) != rowStride)
229 DALI_LOG_ERROR("Error reading the BMP image\n");
232 for(unsigned int i = 0; i < rowStride; i += 4)
234 unsigned char temp = pixelsPtr[i];
235 pixelsPtr[i] = pixelsPtr[i + 2];
236 pixelsPtr[i + 2] = temp;
240 // move past the padding.
241 if( fseek(fp, padding, SEEK_CUR) )
243 DALI_LOG_ERROR("Error moving past BMP_BITFIELDS32V4 padding\n");
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
263 bool DecodeBF32(FILE *fp,
264 unsigned char* pixels,
269 unsigned int rowStride,
270 unsigned int padding)
272 if(fp == NULL || pixels == NULL)
274 DALI_LOG_ERROR("Error decoding BMP_BITFIELDS32 format\n");
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++)
285 unsigned char* pixelsPtr;
288 // the data in the file is top down, and we store the data top down
289 pixelsPtr = pixels + ( yPos * rowStride);
293 // the data in the file is bottom up, and we store the data top down
294 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
297 if (fread(pixelsPtr, 1, rowStride, fp) != rowStride)
299 DALI_LOG_ERROR("Error reading the BMP image\n");
302 for(unsigned int i = 0; i < rowStride; i += 4)
304 unsigned char temp = pixelsPtr[i];
305 pixelsPtr[i] = pixelsPtr[i + 2];
306 pixelsPtr[i + 2] = temp;
311 // move past the padding.
312 if( fseek(fp, padding, SEEK_CUR) )
314 DALI_LOG_ERROR("Error moving past BMP_BITFIELDS32 padding\n");
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
331 bool DecodeBF565(FILE *fp,
332 unsigned char* pixels,
338 if(fp == NULL || pixels == NULL)
340 DALI_LOG_ERROR("Error decoding RGB565 format\n");
343 if( fseek(fp, offset, SEEK_SET) )
345 DALI_LOG_ERROR("Error seeking RGB565 data\n");
349 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
350 unsigned int rowStride = width * 2;
352 for(unsigned int i = 0; i < height; i++)
354 unsigned char* pixelsPtr = NULL;
357 // the data in the file is top down, and we store the data top down
358 pixelsPtr = pixels + ( i * rowStride);
362 // the data in the file is bottom up, and we store the data top down
363 pixelsPtr = pixels + (((height - 1) - i) * rowStride);
365 if(fread(pixelsPtr, 1, rowStride, fp) != rowStride)
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
384 bool DecodeBF555(FILE *fp,
385 unsigned char* pixels,
391 if(fp == NULL || pixels == NULL)
393 DALI_LOG_ERROR("Error decoding BMP_BITFIELDS555 format\n");
397 if( fseek(fp, offset, SEEK_SET) )
399 DALI_LOG_ERROR("Error seeking BMP_BITFIELDS555 data\n");
403 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
405 std::vector<char> raw(width * height * 2);
406 unsigned int rawStride = width * 2;
407 unsigned int rowStride = width * 3;
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++)
421 unsigned char* pixelsPtr = NULL;
424 // the data in the file is top down, and we store the data top down
425 pixelsPtr = pixels + ( yPos * rowStride);
429 // the data in the file is bottom up, and we store the data top down
430 pixelsPtr = pixels + (((height-1)-yPos) * rowStride);
433 for(unsigned int k = 0; k < width; k ++)
435 int 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;
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,
455 unsigned char* pixels,
461 if(fp == NULL || pixels == NULL)
463 DALI_LOG_ERROR("Error decoding BMP_RGB555 format\n");
466 if( fseek(fp, offset, SEEK_SET) )
468 DALI_LOG_ERROR("Error seeking BMP_RGB555 data\n");
472 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
473 std::vector<char> raw(width * height * 2);
474 unsigned int rawStride = width * 2;
475 unsigned int rowStride = width * 3;
478 for(unsigned int j = 0; j < height; j ++)
480 rawPtr = &raw[0] + ( j * rawStride);
481 if(fread(rawPtr, 1, rawStride, fp) != rawStride)
486 for(unsigned int i = 0; i < height; i++)
488 unsigned char* pixelsPtr = NULL;
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,
522 unsigned char* pixels,
528 if(fp == NULL || pixels == NULL)
530 DALI_LOG_ERROR("Error decoding BMP_RGB1 format\n");
533 if( fseek(fp, offset, SEEK_SET) )
535 DALI_LOG_ERROR("Error seeking BMP_RGB1 data\n");
539 unsigned char colorTable[8] = {0};
541 unsigned int fillw = ((width & 63) != 0) ? width + 64 - (width & 63) : width;
542 std::vector<char> colorIndex(fillw * height);
543 unsigned int rowStride = fillw * 3; // RGB
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)
570 unsigned char* pixelsPtr = NULL;
573 // the data in the file is top down, and we store the data top down
574 pixelsPtr = pixels + ( index * rowStride);
578 // the data in the file is bottom up, and we store the data top down
579 pixelsPtr = pixels + (((height - 1) - index) * rowStride);
581 for(unsigned int j = 0; j < fillw; j ++)
583 unsigned int ctIndex = 0;
584 if((fillw * index + j ) < (fillw * height))
586 ctIndex = colorIndex[ fillw * index + j ];
592 // temp solution for PLM bug P130411-5268, there is one mono bmp that cause DecodeRGB1 API crash.
593 if( ((3 * j + 2) < height * fillw * 3) && (ctIndex < 2))
595 pixelsPtr[ 3 * j ] = colorTable[4 * ctIndex + 2];
596 pixelsPtr[3 * j + 1] = colorTable[4 * ctIndex + 1];
597 pixelsPtr[3 * j + 2] = colorTable[4 * ctIndex ];
605 * function to decode format BI_RGB & bpp = 4
606 * @param[in] fp The file to read from
607 * @param[out] pixels The pointer that we want to store bmp data in
608 * @param[in] width bmp width
609 * @param[in] height bmp height
610 * @param[in] offset offset from bmp header to bmp palette data
611 * @param[in] topDown indicate image data is read from bottom or from top
612 * @return true, if decode successful, false otherwise
614 bool DecodeRGB4(FILE *fp,
615 unsigned char* pixels,
621 if(fp == NULL || pixels == NULL)
623 DALI_LOG_ERROR("Error decoding BMP_RGB4 format\n");
626 if( fseek(fp, offset, SEEK_SET) )
628 DALI_LOG_ERROR("Error seeking BMP_RGB4 data\n");
634 unsigned int fillw = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
635 std::vector<char> colorIndex(fillw * height);
636 unsigned int rowStride = fillw * 3;
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);
653 unsigned int ctIndex = 0;
655 for(unsigned int index = 0; index < height; index = index + 1)
657 unsigned char* pixelsPtr = NULL;
660 // the data in the file is top down, and we store the data top down
661 pixelsPtr = pixels + ( index * rowStride);
665 // the data in the file is bottom up, and we store the data top down
666 pixelsPtr = pixels + (((height - 1) - index) * rowStride);
668 for(unsigned int j = 0; j < fillw; j ++)
670 ctIndex = colorIndex[ fillw * index + j ];
671 pixelsPtr[ 3 * j ] = colorTable[4 * ctIndex + 2];
672 pixelsPtr[(3 * j + 1)] = colorTable[4 * ctIndex + 1];
673 pixelsPtr[(3 * j + 2)] = colorTable[4 * ctIndex ];
681 * function to decode format BI_RGB & bpp = 8
682 * @param[in] fp The file to read from
683 * @param[out] pixels The pointer that we want to store bmp data in
684 * @param[in] width bmp width
685 * @param[in] height bmp height
686 * @param[in] offset offset from bmp header to bmp palette data
687 * @param[in] topDown indicate image data is read from bottom or from top
688 * @return true, if decode successful, false otherwise
690 bool DecodeRGB8(FILE *fp,
691 unsigned char* pixels,
697 if(fp == NULL || pixels == NULL)
699 DALI_LOG_ERROR("Error decoding BMP_RGB8 format\n");
702 if( fseek(fp, offset, SEEK_SET) )
704 DALI_LOG_ERROR("Error seeking BMP_RGB8 data\n");
708 std::vector<char> colorTable(1024);
709 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
711 std::vector<char> colorIndex(width * height);
712 unsigned int rowStride = width * 3;//RGB8->RGB24
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)
727 unsigned int ctIndex = 0;
728 for(unsigned int index = 0; index < height; index = index + 1)
730 unsigned char* pixelsPtr = NULL;
733 // the data in the file is top down, and we store the data top down
734 pixelsPtr = pixels + ( index * rowStride);
738 // the data in the file is bottom up, and we store the data top down
739 pixelsPtr = pixels + (((height - 1) - index) * rowStride);
741 for(unsigned int j = 0; j < width; j ++)
743 ctIndex = colorIndex[ width * index + j ];
744 pixelsPtr[ 3 * j ] = colorTable[4 * ctIndex + 2];
745 pixelsPtr[(3 * j + 1)] = colorTable[4 * ctIndex + 1];
746 pixelsPtr[(3 * j + 2)] = colorTable[4 * ctIndex ];
753 * function to decode format BI_RLE4 & bpp = 4
754 * @param[in] fp The file to read from
755 * @param[out] pixels The pointer that we want to store bmp data in
756 * @param[in] width bmp width
757 * @param[in] height bmp height
758 * @param[in] offset offset from bmp header to bmp palette data
759 * @param[in] topDown indicate image data is read from bottom or from top
760 * @return true, if decode successful, false otherwise
762 bool DecodeRLE4(FILE *fp,
763 unsigned char* pixels,
769 if(fp == NULL || pixels == NULL)
771 DALI_LOG_ERROR("Error decoding BMP_RLE4 format\n");
774 unsigned char* pixelsPtr = pixels;
775 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
777 unsigned int cmdStride = 2;
779 std::vector<char> colorIndex(width * height >> 1);
780 std::vector<char> run;
785 width += (width & 1);
790 if( fseek(fp, offset, SEEK_SET) )
792 DALI_LOG_ERROR("Error seeking BMP_RLE4 data\n");
796 if (fread(colorTable, 1, 64, fp) != 64)
801 while((x >> 1) + y * width < width * height)
807 if (fread(cmd, 1, cmdStride, fp) != cmdStride)
811 if(cmd[0] == 0) // ESCAPE
815 case 1: //end of bitmap
818 case 0: // end of line
823 if (fread(cmd, 1, cmdStride, fp) != cmdStride)
825 DALI_LOG_ERROR("Error reading the BMP image\n");
828 dx = cmd[0] & (0xFF);
829 dy = cmd[1] & (0xFF);
834 // decode a literal run
835 unsigned int length = cmd[1] & (0xFF);
836 //size of run, which is word aligned
837 unsigned int bytesize = length;
838 bytesize += (bytesize & 1);
840 bytesize += (bytesize & 1);
841 run.resize(bytesize);
842 if(fread(&run[0], 1, bytesize, fp) != bytesize)
844 DALI_LOG_ERROR("Error reading the BMP image\n");
849 length += (length & 1);
851 for(unsigned int i = 0; i < length; i += 1)
853 colorIndex[(x >> 1) + width * (height - y - 1) + i] = run[i];
858 for(unsigned int i = 0; i < length; i ++)
860 if((i & 1) == 0)//copy high to low
862 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((run[i >> 1] & 0xF0) >> 4);
864 else //copy low to high
866 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((run[i >> 1] & 0x0F) << 4);
870 x += cmd[1] & (0xFF);
876 unsigned int length = cmd[0] & (0xFF);
879 length += (length & 1);
881 for(unsigned int i = 0; i < length; i ++)
883 colorIndex[(height-y-1)*width + i + (x >> 1)] = cmd[1];
888 for(unsigned int i = 0; i < length; i ++)
892 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((cmd[1] & 0xF0) >> 4);
896 colorIndex[((x + i) >> 1) + width * (height - y - 1)] |= ((cmd[1] & 0x0F) << 4);
900 x += cmd[0] & (0xFF);
906 for(unsigned int index = 0; index < (width * height ); index = index + 1)
908 ctIndexHigh = colorIndex[ index] >> 4;
909 ctIndexLow = colorIndex[index] & (0x0F);
910 pixelsPtr[6 * index ] = colorTable[4 * ctIndexHigh + 2];
911 pixelsPtr[6 * index + 1] = colorTable[4 * ctIndexHigh + 1];
912 pixelsPtr[6 * index + 2] = colorTable[4 * ctIndexHigh ];
913 pixelsPtr[6 * index + 3] = colorTable[4 * ctIndexLow + 2];
914 pixelsPtr[6 * index + 4] = colorTable[4 * ctIndexLow + 1];
915 pixelsPtr[6 * index + 5] = colorTable[4 * ctIndexLow ];
921 * function to decode format BI_RLE8 & bpp = 8
922 * @param[in] fp The file to read from
923 * @param[out] pixels The pointer that we want to store bmp data in
924 * @param[in] width bmp width
925 * @param[in] height bmp height
926 * @param[in] offset offset from bmp header to bmp palette data
927 * @param[in] topDown indicate image data is read from bottom or from top
928 * @return true, if decode successful, false otherwise
930 bool DecodeRLE8(FILE *fp,
931 unsigned char* pixels,
937 if(fp == NULL || pixels == NULL)
939 DALI_LOG_ERROR("Error decoding BMP_RLE8 format\n");
942 unsigned char* pixelsPtr = pixels;
945 unsigned int cmdStride = 2;
947 width = ((width & 3) != 0) ? width + 4 - (width & 3) : width;
948 std::vector<char> colorTable(1024);
950 std::vector<char> colorIndex(width * height);
952 if( fseek(fp, offset, SEEK_SET) )
954 DALI_LOG_ERROR("Error seeking BMP_RLE8 data\n");
958 if (fread(&colorTable[0], 1, 1024, fp) != 1024)
966 unsigned int length = 0;
967 unsigned int copylength = 0;
968 std::vector<char> run;
969 while((x + y * width) < width * height )
975 if (fread(cmd, 1, cmdStride, fp) != cmdStride)
980 if(cmd[0] == 0)//ESCAPE
984 case 1: // end of bitmap
987 case 0: // end of line
992 if (fread(cmd, 1, cmdStride, fp) != cmdStride)
994 DALI_LOG_ERROR("Error reading the BMP image\n");
997 dx = cmd[0] & (0xFF);
998 dy = cmd[1] & (0xFF);
1003 //decode a literal run
1004 length = cmd[1] & (0xFF);
1005 copylength = length;
1006 //absolute mode must be word-aligned
1007 length += (length & 1);
1009 if(fread(&run[0], 1, length, fp) != length)
1011 DALI_LOG_ERROR("Error reading the BMP image\n");
1015 for(unsigned int i = 0; i < length; i += 1)
1017 colorIndex[x + width * (height - y - 1) + i] = run[i];
1022 }// end if cmd[0] ==
1025 length = cmd[0] & (0xFF);
1026 for(unsigned int i = 0; i < length; i ++)
1028 colorIndex[(height - y - 1) * width + x] = cmd[1];
1034 for(unsigned int index = 0; index < width * height; index = index + 1)
1036 ctIndex = colorIndex[ index];
1037 pixelsPtr[3 * index ] = colorTable[4 * ctIndex + 2];
1038 pixelsPtr[3 * index + 1] = colorTable[4 * ctIndex + 1];
1039 pixelsPtr[3 * index + 2] = colorTable[4 * ctIndex ];
1044 } // unnamed namespace
1046 bool LoadBmpHeader( const Dali::ImageLoader::Input& input, unsigned int& width, unsigned int& height )
1048 BmpFileHeader fileHeader;
1049 BmpInfoHeader infoHeader;
1051 bool ret = LoadBmpHeader( input.file, width, height, fileHeader, infoHeader );
1056 bool LoadBitmapFromBmp( const Dali::ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap )
1058 //DALI_ASSERT_DEBUG( bitmap.GetPackedPixelsProfile() != 0 && "Need a packed pixel bitmap to load into." );
1059 FILE* const fp = input.file;
1062 DALI_LOG_ERROR("Error loading bitmap\n");
1065 BmpFormat customizedFormat = BMP_NOTEXIST;
1066 BmpFileHeader fileHeader;
1067 BmpInfoHeader infoHeader;
1069 // Load the header info
1070 unsigned int width, height;
1072 if (!LoadBmpHeader(fp, width, height, fileHeader, infoHeader))
1077 Pixel::Format pixelFormat = Pixel::RGB888;
1078 switch(infoHeader.compression)
1081 switch (infoHeader.bitsPerPixel)
1084 pixelFormat = Pixel::BGR8888;
1088 if(fileHeader.offset == FileHeaderOffsetOfRGB24V5)//0x8A
1090 customizedFormat = BMP_RGB24V5;
1094 pixelFormat = Pixel::RGB888;
1099 customizedFormat = BMP_RGB555;
1103 customizedFormat = BMP_RGB8;
1107 customizedFormat = BMP_RGB4;
1111 customizedFormat = BMP_RGB1;
1114 DALI_LOG_WARNING("%d bits per pixel not supported for BMP files\n", infoHeader.bitsPerPixel);
1120 if(infoHeader.bitsPerPixel == 8)
1122 customizedFormat = BMP_RLE8;
1128 if(infoHeader.bitsPerPixel == 4)
1130 customizedFormat = BMP_RLE4;
1134 case 3: // // BI_BITFIELDS
1136 if(infoHeader.bitsPerPixel == 16)
1138 if( fseek(fp, 14 + infoHeader.infoHeaderSize + 1, SEEK_SET) )
1144 if(fread(&mask, 1, 1, fp) != 1)
1149 if((mask & 0x80) == MaskForBFRGB565) // mask is 0xF8
1151 pixelFormat = Pixel::RGB565;
1153 else if((mask & 0x80) == 0)// mask is 0x 7C
1155 customizedFormat = BMP_BITFIELDS555;
1162 else if(infoHeader.bitsPerPixel == 32)
1164 if(fileHeader.offset == FileHeaderOffsetOfBF32V4)// 0x7A
1166 customizedFormat = BMP_BITFIELDS32V4;
1170 customizedFormat = BMP_BITFIELDS32;
1176 DALI_LOG_WARNING("Compression not supported for BMP files\n");
1180 bool topDown = false;
1182 // if height is negative, bitmap data is top down
1183 if (infoHeader.height<0)
1185 infoHeader.height = abs(infoHeader.height);
1186 height = infoHeader.height;
1190 unsigned int rowStride = infoHeader.width * (infoHeader.bitsPerPixel >>3);
1192 // bitmaps row stride is padded to 4 bytes
1193 unsigned int padding = (rowStride % 4);
1196 padding = 4 - padding;
1199 int imageW = infoHeader.width;
1200 int pixelBufferW = infoHeader.width;
1201 int pixelBufferH = infoHeader.height;
1202 auto newPixelFormat = Pixel::Format::INVALID;
1204 switch(customizedFormat)
1211 case BMP_BITFIELDS555:
1213 pixelBufferW = ((imageW & 3) != 0) ? imageW + 4 - (imageW & 3) : imageW;
1214 pixelBufferH = abs(infoHeader.height);
1215 newPixelFormat = Pixel::RGB888;
1220 pixelBufferW = ((imageW & 63) != 0) ? imageW + 64 - (imageW & 63) : imageW;
1221 pixelBufferH = abs(infoHeader.height);
1222 newPixelFormat = Pixel::RGB888;
1225 case BMP_BITFIELDS32:
1226 case BMP_BITFIELDS32V4:
1228 pixelBufferH = abs(infoHeader.height);
1229 newPixelFormat = Pixel::RGB8888;
1234 newPixelFormat = Pixel::RGB888;
1238 if(pixelFormat == Pixel::RGB565 )
1240 pixelBufferW = ((imageW & 3) != 0) ? imageW + 4 - (imageW & 3) : imageW;
1241 pixelBufferH = abs(infoHeader.height);
1242 newPixelFormat = Pixel::RGB565;
1246 pixelBufferW = infoHeader.width;
1247 pixelBufferH = infoHeader.height;
1248 newPixelFormat = pixelFormat;
1253 bitmap = Dali::Devel::PixelBuffer::New(pixelBufferW, pixelBufferH, newPixelFormat);
1254 auto pixels = bitmap.GetBuffer();
1256 // Read the raw bitmap data
1257 decltype(pixels) pixelsIterator = nullptr;
1259 bool decodeResult(false);
1260 switch(customizedFormat)
1264 decodeResult = DecodeRGB1( fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1269 decodeResult = DecodeRGB4(fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1274 decodeResult = DecodeRLE4( fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1277 case BMP_BITFIELDS32:
1279 decodeResult = DecodeBF32(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown, rowStride, padding);
1282 case BMP_BITFIELDS555:
1284 decodeResult = DecodeBF555(fp, pixels,infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown);
1289 decodeResult = DecodeRGB555(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown);
1294 decodeResult = DecodeRGB8(fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1299 decodeResult = DecodeRLE8(fp, pixels, infoHeader.width, abs(infoHeader.height), 14 + infoHeader.infoHeaderSize, topDown);
1304 decodeResult = DecodeRGB24V5(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown, rowStride, padding);
1307 case BMP_BITFIELDS32V4:
1309 decodeResult = DecodeBF32V4(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown, rowStride, padding);
1314 if(pixelFormat == Pixel::RGB565)
1316 decodeResult = DecodeBF565(fp, pixels, infoHeader.width, abs(infoHeader.height), fileHeader.offset, topDown);
1320 for (unsigned int yPos = 0; yPos < height; yPos++)
1324 // the data in the file is top down, and we store the data top down
1325 pixelsIterator = pixels + ( yPos * rowStride);
1329 // the data in the file is bottom up, and we store the data top down
1330 pixelsIterator = pixels + (((height-1)-yPos) * rowStride);
1333 if (fread(pixelsIterator, 1, rowStride, fp) != rowStride)
1335 DALI_LOG_ERROR("Error reading the BMP image\n");
1339 // If 24 bit mode then swap Blue and Red pixels
1340 // BGR888 doesn't seem to be supported by dali-core
1341 if (infoHeader.bitsPerPixel == 24 )
1343 for(unsigned int i = 0; i < rowStride; i += 3)
1345 unsigned char temp = pixelsIterator[i];
1346 pixelsIterator[i] = pixelsIterator[i+2];
1347 pixelsIterator[i+2] = temp;
1353 if( fseek(fp, padding, SEEK_CUR) ) // move past the padding.
1355 DALI_LOG_ERROR("Error moving past BMP padding\n");
1359 decodeResult = true;
1373 } // namespace TizenPlatform