Library to control a Graphics TFT connected to 4-wire SPI - revised for the Raio RA8875 Display Controller.

Dependents:   FRDM_RA8875_mPaint RA8875_Demo RA8875_KeyPadDemo SignalGenerator ... more

Fork of SPI_TFT by Peter Drescher

See Components - RA8875 Based Display

Enhanced touch-screen support - where it previous supported both the Resistive Touch and Capacitive Touch based on the FT5206 Touch Controller, now it also has support for the GSL1680 Touch Controller.

Offline Help Manual (Windows chm)

/media/uploads/WiredHome/ra8875.zip.bin (download, rename to .zip and unzip)

Committer:
WiredHome
Date:
Sat Sep 21 17:30:00 2019 +0000
Revision:
190:3132b7dfad82
Parent:
182:8832d03a2a29
Child:
198:9b6851107426
Fonts Add & mods; Add methods; - get dimensions of image file; - round or square cap for thicklines; - word-wrap for puts; - align one rect to another; - independently set the text font fill; - get the width of a character, or a string

Who changed what in which revision?

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