sGUI  V1.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
bmp.c
Go to the documentation of this file.
1 
78 #ifdef __cplusplus
79 extern "C" {
80 #endif /* __cplusplus */
81 
82 /*----- Header-Files -------------------------------------------------------*/
83 #include <stdlib.h> /* Common types, and functions */
84 #include <stdint.h> /* Standard integer formats */
85 #include <string.h> /* memory and string functions */
86 #include <ff.h> /* Fat file system */
87 #include "lcd.h" /* Simple graphic library */
88 
89 /*----- Macros -------------------------------------------------------------*/
90 #ifndef _FATFS /* This module only works with FatFs */
91  #error Add the FatFs Library or delete the Bitmap module.
92 #endif /* _FATFS */
93 
94 /*----- Data types ---------------------------------------------------------*/
95 
96 /*----- Function prototypes ------------------------------------------------*/
97 BMP_STATUS LCD_BMP_ReadHeader(BMP *bmp, FIL *f);
98 static int LCD_BMP_Read_uint32_t(uint32_t *x, FIL *f);
99 static int LCD_BMP_Read_uint16_t(uint16_t *x, FIL *f);
100 
101 /*----- Data ---------------------------------------------------------------*/
102 /* Error description strings */
103 static const char* BMP_ERROR_STRING[] = {
104  "",
105  "General error",
106  "Could not allocate enough memory to complete the operation",
107  "File input/output error",
108  "File not found",
109  "File is not a supported BMP variant (must be uncompressed 16, 24 or 32 BPP)",
110  "File is not a valid BMP image",
111  "An argument is invalid or out of range",
112  "The requested action is not compatible with the BMP's type"
113 };
114 
115 /*----- Implementation -----------------------------------------------------*/
127 BMP_STATUS LCD_BMP_DrawBitmap(const char *filename, uint16_t Xpos,
128  uint16_t Ypos) {
129 
130  BMP bmp;
131  FIL f;
132  UINT bytesread;
133  uint8_t buffer[4];
134  uint16_t x, y;
135  uint16_t pixel = 0;
136 
137  if (filename == NULL) {
138  return BMP_INVALID_ARGUMENT;
139  }
140 
141  /* Open file */
142  if (f_open(&f, filename, FA_READ) != FR_OK) {
143  return BMP_FILE_NOT_FOUND;
144  }
145 
146  /* Read header */
147  if (LCD_BMP_ReadHeader(&bmp, &f) != BMP_OK
148  || bmp.Header.Magic != 0x4D42) {
149  f_close(&f);
150  return BMP_FILE_INVALID;
151  }
152 
153  /* Verify that the bitmap variant is supported */
154  if ((bmp.Header.BitsPerPixel != 32 && bmp.Header.BitsPerPixel != 24
155  && bmp.Header.BitsPerPixel != 16)
156  || bmp.Header.CompressionType != 0
157  || bmp.Header.HeaderSize != 40) {
158  f_close(&f);
159  return BMP_FILE_NOT_SUPPORTED;
160  }
161 
162  /* Read image data */
163  for (y = 0; y < bmp.Header.Height; y++) {
164  for (x = 0; x < bmp.Header.Width; x++) {
165  /* Read one pixel in format BGR */
166  if (f_read(&f, &buffer[0], bmp.Header.BitsPerPixel / 8,
167  &bytesread) == FR_OK) {
168  if (bmp.Header.BitsPerPixel == 16) {
169  /* BMP is still in the RGB 5-6-5 format */
170  pixel = (buffer[0] << 8) | buffer[1];
171  }
172  else {
173  /* Format pixel into the RGB 5-6-5 format */
174  pixel = ((buffer[0] >> 3) & 0x001F)
175  | ((buffer[1] << 3) & 0x07E0)
176  | ((buffer[2] << 8) & 0xF800);
177  }
178  LCD_WritePixel(Xpos + x, bmp.Header.Height + Ypos - y, pixel);
179  }
180  else {
181  f_close(&f);
182  return BMP_FILE_INVALID;
183  }
184  }
185  }
186 
187  f_close(&f);
188 
189  return BMP_OK;
190 }
191 
200 BMP_STATUS LCD_BMP_ReadFile(BMP *bmp, const char *filename) {
201 
202  FIL f;
203  UINT bytesread;
204 
205  if (filename == NULL) {
206  return BMP_INVALID_ARGUMENT;
207  }
208 
209  if (bmp == NULL) {
210  return BMP_OUT_OF_MEMORY;
211  }
212 
213  /* Open file */
214  if (f_open(&f, filename, FA_READ) != FR_OK) {
215  return BMP_FILE_NOT_FOUND;
216  }
217 
218  /* Read header */
219  if (LCD_BMP_ReadHeader(bmp, &f) != BMP_OK
220  || bmp->Header.Magic != 0x4D42) {
221  f_close(&f);
222  return BMP_FILE_INVALID;
223  }
224 
225  /* Verify that the bitmap variant is supported */
226  if ((bmp->Header.BitsPerPixel != 32 && bmp->Header.BitsPerPixel != 24
227  && bmp->Header.BitsPerPixel != 16)
228  || bmp->Header.CompressionType != 0
229  || bmp->Header.HeaderSize != 40) {
230  f_close(&f);
231  return BMP_FILE_NOT_SUPPORTED;
232  }
233 
234  /* Allocate memory for image data */
235  if (bmp->Data == NULL) {
236  f_close(&f);
237  return BMP_OUT_OF_MEMORY;
238  }
239 
240  /* Read image data */
241  if ((f_read(&f, bmp->Data, bmp->Header.ImageDataSize, &bytesread) != FR_OK)
242  || (bytesread != bmp->Header.ImageDataSize)) {
243  f_close(&f);
244  return BMP_FILE_INVALID;
245  }
246 
247  f_close(&f);
248 
249  return BMP_OK;
250 }
251 
257 uint32_t LCD_BMP_GetWidth(BMP *bmp) {
258 
259  if (bmp == NULL) {
260  return -1;
261  }
262 
263  return (bmp->Header.Width);
264 }
265 
271 uint32_t LCD_BMP_GetHeight(BMP *bmp) {
272 
273  if (bmp == NULL) {
274  return -1;
275  }
276 
277  return (bmp->Header.Height);
278 }
279 
285 uint16_t LCD_BMP_GetDepth(BMP *bmp) {
286 
287  if (bmp == NULL) {
288  return -1;
289  }
290 
291  return (bmp->Header.BitsPerPixel);
292 }
293 
304 BMP_STATUS LCD_BMP_GetPixelRGB(BMP *bmp, uint32_t x, uint32_t y, uint8_t *r,
305  uint8_t *g, uint8_t *b) {
306 
307  uint8_t *pixel;
308  uint32_t bytes_per_row;
309  uint8_t bytes_per_pixel;
310 
311  if (bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0
312  || y >= bmp->Header.Height) {
313  return BMP_INVALID_ARGUMENT;
314  }
315  else {
316  bytes_per_pixel = bmp->Header.BitsPerPixel >> 3;
317 
318  /* Row's size is rounded up to the next multiple of 4 bytes */
319  bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
320 
321  /* Calculate the location of the relevant pixel (rows are flipped) */
322  pixel = bmp->Data
323  + ((bmp->Header.Height - y - 1) * bytes_per_row
324  + x * bytes_per_pixel);
325 
326  /* Note: colors are stored in BGR order */
327  if (r) {
328  *r = *(pixel + 2);
329  }
330  if (g) {
331  *g = *(pixel + 1);
332  }
333  if (b) {
334  *b = *(pixel + 0);
335  }
336  }
337 
338  return BMP_OK;
339 }
340 
346 const char* LCD_BMP_GetErrorDescription(uint8_t errorcode) {
347 
348  if (errorcode > 0 && errorcode < BMP_ERROR_NUM) {
349  return BMP_ERROR_STRING[errorcode];
350  }
351  else {
352  return NULL;
353  }
354 }
355 
363 
364  if (bmp == NULL || f == NULL) {
365  return BMP_INVALID_ARGUMENT;
366  }
367 
368  /* The header's fields are read one by one, and converted from the format's
369  little endian to the system's native representation. */
370  if (!LCD_BMP_Read_uint16_t(&(bmp->Header.Magic), f))
371  return BMP_IO_ERROR;
372  if (!LCD_BMP_Read_uint32_t(&(bmp->Header.FileSize), f))
373  return BMP_IO_ERROR;
374  if (!LCD_BMP_Read_uint16_t(&(bmp->Header.Reserved1), f))
375  return BMP_IO_ERROR;
376  if (!LCD_BMP_Read_uint16_t(&(bmp->Header.Reserved2), f))
377  return BMP_IO_ERROR;
378  if (!LCD_BMP_Read_uint32_t(&(bmp->Header.DataOffset), f))
379  return BMP_IO_ERROR;
380  if (!LCD_BMP_Read_uint32_t(&(bmp->Header.HeaderSize), f))
381  return BMP_IO_ERROR;
382  if (!LCD_BMP_Read_uint32_t(&(bmp->Header.Width), f))
383  return BMP_IO_ERROR;
384  if (!LCD_BMP_Read_uint32_t(&(bmp->Header.Height), f))
385  return BMP_IO_ERROR;
386  if (!LCD_BMP_Read_uint16_t(&(bmp->Header.Planes), f))
387  return BMP_IO_ERROR;
388  if (!LCD_BMP_Read_uint16_t(&(bmp->Header.BitsPerPixel), f))
389  return BMP_IO_ERROR;
391  return BMP_IO_ERROR;
392  if (!LCD_BMP_Read_uint32_t(&(bmp->Header.ImageDataSize), f))
393  return BMP_IO_ERROR;
395  return BMP_IO_ERROR;
397  return BMP_IO_ERROR;
398  if (!LCD_BMP_Read_uint32_t(&(bmp->Header.ColorsUsed), f))
399  return BMP_IO_ERROR;
401  return BMP_IO_ERROR;
402 
403  return BMP_OK;
404 }
405 
412 static int LCD_BMP_Read_uint32_t(uint32_t *x, FIL *f) {
413 
414  UINT bytesread;
415  uint8_t little[4]; /* BMPs use 32 bit ints */
416 
417  if (x == NULL || f == NULL) {
418  return 0;
419  }
420 
421  if ((f_read(f, little, 4, &bytesread) != FR_OK) || (bytesread != 4)) {
422  return 0;
423  }
424 
425  *x = (little[3] << 24 | little[2] << 16 | little[1] << 8 | little[0]);
426 
427  return 1;
428 }
429 
436 static int LCD_BMP_Read_uint16_t(uint16_t *x, FIL *f) {
437 
438  UINT bytesread;
439  uint8_t little[2]; /* BMPs use 16 bit shorts */
440 
441  if (x == NULL || f == NULL) {
442  return 0;
443  }
444 
445  if ((f_read(f, little, 2, &bytesread) != FR_OK) || (bytesread != 2)) {
446  return 0;
447  }
448 
449  *x = (little[1] << 8 | little[0]);
450 
451  return 1;
452 }
453 
454 /*----- EOF ----------------------------------------------------------------*/
455 
456 #ifdef __cplusplus
457 }
458 #endif /* __cplusplus */
459 
uint32_t VPixelsPerMeter
Definition: lcd.h:105
uint32_t LCD_BMP_GetWidth(BMP *bmp)
Returns the image's width.
Definition: bmp.c:257
uint32_t FileSize
Definition: lcd.h:91
uint32_t DataOffset
Definition: lcd.h:94
uint16_t Magic
Definition: lcd.h:90
uint32_t ColorsRequired
Definition: lcd.h:109
static int LCD_BMP_Read_uint16_t(uint16_t *x, FIL *f)
Reads a little-endian unsigned short int from the file.
Definition: bmp.c:436
static void LCD_WritePixel(uint16_t x, uint16_t y, uint16_t pixel)
Write one pixel to the display.
Definition: lcd_lld.h:129
uint16_t Reserved2
Definition: lcd.h:93
uint32_t CompressionType
Definition: lcd.h:101
BMP_STATUS LCD_BMP_GetPixelRGB(BMP *bmp, uint32_t x, uint32_t y, uint8_t *r, uint8_t *g, uint8_t *b)
Populates the arguments with the specified pixel's RGB values.
Definition: bmp.c:304
BMP_STATUS LCD_BMP_DrawBitmap(const char *filename, uint16_t Xpos, uint16_t Ypos)
Reads the specified BMP image file and print it to the LCD. It does only read bitmaps with 16...
Definition: bmp.c:127
const char * LCD_BMP_GetErrorDescription(uint8_t errorcode)
Returns a description of the last error code.
Definition: bmp.c:346
uint16_t LCD_BMP_GetDepth(BMP *bmp)
Returns the image's color depth (bits per pixel).
Definition: bmp.c:285
uint32_t Height
Definition: lcd.h:98
uint32_t HPixelsPerMeter
Definition: lcd.h:103
Definition: lcd.h:126
uint16_t BitsPerPixel
Definition: lcd.h:100
BMP_STATUS LCD_BMP_ReadHeader(BMP *bmp, FIL *f)
Reads the BMP file's header into the data structure.
Definition: bmp.c:362
uint16_t Planes
Definition: lcd.h:99
Simple graphic library main functionality.
uint32_t ImageDataSize
Definition: lcd.h:102
enum _BMP_STATUS BMP_STATUS
Error codes.
BMP_Header Header
Definition: lcd.h:117
static int LCD_BMP_Read_uint32_t(uint32_t *x, FIL *f)
Reads a little-endian unsigned int from the file.
Definition: bmp.c:412
uint8_t * Data
Definition: lcd.h:118
uint32_t LCD_BMP_GetHeight(BMP *bmp)
Returns the image's height.
Definition: bmp.c:271
uint32_t Width
Definition: lcd.h:97
BMP_STATUS LCD_BMP_ReadFile(BMP *bmp, const char *filename)
Reads the specified BMP image file. It does only read bitmaps with 16, 24 or 32 bits per pixel and u...
Definition: bmp.c:200
uint32_t ColorsUsed
Definition: lcd.h:106
uint16_t Reserved1
Definition: lcd.h:92
Bitmap image.
Definition: lcd.h:116
uint32_t HeaderSize
Definition: lcd.h:96