Companion: Russian UI (#7180)
[opentx.git] / radio / src / gui / 128x64 / bmp.cpp
blob81f352e0039438f3a85c6c13a848f8f285781e9a
1 /*
2 * Copyright (C) OpenTX
4 * Based on code named
5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
21 #include "opentx.h"
23 uint8_t * lcdLoadBitmap(uint8_t * bmp, const char * filename, uint8_t width, uint8_t height)
25 FIL bmpFile;
26 UINT read;
27 uint8_t bmpBuf[LCD_W]; /* maximum with LCD_W */
28 uint8_t * buf = &bmpBuf[0];
30 if (width > LCD_W) {
31 return NULL;
34 FRESULT result = f_open(&bmpFile, filename, FA_OPEN_EXISTING | FA_READ);
35 if (result != FR_OK) {
36 return NULL;
39 if (f_size(&bmpFile) < 14) {
40 f_close(&bmpFile);
41 return NULL;
44 result = f_read(&bmpFile, buf, 14, &read);
45 if (result != FR_OK || read != 14) {
46 f_close(&bmpFile);
47 return NULL;
50 if (buf[0] != 'B' || buf[1] != 'M') {
51 f_close(&bmpFile);
52 return NULL;
55 uint32_t fsize = *((uint32_t *)&buf[2]);
56 uint32_t hsize = *((uint32_t *)&buf[10]); /* header size */
58 uint32_t len = limit((uint32_t)4, (uint32_t)(hsize-14), (uint32_t)32);
59 result = f_read(&bmpFile, buf, len, &read);
60 if (result != FR_OK || read != len) {
61 f_close(&bmpFile);
62 return NULL;
65 uint32_t ihsize = *((uint32_t *)&buf[0]); /* more header size */
67 /* invalid header size */
68 if (ihsize + 14 > hsize) {
69 f_close(&bmpFile);
70 return NULL;
73 /* sometimes file size is set to some headers size, set a real size in that case */
74 if (fsize == 14 || fsize == ihsize + 14) {
75 fsize = f_size(&bmpFile) - 2;
78 /* declared file size less than header size */
79 if (fsize <= hsize) {
80 f_close(&bmpFile);
81 return NULL;
84 uint32_t w, h;
86 switch (ihsize){
87 case 40: // windib
88 case 56: // windib v3
89 case 64: // OS/2 v2
90 case 108: // windib v4
91 case 124: // windib v5
92 w = *((uint32_t *)&buf[4]);
93 h = *((uint32_t *)&buf[8]);
94 buf += 12;
95 break;
96 case 12: // OS/2 v1
97 w = *((uint16_t *)&buf[4]);
98 h = *((uint16_t *)&buf[6]);
99 buf += 8;
100 break;
101 default:
102 f_close(&bmpFile);
103 return NULL;
106 if (*((uint16_t *)&buf[0]) != 1) { /* planes */
107 f_close(&bmpFile);
108 return NULL;
111 if (w > width || h > height) {
112 f_close(&bmpFile);
113 return NULL;
116 uint16_t depth = *((uint16_t *)&buf[2]);
118 buf = &bmpBuf[0];
120 if (f_lseek(&bmpFile, hsize) != FR_OK) {
121 f_close(&bmpFile);
122 return NULL;
125 uint8_t * dest = bmp;
127 *dest++ = w;
128 *dest++ = h;
130 memset(dest, 0, BITMAP_BUFFER_SIZE(w, h) - 2);
132 uint8_t rowSize;
134 switch (depth) {
135 case 1:
136 rowSize = ((w + 31) / 32) * 4;
137 for (int8_t i=h-1; i>=0; i--) {
138 result = f_read(&bmpFile, buf, rowSize, &read);
139 if (result != FR_OK || read != rowSize) {
140 f_close(&bmpFile);
141 return NULL;
144 for (uint8_t j=0; j<w; j++) {
145 if (!(buf[j/8] & (1<<(7-(j%8))))) {
146 uint8_t *dst = dest + i / 8 * w + j;
147 *dst |= (0x01 << (i & 0x07));
151 break;
153 default:
154 f_close(&bmpFile);
155 return NULL;
158 f_close(&bmpFile);
159 return bmp;