Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of RA8875 by
GraphicsDisplay.cpp
00001 /* mbed GraphicsDisplay Display Library Base Class 00002 * Copyright (c) 2007-2009 sford 00003 * Released under the MIT License: http://mbed.org/license/mit 00004 * 00005 * Derivative work by D.Smart 2014 00006 */ 00007 00008 #include "GraphicsDisplay.h" 00009 #include "Bitmap.h" 00010 #include "string.h" 00011 00012 //#define DEBUG "GD" 00013 // ... 00014 // INFO("Stuff to show %d", var); // new-line is automatically appended 00015 // 00016 #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) 00017 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00018 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00019 #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00020 static void HexDump(char * title, uint8_t * p, int count) 00021 { 00022 int i; 00023 char buf[100] = "0000: "; 00024 00025 if (*title) 00026 INFO("%s", title); 00027 for (i=0; i<count; ) { 00028 sprintf(buf + strlen(buf), "%02X ", *(p+i)); 00029 if ((++i & 0x0F) == 0x00) { 00030 INFO("%s", buf); 00031 if (i < count) 00032 sprintf(buf, "%04X: ", i); 00033 else 00034 buf[0] = '\0'; 00035 } 00036 } 00037 if (strlen(buf)) 00038 INFO("%s", buf); 00039 } 00040 #else 00041 #define INFO(x, ...) 00042 #define WARN(x, ...) 00043 #define ERR(x, ...) 00044 #define HexDump(a, b, c) 00045 #endif 00046 00047 #ifdef LOCALFONT 00048 const unsigned char FONT8x8[97][8] = { 00049 0x08, 0x08, 0x08, 0X00, 0X00, 0X00, 0X00, 0X00, // columns, rows, num_bytes_per_char 00050 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // space 0x20 00051 0x30, 0x78, 0x78, 0x30, 0x30, 0X00, 0x30, 0X00, // ! 00052 0x6C, 0x6C, 0x6C, 0X00, 0X00, 0X00, 0X00, 0X00, // " 00053 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0X00, // # 00054 0x18, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x18, 0X00, // $ 00055 0X00, 0x63, 0x66, 0x0C, 0x18, 0x33, 0x63, 0X00, // % 00056 0x1C, 0x36, 0x1C, 0x3B, 0x6E, 0x66, 0x3B, 0X00, // & 00057 0x30, 0x30, 0x60, 0X00, 0X00, 0X00, 0X00, 0X00, // ' 00058 0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0X00, // ( 00059 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0X00, // ) 00060 0X00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0X00, 0X00, // * 00061 0X00, 0x30, 0x30, 0xFC, 0x30, 0x30, 0X00, 0X00, // + 00062 0X00, 0X00, 0X00, 0X00, 0X00, 0x18, 0x18, 0x30, // , 00063 0X00, 0X00, 0X00, 0x7E, 0X00, 0X00, 0X00, 0X00, // - 00064 0X00, 0X00, 0X00, 0X00, 0X00, 0x18, 0x18, 0X00, // . 00065 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0X00, // / (forward slash) 00066 0x3E, 0x63, 0x63, 0x6B, 0x63, 0x63, 0x3E, 0X00, // 0 0x30 00067 0x18, 0x38, 0x58, 0x18, 0x18, 0x18, 0x7E, 0X00, // 1 00068 0x3C, 0x66, 0x06, 0x1C, 0x30, 0x66, 0x7E, 0X00, // 2 00069 0x3C, 0x66, 0x06, 0x1C, 0x06, 0x66, 0x3C, 0X00, // 3 00070 0x0E, 0x1E, 0x36, 0x66, 0x7F, 0x06, 0x0F, 0X00, // 4 00071 0x7E, 0x60, 0x7C, 0x06, 0x06, 0x66, 0x3C, 0X00, // 5 00072 0x1C, 0x30, 0x60, 0x7C, 0x66, 0x66, 0x3C, 0X00, // 6 00073 0x7E, 0x66, 0x06, 0x0C, 0x18, 0x18, 0x18, 0X00, // 7 00074 0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0X00, // 8 00075 0x3C, 0x66, 0x66, 0x3E, 0x06, 0x0C, 0x38, 0X00, // 9 00076 0X00, 0x18, 0x18, 0X00, 0X00, 0x18, 0x18, 0X00, // : 00077 0X00, 0x18, 0x18, 0X00, 0X00, 0x18, 0x18, 0x30, // ; 00078 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0X00, // < 00079 0X00, 0X00, 0x7E, 0X00, 0X00, 0x7E, 0X00, 0X00, // = 00080 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0X00, // > 00081 0x3C, 0x66, 0x06, 0x0C, 0x18, 0X00, 0x18, 0X00, // ? 00082 0x3E, 0x63, 0x6F, 0x69, 0x6F, 0x60, 0x3E, 0X00, // @ 0x40 00083 0x18, 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0X00, // A 00084 0x7E, 0x33, 0x33, 0x3E, 0x33, 0x33, 0x7E, 0X00, // B 00085 0x1E, 0x33, 0x60, 0x60, 0x60, 0x33, 0x1E, 0X00, // C 00086 0x7C, 0x36, 0x33, 0x33, 0x33, 0x36, 0x7C, 0X00, // D 00087 0x7F, 0x31, 0x34, 0x3C, 0x34, 0x31, 0x7F, 0X00, // E 00088 0x7F, 0x31, 0x34, 0x3C, 0x34, 0x30, 0x78, 0X00, // F 00089 0x1E, 0x33, 0x60, 0x60, 0x67, 0x33, 0x1F, 0X00, // G 00090 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0X00, // H 00091 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0X00, // I 00092 0x0F, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0X00, // J 00093 0x73, 0x33, 0x36, 0x3C, 0x36, 0x33, 0x73, 0X00, // K 00094 0x78, 0x30, 0x30, 0x30, 0x31, 0x33, 0x7F, 0X00, // L 00095 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0X00, // M 00096 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x63, 0x63, 0X00, // N 00097 0x3E, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3E, 0X00, // O 00098 0x7E, 0x33, 0x33, 0x3E, 0x30, 0x30, 0x78, 0X00, // P 0x50 00099 0x3C, 0x66, 0x66, 0x66, 0x6E, 0x3C, 0x0E, 0X00, // Q 00100 0x7E, 0x33, 0x33, 0x3E, 0x36, 0x33, 0x73, 0X00, // R 00101 0x3C, 0x66, 0x30, 0x18, 0x0C, 0x66, 0x3C, 0X00, // S 00102 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x3C, 0X00, // T 00103 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7E, 0X00, // U 00104 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0X00, // V 00105 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0X00, // W 00106 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0X00, // X 00107 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x3C, 0X00, // Y 00108 0x7F, 0x63, 0x46, 0x0C, 0x19, 0x33, 0x7F, 0X00, // Z 00109 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0X00, // [ 00110 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0X00, // \ (back slash) 00111 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0X00, // ] 00112 0x08, 0x1C, 0x36, 0x63, 0X00, 0X00, 0X00, 0X00, // ^ 00113 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0xFF, // _ 00114 0x18, 0x18, 0x0C, 0X00, 0X00, 0X00, 0X00, 0X00, // ` 0x60 00115 0X00, 0X00, 0x3C, 0x06, 0x3E, 0x66, 0x3B, 0X00, // a 00116 0x70, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x6E, 0X00, // b 00117 0X00, 0X00, 0x3C, 0x66, 0x60, 0x66, 0x3C, 0X00, // c 00118 0x0E, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3B, 0X00, // d 00119 0X00, 0X00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0X00, // e 00120 0x1C, 0x36, 0x30, 0x78, 0x30, 0x30, 0x78, 0X00, // f 00121 0X00, 0X00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x7C, // g 00122 0x70, 0x30, 0x36, 0x3B, 0x33, 0x33, 0x73, 0X00, // h 00123 0x18, 0X00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0X00, // i 00124 0x06, 0X00, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, // j 00125 0x70, 0x30, 0x33, 0x36, 0x3C, 0x36, 0x73, 0X00, // k 00126 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0X00, // l 00127 0X00, 0X00, 0x66, 0x7F, 0x7F, 0x6B, 0x63, 0X00, // m 00128 0X00, 0X00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0X00, // n 00129 0X00, 0X00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0X00, // o 00130 0X00, 0X00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78, // p 00131 0X00, 0X00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F, // q 00132 0X00, 0X00, 0x6E, 0x3B, 0x33, 0x30, 0x78, 0X00, // r 00133 0X00, 0X00, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0X00, // s 00134 0x08, 0x18, 0x3E, 0x18, 0x18, 0x1A, 0x0C, 0X00, // t 00135 0X00, 0X00, 0x66, 0x66, 0x66, 0x66, 0x3B, 0X00, // u 00136 0X00, 0X00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0X00, // v 00137 0X00, 0X00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0X00, // w 00138 0X00, 0X00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0X00, // x 00139 0X00, 0X00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x7C, // y 00140 0X00, 0X00, 0x7E, 0x4C, 0x18, 0x32, 0x7E, 0X00, // z 00141 0x0E, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0E, 0X00, // { 00142 0x0C, 0x0C, 0x0C, 0X00, 0x0C, 0x0C, 0x0C, 0X00, // | 00143 0x70, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x70, 0X00, // } 00144 0x3B, 0x6E, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, // ~ 00145 0x1C, 0x36, 0x36, 0x1C, 0X00, 0X00, 0X00, 0X00 // DEL 00146 }; 00147 #endif // LOCALFONT 00148 00149 char mytolower(char a) { 00150 if (a >= 'A' && a <= 'Z') 00151 return (a - 'A' + 'a'); 00152 else 00153 return a; 00154 } 00155 /// mystrnicmp exists because not all compiler libraries have this function. 00156 /// 00157 /// Some have strnicmp, others _strnicmp, and others have C++ methods, which 00158 /// is outside the scope of this C-portable set of functions. 00159 /// 00160 /// @param l is a pointer to the string on the left 00161 /// @param r is a pointer to the string on the right 00162 /// @param n is the number of characters to compare 00163 /// @returns -1 if l < r 00164 /// @returns 0 if l == r 00165 /// @returns +1 if l > r 00166 /// 00167 int mystrnicmp(const char *l, const char *r, size_t n) { 00168 int result = 0; 00169 00170 if (n != 0) { 00171 do { 00172 result = mytolower(*l++) - mytolower(*r++); 00173 } while ((result == 0) && (*l != '\0') && (--n > 0)); 00174 } 00175 if (result < -1) 00176 result = -1; 00177 else if (result > 1) 00178 result = 1; 00179 return result; 00180 } 00181 00182 00183 GraphicsDisplay::GraphicsDisplay(const char *name) 00184 : TextDisplay(name) 00185 { 00186 font = NULL; 00187 } 00188 00189 RetCode_t GraphicsDisplay::set_font(const unsigned char * _font) 00190 { 00191 font = _font; // trusting them, but it might be good to put some checks in here... 00192 return noerror; 00193 } 00194 00195 #ifdef LOCALFONT 00196 int GraphicsDisplay::character(int x, int y, int value) 00197 { 00198 if (value <= 0x1F && value >= 7F) 00199 return 0; 00200 00201 return blitbit(x, y, FONT8X8[0][0], FONT8X8[0][1], 00202 (char *)&(FONT8x8[value - 0x1F][0])); 00203 } 00204 #else 00205 int GraphicsDisplay::character(int x, int y, int c) 00206 { 00207 unsigned int offset; 00208 const unsigned char * charRecord; 00209 00210 if (c <= 0x1F || c >= 0x7F) 00211 return 0; 00212 offset = font[0]; // bytes / char 00213 charRecord = &font[((c - ' ') * offset) + 4]; // start of char bitmap 00214 return fontblit(x, y, font, charRecord); 00215 } 00216 #endif 00217 00218 RetCode_t GraphicsDisplay::window(loc_t x, loc_t y, dim_t w, dim_t h) 00219 { 00220 // current pixel location 00221 _x = x; 00222 _y = y; 00223 // window settings 00224 _x1 = x; 00225 _x2 = x + w - 1; 00226 _y1 = y; 00227 _y2 = y + h - 1; 00228 return noerror; 00229 } 00230 00231 void GraphicsDisplay::WindowMax(void) 00232 { 00233 window(0,0, width(),height()); 00234 } 00235 00236 RetCode_t GraphicsDisplay::putp(color_t color) 00237 { 00238 pixel(_x, _y, color); 00239 // update pixel location based on window settings 00240 _x++; 00241 if(_x > _x2) { 00242 _x = _x1; 00243 _y++; 00244 if(_y > _y2) { 00245 _y = _y1; 00246 } 00247 } 00248 return noerror; 00249 } 00250 00251 void GraphicsDisplay::fill(int x, int y, int w, int h, color_t color) 00252 { 00253 fillrect(x,y, x+w, y+h, color); 00254 } 00255 00256 RetCode_t GraphicsDisplay::cls() 00257 { 00258 fill(0, 0, width(), height(), _background); 00259 return noerror; 00260 } 00261 00262 void GraphicsDisplay::blit(int x, int y, int w, int h, const int * color) 00263 { 00264 window(x, y, w, h); 00265 _StartGraphicsStream(); 00266 for (int i=0; i<w*h; i++) { 00267 putp(color[i]); 00268 } 00269 _EndGraphicsStream(); 00270 WindowMax(); 00271 } 00272 00273 #ifdef LOCALFONT 00274 int GraphicsDisplay::blitbit(int x, int y, int w, int h, const char * color) 00275 { 00276 _foreground = 0xFFFF; 00277 INFO("blitbit(%d,%d, %d,%d, %02X) [%04X,%04X]", x,y, w,h, *color, _foreground, _background); 00278 INFO("%lu %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", 00279 color, 00280 color[0], color[1], color[2], color[3], color[4], color[5], color[6], color[7], 00281 color[8], color[9], color[10], color[11], color[12], color[13], color[14], color[15]); 00282 window(x, y, w, h); 00283 _StartGraphicsStream(); 00284 for (int i = 0; i < w*h; i++) { 00285 char byte = color[i >> 3]; 00286 int offset = i & 0x7; 00287 if (offset == 0) 00288 INFO(" %2d = %02X", i>>3, byte); 00289 int c = ((byte << offset) & 0x80) ? _foreground : _background; 00290 putp(c); 00291 } 00292 _EndGraphicsStream(); 00293 WindowMax(); 00294 return w; 00295 } 00296 #endif 00297 00298 00299 int GraphicsDisplay::fontblit(int x, int y, const unsigned char * fontTable, const unsigned char * fontChar) 00300 { 00301 //int fontWidth = font[1]; // get hor size of font 00302 int fontHeight = font[2]; // get vert size of font 00303 int bytesPerLine = font[3]; // bytes per line 00304 int charWidth = fontChar[0]; // width of this character 00305 int px, py; 00306 00307 //INFO("(%d,%d) %lu, %lu %X/%X", x,y, fontTable, fontChar, _foreground, _background); 00308 //INFO("char size (%d,%d)", charWidth, fontHeight); 00309 //HexDump("char", (uint8_t *)fontChar, 32); 00310 //INFO("(f,b) = (%04X,%04X)", _foreground, _background) 00311 window(x, y, charWidth, fontHeight); 00312 _StartGraphicsStream(); 00313 //INFO("(f,b) = (%04X,%04X)", _foreground, _background) 00314 for (py = 0; py < fontHeight; py++) { 00315 int bitmask = 1 << (py & 7); 00316 00317 for (px = 0; px < charWidth; px++) { 00318 int offset = (py / 8) + px * bytesPerLine; 00319 unsigned char byte = fontChar[offset + 1]; // skip the char's # bits wide value 00320 color_t c = (byte & bitmask) ? _foreground : _background; 00321 //INFO("(%2d,%2d) %02X & %02X => %04X [%04X,%04X]", px, py, byte, bitmask, c, _foreground, _background); 00322 //pixel(x+px, y+py, c); 00323 putp(c); 00324 } 00325 } 00326 _EndGraphicsStream(); 00327 WindowMax(); 00328 return charWidth; 00329 } 00330 00331 // BMP Color Palette is BGRx 00332 // BBBB BBBB GGGG GGGG RRRR RRRR 0000 0000 00333 // RGB16 is 00334 // RRRR RGGG GGGB BBBB 00335 // swap to little endian 00336 // GGGB BBBB RRRR RGGG 00337 color_t GraphicsDisplay::RGBQuadToRGB16(RGBQUAD * colorPalette, uint16_t i) 00338 { 00339 color_t c; 00340 00341 c = ((colorPalette[i].rgbBlue >> 3) << 0); 00342 c |= ((colorPalette[i].rgbGreen >> 2) << 5); 00343 c |= ((colorPalette[i].rgbRed >> 3) << 11); 00344 return c; 00345 } 00346 00347 /// RRRR RGGG GGGB BBBB 00348 RGBQUAD GraphicsDisplay::RGB16ToRGBQuad(color_t c) 00349 { 00350 RGBQUAD q; 00351 00352 memset(&q, 0, sizeof(q)); 00353 q.rgbBlue = (c & 0x001F) << 3; /* Blue value */ 00354 q.rgbGreen = (c & 0x07E0) >> 3; /* Green value */ 00355 q.rgbRed = (c & 0xF800) >> 8; /* Red value */ 00356 q.rgbReserved = 0; 00357 return q; 00358 } 00359 00360 00361 RetCode_t GraphicsDisplay::PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP) 00362 { 00363 BITMAPFILEHEADER BMP_Header; 00364 BITMAPINFOHEADER BMP_Info; 00365 00366 INFO("(%d,%d) - (%d,%d) %s", x,y,w,h,Name_BMP); 00367 if (x >= 0 && x < width() 00368 && y >= 0 && y < height() 00369 && w > 0 && x + w <= width() 00370 && h > 0 && y + h <= height()) { 00371 00372 BMP_Header.bfType = BF_TYPE; 00373 BMP_Header.bfSize = (w * h * sizeof(RGBQUAD)) + sizeof(BMP_Header) + sizeof(BMP_Header); 00374 BMP_Header.bfReserved1 = 0; 00375 BMP_Header.bfReserved2 = 0; 00376 BMP_Header.bfOffBits = sizeof(BMP_Header) + sizeof(BMP_Header); 00377 00378 BMP_Info.biSize = sizeof(BMP_Info); 00379 BMP_Info.biWidth = w; 00380 BMP_Info.biHeight = h; 00381 BMP_Info.biPlanes = 1; 00382 BMP_Info.biBitCount = 24; 00383 BMP_Info.biCompression = BI_RGB; 00384 BMP_Info.biSizeImage = 0; 00385 BMP_Info.biXPelsPerMeter = 0; 00386 BMP_Info.biYPelsPerMeter = 0; 00387 BMP_Info.biClrUsed = 0; 00388 BMP_Info.biClrImportant = 0; 00389 00390 INFO("Writing {%s}", Name_BMP); 00391 FILE *Image = fopen(Name_BMP, "wb"); 00392 if (!Image) { 00393 ERR("File not found"); 00394 return(file_not_found); 00395 } 00396 00397 // Be optimistic - don't check for errors. 00398 //HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header)); 00399 fwrite(&BMP_Header, sizeof(char), sizeof(BMP_Header), Image); 00400 //INFO("fwrite returned %d", r); 00401 00402 //HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info)); 00403 fwrite(&BMP_Info, sizeof(char), sizeof(BMP_Info), Image); 00404 //INFO("fwrite returned %d", r); 00405 00406 int lineBufSize = ((24 * w + 7)/8); 00407 uint8_t * lineBuffer = (uint8_t *)malloc(lineBufSize); 00408 if (lineBuffer == NULL) { 00409 fclose(Image); 00410 ERR("Not enough RAM for lineBuffer"); 00411 return(not_enough_ram); 00412 } 00413 color_t * pixelBuffer = (color_t *)malloc(w * sizeof(color_t)); 00414 if (pixelBuffer == NULL) { 00415 fclose(Image); 00416 free(lineBuffer); 00417 ERR("Not enough RAM for pixelBuffer"); 00418 return(not_enough_ram); 00419 } 00420 00421 // Read the display from the last line toward the top 00422 // so we can write the file in one pass. 00423 for (int j = h - 1; j >= 0; j--) { 00424 // Read one line of pixels to a local buffer 00425 if (getPixelStream(pixelBuffer, w, x,y+j) != noerror) { 00426 ERR("getPixelStream error, and no recovery handler..."); 00427 } 00428 // Convert the local buffer to RGBQUAD format 00429 int lb = 0; 00430 for (int i=0; i<w; i++) { 00431 color_t pixel = pixelBuffer[x+i]; 00432 // Scale to 24-bits 00433 RGBQUAD q = RGB16ToRGBQuad(pixel); 00434 lineBuffer[lb++] = q.rgbBlue; 00435 lineBuffer[lb++] = q.rgbGreen; 00436 lineBuffer[lb++] = q.rgbRed; 00437 } 00438 // Write to disk 00439 //HexDump("Line", lineBuffer, lineBufSize); 00440 fwrite(lineBuffer, sizeof(char), lb, Image); 00441 } 00442 fclose(Image); 00443 INFO("Image closed"); 00444 return noerror; 00445 } else { 00446 return bad_parameter; 00447 } 00448 } 00449 00450 RetCode_t GraphicsDisplay::_RenderBitmap(loc_t x, loc_t y, uint32_t fileOffset, FILE * Image) 00451 { 00452 BITMAPINFOHEADER BMP_Info; 00453 RGBQUAD * colorPalette = NULL; 00454 int colorCount; 00455 uint8_t * lineBuffer = NULL; 00456 uint16_t BPP_t; 00457 uint32_t PixelWidth, PixelHeight; 00458 //uint32_t start_data; 00459 unsigned int i, offset; 00460 int padd,j; 00461 00462 // Now, Read the bitmap info header 00463 fread(&BMP_Info, 1, sizeof(BMP_Info), Image); 00464 //HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info)); 00465 BPP_t = BMP_Info.biBitCount; 00466 INFO("biBitCount %04X", BPP_t); 00467 if (BPP_t != 4 && BPP_t != 8 && BPP_t != 16 && BPP_t != 24) { // Support 4, 8, 16, 24-bits per pixel 00468 fclose(Image); 00469 return(not_supported_format); 00470 } 00471 00472 PixelHeight = BMP_Info.biHeight; 00473 PixelWidth = BMP_Info.biWidth; 00474 if (PixelHeight > height() + y || PixelWidth > width() + x) { 00475 fclose(Image); 00476 return(image_too_big); 00477 } 00478 INFO("(%d,%d) (%d,%d)", x,y, PixelWidth,PixelHeight); 00479 if (BMP_Info.biBitCount <= 8) { 00480 int paletteSize; 00481 // Read the color palette 00482 colorCount = 1 << BMP_Info.biBitCount; 00483 paletteSize = sizeof(RGBQUAD) * colorCount; 00484 colorPalette = (RGBQUAD *)malloc(paletteSize); 00485 if (colorPalette == NULL) { 00486 fclose(Image); 00487 return(not_enough_ram); 00488 } 00489 fread(colorPalette, 1, paletteSize, Image); 00490 //HexDump("Color Palette", (uint8_t *)colorPalette, paletteSize); 00491 } 00492 00493 int lineBufSize = ((BPP_t * PixelWidth + 7)/8); 00494 //INFO("BPP_t %d, PixelWidth %d, lineBufSize %d", BPP_t, PixelWidth, lineBufSize); 00495 lineBuffer = (uint8_t *)malloc(lineBufSize); 00496 if (lineBuffer == NULL) { 00497 free(colorPalette); 00498 fclose(Image); 00499 return(not_enough_ram); 00500 } 00501 color_t * pixelBuffer = (color_t *)malloc(PixelWidth * sizeof(color_t)); 00502 if (pixelBuffer == NULL) { 00503 free(colorPalette); 00504 free(lineBuffer); 00505 fclose(Image); 00506 return(not_enough_ram); 00507 } 00508 00509 // the Raw Data records are padded to a multiple of 4 bytes 00510 int recordSize = 2; 00511 if (BPP_t == 4) { 00512 recordSize = 1; 00513 } else if (BPP_t == 8) { 00514 recordSize = 1; 00515 } else if (BPP_t == 16) { 00516 recordSize = 2; 00517 } else if (BPP_t == 24) { 00518 recordSize = 3; 00519 } 00520 padd = -1; 00521 do { 00522 padd++; 00523 } while ((PixelWidth * recordSize + padd) % 4 != 0); 00524 00525 // Define window for top to bottom and left to right so writing auto-wraps 00526 window(x,y, PixelWidth,PixelHeight); 00527 SetGraphicsCursor(x, y); 00528 _StartGraphicsStream(); 00529 00530 //start_data = BMP_Header.bfOffBits; 00531 //HexDump("Raw Data", (uint8_t *)&start_data, 32); 00532 //INFO("(%d,%d) (%d,%d), [%d,%d]", x,y, PixelWidth,PixelHeight, lineBufSize, padd); 00533 for (j = PixelHeight - 1; j >= 0; j--) { //Lines bottom up 00534 offset = fileOffset + j * (lineBufSize + padd); // start of line 00535 fseek(Image, offset, SEEK_SET); 00536 fread(lineBuffer, 1, lineBufSize, Image); // read a line - slow ! 00537 //INFO("offset: %6X", offset); 00538 for (i = 0; i < PixelWidth; i++) { // copy pixel data to TFT 00539 if (BPP_t == 4) { 00540 uint8_t dPix = lineBuffer[i/2]; 00541 if ((i & 1) == 0) 00542 dPix >>= 4; 00543 dPix &= 0x0F; 00544 pixelBuffer[i] = RGBQuadToRGB16(colorPalette, dPix); 00545 //putp(RGBQuadToRGB16(colorPalette, dPix)); 00546 } else if (BPP_t == 8) { 00547 pixelBuffer[i] = RGBQuadToRGB16(colorPalette, lineBuffer[i]); 00548 //putp(RGBQuadToRGB16(colorPalette, lineBuffer[i])); 00549 } else if (BPP_t == 16) { 00550 pixelBuffer[i] = lineBuffer[i]; 00551 //putp(lineBuffer[i]); 00552 } else if (BPP_t == 24) { 00553 color_t color; 00554 color = RGB(lineBuffer[i*3+2], lineBuffer[i*3+1], lineBuffer[i*3+0]); 00555 pixelBuffer[i] = color; 00556 //putp(color); 00557 } 00558 } 00559 pixelStream(pixelBuffer, PixelWidth, x, y++); 00560 } 00561 _EndGraphicsStream(); 00562 WindowMax(); 00563 free(lineBuffer); 00564 free(colorPalette); 00565 return (noerror); 00566 } 00567 00568 00569 RetCode_t GraphicsDisplay::RenderImageFile(loc_t x, loc_t y, const char *FileName) 00570 { 00571 if (mystrnicmp(FileName + strlen(FileName) - 4, ".bmp", 4) == 0) { 00572 return RenderBitmapFile(x,y,FileName); 00573 } else if (mystrnicmp(FileName + strlen(FileName) - 4, ".ico", 4) == 0) { 00574 return RenderIconFile(x,y,FileName); 00575 } else { 00576 return not_supported_format; 00577 } 00578 } 00579 00580 RetCode_t GraphicsDisplay::RenderBitmapFile(loc_t x, loc_t y, const char *Name_BMP) 00581 { 00582 BITMAPFILEHEADER BMP_Header; 00583 00584 INFO("Opening {%s}", Name_BMP); 00585 FILE *Image = fopen(Name_BMP, "rb"); 00586 if (!Image) { 00587 return(file_not_found); 00588 } 00589 00590 fread(&BMP_Header, 1, sizeof(BMP_Header), Image); // get the BMP Header 00591 INFO("bfType %04X", BMP_Header.bfType); 00592 //HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header)); 00593 if (BMP_Header.bfType != BF_TYPE) { 00594 fclose(Image); 00595 return(not_bmp_format); 00596 } 00597 RetCode_t rt = _RenderBitmap(x, y, BMP_Header.bfOffBits, Image); 00598 if (rt != noerror) { 00599 return rt; 00600 } else { 00601 fclose(Image); 00602 return (noerror); 00603 } 00604 } 00605 00606 RetCode_t GraphicsDisplay::RenderIconFile(loc_t x, loc_t y, const char *Name_ICO) 00607 { 00608 ICOFILEHEADER ICO_Header; 00609 ICODIRENTRY ICO_DirEntry; 00610 00611 INFO("Opening {%s}", Name_ICO); 00612 FILE *Image = fopen(Name_ICO, "rb"); 00613 if (!Image) { 00614 return(file_not_found); 00615 } 00616 00617 fread(&ICO_Header, 1, sizeof(ICO_Header), Image); // get the BMP Header 00618 HexDump("ICO_Header", (uint8_t *)&ICO_Header, sizeof(ICO_Header)); 00619 if (ICO_Header.Reserved_zero != 0 00620 || ICO_Header.icType != IC_TYPE 00621 || ICO_Header.icImageCount == 0) { 00622 fclose(Image); 00623 return(not_ico_format); 00624 } 00625 00626 // Read ONLY the first of n possible directory entries. 00627 fread(&ICO_DirEntry, 1, sizeof(ICO_DirEntry), Image); 00628 HexDump("ICO_DirEntry", (uint8_t *)&ICO_DirEntry, sizeof(ICO_DirEntry)); 00629 INFO("biBitCount %04X", ICO_DirEntry.biBitCount); 00630 if (ICO_DirEntry.biBitCount != 0) { // Expecting this to be zero for ico 00631 fclose(Image); 00632 return(not_supported_format); 00633 } 00634 00635 RetCode_t rt = _RenderBitmap(x, y, ICO_DirEntry.bfOffBits, Image); 00636 if (rt == noerror) { 00637 fclose(Image); 00638 return (noerror); 00639 } else { 00640 return rt; 00641 } 00642 } 00643 00644 int GraphicsDisplay::columns() 00645 { 00646 return width() / 8; 00647 } 00648 00649 int GraphicsDisplay::rows() 00650 { 00651 return height() / 8; 00652 } 00653 00654
Generated on Tue Jul 12 2022 21:36:16 by
1.7.2
