Fork of David Smart's RA8875 library for the purpose of adding touch screen support
Fork of RA8875 by
Diff: GraphicsDisplay.cpp
- Revision:
- 31:c72e12cd5c67
- Parent:
- 29:422616aa04bd
- Child:
- 32:0e4f2ae512e2
--- a/GraphicsDisplay.cpp Sun Jan 19 04:42:25 2014 +0000 +++ b/GraphicsDisplay.cpp Mon Jan 20 19:19:48 2014 +0000 @@ -4,6 +4,7 @@ */ #include "GraphicsDisplay.h" +#include "Bitmap.h" #define DEBUG "GD" // ... @@ -13,10 +14,31 @@ #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +void HexDump(char * title, uint8_t * p, int count) +{ + int i; + char buf[100] = "0000: "; + + if (*title) + INFO("%s", title); + for (i=0; i<count; ) { + sprintf(buf + strlen(buf), "%02X ", *(p+i)); + if ((++i & 0x0F) == 0x00) { + INFO("%s", buf); + if (i < count) + sprintf(buf, "%04X: ", i); + else + buf[0] = '\0'; + } + } + if (strlen(buf)) + INFO("%s", buf); +} #else #define INFO(x, ...) #define WARN(x, ...) #define ERR(x, ...) +#define HexDump(a, b) #endif // #define LOCALFONT @@ -174,7 +196,12 @@ _y2 = y + h - 1; } -void GraphicsDisplay::putp(int colour) +void GraphicsDisplay::WindowMax(void) +{ + window(0,0, width(),height()); +} + +void GraphicsDisplay::putp(color_t colour) { // put pixel at current pixel location pixel(_x, _y, colour); @@ -189,7 +216,7 @@ } } -void GraphicsDisplay::fill(int x, int y, int w, int h, int colour) +void GraphicsDisplay::fill(int x, int y, int w, int h, color_t colour) { window(x, y, w, h); for(int i=0; i<w*h; i++) { @@ -206,7 +233,7 @@ void GraphicsDisplay::blit(int x, int y, int w, int h, const int * colour) { window(x, y, w, h); - for(int i=0; i<w*h; i++) { + for (int i=0; i<w*h; i++) { putp(colour[i]); } } @@ -227,7 +254,6 @@ INFO(" %2d = %02X", i>>3, byte); int c = ((byte << offset) & 0x80) ? _foreground : _background; putp(c); - //wait_ms(100); } return w; } @@ -256,8 +282,155 @@ return charWidth; } +// BMP Color Palette is BGRx +// BBBB BBBB GGGG GGGG RRRR RRRR 0000 0000 +// RGB16 is +// RRRR RGGG GGGB BBBB +// swap to little endian +// GGGB BBBB RRRR RGGG +color_t RGBQuadToRGB16(RGBQUAD * colorPalette, uint16_t i) +{ + color_t c; + + c = ((colorPalette[i].rgbBlue >> 3) << 0); + c |= ((colorPalette[i].rgbGreen >> 2) << 5); + c |= ((colorPalette[i].rgbRed >> 3) << 11); + c = (c >> 8) | (c << 8); + //INFO("B %02X G %02X R %02X c %04X", colorPalette[i].rgbBlue, colorPalette[i].rgbGreen, + // colorPalette[i].rgbRed, c); + return c; +} +RetCode_t GraphicsDisplay::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP) +{ + #define OffsetPixelWidth 18 + #define OffsetPixelHeight 22 + #define OffsetFileSize 34 + #define OffsetPixData 10 + #define OffsetBPP 28 + + char filename[50]; + BITMAPFILEHEADER BMP_Header; + BITMAPINFOHEADER BMP_Info; + RGBQUAD * colorPalette = NULL; + int colorCount; + char * lineBuffer = NULL; + + uint16_t BPP_t; + uint32_t PixelWidth, PixelHeight; + uint32_t start_data; + unsigned int i, offset; + int padd,j; + + // get the filename + LocalFileSystem local("local"); + sprintf(filename,"/local/%s", Name_BMP); + INFO("Opening {%s}", filename); + FILE *Image = fopen(filename, "rb"); // open the bmp file + if (!Image) { + return(file_not_found); + } + + fread(&BMP_Header, 1, sizeof(BMP_Header), Image); // get the BMP Header + INFO("bfType %04X", BMP_Header.bfType); + //HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header)); + if (BMP_Header.bfType != BF_TYPE) { // BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) { // check magic byte + fclose(Image); + return(not_bmp_format); // error no BMP file + } + + fread(&BMP_Info, 1, sizeof(BMP_Info), Image); + //HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info)); + BPP_t = BMP_Info.biBitCount; + INFO("biBitCount %04X", BPP_t); + if (BPP_t != 4 && BPP_t != 8 && BPP_t != 16) { // Support 4, 8, 16-bits per pixel + fclose(Image); + return(not_supported_format); + } + + //PixelHeight = BMP_Header[OffsetPixelHeight] + (BMP_Header[OffsetPixelHeight + 1] << 8) + (BMP_Header[OffsetPixelHeight + 2] << 16) + (BMP_Header[OffsetPixelHeight + 3] << 24); + //PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24); + PixelHeight = BMP_Info.biHeight; + PixelWidth = BMP_Info.biWidth; + if (PixelHeight > height() + y || PixelWidth > width() + x) { + fclose(Image); + return(image_too_big); + } + INFO("(%d,%d) (%d,%d)", x,y, PixelWidth,PixelHeight); + + if (BMP_Info.biBitCount <= 8) { + int paletteSize; + // Read the color palette + colorCount = 1 << BMP_Info.biBitCount; + paletteSize = sizeof(RGBQUAD) * colorCount; + //INFO("colors: %d, paletteSize: %d", colorCount, paletteSize); + colorPalette = (RGBQUAD *)malloc(paletteSize); + if (colorPalette == NULL) { + fclose(Image); + return(not_enough_ram); + } + fread(colorPalette, 1, paletteSize, Image); + HexDump("Color Palette", (uint8_t *)colorPalette, paletteSize); + } else { + ERR("Bits per pixel > 8 [%d]", BMP_Info.biBitCount); + } + + //start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24); + start_data = BMP_Header.bfOffBits; + + //HexDump("Raw Data", (uint8_t *)&start_data, 32); + int lineBufSize = ((BPP_t * PixelWidth + 31)/32)*4; + //INFO("lineBufSize = %d", lineBufSize); + lineBuffer = (char *)malloc(lineBufSize); + if (lineBuffer == NULL) { + free(colorPalette); + fclose(Image); + return(not_enough_ram); + } + + // the bmp lines are padded to multiple of 4 bytes + padd = -1; + do { + padd++; + } while ((PixelWidth * sizeof(color_t) + padd) % 4 != 0); + + // Define window for top to bottom and left to right + window(x,y, PixelWidth,PixelHeight); + //INFO("(%d,%d) (%d,%d)", x,y, PixelWidth,PixelHeight); + for (j = PixelHeight - 1; j >= 0; j--) { //Lines bottom up + //INFO("line %d", j); + offset = start_data + j * (lineBufSize + padd); // start of line + fseek(Image, offset, SEEK_SET); + fread(lineBuffer, 1, lineBufSize, Image); // read a line - slow ! + //HexDump("Line", (uint8_t *)lineBuffer, lineBufSize); + for (i = 0; i < PixelWidth; i++) { // copy pixel data to TFT + if (BPP_t == 4) { + uint8_t dPix = lineBuffer[i/2]; + if ((i & 1) == 0) + dPix >>= 4; + dPix &= 0x0F; + color_t color; + color = RGBQuadToRGB16(colorPalette, dPix); + putp(color); + } else if (BPP_t == 8) { + color_t color; + color = RGBQuadToRGB16(colorPalette, lineBuffer[i]); + putp(color); + } else if (BPP_t == 16) { + putp(lineBuffer[i] & 0xFF); + putp(lineBuffer[i] >> 8); + } + } + } + free(lineBuffer); + free(colorPalette); + fclose(Image); + //INFO("Freed and closed"); + WindowMax(); + return(noerror); +} + int GraphicsDisplay::columns() { return width() / 8;