Forked para SNOCC

Dependencies:   GPS

Dependents:   SNOCC_V1 SNOCC_V2

Fork of RA8875 by SNOCC

Committer:
WiredHome
Date:
Sun Jan 17 22:16:37 2016 +0000
Revision:
101:e0aad446094a
Parent:
100:0b084475d5a9
Child:
104:8d1d3832a215
External fonts now wrap correctly at the edge of the screen (right edge by moving down one line and to the left margin, and last row by wrapping to the top row.
; Altered the soft font <space> character; auto-generated fonts computed zero width.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dreschpe 0:de9d1462a835 1 /* mbed GraphicsDisplay Display Library Base Class
dreschpe 0:de9d1462a835 2 * Copyright (c) 2007-2009 sford
dreschpe 0:de9d1462a835 3 * Released under the MIT License: http://mbed.org/license/mit
WiredHome 32:0e4f2ae512e2 4 *
WiredHome 34:c99ec28fac66 5 * Derivative work by D.Smart 2014
dreschpe 0:de9d1462a835 6 */
WiredHome 19:3f82c1161fd2 7
dreschpe 0:de9d1462a835 8 #include "GraphicsDisplay.h"
WiredHome 31:c72e12cd5c67 9 #include "Bitmap.h"
WiredHome 42:7cbdfd2bbfc5 10 #include "string.h"
dreschpe 0:de9d1462a835 11
WiredHome 42:7cbdfd2bbfc5 12 //#define DEBUG "GD"
WiredHome 29:422616aa04bd 13 // ...
WiredHome 29:422616aa04bd 14 // INFO("Stuff to show %d", var); // new-line is automatically appended
WiredHome 29:422616aa04bd 15 //
WiredHome 29:422616aa04bd 16 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
WiredHome 29:422616aa04bd 17 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 29:422616aa04bd 18 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 29:422616aa04bd 19 #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 98:ecebed9b80b2 20 static void HexDump(const char * title, const uint8_t * p, int count)
WiredHome 31:c72e12cd5c67 21 {
WiredHome 31:c72e12cd5c67 22 int i;
WiredHome 31:c72e12cd5c67 23 char buf[100] = "0000: ";
WiredHome 31:c72e12cd5c67 24
WiredHome 31:c72e12cd5c67 25 if (*title)
WiredHome 31:c72e12cd5c67 26 INFO("%s", title);
WiredHome 31:c72e12cd5c67 27 for (i=0; i<count; ) {
WiredHome 31:c72e12cd5c67 28 sprintf(buf + strlen(buf), "%02X ", *(p+i));
WiredHome 31:c72e12cd5c67 29 if ((++i & 0x0F) == 0x00) {
WiredHome 31:c72e12cd5c67 30 INFO("%s", buf);
WiredHome 31:c72e12cd5c67 31 if (i < count)
WiredHome 31:c72e12cd5c67 32 sprintf(buf, "%04X: ", i);
WiredHome 31:c72e12cd5c67 33 else
WiredHome 31:c72e12cd5c67 34 buf[0] = '\0';
WiredHome 31:c72e12cd5c67 35 }
WiredHome 31:c72e12cd5c67 36 }
WiredHome 31:c72e12cd5c67 37 if (strlen(buf))
WiredHome 31:c72e12cd5c67 38 INFO("%s", buf);
WiredHome 31:c72e12cd5c67 39 }
WiredHome 29:422616aa04bd 40 #else
WiredHome 29:422616aa04bd 41 #define INFO(x, ...)
WiredHome 29:422616aa04bd 42 #define WARN(x, ...)
WiredHome 29:422616aa04bd 43 #define ERR(x, ...)
WiredHome 32:0e4f2ae512e2 44 #define HexDump(a, b, c)
WiredHome 29:422616aa04bd 45 #endif
WiredHome 29:422616aa04bd 46
WiredHome 19:3f82c1161fd2 47
WiredHome 42:7cbdfd2bbfc5 48 char mytolower(char a) {
WiredHome 42:7cbdfd2bbfc5 49 if (a >= 'A' && a <= 'Z')
WiredHome 42:7cbdfd2bbfc5 50 return (a - 'A' + 'a');
WiredHome 42:7cbdfd2bbfc5 51 else
WiredHome 42:7cbdfd2bbfc5 52 return a;
WiredHome 42:7cbdfd2bbfc5 53 }
WiredHome 42:7cbdfd2bbfc5 54 /// mystrnicmp exists because not all compiler libraries have this function.
WiredHome 42:7cbdfd2bbfc5 55 ///
WiredHome 42:7cbdfd2bbfc5 56 /// Some have strnicmp, others _strnicmp, and others have C++ methods, which
WiredHome 42:7cbdfd2bbfc5 57 /// is outside the scope of this C-portable set of functions.
WiredHome 42:7cbdfd2bbfc5 58 ///
WiredHome 42:7cbdfd2bbfc5 59 /// @param l is a pointer to the string on the left
WiredHome 42:7cbdfd2bbfc5 60 /// @param r is a pointer to the string on the right
WiredHome 42:7cbdfd2bbfc5 61 /// @param n is the number of characters to compare
WiredHome 42:7cbdfd2bbfc5 62 /// @returns -1 if l < r
WiredHome 42:7cbdfd2bbfc5 63 /// @returns 0 if l == r
WiredHome 42:7cbdfd2bbfc5 64 /// @returns +1 if l > r
WiredHome 42:7cbdfd2bbfc5 65 ///
WiredHome 42:7cbdfd2bbfc5 66 int mystrnicmp(const char *l, const char *r, size_t n) {
WiredHome 42:7cbdfd2bbfc5 67 int result = 0;
WiredHome 42:7cbdfd2bbfc5 68
WiredHome 42:7cbdfd2bbfc5 69 if (n != 0) {
WiredHome 42:7cbdfd2bbfc5 70 do {
WiredHome 42:7cbdfd2bbfc5 71 result = mytolower(*l++) - mytolower(*r++);
WiredHome 42:7cbdfd2bbfc5 72 } while ((result == 0) && (*l != '\0') && (--n > 0));
WiredHome 42:7cbdfd2bbfc5 73 }
WiredHome 42:7cbdfd2bbfc5 74 if (result < -1)
WiredHome 42:7cbdfd2bbfc5 75 result = -1;
WiredHome 42:7cbdfd2bbfc5 76 else if (result > 1)
WiredHome 42:7cbdfd2bbfc5 77 result = 1;
WiredHome 42:7cbdfd2bbfc5 78 return result;
WiredHome 42:7cbdfd2bbfc5 79 }
WiredHome 42:7cbdfd2bbfc5 80
WiredHome 42:7cbdfd2bbfc5 81
WiredHome 29:422616aa04bd 82 GraphicsDisplay::GraphicsDisplay(const char *name)
WiredHome 29:422616aa04bd 83 : TextDisplay(name)
WiredHome 19:3f82c1161fd2 84 {
WiredHome 29:422616aa04bd 85 font = NULL;
dreschpe 0:de9d1462a835 86 }
WiredHome 19:3f82c1161fd2 87
WiredHome 98:ecebed9b80b2 88 RetCode_t GraphicsDisplay::SelectUserFont(const unsigned char * _font)
WiredHome 29:422616aa04bd 89 {
WiredHome 98:ecebed9b80b2 90 font = _font; // trusting them, but it might be good to put some checks in here...
WiredHome 98:ecebed9b80b2 91 return noerror;
WiredHome 29:422616aa04bd 92 }
WiredHome 98:ecebed9b80b2 93
WiredHome 29:422616aa04bd 94 int GraphicsDisplay::character(int x, int y, int c)
WiredHome 29:422616aa04bd 95 {
WiredHome 101:e0aad446094a 96 return fontblit(x, y, c);
WiredHome 29:422616aa04bd 97 }
WiredHome 19:3f82c1161fd2 98
WiredHome 37:f19b7e7449dc 99 RetCode_t GraphicsDisplay::window(loc_t x, loc_t y, dim_t w, dim_t h)
WiredHome 19:3f82c1161fd2 100 {
dreschpe 0:de9d1462a835 101 // current pixel location
dreschpe 0:de9d1462a835 102 _x = x;
dreschpe 0:de9d1462a835 103 _y = y;
dreschpe 0:de9d1462a835 104 // window settings
dreschpe 0:de9d1462a835 105 _x1 = x;
dreschpe 0:de9d1462a835 106 _x2 = x + w - 1;
dreschpe 0:de9d1462a835 107 _y1 = y;
dreschpe 0:de9d1462a835 108 _y2 = y + h - 1;
WiredHome 32:0e4f2ae512e2 109 return noerror;
dreschpe 0:de9d1462a835 110 }
WiredHome 19:3f82c1161fd2 111
WiredHome 79:544eb4964795 112 RetCode_t GraphicsDisplay::WindowMax(void)
WiredHome 31:c72e12cd5c67 113 {
WiredHome 79:544eb4964795 114 return window(0,0, width(),height());
WiredHome 31:c72e12cd5c67 115 }
WiredHome 31:c72e12cd5c67 116
WiredHome 55:dfbabef7003e 117 RetCode_t GraphicsDisplay::_putp(color_t color)
WiredHome 19:3f82c1161fd2 118 {
WiredHome 33:b6b710758ab3 119 pixel(_x, _y, color);
dreschpe 0:de9d1462a835 120 // update pixel location based on window settings
dreschpe 0:de9d1462a835 121 _x++;
dreschpe 0:de9d1462a835 122 if(_x > _x2) {
dreschpe 0:de9d1462a835 123 _x = _x1;
dreschpe 0:de9d1462a835 124 _y++;
dreschpe 0:de9d1462a835 125 if(_y > _y2) {
dreschpe 0:de9d1462a835 126 _y = _y1;
dreschpe 0:de9d1462a835 127 }
dreschpe 0:de9d1462a835 128 }
WiredHome 32:0e4f2ae512e2 129 return noerror;
dreschpe 0:de9d1462a835 130 }
dreschpe 0:de9d1462a835 131
WiredHome 79:544eb4964795 132 RetCode_t GraphicsDisplay::fill(int x, int y, int w, int h, color_t color)
WiredHome 19:3f82c1161fd2 133 {
WiredHome 79:544eb4964795 134 return fillrect(x,y, x+w, y+h, color);
dreschpe 0:de9d1462a835 135 }
WiredHome 19:3f82c1161fd2 136
WiredHome 61:8f3153bf0baa 137 RetCode_t GraphicsDisplay::cls(uint16_t layers)
WiredHome 19:3f82c1161fd2 138 {
WiredHome 79:544eb4964795 139 return fill(0, 0, width(), height(), _background);
dreschpe 0:de9d1462a835 140 }
WiredHome 19:3f82c1161fd2 141
WiredHome 79:544eb4964795 142 RetCode_t GraphicsDisplay::blit(int x, int y, int w, int h, const int * color)
WiredHome 19:3f82c1161fd2 143 {
dreschpe 0:de9d1462a835 144 window(x, y, w, h);
WiredHome 37:f19b7e7449dc 145 _StartGraphicsStream();
WiredHome 31:c72e12cd5c67 146 for (int i=0; i<w*h; i++) {
WiredHome 55:dfbabef7003e 147 _putp(color[i]);
dreschpe 0:de9d1462a835 148 }
WiredHome 37:f19b7e7449dc 149 _EndGraphicsStream();
WiredHome 79:544eb4964795 150 return WindowMax();
dreschpe 0:de9d1462a835 151 }
WiredHome 19:3f82c1161fd2 152
WiredHome 98:ecebed9b80b2 153 // 8 byte "info" section
WiredHome 98:ecebed9b80b2 154 //0x00, // unknown ????????
WiredHome 98:ecebed9b80b2 155 //0x00, // unknown ????????
WiredHome 98:ecebed9b80b2 156 //0x20,0x00, // First char 32
WiredHome 98:ecebed9b80b2 157 //0x7F,0x00, // Last char 127
WiredHome 98:ecebed9b80b2 158 //0x25, // Font Height 37
WiredHome 98:ecebed9b80b2 159 //0x00, // Unknown 0 ????????
WiredHome 98:ecebed9b80b2 160 //
WiredHome 98:ecebed9b80b2 161 //0x01,0x88,0x01,0x00 // ' ' is 1 pixel wide, data is at offset 0x0188
WiredHome 98:ecebed9b80b2 162 //0x0B,0xAD,0x01,0x00 // '!' is 11 pixels wide, data is at offset 0x01AD
WiredHome 98:ecebed9b80b2 163 //0x0D,0xF7,0x01,0x00 // '"' is 13 pixels wide, data is at offset 0x01F7
WiredHome 98:ecebed9b80b2 164 //...
WiredHome 98:ecebed9b80b2 165 //0x00,... // ' ' data stream.
WiredHome 98:ecebed9b80b2 166 //0x00,0x06,0x00,0x07,0x80,0x07,0xC0,0x07,0xC0,0x07,0xC0 // '!'
WiredHome 98:ecebed9b80b2 167 //...
WiredHome 101:e0aad446094a 168
WiredHome 101:e0aad446094a 169
WiredHome 101:e0aad446094a 170 const uint8_t * GraphicsDisplay::getCharMetrics(const unsigned char c, uint8_t * width, uint8_t * height)
WiredHome 19:3f82c1161fd2 171 {
WiredHome 98:ecebed9b80b2 172 uint16_t offsetToCharLookup;
WiredHome 98:ecebed9b80b2 173 uint16_t firstChar = font[3] * 256 + font[2];
WiredHome 98:ecebed9b80b2 174 uint16_t lastChar = font[5] * 256 + font[4];
WiredHome 98:ecebed9b80b2 175 uint8_t charHeight = font[6];
WiredHome 98:ecebed9b80b2 176 const unsigned char * charRecord; // width, data, data, data, ...
WiredHome 98:ecebed9b80b2 177
WiredHome 98:ecebed9b80b2 178 INFO("first:%d, last:%d, c:%d", firstChar, lastChar, c);
WiredHome 98:ecebed9b80b2 179 if (c < firstChar || c > lastChar)
WiredHome 101:e0aad446094a 180 return NULL; // advance zero pixels since it was unprintable...
WiredHome 101:e0aad446094a 181
WiredHome 101:e0aad446094a 182 // 8 bytes of preamble to the first level lookup table
WiredHome 101:e0aad446094a 183 offsetToCharLookup = 8 + 4 * (c - firstChar); // 4-bytes: width(pixels), 16-bit offset from table start, 0
WiredHome 101:e0aad446094a 184 uint8_t charWidth = font[offsetToCharLookup];
WiredHome 101:e0aad446094a 185 charRecord = font + font[offsetToCharLookup + 2] * 256 + font[offsetToCharLookup + 1];
WiredHome 101:e0aad446094a 186 //INFO("hgt:%d, wdt:%d", charHeight, charWidth);
WiredHome 101:e0aad446094a 187 if (width)
WiredHome 101:e0aad446094a 188 *width = charWidth;
WiredHome 101:e0aad446094a 189 if (height)
WiredHome 101:e0aad446094a 190 *height = charHeight;
WiredHome 101:e0aad446094a 191 return charRecord;
WiredHome 101:e0aad446094a 192 }
WiredHome 101:e0aad446094a 193
WiredHome 101:e0aad446094a 194 int GraphicsDisplay::fontblit(int x, int y, const unsigned char c)
WiredHome 101:e0aad446094a 195 {
WiredHome 101:e0aad446094a 196 #if 0
WiredHome 101:e0aad446094a 197 uint16_t offsetToCharLookup;
WiredHome 101:e0aad446094a 198 uint16_t firstChar = font[3] * 256 + font[2];
WiredHome 101:e0aad446094a 199 uint16_t lastChar = font[5] * 256 + font[4];
WiredHome 101:e0aad446094a 200 uint8_t charHeight = font[6];
WiredHome 101:e0aad446094a 201 const unsigned char * charRecord; // width, data, data, data, ...
WiredHome 101:e0aad446094a 202
WiredHome 101:e0aad446094a 203 INFO("first:%d, last:%d, c:%d", firstChar, lastChar, c);
WiredHome 101:e0aad446094a 204 if (c < firstChar || c > lastChar)
WiredHome 98:ecebed9b80b2 205 return 0; // advance zero pixels since it was unprintable...
WiredHome 98:ecebed9b80b2 206
WiredHome 98:ecebed9b80b2 207 // 8 bytes of preamble to the first level lookup table
WiredHome 98:ecebed9b80b2 208 offsetToCharLookup = 8 + 4 * (c - firstChar); // 4-bytes: width(pixels), 16-bit offset from table start, 0
WiredHome 98:ecebed9b80b2 209 uint8_t charWidth = font[offsetToCharLookup];
WiredHome 98:ecebed9b80b2 210 charRecord = font + font[offsetToCharLookup + 2] * 256 + font[offsetToCharLookup + 1];
WiredHome 101:e0aad446094a 211 #endif
WiredHome 101:e0aad446094a 212 const unsigned char * charRecord; // width, data, data, data, ...
WiredHome 101:e0aad446094a 213 uint8_t charWidth, charHeight;
WiredHome 101:e0aad446094a 214 charRecord = getCharMetrics(c, &charWidth, &charHeight);
WiredHome 101:e0aad446094a 215 if (charRecord) {
WiredHome 101:e0aad446094a 216 INFO("hgt:%d, wdt:%d", charHeight, charWidth);
WiredHome 101:e0aad446094a 217 // clip to the edge of the screen
WiredHome 101:e0aad446094a 218 //if (x + charWidth >= width())
WiredHome 101:e0aad446094a 219 // charWidth = width() - x;
WiredHome 101:e0aad446094a 220 //if (y + charHeight >= height())
WiredHome 101:e0aad446094a 221 // charHeight = height() - y;
WiredHome 101:e0aad446094a 222 window(x, y, charWidth, charHeight);
WiredHome 101:e0aad446094a 223 _StartGraphicsStream();
WiredHome 101:e0aad446094a 224 while (charHeight--) {
WiredHome 101:e0aad446094a 225 uint8_t pixels = charWidth;
WiredHome 101:e0aad446094a 226 uint8_t bitmask = 0x01;
WiredHome 101:e0aad446094a 227
WiredHome 101:e0aad446094a 228 while (pixels) {
WiredHome 101:e0aad446094a 229 uint8_t byte = *charRecord;
WiredHome 101:e0aad446094a 230 INFO("byte, mask: %02X, %02X", byte, bitmask);
WiredHome 101:e0aad446094a 231 color_t c = (byte & bitmask) ? _foreground : _background;
WiredHome 101:e0aad446094a 232 _putp(c);
WiredHome 101:e0aad446094a 233 bitmask <<= 1;
WiredHome 101:e0aad446094a 234 if (pixels > 1 && bitmask == 0) {
WiredHome 101:e0aad446094a 235 bitmask = 0x01;
WiredHome 101:e0aad446094a 236 charRecord++;
WiredHome 101:e0aad446094a 237 }
WiredHome 101:e0aad446094a 238 pixels--;
WiredHome 98:ecebed9b80b2 239 }
WiredHome 101:e0aad446094a 240 charRecord++;
WiredHome 29:422616aa04bd 241 }
WiredHome 101:e0aad446094a 242 _EndGraphicsStream();
WiredHome 101:e0aad446094a 243 WindowMax();
WiredHome 101:e0aad446094a 244 return charWidth;
WiredHome 101:e0aad446094a 245 } else {
WiredHome 101:e0aad446094a 246 return 0;
WiredHome 29:422616aa04bd 247 }
dreschpe 0:de9d1462a835 248 }
dreschpe 0:de9d1462a835 249
WiredHome 31:c72e12cd5c67 250 // BMP Color Palette is BGRx
WiredHome 31:c72e12cd5c67 251 // BBBB BBBB GGGG GGGG RRRR RRRR 0000 0000
WiredHome 31:c72e12cd5c67 252 // RGB16 is
WiredHome 31:c72e12cd5c67 253 // RRRR RGGG GGGB BBBB
WiredHome 31:c72e12cd5c67 254 // swap to little endian
WiredHome 31:c72e12cd5c67 255 // GGGB BBBB RRRR RGGG
WiredHome 32:0e4f2ae512e2 256 color_t GraphicsDisplay::RGBQuadToRGB16(RGBQUAD * colorPalette, uint16_t i)
WiredHome 31:c72e12cd5c67 257 {
WiredHome 31:c72e12cd5c67 258 color_t c;
WiredHome 31:c72e12cd5c67 259
WiredHome 31:c72e12cd5c67 260 c = ((colorPalette[i].rgbBlue >> 3) << 0);
WiredHome 31:c72e12cd5c67 261 c |= ((colorPalette[i].rgbGreen >> 2) << 5);
WiredHome 31:c72e12cd5c67 262 c |= ((colorPalette[i].rgbRed >> 3) << 11);
WiredHome 31:c72e12cd5c67 263 return c;
WiredHome 31:c72e12cd5c67 264 }
WiredHome 29:422616aa04bd 265
WiredHome 93:6fbc516de05e 266 // RGB16 little endian
WiredHome 93:6fbc516de05e 267 // GGGB BBBB RRRR RGGG
WiredHome 93:6fbc516de05e 268 // swap
WiredHome 93:6fbc516de05e 269 // RRRR RGGG GGGB BBBB
WiredHome 93:6fbc516de05e 270 // RRRR R
WiredHome 93:6fbc516de05e 271 // extend to BMP Color Palette is BGRx
WiredHome 93:6fbc516de05e 272 // BBBB BBBB GGGG GGGG RRRR RRRR 0000 0000
WiredHome 41:2956a0a221e5 273 RGBQUAD GraphicsDisplay::RGB16ToRGBQuad(color_t c)
WiredHome 41:2956a0a221e5 274 {
WiredHome 41:2956a0a221e5 275 RGBQUAD q;
WiredHome 41:2956a0a221e5 276
WiredHome 41:2956a0a221e5 277 memset(&q, 0, sizeof(q));
WiredHome 93:6fbc516de05e 278 c = (c << 8) | (c >> 8); // swap
WiredHome 72:ecffe56af969 279 q.rgbBlue = ((c & 0x001F) << 3) | (c & 0x07); /* Blue value */
WiredHome 93:6fbc516de05e 280 q.rgbGreen = ((c & 0x07E0) >> 3) | ((c >> 9) & 0x03); /* Green value */
WiredHome 93:6fbc516de05e 281 q.rgbRed = ((c & 0xF800) >> 8) | ((c >> 13) & 0x07); /* Red value */
WiredHome 41:2956a0a221e5 282 q.rgbReserved = 0;
WiredHome 41:2956a0a221e5 283 return q;
WiredHome 41:2956a0a221e5 284 }
WiredHome 41:2956a0a221e5 285
WiredHome 42:7cbdfd2bbfc5 286 RetCode_t GraphicsDisplay::_RenderBitmap(loc_t x, loc_t y, uint32_t fileOffset, FILE * Image)
WiredHome 31:c72e12cd5c67 287 {
WiredHome 31:c72e12cd5c67 288 BITMAPINFOHEADER BMP_Info;
WiredHome 31:c72e12cd5c67 289 RGBQUAD * colorPalette = NULL;
WiredHome 31:c72e12cd5c67 290 int colorCount;
WiredHome 32:0e4f2ae512e2 291 uint8_t * lineBuffer = NULL;
WiredHome 69:636867df24a1 292 color_t * pixelBuffer = NULL;
WiredHome 31:c72e12cd5c67 293 uint16_t BPP_t;
WiredHome 95:ef538bd687c0 294 dim_t PixelWidth, PixelHeight;
WiredHome 31:c72e12cd5c67 295 unsigned int i, offset;
WiredHome 31:c72e12cd5c67 296 int padd,j;
WiredHome 59:fb40aad4efd4 297 #ifdef DEBUG
WiredHome 59:fb40aad4efd4 298 uint32_t start_data;
WiredHome 59:fb40aad4efd4 299 #endif
WiredHome 31:c72e12cd5c67 300
WiredHome 42:7cbdfd2bbfc5 301 // Now, Read the bitmap info header
WiredHome 31:c72e12cd5c67 302 fread(&BMP_Info, 1, sizeof(BMP_Info), Image);
WiredHome 59:fb40aad4efd4 303 HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info));
WiredHome 31:c72e12cd5c67 304 BPP_t = BMP_Info.biBitCount;
WiredHome 31:c72e12cd5c67 305 INFO("biBitCount %04X", BPP_t);
WiredHome 32:0e4f2ae512e2 306 if (BPP_t != 4 && BPP_t != 8 && BPP_t != 16 && BPP_t != 24) { // Support 4, 8, 16, 24-bits per pixel
WiredHome 31:c72e12cd5c67 307 fclose(Image);
WiredHome 31:c72e12cd5c67 308 return(not_supported_format);
WiredHome 31:c72e12cd5c67 309 }
WiredHome 31:c72e12cd5c67 310
WiredHome 31:c72e12cd5c67 311 PixelHeight = BMP_Info.biHeight;
WiredHome 31:c72e12cd5c67 312 PixelWidth = BMP_Info.biWidth;
WiredHome 79:544eb4964795 313 INFO("(%d,%d) (%d,%d) (%d,%d)", x,y, PixelWidth,PixelHeight, width(), height());
WiredHome 31:c72e12cd5c67 314 if (PixelHeight > height() + y || PixelWidth > width() + x) {
WiredHome 31:c72e12cd5c67 315 fclose(Image);
WiredHome 31:c72e12cd5c67 316 return(image_too_big);
WiredHome 31:c72e12cd5c67 317 }
WiredHome 31:c72e12cd5c67 318 if (BMP_Info.biBitCount <= 8) {
WiredHome 31:c72e12cd5c67 319 int paletteSize;
WiredHome 31:c72e12cd5c67 320 // Read the color palette
WiredHome 31:c72e12cd5c67 321 colorCount = 1 << BMP_Info.biBitCount;
WiredHome 31:c72e12cd5c67 322 paletteSize = sizeof(RGBQUAD) * colorCount;
WiredHome 31:c72e12cd5c67 323 colorPalette = (RGBQUAD *)malloc(paletteSize);
WiredHome 31:c72e12cd5c67 324 if (colorPalette == NULL) {
WiredHome 31:c72e12cd5c67 325 fclose(Image);
WiredHome 31:c72e12cd5c67 326 return(not_enough_ram);
WiredHome 31:c72e12cd5c67 327 }
WiredHome 31:c72e12cd5c67 328 fread(colorPalette, 1, paletteSize, Image);
WiredHome 59:fb40aad4efd4 329 HexDump("Color Palette", (uint8_t *)colorPalette, paletteSize);
WiredHome 31:c72e12cd5c67 330 }
WiredHome 31:c72e12cd5c67 331
WiredHome 32:0e4f2ae512e2 332 int lineBufSize = ((BPP_t * PixelWidth + 7)/8);
WiredHome 59:fb40aad4efd4 333 INFO("BPP_t %d, PixelWidth %d, lineBufSize %d", BPP_t, PixelWidth, lineBufSize);
WiredHome 32:0e4f2ae512e2 334 lineBuffer = (uint8_t *)malloc(lineBufSize);
WiredHome 31:c72e12cd5c67 335 if (lineBuffer == NULL) {
WiredHome 31:c72e12cd5c67 336 free(colorPalette);
WiredHome 31:c72e12cd5c67 337 fclose(Image);
WiredHome 31:c72e12cd5c67 338 return(not_enough_ram);
WiredHome 31:c72e12cd5c67 339 }
WiredHome 69:636867df24a1 340 pixelBuffer = (color_t *)malloc(PixelWidth * sizeof(color_t));
WiredHome 41:2956a0a221e5 341 if (pixelBuffer == NULL) {
WiredHome 41:2956a0a221e5 342 free(lineBuffer);
WiredHome 69:636867df24a1 343 if (colorPalette)
WiredHome 69:636867df24a1 344 free(colorPalette);
WiredHome 41:2956a0a221e5 345 fclose(Image);
WiredHome 41:2956a0a221e5 346 return(not_enough_ram);
WiredHome 41:2956a0a221e5 347 }
WiredHome 31:c72e12cd5c67 348
WiredHome 32:0e4f2ae512e2 349 // the Raw Data records are padded to a multiple of 4 bytes
WiredHome 32:0e4f2ae512e2 350 int recordSize = 2;
WiredHome 32:0e4f2ae512e2 351 if (BPP_t == 4) {
WiredHome 32:0e4f2ae512e2 352 recordSize = 1;
WiredHome 32:0e4f2ae512e2 353 } else if (BPP_t == 8) {
WiredHome 32:0e4f2ae512e2 354 recordSize = 1;
WiredHome 32:0e4f2ae512e2 355 } else if (BPP_t == 16) {
WiredHome 32:0e4f2ae512e2 356 recordSize = 2;
WiredHome 32:0e4f2ae512e2 357 } else if (BPP_t == 24) {
WiredHome 32:0e4f2ae512e2 358 recordSize = 3;
WiredHome 32:0e4f2ae512e2 359 }
WiredHome 31:c72e12cd5c67 360 padd = -1;
WiredHome 31:c72e12cd5c67 361 do {
WiredHome 31:c72e12cd5c67 362 padd++;
WiredHome 32:0e4f2ae512e2 363 } while ((PixelWidth * recordSize + padd) % 4 != 0);
WiredHome 31:c72e12cd5c67 364
WiredHome 32:0e4f2ae512e2 365 // Define window for top to bottom and left to right so writing auto-wraps
WiredHome 31:c72e12cd5c67 366 window(x,y, PixelWidth,PixelHeight);
WiredHome 32:0e4f2ae512e2 367 SetGraphicsCursor(x, y);
WiredHome 32:0e4f2ae512e2 368 _StartGraphicsStream();
WiredHome 32:0e4f2ae512e2 369
WiredHome 42:7cbdfd2bbfc5 370 //start_data = BMP_Header.bfOffBits;
WiredHome 59:fb40aad4efd4 371 HexDump("Raw Data", (uint8_t *)&start_data, 32);
WiredHome 59:fb40aad4efd4 372 INFO("(%d,%d) (%d,%d), [%d,%d]", x,y, PixelWidth,PixelHeight, lineBufSize, padd);
WiredHome 32:0e4f2ae512e2 373 for (j = PixelHeight - 1; j >= 0; j--) { //Lines bottom up
WiredHome 42:7cbdfd2bbfc5 374 offset = fileOffset + j * (lineBufSize + padd); // start of line
WiredHome 31:c72e12cd5c67 375 fseek(Image, offset, SEEK_SET);
WiredHome 32:0e4f2ae512e2 376 fread(lineBuffer, 1, lineBufSize, Image); // read a line - slow !
WiredHome 79:544eb4964795 377 //INFO("offset: %6X", offset);
WiredHome 32:0e4f2ae512e2 378 for (i = 0; i < PixelWidth; i++) { // copy pixel data to TFT
WiredHome 31:c72e12cd5c67 379 if (BPP_t == 4) {
WiredHome 31:c72e12cd5c67 380 uint8_t dPix = lineBuffer[i/2];
WiredHome 31:c72e12cd5c67 381 if ((i & 1) == 0)
WiredHome 31:c72e12cd5c67 382 dPix >>= 4;
WiredHome 31:c72e12cd5c67 383 dPix &= 0x0F;
WiredHome 41:2956a0a221e5 384 pixelBuffer[i] = RGBQuadToRGB16(colorPalette, dPix);
WiredHome 31:c72e12cd5c67 385 } else if (BPP_t == 8) {
WiredHome 41:2956a0a221e5 386 pixelBuffer[i] = RGBQuadToRGB16(colorPalette, lineBuffer[i]);
WiredHome 32:0e4f2ae512e2 387 } else if (BPP_t == 16) {
WiredHome 41:2956a0a221e5 388 pixelBuffer[i] = lineBuffer[i];
WiredHome 32:0e4f2ae512e2 389 } else if (BPP_t == 24) {
WiredHome 37:f19b7e7449dc 390 color_t color;
WiredHome 32:0e4f2ae512e2 391 color = RGB(lineBuffer[i*3+2], lineBuffer[i*3+1], lineBuffer[i*3+0]);
WiredHome 41:2956a0a221e5 392 pixelBuffer[i] = color;
WiredHome 31:c72e12cd5c67 393 }
WiredHome 31:c72e12cd5c67 394 }
WiredHome 41:2956a0a221e5 395 pixelStream(pixelBuffer, PixelWidth, x, y++);
WiredHome 31:c72e12cd5c67 396 }
WiredHome 42:7cbdfd2bbfc5 397 _EndGraphicsStream();
WiredHome 42:7cbdfd2bbfc5 398 WindowMax();
WiredHome 69:636867df24a1 399 free(pixelBuffer); // don't leak memory
WiredHome 31:c72e12cd5c67 400 free(lineBuffer);
WiredHome 69:636867df24a1 401 if (colorPalette)
WiredHome 69:636867df24a1 402 free(colorPalette);
WiredHome 32:0e4f2ae512e2 403 return (noerror);
WiredHome 31:c72e12cd5c67 404 }
WiredHome 31:c72e12cd5c67 405
WiredHome 42:7cbdfd2bbfc5 406
WiredHome 42:7cbdfd2bbfc5 407 RetCode_t GraphicsDisplay::RenderImageFile(loc_t x, loc_t y, const char *FileName)
WiredHome 42:7cbdfd2bbfc5 408 {
WiredHome 42:7cbdfd2bbfc5 409 if (mystrnicmp(FileName + strlen(FileName) - 4, ".bmp", 4) == 0) {
WiredHome 42:7cbdfd2bbfc5 410 return RenderBitmapFile(x,y,FileName);
WiredHome 42:7cbdfd2bbfc5 411 } else if (mystrnicmp(FileName + strlen(FileName) - 4, ".ico", 4) == 0) {
WiredHome 42:7cbdfd2bbfc5 412 return RenderIconFile(x,y,FileName);
WiredHome 42:7cbdfd2bbfc5 413 } else {
WiredHome 42:7cbdfd2bbfc5 414 return not_supported_format;
WiredHome 42:7cbdfd2bbfc5 415 }
WiredHome 42:7cbdfd2bbfc5 416 }
WiredHome 42:7cbdfd2bbfc5 417
WiredHome 42:7cbdfd2bbfc5 418 RetCode_t GraphicsDisplay::RenderBitmapFile(loc_t x, loc_t y, const char *Name_BMP)
WiredHome 42:7cbdfd2bbfc5 419 {
WiredHome 42:7cbdfd2bbfc5 420 BITMAPFILEHEADER BMP_Header;
WiredHome 42:7cbdfd2bbfc5 421
WiredHome 42:7cbdfd2bbfc5 422 INFO("Opening {%s}", Name_BMP);
WiredHome 42:7cbdfd2bbfc5 423 FILE *Image = fopen(Name_BMP, "rb");
WiredHome 42:7cbdfd2bbfc5 424 if (!Image) {
WiredHome 42:7cbdfd2bbfc5 425 return(file_not_found);
WiredHome 42:7cbdfd2bbfc5 426 }
WiredHome 42:7cbdfd2bbfc5 427
WiredHome 42:7cbdfd2bbfc5 428 fread(&BMP_Header, 1, sizeof(BMP_Header), Image); // get the BMP Header
WiredHome 42:7cbdfd2bbfc5 429 INFO("bfType %04X", BMP_Header.bfType);
WiredHome 59:fb40aad4efd4 430 HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header));
WiredHome 42:7cbdfd2bbfc5 431 if (BMP_Header.bfType != BF_TYPE) {
WiredHome 42:7cbdfd2bbfc5 432 fclose(Image);
WiredHome 42:7cbdfd2bbfc5 433 return(not_bmp_format);
WiredHome 42:7cbdfd2bbfc5 434 }
WiredHome 42:7cbdfd2bbfc5 435 RetCode_t rt = _RenderBitmap(x, y, BMP_Header.bfOffBits, Image);
WiredHome 42:7cbdfd2bbfc5 436 if (rt != noerror) {
WiredHome 42:7cbdfd2bbfc5 437 return rt;
WiredHome 42:7cbdfd2bbfc5 438 } else {
WiredHome 42:7cbdfd2bbfc5 439 fclose(Image);
WiredHome 42:7cbdfd2bbfc5 440 return (noerror);
WiredHome 42:7cbdfd2bbfc5 441 }
WiredHome 42:7cbdfd2bbfc5 442 }
WiredHome 42:7cbdfd2bbfc5 443
WiredHome 42:7cbdfd2bbfc5 444 RetCode_t GraphicsDisplay::RenderIconFile(loc_t x, loc_t y, const char *Name_ICO)
WiredHome 42:7cbdfd2bbfc5 445 {
WiredHome 42:7cbdfd2bbfc5 446 ICOFILEHEADER ICO_Header;
WiredHome 42:7cbdfd2bbfc5 447 ICODIRENTRY ICO_DirEntry;
WiredHome 42:7cbdfd2bbfc5 448
WiredHome 42:7cbdfd2bbfc5 449 INFO("Opening {%s}", Name_ICO);
WiredHome 42:7cbdfd2bbfc5 450 FILE *Image = fopen(Name_ICO, "rb");
WiredHome 42:7cbdfd2bbfc5 451 if (!Image) {
WiredHome 42:7cbdfd2bbfc5 452 return(file_not_found);
WiredHome 42:7cbdfd2bbfc5 453 }
WiredHome 42:7cbdfd2bbfc5 454
WiredHome 42:7cbdfd2bbfc5 455 fread(&ICO_Header, 1, sizeof(ICO_Header), Image); // get the BMP Header
WiredHome 42:7cbdfd2bbfc5 456 HexDump("ICO_Header", (uint8_t *)&ICO_Header, sizeof(ICO_Header));
WiredHome 42:7cbdfd2bbfc5 457 if (ICO_Header.Reserved_zero != 0
WiredHome 42:7cbdfd2bbfc5 458 || ICO_Header.icType != IC_TYPE
WiredHome 42:7cbdfd2bbfc5 459 || ICO_Header.icImageCount == 0) {
WiredHome 42:7cbdfd2bbfc5 460 fclose(Image);
WiredHome 42:7cbdfd2bbfc5 461 return(not_ico_format);
WiredHome 42:7cbdfd2bbfc5 462 }
WiredHome 42:7cbdfd2bbfc5 463
WiredHome 42:7cbdfd2bbfc5 464 // Read ONLY the first of n possible directory entries.
WiredHome 42:7cbdfd2bbfc5 465 fread(&ICO_DirEntry, 1, sizeof(ICO_DirEntry), Image);
WiredHome 42:7cbdfd2bbfc5 466 HexDump("ICO_DirEntry", (uint8_t *)&ICO_DirEntry, sizeof(ICO_DirEntry));
WiredHome 42:7cbdfd2bbfc5 467 INFO("biBitCount %04X", ICO_DirEntry.biBitCount);
WiredHome 42:7cbdfd2bbfc5 468 if (ICO_DirEntry.biBitCount != 0) { // Expecting this to be zero for ico
WiredHome 42:7cbdfd2bbfc5 469 fclose(Image);
WiredHome 42:7cbdfd2bbfc5 470 return(not_supported_format);
WiredHome 42:7cbdfd2bbfc5 471 }
WiredHome 42:7cbdfd2bbfc5 472
WiredHome 42:7cbdfd2bbfc5 473 RetCode_t rt = _RenderBitmap(x, y, ICO_DirEntry.bfOffBits, Image);
WiredHome 42:7cbdfd2bbfc5 474 if (rt == noerror) {
WiredHome 42:7cbdfd2bbfc5 475 fclose(Image);
WiredHome 42:7cbdfd2bbfc5 476 return (noerror);
WiredHome 42:7cbdfd2bbfc5 477 } else {
WiredHome 42:7cbdfd2bbfc5 478 return rt;
WiredHome 42:7cbdfd2bbfc5 479 }
WiredHome 42:7cbdfd2bbfc5 480 }
WiredHome 42:7cbdfd2bbfc5 481
WiredHome 19:3f82c1161fd2 482 int GraphicsDisplay::columns()
WiredHome 19:3f82c1161fd2 483 {
WiredHome 19:3f82c1161fd2 484 return width() / 8;
dreschpe 0:de9d1462a835 485 }
dreschpe 0:de9d1462a835 486
WiredHome 19:3f82c1161fd2 487 int GraphicsDisplay::rows()
WiredHome 19:3f82c1161fd2 488 {
WiredHome 19:3f82c1161fd2 489 return height() / 8;
WiredHome 19:3f82c1161fd2 490 }