This is the David Smart RA8875 Library with mods for working with FRDM-K64F
Diff: RA8875.cpp
- Revision:
- 164:76edd7d9cb68
- Parent:
- 163:17526689a3ed
- Child:
- 165:695c24cc5197
diff -r 17526689a3ed -r 76edd7d9cb68 RA8875.cpp --- a/RA8875.cpp Wed Feb 13 04:20:12 2019 +0000 +++ b/RA8875.cpp Thu Feb 14 12:34:52 2019 +0000 @@ -108,6 +108,11 @@ uint8_t a; } rgbTrio_t; +/// This is defined as a "Web-Safe" color palette of 216 colors. +/// +/// It is defined so it can be emitted into a BMP file as the color palette, and it is then used +/// for downscaling from higher resolution color depth to an 8-bit format. +/// static const rgbTrio_t WebColorPalette[] = { {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x33,0xFF}, {0x00,0x00,0x66,0xFF}, {0x00,0x00,0x99,0xFF}, {0x00,0x00,0xCC,0xFF}, {0x00,0x00,0xFF,0xFF}, {0x00,0x33,0x00,0xFF}, {0x00,0x33,0x33,0xFF}, {0x00,0x33,0x66,0xFF}, {0x00,0x33,0x99,0xFF}, {0x00,0x33,0xCC,0xFF}, {0x00,0x33,0xFF,0xFF}, @@ -155,13 +160,21 @@ {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, }; -#define sqr(a) (double)((a) * (a)) - +#define sqr(a) ((a) * (a)) + +/// Find the nearest color match in the lookup table. +/// +/// The typical process is to find the difference between a given color and each entry in +/// the table. The difference is defined as: +/// diff = sqrt(sqr(r - table[i].r) + sqr(g - table[i].g) + sqr(b - table[i].b)) +/// The square root function is very CPU intensive, especially w/o a floating point unit, +/// so that step is omitted to speed it up a bit. +/// static int FindNearestWebColor(uint8_t r, uint8_t g, uint8_t b) { int bestNdx = 0; - float bestDiff = sqrt(sqr(r - WebColorPalette[0].r) + sqr(g - WebColorPalette[0].g) + sqr(b - WebColorPalette[0].b)); + float bestDiff = (sqr(r - WebColorPalette[0].r) + sqr(g - WebColorPalette[0].g) + sqr(b - WebColorPalette[0].b)); for (int i=1; i<216; i++) { - float thisDiff = sqrt(sqr(r - WebColorPalette[i].r) + sqr(g - WebColorPalette[i].g) + sqr(b - WebColorPalette[i].b)); + float thisDiff = (sqr(r - WebColorPalette[i].r) + sqr(g - WebColorPalette[i].g) + sqr(b - WebColorPalette[i].b)); if (thisDiff < bestDiff) { bestDiff = thisDiff; bestNdx = i; @@ -2137,7 +2150,7 @@ return ((value + roundTo - 1) / roundTo) * roundTo; } -RetCode_t RA8875::PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h) +RetCode_t RA8875::PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h, uint8_t bitsPerPixel) { BITMAPFILEHEADER BMP_Header; BITMAPINFOHEADER BMP_Info; @@ -2145,33 +2158,49 @@ color_t * pixelBuffer = NULL; color_t * pixelBuffer2 = NULL; - INFO("(%d,%d) - (%d,%d)", x,y,w,h); + INFO("(%d,%d)-(%d,%d)x%d", x,y,w,h,bitsPerPixel); if (x >= 0 && x < screenwidth && y >= 0 && y < screenheight && w > 0 && x + w <= screenwidth && h > 0 && y + h <= screenheight) { - BMP_Header.bfType = BF_TYPE; - BMP_Header.bfSize = (w * h * sizeof(RGBQUAD)) + sizeof(BMP_Header) + sizeof(BMP_Info); BMP_Header.bfReserved1 = 0; BMP_Header.bfReserved2 = 0; - BMP_Header.bfOffBits = sizeof(BMP_Header) + sizeof(BMP_Info); + switch (bitsPerPixel) { + case 24: + BMP_Header.bfOffBits = sizeof(BMP_Header) + sizeof(BMP_Info); + BMP_Header.bfSize = (h * RoundUp(w * sizeof(RGBQUAD),4)) + BMP_Header.bfOffBits; + break; + case 8: + default: + BMP_Header.bfOffBits = sizeof(BMP_Header) + sizeof(BMP_Info) + sizeof(WebColorPalette); + INFO("Initial Offset to Bitstream %X", BMP_Header.bfOffBits); + //if (BMP_Header.bfOffBits & 0x03) { + // BMP_Header.bfOffBits += (4 - (BMP_Header.bfOffBits & 0x03)); + //} + BMP_Header.bfSize = (h * RoundUp(w * 1,4)) + BMP_Header.bfOffBits; + break; + } + INFO("Offset to Bitstream %X", BMP_Header.bfOffBits); // Bytes in the line buffer - int lineBufSize = RoundUp(3 * w, 4); // ((24 * w + 7)/8); + int lineBufSize = RoundUp(((bitsPerPixel == 24) ? 3 : 1) * w, 4); INFO("LineBufSize: %d", lineBufSize); BMP_Info.biSize = sizeof(BMP_Info); BMP_Info.biWidth = w; BMP_Info.biHeight = h; BMP_Info.biPlanes = 1; - BMP_Info.biBitCount = 24; + BMP_Info.biBitCount = bitsPerPixel; BMP_Info.biCompression = BI_RGB; BMP_Info.biSizeImage = lineBufSize * h; BMP_Info.biXPelsPerMeter = 0; BMP_Info.biYPelsPerMeter = 0; - BMP_Info.biClrUsed = 0; - BMP_Info.biClrImportant = 0; + // for 24-bit, there is no palette, so these are zero + // for 8-bit, there can be up to 256 RGB values in the palette + + BMP_Info.biClrUsed = (bitsPerPixel == 24) ? 0 : sizeof(WebColorPalette)/sizeof(WebColorPalette[0]); // for 8b/pixel + BMP_Info.biClrImportant = BMP_Info.biClrUsed; // Allocate the memory we need to proceed lineBuffer = (uint8_t *)swMalloc(lineBufSize); @@ -2207,6 +2236,7 @@ } // Get the file primed... + /// @todo check return value for possibility of a fatal error privateCallback(OPEN, (uint8_t *)&BMP_Header.bfSize, 4); // Be optimistic - don't check for errors. @@ -2217,7 +2247,16 @@ HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info)); //fwrite(&BMP_Info, sizeof(char), sizeof(BMP_Info), Image); privateCallback(WRITE, (uint8_t *)&BMP_Info, sizeof(BMP_Info)); - + if (bitsPerPixel != 24) { + HexDump("Palette", (uint8_t *)&WebColorPalette, sizeof(WebColorPalette)); + //fwrite(&WebColorPalette, sizeof(char), sizeof(WebColorPalette), Image); + privateCallback(WRITE, (uint8_t *)&WebColorPalette, sizeof(WebColorPalette)); + if (0 && sizeof(WebColorPalette) % 4) { + const uint8_t padd[] = { 0, 0, 0 }; + //fwrite(&padd, sizeof(char), (sizeof(BMP_Header) + sizeof(BMP_Info) + sizeof(WebColorPalette)) % 4, Image); + privateCallback(WRITE, (uint8_t *)&padd, (sizeof(BMP_Header) + sizeof(BMP_Info) + sizeof(WebColorPalette)) % 4); + } + } //color_t transparency = GetBackgroundTransparencyColor(); LayerMode_T ltpr0 = GetLayerMode(); @@ -2253,8 +2292,8 @@ ERR("getPixelStream error, and no recovery handler..."); } } - INFO("1st Color: %04X", pixelBuffer[0]); - HexDump("Raster", (uint8_t *)pixelBuffer, w * 3); + INFO("Line: %3d", j); + //HexDump("Raster", (uint8_t *)pixelBuffer, w * sizeof(color_t)); // Convert the local buffer to RGBQUAD format int lb = 0; for (int i=0; i<w; i++) { @@ -2270,32 +2309,42 @@ case 2: // lighten-overlay (@TODO Not supported yet) case 6: // Floating Windows (@TODO not sure how to support) default: // Reserved... + //lineBuffer[lb++] = q0.rgbBlue; + //lineBuffer[lb++] = q0.rgbGreen; + //lineBuffer[lb++] = q0.rgbRed; + break; + case 3: // transparent mode (@TODO Read the background color register for transparent) + case 4: // boolean or + q0.rgbBlue = q0.rgbBlue | q1.rgbBlue; + q0.rgbGreen = q0.rgbGreen | q1.rgbGreen; + q0.rgbRed = q0.rgbRed | q1.rgbRed; + break; + case 5: // boolean AND + q0.rgbBlue = q0.rgbBlue & q1.rgbBlue; + q0.rgbGreen = q0.rgbGreen & q1.rgbGreen; + q0.rgbRed = q0.rgbRed & q1.rgbRed; + break; + } + switch (bitsPerPixel) { + case 24: lineBuffer[lb++] = q0.rgbBlue; lineBuffer[lb++] = q0.rgbGreen; lineBuffer[lb++] = q0.rgbRed; break; - case 3: // transparent mode (@TODO Read the background color register for transparent) - case 4: // boolean or - lineBuffer[lb++] = q0.rgbBlue | q1.rgbBlue; - lineBuffer[lb++] = q0.rgbGreen | q1.rgbGreen; - lineBuffer[lb++] = q0.rgbRed | q1.rgbRed; - break; - case 5: // boolean AND - lineBuffer[lb++] = q0.rgbBlue & q1.rgbBlue; - lineBuffer[lb++] = q0.rgbGreen & q1.rgbGreen; - lineBuffer[lb++] = q0.rgbRed & q1.rgbRed; + case 8: + default: + lineBuffer[lb++] = FindNearestWebColor(q0.rgbRed,q0.rgbGreen,q0.rgbBlue); break; } } - if (j == h - 1) { - HexDump("LineBuffer", lineBuffer, lineBufSize); - } + //if (j == h - 1) { + // HexDump("Line", lineBuffer, lineBufSize); + //} // Write to disk privateCallback(WRITE, (uint8_t *)lineBuffer, lineBufSize); } SelectDrawingLayer(prevLayer); privateCallback(CLOSE, NULL, 0); - #ifndef DOUBLEBUF if (pixelBuffer2) swFree(pixelBuffer2); @@ -2311,6 +2360,7 @@ } + RetCode_t RA8875::PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP, uint8_t bitsPerPixel) { BITMAPFILEHEADER BMP_Header;