EZR32 Wonder Gecko Software Documentation  ezr32wg-doc-5.1.2
bmp.c
1  /*************************************************************************/
16 /* BMP Header files */
17 #include "bmp.h"
18 
19 /* C Standard header files */
20 #include <stdint.h>
21 
22 /* EM types */
23 #include "em_types.h"
24 
27 #define MODE_RLE (0)
28 #define MODE_8BIT (1)
29 
30 BMP_Header bmpHeader;
31 BMP_Palette bmpPalette;
32 
33 static uint8_t localCache[ BMP_LOCAL_CACHE_SIZE ];
34 
35 /* Local variables */
36 static uint32_t moduleInit = 0;
37 static uint32_t fileReset = 0;
38 static uint32_t paletteRead = 0;
39 static uint32_t bytesInImage = 0;
40 static uint32_t dataIdx = 0;
41 
43 typedef struct __BMP_RleInfo
44 {
46  uint32_t mode;
48  uint32_t isPadding;
50  uint8_t pixelsRemaining;
52  uint8_t pixelIdx;
53 } RleInfo;
54 
55 RleInfo rleInfo;
56 
57 /* Local function pointer */
58 EMSTATUS (*fpReadData)(uint8_t buffer[], uint32_t bufLength, uint32_t bytesToRead);
59 
62 /* Local function declarations */
63 static EMSTATUS BMP_readRawData8bit(BMP_DataType *dataType, uint8_t buffer[], uint32_t bufLength);
64 static EMSTATUS BMP_readRawData24bit(BMP_DataType *dataType, uint8_t buffer[], uint32_t bufLength);
65 static EMSTATUS BMP_readRawDataRLE8(BMP_DataType *dataType, uint8_t buffer[], uint32_t bufLength);
66 static EMSTATUS BMP_readPaddingBytes(uint8_t paddingBytes);
67 static EMSTATUS BMP_readRleData(BMP_DataType *dataType, uint8_t buffer[], uint32_t bufLength);
68 static EMSTATUS BMP_readRgbDataRLE8(uint8_t buffer[], uint32_t bufLength, uint32_t *pixelsRead);
69 
70 /**************************************************************************/
99 EMSTATUS BMP_init(uint8_t *palette, uint32_t paletteSize, EMSTATUS (*fp)(uint8_t buffer[], uint32_t bufLength, uint32_t bytesToRead))
100 {
101  /* Check if compiler has aligned structure members on equal boundarys */
102  if (sizeof(bmpHeader) != BMP_HEADER_SIZE) return BMP_ERROR_HEADER_SIZE_MISMATCH;
103 
104  /* Check buffer size */
106 
107  bmpPalette.data = palette;
108  bmpPalette.size = paletteSize;
109 
110  /* Set function pointer */
111  fpReadData = fp;
112 
113  fileReset = 0;
114  paletteRead = 0;
115  dataIdx = 0;
116 
117  moduleInit = 1;
118 
119  return BMP_OK;
120 }
121 
122 /**************************************************************************/
131 EMSTATUS BMP_reset()
132 {
133  /* Check if module is initialized */
134  if (moduleInit == 0) return BMP_ERROR_MODULE_NOT_INITIALIZED;
135 
136  EMSTATUS status;
137 
138  /* Read in header */
139  status = fpReadData((uint8_t *) &bmpHeader, BMP_HEADER_SIZE, BMP_HEADER_SIZE);
140  if (status != BMP_OK)
141  {
142  return status;
143  }
144 
145  /* Do all the neccesary checks */
146  /* Check for little-endian */
147  if (bmpHeader.magic != 0x4D42)
148  {
149  if (bmpHeader.magic == 0x424D)
150  {
152  }
153  else
154  {
155  return BMP_ERROR_FILE_INVALID;
156  }
157  }
158 
159  /* Check if header size is correct. The header size is used to indicate the version of BMP */
160  if (bmpHeader.headerSize != 40)
161  {
163  }
164 
165  /* Check if file is supported */
166  if (bmpHeader.bitsPerPixel != 24 && bmpHeader.bitsPerPixel != 8)
167  {
169  }
170 
171  /* Check if compression is supported */
172  if (bmpHeader.compressionType > 1)
173  {
175  }
176 
177  /* Do a fix if imageDataSize is broken. It happens to some BMP pictures in some editors */
178  if (bmpHeader.imageDataSize == 0)
179  {
180  bmpHeader.imageDataSize = bmpHeader.fileSize - bmpHeader.dataOffset;
181  }
182 
183  bytesInImage = bmpHeader.imageDataSize;
184  /* Set a byte limit to the number of bytes in images. This is required because some bmp editors store bmps differently */
185  if (bmpHeader.compressionType == 0) bytesInImage = (bmpHeader.imageDataSize / bmpHeader.height) * bmpHeader.height;
186 
187  /* Check if palette is necessary */
188  if (bmpHeader.bitsPerPixel == 8)
189  {
190  /* Check if BMP_Palette is big enough */
191  uint32_t pSize = bmpHeader.dataOffset - BMP_HEADER_SIZE;
192  if (pSize > bmpPalette.size) return BMP_ERROR_INVALID_PALETTE_SIZE;
193 
194  if (bmpPalette.data == NULL) return BMP_ERROR_PALETTE_NOT_READ;
195 
196  /* Read in palette */
197  status = fpReadData(bmpPalette.data, bmpPalette.size, pSize);
198  if (status != BMP_OK)
199  {
200  return status;
201  }
202 
203  uint8_t swap;
204  uint32_t i;
205  /* Convert BGR values to RGB values */
206  for (i = 0; i < pSize; i += 4)
207  {
208  swap = bmpPalette.data[i];
209 
210  bmpPalette.data[i] = bmpPalette.data[i + 2];
211 
212  bmpPalette.data[i + 2] = swap;
213  }
214 
215  paletteRead = 1;
216  }
217 
218  /* Reset static variables */
219  fileReset = 1;
220  dataIdx = 0;
221  rleInfo.mode = MODE_RLE;
222  rleInfo.isPadding = 0;
223  rleInfo.pixelsRemaining = 0;
224  rleInfo.pixelIdx = 0;
225 
226  return BMP_OK;
227 }
228 
229 /**************************************************************************/
247 EMSTATUS BMP_readRgbData(uint8_t buffer[], uint32_t bufLength, uint32_t *pixelsRead)
248 {
249  *pixelsRead = 0;
250 
251  /* Check if module is initialized */
252  if (moduleInit == 0) return BMP_ERROR_MODULE_NOT_INITIALIZED;
253 
254  /* Check file is reset */
255  if (fileReset == 0) return BMP_ERROR_FILE_NOT_RESET;
256 
257  /* Check if end of file is reached */
258  if (dataIdx >= bytesInImage) return BMP_ERROR_END_OF_FILE;
259 
260  /* Check if buffer is big enough to hold at least one pixel (3 bytes) */
261  if (bufLength < 3) return BMP_ERROR_BUFFER_TOO_SMALL;
262 
263  EMSTATUS status = BMP_OK;
264 
265  /* Calculate how many bytes to read */
266  uint32_t bytesLeftInBuffer = bufLength - (bufLength % 3);
267  uint32_t bytesToRead;
268  uint32_t bytesPerRow = bmpHeader.imageDataSize / bmpHeader.height;
269  uint32_t bufferIdx = 0;
270  uint32_t i = 0;
271 
272  BMP_DataType dataType;
273 
274  /* Check color depth of BMP */
275  if (bmpHeader.bitsPerPixel == 8)
276  {
277  /* Check if palette is read */
278  if (paletteRead == 0) return BMP_ERROR_PALETTE_NOT_READ;
279 
280  /* Check for compression */
281  if (bmpHeader.compressionType == RLE8_COMPRESSION)
282  {
283  /* Read 8-bit RLE */
284  status = BMP_readRgbDataRLE8(buffer, bufLength, pixelsRead);
285  if (status != BMP_OK) return status;
286  }
287  else if (bmpHeader.compressionType == NO_COMPRESSION)
288  {
289  /* Reads 8-bit data */
290  dataType.endOfRow = 0;
291 
292  while (bytesLeftInBuffer > 0 && dataType.endOfRow == 0)
293  {
294  /* Calculate how many bytes to read */
295  bytesToRead = BMP_LOCAL_CACHE_SIZE;
296 
297  /* If bytesLeftInBuffer is not large enough, reduce bytesToRead */
298  if (bytesLeftInBuffer < bytesToRead * 3)
299  {
300  bytesToRead = bytesLeftInBuffer / 3;
301  }
302 
303  /* Read in palette indicies */
304  status = BMP_readRawData8bit(&dataType, localCache, bytesToRead);
305  if (status != BMP_OK) return status;
306 
307  /* Decode the indicies to RGB values */
308  for (i = 0; i < dataType.size; ++i)
309  {
310  /* Set red */
311  buffer[ bufferIdx ] = bmpPalette.data[ 4 * localCache[i] ];
312  /* Set green */
313  buffer[ bufferIdx + 1 ] = bmpPalette.data[ 4 * localCache[i] + 1 ];
314  /* Set blue */
315  buffer[ bufferIdx + 2 ] = bmpPalette.data[ 4 * localCache[i] + 2 ];
316 
317  bufferIdx += 3;
318  }
319 
320  *pixelsRead += dataType.size;
321  bytesLeftInBuffer -= dataType.size * 3;
322  }
323 
324  /* Check if padding bytes needs to be read */
325  if (dataType.endOfRow == 1)
326  {
327  uint8_t paddingBytes = bytesPerRow - bmpHeader.width;
328 
329  status = BMP_readPaddingBytes(paddingBytes);
330  if (status != BMP_OK) return BMP_OK;
331  }
332  }
333  }
334  else if (bmpHeader.bitsPerPixel == 24)
335  {
336  /* Reads 24-bit data */
337  status = BMP_readRawData(&dataType, buffer, bufLength);
338  *pixelsRead = dataType.size / 3;
339  }
340 
341  return status;
342 }
343 
344 /**************************************************************************/
359 static EMSTATUS BMP_readRgbDataRLE8(uint8_t buffer[], uint32_t bufLength, uint32_t *pixelsRead)
360 {
361  EMSTATUS status;
362  BMP_DataType dataType;
363  dataType.endOfRow = 0;
364  uint32_t bufferIdx = 0;
365  uint32_t bytesLeftInBuffer = bufLength - (bufLength % 3);
366  uint32_t bytesToRead;
367  uint32_t i;
368 
369  while (bytesLeftInBuffer > 0 && dataType.endOfRow == 0)
370  {
371  if (rleInfo.mode == MODE_RLE)
372  {
373  /* RLE mode */
374 
375  /* Check if any RLE pixels are left to read and convert remaining pixels */
376  while (rleInfo.pixelsRemaining > 0 && bytesLeftInBuffer > 0)
377  {
378  /* Set red */
379  buffer[ bufferIdx ] = bmpPalette.data[ 4 * rleInfo.pixelIdx ];
380  /* Set green */
381  buffer[ bufferIdx + 1 ] = bmpPalette.data[ 4 * rleInfo.pixelIdx + 1 ];
382  /* Set blue */
383  buffer[ bufferIdx + 2 ] = bmpPalette.data[ 4 * rleInfo.pixelIdx + 2 ];
384 
385  rleInfo.pixelsRemaining -= 1;
386  bytesLeftInBuffer -= 3;
387  bufferIdx += 3;
388  *pixelsRead += 1;
389  }
390 
391  /* Check if all RLE pixels has been decoded */
392  if (rleInfo.pixelsRemaining == 0)
393  {
394  /* Read in 2 RLE bytes */
395  status = BMP_readRleData(&dataType, localCache, BMP_LOCAL_CACHE_SIZE);
396  if (status != BMP_OK) return status;
397 
398  /* Check if localCache contains RLE info */
399  if (localCache[0] > 0)
400  {
401  /* Store the RLE info in buffer */
402  rleInfo.pixelsRemaining = localCache[0];
403  rleInfo.pixelIdx = localCache[ 1 ];
404  }
405  }
406  }
407 
408  if (rleInfo.mode == MODE_8BIT)
409  {
410  /* 8Bit mode */
411 
412  /* Calculate how many bytes to read */
413  bytesToRead = rleInfo.pixelsRemaining;
414 
415  if (bytesToRead * 3 > bytesLeftInBuffer)
416  {
417  bytesToRead = bytesLeftInBuffer / 3;
418  }
419 
420  /* Check if bytesToRead fit in localCache */
421  if (bytesToRead > BMP_LOCAL_CACHE_SIZE)
422  {
423  bytesToRead = BMP_LOCAL_CACHE_SIZE;
424  }
425 
426  /* Read in bytesToRead */
427  status = fpReadData(localCache, BMP_LOCAL_CACHE_SIZE, bytesToRead);
428  if (status != BMP_OK)
429  {
430  return status;
431  }
432 
433  dataIdx += bytesToRead;
434 
435  /* Convert 8-bit bytes to RGB values */
436  for (i = 0; i < bytesToRead; ++i)
437  {
438  /* Set red */
439  buffer[ bufferIdx ] = bmpPalette.data[ 4 * localCache[i] ];
440  /* Set green */
441  buffer[ bufferIdx + 1 ] = bmpPalette.data[ 4 * localCache[i] + 1 ];
442  /* Set blue */
443  buffer[ bufferIdx + 2 ] = bmpPalette.data[ 4 * localCache[i] + 2 ];
444 
445  bufferIdx += 3;
446  bytesLeftInBuffer -= 3;
447  }
448 
449  *pixelsRead += bytesToRead;
450  rleInfo.pixelsRemaining -= bytesToRead;
451 
452  if (rleInfo.pixelsRemaining == 0)
453  {
454  /* Switch to RLE mode */
455  rleInfo.mode = MODE_RLE;
456 
457  /* Read in padding if necessary */
458  if (rleInfo.isPadding == 1)
459  {
460  status = fpReadData(localCache, BMP_LOCAL_CACHE_SIZE, 1);
461  if (status != BMP_OK) return status;
462 
463  dataIdx += 1;
464  }
465 
466  /* Read in the next 2 bytes to see if end of row is reached or end of file */
467  status = BMP_readRleData(&dataType, localCache, BMP_LOCAL_CACHE_SIZE);
468  if (status != BMP_OK) return status;
469 
470  /* Check if the next 2 bytes is RLE info */
471  if (localCache[0] > 0)
472  {
473  /* Store rle bytes */
474  rleInfo.pixelsRemaining = localCache[0];
475  rleInfo.pixelIdx = localCache[1];
476  }
477  }
478  }
479  }
480 
481  return BMP_OK;
482 }
483 
484 /**************************************************************************/
498 static EMSTATUS BMP_readRawData8bit(BMP_DataType *dataType, uint8_t buffer[], uint32_t bufLength)
499 {
500  /* Check if end of file is reached */
501  if (dataIdx >= bytesInImage) return BMP_ERROR_END_OF_FILE;
502 
503  EMSTATUS status;
504 
505  uint32_t bytesToRead;
506  uint32_t bytesPerRow = bmpHeader.imageDataSize / bmpHeader.height;
507 
508  dataType->bitsPerPixel = 8;
509  dataType->compressionType = 0;
510  dataType->endOfRow = 0;
511 
512  /* Calculate how many bytes to read */
513  /* Set bytes to read to end of row */
514  bytesToRead = bmpHeader.width - dataIdx % bytesPerRow;
515  dataType->endOfRow = 1;
516 
517  /* If bytesLeftInBuffer is not large enough, reduce bytesToRead */
518  if (bufLength < bytesToRead)
519  {
520  bytesToRead = bufLength;
521  dataType->endOfRow = 0;
522  }
523 
524  /* Read in bytesToRead */
525  status = fpReadData(buffer, bufLength, bytesToRead);
526  if (status != BMP_OK)
527  {
528  return status;
529  }
530 
531  dataIdx += bytesToRead;
532  dataType->size = bytesToRead;
533 
534  return BMP_OK;
535 }
536 
537 /**************************************************************************/
551 static EMSTATUS BMP_readRawData24bit(BMP_DataType *dataType, uint8_t buffer[], uint32_t bufLength)
552 {
553  /* Check if end of file is reached */
554  if (dataIdx >= bytesInImage) return BMP_ERROR_END_OF_FILE;
555 
556  EMSTATUS status;
557 
558  uint32_t i;
559  uint32_t bytesLeftInBuffer = bufLength - (bufLength % 3);
560  uint32_t bytesToRead;
561  uint32_t bytesPerRow = bmpHeader.imageDataSize / bmpHeader.height;
562  uint8_t swap;
563 
564  dataType->bitsPerPixel = 24;
565  dataType->compressionType = NO_COMPRESSION;
566 
567  /* Read 24-bits data */
568  /* Set bytesToRead to end of row */
569  bytesToRead = bmpHeader.width * 3 - dataIdx % bytesPerRow;
570  dataType->endOfRow = 1;
571 
572  if (bytesToRead > bytesLeftInBuffer)
573  {
574  bytesToRead = bytesLeftInBuffer;
575  dataType->endOfRow = 0;
576  }
577 
578  /* Read in bytesToRead */
579  status = fpReadData(buffer, bufLength, bytesToRead);
580  if (status != BMP_OK)
581  {
582  return status;
583  }
584 
585  dataIdx += bytesToRead;
586  dataType->size = bytesToRead;
587 
588  /* Copy BGR values to buffer. Flip BGR to RGB */
589  for (i = 0; i < bytesToRead; i += 3)
590  {
591  swap = buffer[ i ];
592  /* Set Red */
593  buffer[ i ] = buffer[i + 2];
594  /* Set Blue */
595  buffer[ i + 2 ] = swap;
596  }
597 
598  bytesLeftInBuffer -= bytesToRead;
599 
600  return BMP_OK;
601 }
602 
603 /**************************************************************************/
617 static EMSTATUS BMP_readRawDataRLE8(BMP_DataType *dataType, uint8_t buffer[], uint32_t bufLength)
618 {
619  EMSTATUS status;
620 
621  uint32_t bufferIdx = 0;
622 
623  dataType->bitsPerPixel = 8;
624 
625  if (rleInfo.mode == MODE_RLE)
626  {
627  /* RLE mode */
628 
629  dataType->compressionType = RLE8_COMPRESSION; /* RLE compressionType */
630 
631  /* Reduce bufLength to an even number if necessary */
632  if (bufLength % 2 == 1) bufLength--;
633 
634  /* Check if any RLE pixels are left to read */
635  if (rleInfo.pixelsRemaining > 0)
636  {
637  buffer[ bufferIdx ] = rleInfo.pixelsRemaining;
638  buffer[ bufferIdx + 1 ] = rleInfo.pixelIdx;
639 
640  bufferIdx += 2;
641  dataType->size += 2;
642  }
643 
644  while (rleInfo.mode == MODE_RLE && bufferIdx < bufLength && dataType->endOfRow == 0)
645  {
646  /* Read in 2 RLE bytes */
647  status = BMP_readRleData(dataType, localCache, BMP_LOCAL_CACHE_SIZE);
648  if (status != BMP_OK) return status;
649 
650  /* Check if localCache contains RLE info */
651  if (localCache[0] > 0)
652  {
653  /* Store the RLE info in buffer */
654  buffer[ bufferIdx ] = localCache[0];
655  buffer[ bufferIdx + 1 ] = localCache[1];
656 
657  bufferIdx += 2;
658  dataType->size += 2;
659  }
660  }
661  }
662 
663  if (rleInfo.mode == MODE_8BIT && bufferIdx == 0)
664  {
665  /* 8Bit mode */
666  dataType->compressionType = NO_COMPRESSION;
667  /* Calculate how many bytes to read */
668  uint32_t bytesToRead = rleInfo.pixelsRemaining;
669 
670  if (bytesToRead > bufLength)
671  {
672  bytesToRead = bufLength;
673  }
674 
675  /* Read in bytesToRead */
676  status = fpReadData(buffer, bufLength, bytesToRead);
677  if (status != BMP_OK)
678  {
679  return status;
680  }
681 
682  /* Update variables */
683  rleInfo.pixelsRemaining -= bytesToRead;
684  dataIdx += bytesToRead;
685  dataType->size = bytesToRead;
686 
687  if (rleInfo.pixelsRemaining == 0)
688  {
689  /* Switch to RLE mode */
690  rleInfo.mode = MODE_RLE;
691 
692  /* Read in padding if necessary */
693  if (rleInfo.isPadding == 1)
694  {
695  status = fpReadData(localCache, BMP_LOCAL_CACHE_SIZE, 1);
696  if (status != BMP_OK) return status;
697 
698  dataIdx += 1;
699  }
700  }
701  }
702 
703 
704  if (rleInfo.mode == MODE_RLE && rleInfo.pixelsRemaining == 0 && dataType->endOfRow == 0)
705  {
706  /* Read in the next 2 bytes to see if end of row is reached or end of file */
707  status = BMP_readRleData(dataType, localCache, BMP_LOCAL_CACHE_SIZE);
708  if (status != BMP_OK) return status;
709 
710  /* Check if the next 2 bytes is RLE info */
711  if (localCache[0] > 0)
712  {
713  /* Store rle bytes */
714  rleInfo.pixelsRemaining = localCache[0];
715  rleInfo.pixelIdx = localCache[1];
716  }
717  }
718 
719  return BMP_OK;
720 }
721 
722 /**************************************************************************/
732 static EMSTATUS BMP_readPaddingBytes(uint8_t paddingBytes)
733 {
734  if (paddingBytes > 0)
735  {
736  /* Read in padding bytes from bmp file */
737  EMSTATUS status = fpReadData(localCache, BMP_LOCAL_CACHE_SIZE, paddingBytes);
738  if (status != BMP_OK)
739  {
740  return status;
741  }
742 
743  dataIdx += paddingBytes;
744  }
745 
746  return BMP_OK;
747 }
748 
749 /**************************************************************************/
766 static EMSTATUS BMP_readRleData(BMP_DataType *dataType, uint8_t buffer[], uint32_t bufLength)
767 {
768  EMSTATUS status;
769  (void)buffer; /* Unused parameter */
770  (void)bufLength; /* Unused parameter */
771 
772  rleInfo.mode = MODE_RLE;
773  rleInfo.pixelsRemaining = 0;
774  rleInfo.pixelIdx = 0;
775  rleInfo.isPadding = 0;
776 
777  /* Read in 2 bytes */
778  status = fpReadData(localCache, BMP_LOCAL_CACHE_SIZE, 2);
779  if (status != BMP_OK) return status;
780 
781  dataIdx += 2;
782 
783  if (dataIdx >= bytesInImage)
784  {
785  dataType->endOfRow = 1;
786  return BMP_ERROR_END_OF_FILE;
787  }
788 
789  /* 1. Check for marker */
790  if (localCache[0] == 0)
791  {
792  /* a. End of scan line marker */
793  if (localCache[1] == 0)
794  {
795  dataType->endOfRow = 1;
796  }
797  /* b. End of file marker */
798  else if (localCache[1] == 1)
799  {
800  dataType->endOfRow = 1;
801  return BMP_ERROR_END_OF_FILE;
802  }
803  /* c. Run offset marker */
804  else if (localCache[1] == 2)
805  {
806  /* Read in coordinates for offset marker */
807  /* BMP Module doesnt support this marker, but needs to read it in anyway */
808  status = fpReadData(localCache, BMP_LOCAL_CACHE_SIZE, 2);
809  if (status != BMP_OK) return status;
810 
811  dataIdx += 2;
812  }
813  /* d. Unencoded run marker */
814  else if (localCache[1] > 2)
815  {
816  /* Switch to 8bit mode and set pixelsRemaining */
817  rleInfo.mode = MODE_8BIT;
818  rleInfo.pixelsRemaining = localCache[1];
819 
820  if (rleInfo.pixelsRemaining % 2 == 1) rleInfo.isPadding = 1;
821  }
822  }
823 
824  return BMP_OK;
825 }
826 
827 /**************************************************************************/
850 EMSTATUS BMP_readRawData(BMP_DataType *dataType, uint8_t buffer[], uint32_t bufLength)
851 {
852  EMSTATUS status = BMP_OK;
853  uint32_t bytesPerRow = bmpHeader.imageDataSize / bmpHeader.height;
854  uint8_t paddingBytes;
855 
856  dataType->size = 0;
857  dataType->bitsPerPixel = 0;
858  dataType->compressionType = 0;
859  dataType->endOfRow = 0;
860 
861  /* Check if module is initialized */
862  if (moduleInit == 0) return BMP_ERROR_MODULE_NOT_INITIALIZED;
863 
864  /* Check file is reset */
865  if (fileReset == 0) return BMP_ERROR_FILE_NOT_RESET;
866 
867  if (dataIdx >= bytesInImage) return BMP_ERROR_END_OF_FILE;
868 
869  if (dataType == NULL || buffer == NULL) return BMP_ERROR_INVALID_ARGUMENT;
870 
871 
872  if (bmpHeader.bitsPerPixel == 24)
873  {
874  /* Read 24 bit data */
875  status = BMP_readRawData24bit(dataType, buffer, bufLength);
876 
877  /* Check if end of row is reached */
878  if (dataType->endOfRow == 1)
879  {
880  /* Read in padding bytes */
881  paddingBytes = bytesPerRow - bmpHeader.width * 3;
882 
883  status = BMP_readPaddingBytes(paddingBytes);
884  if (status != BMP_OK) return status;
885  }
886  }
887  else if (bmpHeader.bitsPerPixel == 8)
888  {
889  /* Check if palette is read */
890  if (paletteRead == 0) return BMP_ERROR_PALETTE_NOT_READ;
891 
892  /* Check for RLE compression */
893  if (bmpHeader.compressionType == NO_COMPRESSION)
894  {
895  /* Read in 8 bit data */
896  status = BMP_readRawData8bit(dataType, buffer, bufLength);
897 
898  /* Check if end of row is reached */
899  if (dataType->endOfRow == 1)
900  {
901  /* Read in padding bytes */
902  paddingBytes = bytesPerRow - bmpHeader.width;
903 
904  status = BMP_readPaddingBytes(paddingBytes);
905  if (status != BMP_OK) return status;
906  }
907  }
908  else if (bmpHeader.compressionType == RLE8_COMPRESSION)
909  {
910  /* Read in RLE8 data */
911  status = BMP_readRawDataRLE8(dataType, buffer, bufLength);
912  }
913  }
914 
915  return status;
916 }
917 
918 /**************************************************************************/
924 int32_t BMP_getWidth()
925 {
926  /* Check if header is read correctly */
927  if (moduleInit == 0 || fileReset == 0) return -1;
928 
929  return bmpHeader.width;
930 }
931 
932 /**************************************************************************/
938 int32_t BMP_getHeight()
939 {
940  /* Check if header is read correctly */
941  if (moduleInit == 0 || fileReset == 0) return -1;
942 
943  return bmpHeader.height;
944 }
945 
946 /**************************************************************************/
953 {
954  /* Check if header is read correctly */
955  if (moduleInit == 0 || fileReset == 0) return -1;
956 
957  return bmpHeader.bitsPerPixel;
958 }
959 
960 /**************************************************************************/
971 {
972  /* Check if header is read correctly */
973  if (moduleInit == 0 || fileReset == 0) return -1;
974 
975  return bmpHeader.compressionType;
976 }
977 
978 /**************************************************************************/
985 {
986  /* Check if header is read correctly */
987  if (moduleInit == 0 || fileReset == 0) return -1;
988 
989  return bmpHeader.imageDataSize;
990 }
991 
992 /**************************************************************************/
999 {
1000  /* Check if header is read correctly */
1001  if (moduleInit == 0 || fileReset == 0) return -1;
1002 
1003  return bmpHeader.dataOffset;
1004 }
1005 
1006 /**************************************************************************/
1013 {
1014  /* Check if header is read correctly */
1015  if (moduleInit == 0 || fileReset == 0) return -1;
1016 
1017  return bmpHeader.fileSize;
1018 }
#define BMP_ERROR_INVALID_ARGUMENT
Definition: bmp.h:52
EMSTATUS BMP_reset()
Makes the module ready for new bmp file. Reads in header from file, and checks if the provided bmp fi...
Definition: bmp.c:131
uint32_t size
Definition: bmp.h:136
uint32_t compressionType
Definition: bmp.h:146
#define BMP_ERROR_MODULE_NOT_INITIALIZED
Definition: bmp.h:54
#define BMP_ERROR_FILE_NOT_SUPPORTED
Definition: bmp.h:48
uint32_t height
Definition: bmp.h:104
uint32_t fileSize
Definition: bmp.h:92
uint8_t * data
Definition: bmp.h:134
#define BMP_ERROR_PALETTE_NOT_READ
Definition: bmp.h:64
#define BMP_HEADER_SIZE
Definition: bmp.h:69
uint32_t size
Definition: bmp.h:148
#define BMP_ERROR_FILE_NOT_RESET
Definition: bmp.h:58
int32_t BMP_getHeight()
Get height of BMP image in pixels.
Definition: bmp.c:938
uint16_t magic
Definition: bmp.h:90
#define RLE8_COMPRESSION
Definition: bmp.h:74
BMP palette structure to hold palette pointer and size.
Definition: bmp.h:131
#define NO_COMPRESSION
Definition: bmp.h:76
uint32_t compressionType
Definition: bmp.h:110
#define BMP_LOCAL_CACHE_SIZE
Definition: bmp.h:79
#define BMP_ERROR_END_OF_FILE
Definition: bmp.h:60
int32_t BMP_getWidth()
Get width of BMP image in pixels.
Definition: bmp.c:924
int32_t BMP_getCompressionType()
Get compression type.
Definition: bmp.c:970
uint32_t endOfRow
Definition: bmp.h:150
uint32_t imageDataSize
Definition: bmp.h:112
uint32_t headerSize
Definition: bmp.h:100
int32_t BMP_getFileSize()
Get the fileSize in bytes.
Definition: bmp.c:1012
#define BMP_ERROR_BUFFER_TOO_SMALL
Definition: bmp.h:62
int16_t BMP_getBitsPerPixel()
Get color depth (bits per pixel)
Definition: bmp.c:952
#define BMP_ERROR_ENDIAN_MISMATCH
Definition: bmp.h:46
#define BMP_ERROR_FILE_INVALID
Definition: bmp.h:50
EMSTATUS BMP_readRawData(BMP_DataType *dataType, uint8_t buffer[], uint32_t bufLength)
Fills buffer with raw data from BMP file.
Definition: bmp.c:850
uint16_t bitsPerPixel
Definition: bmp.h:144
#define BMP_ERROR_INVALID_PALETTE_SIZE
Definition: bmp.h:56
BMP Module header structure. Must be packed to exact 54 bytes.
Definition: bmp.h:84
EMSTATUS BMP_init(uint8_t *palette, uint32_t paletteSize, EMSTATUS(*fp)(uint8_t buffer[], uint32_t bufLength, uint32_t bytesToRead))
Initializes BMP Module.
Definition: bmp.c:99
uint32_t width
Definition: bmp.h:102
BMP Data type structure to hold information about the bmp data returned.
Definition: bmp.h:141
#define BMP_ERROR_HEADER_SIZE_MISMATCH
Definition: bmp.h:44
int32_t BMP_getImageDataSize()
Get imageDataSize in bytes.
Definition: bmp.c:984
int32_t BMP_getDataOffset()
Get the offset, i.e. starting address, of the byte where the bitmap data can be found.
Definition: bmp.c:998
EMSTATUS BMP_readRgbData(uint8_t buffer[], uint32_t bufLength, uint32_t *pixelsRead)
Reads in data from BMP file and fills buffer with RGB values. This function terminates either when th...
Definition: bmp.c:247
#define BMP_LOCAL_CACHE_LIMIT
Definition: bmp.h:71
#define BMP_OK
Definition: bmp.h:38
uint16_t bitsPerPixel
Definition: bmp.h:108
uint32_t dataOffset
Definition: bmp.h:98