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