brw1

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GraphicsDisplay.cpp Source File

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 RetCode_t GraphicsDisplay::WindowMax(void)
00232 {
00233     return 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 RetCode_t GraphicsDisplay::fill(int x, int y, int w, int h, color_t color)
00252 {
00253     return fillrect(x,y, x+w, y+h, color);
00254 }
00255 
00256 RetCode_t GraphicsDisplay::cls(uint16_t layers)
00257 {
00258     return fill(0, 0, width(), height(), _background);
00259 }
00260 
00261 RetCode_t GraphicsDisplay::blit(int x, int y, int w, int h, const int * color)
00262 {
00263     window(x, y, w, h);
00264     _StartGraphicsStream();
00265     for (int i=0; i<w*h; i++) {
00266         _putp(color[i]);
00267     }
00268     _EndGraphicsStream();
00269     return WindowMax();
00270 }
00271 
00272 #ifdef LOCALFONT
00273 int GraphicsDisplay::blitbit(int x, int y, int w, int h, const char * color)
00274 {
00275     _foreground = 0xFFFF;
00276     INFO("blitbit(%d,%d, %d,%d, %02X) [%04X,%04X]", x,y, w,h, *color, _foreground, _background);
00277     INFO("%lu  %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
00278         color,
00279         color[0], color[1], color[2], color[3], color[4], color[5], color[6], color[7], 
00280         color[8], color[9], color[10], color[11], color[12], color[13], color[14], color[15]);
00281     window(x, y, w, h);
00282     _StartGraphicsStream();
00283     for (int i = 0; i < w*h; i++) {
00284         char byte = color[i >> 3];
00285         int offset = i & 0x7;
00286         if (offset == 0)
00287             INFO(" %2d = %02X", i>>3, byte);
00288         int c = ((byte << offset) & 0x80) ? _foreground : _background;
00289         _putp(c);
00290     }
00291     _EndGraphicsStream();
00292     WindowMax();
00293     return w;
00294 }
00295 #endif
00296 
00297 
00298 int GraphicsDisplay::fontblit(int x, int y, const unsigned char * fontTable, const unsigned char * fontChar)
00299 {
00300     //int fontWidth = font[1];                       // get hor size of font
00301     int fontHeight = font[2];                      // get vert size of font
00302     int bytesPerLine = font[3];                       // bytes per line
00303     int charWidth = fontChar[0];        // width of this character
00304     int px, py;
00305     
00306     //INFO("(%d,%d) %lu, %lu %X/%X", x,y, fontTable, fontChar, _foreground, _background);
00307     //INFO("char size (%d,%d)", charWidth, fontHeight);
00308     //HexDump("char", (uint8_t *)fontChar, 32);
00309     //INFO("(f,b) = (%04X,%04X)", _foreground, _background)
00310     window(x, y, charWidth, fontHeight);
00311     _StartGraphicsStream();
00312     //INFO("(f,b) = (%04X,%04X)", _foreground, _background)
00313     for (py = 0; py < fontHeight; py++) {
00314         int bitmask = 1 << (py & 7);
00315         
00316         for (px = 0; px < charWidth; px++) {
00317             int offset = (py / 8) + px * bytesPerLine;
00318             unsigned char byte = fontChar[offset + 1];  // skip the char's # bits wide value
00319             color_t c = (byte & bitmask) ? _foreground : _background;
00320             //INFO("(%2d,%2d) %02X & %02X => %04X [%04X,%04X]", px, py, byte, bitmask, c, _foreground, _background);
00321             //pixel(x+px, y+py, c);
00322             _putp(c);
00323         }
00324     }
00325     _EndGraphicsStream();
00326     WindowMax();
00327     return charWidth;
00328 }
00329 
00330 // BMP Color Palette is BGRx
00331 //      BBBB BBBB GGGG GGGG RRRR RRRR 0000 0000
00332 // RGB16 is
00333 //      RRRR RGGG GGGB BBBB
00334 // swap to little endian
00335 //      GGGB BBBB RRRR RGGG
00336 color_t GraphicsDisplay::RGBQuadToRGB16(RGBQUAD * colorPalette, uint16_t i)
00337 {
00338     color_t c;
00339  
00340     c  = ((colorPalette[i].rgbBlue  >> 3) <<  0);
00341     c |= ((colorPalette[i].rgbGreen >> 2) <<  5);
00342     c |= ((colorPalette[i].rgbRed   >> 3) << 11);
00343     return c;
00344 }
00345 
00346 /// RRRR RGGG GGGB BBBB
00347 RGBQUAD GraphicsDisplay::RGB16ToRGBQuad(color_t c)
00348 {
00349     RGBQUAD q;
00350     
00351     memset(&q, 0, sizeof(q));
00352     q.rgbBlue  = ((c & 0x001F) << 3) | (c & 0x07);          /* Blue value */
00353     q.rgbGreen = ((c & 0x07E0) >> 3) | ((c >> 7) & 0x03);   /* Green value */
00354     q.rgbRed   = ((c & 0xF800) >> 8) | ((c >> 11) & 0x07);  /* Red value */
00355     q.rgbReserved = 0;
00356     return q;
00357 }
00358 
00359 RetCode_t GraphicsDisplay::_RenderBitmap(loc_t x, loc_t y, uint32_t fileOffset, FILE * Image)
00360 {
00361     BITMAPINFOHEADER BMP_Info;
00362     RGBQUAD * colorPalette = NULL;
00363     int colorCount;
00364     uint8_t * lineBuffer = NULL;
00365     color_t * pixelBuffer = NULL;
00366     uint16_t BPP_t;
00367     uint32_t PixelWidth, PixelHeight;
00368     unsigned int    i, offset;
00369     int padd,j;
00370     #ifdef DEBUG
00371     uint32_t start_data;
00372     #endif
00373 
00374     // Now, Read the bitmap info header
00375     fread(&BMP_Info, 1, sizeof(BMP_Info), Image);
00376     HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info));
00377     BPP_t = BMP_Info.biBitCount;
00378     INFO("biBitCount %04X", BPP_t);
00379     if (BPP_t != 4 && BPP_t != 8 && BPP_t != 16 && BPP_t != 24) { // Support 4, 8, 16, 24-bits per pixel
00380         fclose(Image);
00381         return(not_supported_format);
00382     }
00383 
00384     PixelHeight = BMP_Info.biHeight;
00385     PixelWidth = BMP_Info.biWidth;
00386     INFO("(%d,%d) (%d,%d) (%d,%d)", x,y, PixelWidth,PixelHeight, width(), height());
00387     if (PixelHeight > height() + y || PixelWidth > width() + x) {
00388         fclose(Image);
00389         return(image_too_big);
00390     }
00391     if (BMP_Info.biBitCount <= 8) {
00392         int paletteSize;
00393         // Read the color palette
00394         colorCount = 1 << BMP_Info.biBitCount;
00395         paletteSize = sizeof(RGBQUAD) * colorCount;
00396         colorPalette = (RGBQUAD *)malloc(paletteSize);
00397         if (colorPalette == NULL) {
00398             fclose(Image);
00399             return(not_enough_ram);
00400         }
00401         fread(colorPalette, 1, paletteSize, Image);
00402         HexDump("Color Palette", (uint8_t *)colorPalette, paletteSize);
00403     }
00404 
00405     int lineBufSize = ((BPP_t * PixelWidth + 7)/8);
00406     INFO("BPP_t %d, PixelWidth %d, lineBufSize %d", BPP_t, PixelWidth, lineBufSize);
00407     lineBuffer = (uint8_t *)malloc(lineBufSize);
00408     if (lineBuffer == NULL) {
00409         free(colorPalette);
00410         fclose(Image);
00411         return(not_enough_ram);
00412     }
00413     pixelBuffer = (color_t *)malloc(PixelWidth * sizeof(color_t));
00414     if (pixelBuffer == NULL) {
00415         free(lineBuffer);
00416         if (colorPalette)
00417             free(colorPalette);
00418         fclose(Image);
00419         return(not_enough_ram);
00420     }
00421 
00422     // the Raw Data records are padded to a multiple of 4 bytes
00423     int recordSize = 2;
00424     if (BPP_t == 4) {
00425         recordSize = 1;
00426     } else if (BPP_t == 8) {
00427         recordSize = 1;
00428     } else if (BPP_t == 16) {
00429         recordSize = 2;
00430     } else if (BPP_t == 24) {
00431         recordSize = 3;
00432     }
00433     padd = -1;
00434     do {
00435         padd++;
00436     } while ((PixelWidth * recordSize + padd) % 4 != 0);
00437 
00438     // Define window for top to bottom and left to right so writing auto-wraps
00439     window(x,y, PixelWidth,PixelHeight);
00440     SetGraphicsCursor(x, y);
00441     _StartGraphicsStream();
00442     
00443     //start_data = BMP_Header.bfOffBits;
00444     HexDump("Raw Data", (uint8_t *)&start_data, 32);
00445     INFO("(%d,%d) (%d,%d), [%d,%d]", x,y, PixelWidth,PixelHeight, lineBufSize, padd);
00446     for (j = PixelHeight - 1; j >= 0; j--) {                //Lines bottom up
00447         offset = fileOffset + j * (lineBufSize + padd);     // start of line
00448         fseek(Image, offset, SEEK_SET);
00449         fread(lineBuffer, 1, lineBufSize, Image);           // read a line - slow !
00450         //INFO("offset: %6X", offset);
00451         for (i = 0; i < PixelWidth; i++) {                  // copy pixel data to TFT
00452             if (BPP_t == 4) {
00453                 uint8_t dPix = lineBuffer[i/2];
00454                 if ((i & 1) == 0)
00455                     dPix >>= 4;
00456                 dPix &= 0x0F;
00457                 pixelBuffer[i] = RGBQuadToRGB16(colorPalette, dPix);
00458             } else if (BPP_t == 8) {
00459                 pixelBuffer[i] = RGBQuadToRGB16(colorPalette, lineBuffer[i]);
00460             } else if (BPP_t == 16) {
00461                 pixelBuffer[i] = lineBuffer[i];
00462             } else if (BPP_t == 24) {
00463                 color_t color;
00464                 color = RGB(lineBuffer[i*3+2], lineBuffer[i*3+1], lineBuffer[i*3+0]);
00465                 pixelBuffer[i] = color;
00466             }
00467         }
00468         pixelStream(pixelBuffer, PixelWidth, x, y++);
00469     }
00470     _EndGraphicsStream();
00471     WindowMax();
00472     free(pixelBuffer);      // don't leak memory
00473     free(lineBuffer);
00474     if (colorPalette)
00475         free(colorPalette);
00476     return (noerror);
00477 }
00478 
00479 
00480 RetCode_t GraphicsDisplay::RenderImageFile(loc_t x, loc_t y, const char *FileName)
00481 {
00482     if (mystrnicmp(FileName + strlen(FileName) - 4, ".bmp", 4) == 0) {
00483         return RenderBitmapFile(x,y,FileName);
00484     } else if (mystrnicmp(FileName + strlen(FileName) - 4, ".ico", 4) == 0) {
00485         return RenderIconFile(x,y,FileName);
00486     } else {
00487         return not_supported_format;
00488     }
00489 }
00490 
00491 RetCode_t GraphicsDisplay::RenderBitmapFile(loc_t x, loc_t y, const char *Name_BMP)
00492 {
00493     BITMAPFILEHEADER BMP_Header;
00494 
00495     INFO("Opening {%s}", Name_BMP);
00496     FILE *Image = fopen(Name_BMP, "rb");
00497     if (!Image) {
00498         return(file_not_found);
00499     }
00500 
00501     fread(&BMP_Header, 1, sizeof(BMP_Header), Image);      // get the BMP Header
00502     INFO("bfType %04X", BMP_Header.bfType);
00503     HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header));
00504     if (BMP_Header.bfType != BF_TYPE) {
00505         fclose(Image);
00506         return(not_bmp_format);
00507     }
00508     RetCode_t rt = _RenderBitmap(x, y, BMP_Header.bfOffBits, Image);
00509     if (rt != noerror) {
00510         return rt;
00511     } else {
00512         fclose(Image);
00513         return (noerror);
00514     }
00515 }
00516 
00517 RetCode_t GraphicsDisplay::RenderIconFile(loc_t x, loc_t y, const char *Name_ICO)
00518 {
00519     ICOFILEHEADER ICO_Header;
00520     ICODIRENTRY ICO_DirEntry;
00521 
00522     INFO("Opening {%s}", Name_ICO);
00523     FILE *Image = fopen(Name_ICO, "rb");
00524     if (!Image) {
00525         return(file_not_found);
00526     }
00527 
00528     fread(&ICO_Header, 1, sizeof(ICO_Header), Image);      // get the BMP Header
00529     HexDump("ICO_Header", (uint8_t *)&ICO_Header, sizeof(ICO_Header));
00530     if (ICO_Header.Reserved_zero != 0
00531     || ICO_Header.icType != IC_TYPE
00532     || ICO_Header.icImageCount == 0) {
00533         fclose(Image);
00534         return(not_ico_format);
00535     }
00536 
00537     // Read ONLY the first of n possible directory entries.
00538     fread(&ICO_DirEntry, 1, sizeof(ICO_DirEntry), Image);
00539     HexDump("ICO_DirEntry", (uint8_t *)&ICO_DirEntry, sizeof(ICO_DirEntry));
00540     INFO("biBitCount %04X", ICO_DirEntry.biBitCount);
00541     if (ICO_DirEntry.biBitCount != 0) {     // Expecting this to be zero for ico
00542         fclose(Image);
00543         return(not_supported_format);
00544     }
00545 
00546     RetCode_t rt = _RenderBitmap(x, y, ICO_DirEntry.bfOffBits, Image);
00547     if (rt == noerror) {
00548         fclose(Image);
00549         return (noerror);
00550     } else {
00551         return rt;
00552     }
00553 }
00554 
00555 int GraphicsDisplay::columns()
00556 {
00557     return width() / 8;
00558 }
00559 
00560 int GraphicsDisplay::rows()
00561 {
00562     return height() / 8;
00563 }