KSM edits to RA8875

Dependents:   Liz_Test_Code

Revision:
163:17526689a3ed
Parent:
162:a2d7f1988711
Child:
164:76edd7d9cb68
--- a/RA8875.cpp	Mon Feb 11 03:44:42 2019 +0000
+++ b/RA8875.cpp	Wed Feb 13 04:20:12 2019 +0000
@@ -101,6 +101,75 @@
     "external abort",         ///< during an idle callback, the user code initiated an abort
 };
 
+typedef struct {
+    uint8_t b;
+    uint8_t g;
+    uint8_t r;
+    uint8_t a;
+} rgbTrio_t;
+
+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},
+    {0x00,0x66,0x00,0xFF}, {0x00,0x66,0x33,0xFF}, {0x00,0x66,0x66,0xFF}, {0x00,0x66,0x99,0xFF}, {0x00,0x66,0xCC,0xFF}, {0x00,0x66,0xFF,0xFF},
+    {0x00,0x99,0x00,0xFF}, {0x00,0x99,0x33,0xFF}, {0x00,0x99,0x66,0xFF}, {0x00,0x99,0x99,0xFF}, {0x00,0x99,0xCC,0xFF}, {0x00,0x99,0xFF,0xFF},
+    {0x00,0xCC,0x00,0xFF}, {0x00,0xCC,0x33,0xFF}, {0x00,0xCC,0x66,0xFF}, {0x00,0xCC,0x99,0xFF}, {0x00,0xCC,0xCC,0xFF}, {0x00,0xCC,0xFF,0xFF},
+    {0x00,0xFF,0x00,0xFF}, {0x00,0xFF,0x33,0xFF}, {0x00,0xFF,0x66,0xFF}, {0x00,0xFF,0x99,0xFF}, {0x00,0xFF,0xCC,0xFF}, {0x00,0xFF,0xFF,0xFF},
+    {0x33,0x00,0x00,0xFF}, {0x33,0x00,0x33,0xFF}, {0x33,0x00,0x66,0xFF}, {0x33,0x00,0x99,0xFF}, {0x33,0x00,0xCC,0xFF}, {0x33,0x00,0xFF,0xFF},
+    {0x33,0x33,0x00,0xFF}, {0x33,0x33,0x33,0xFF}, {0x33,0x33,0x66,0xFF}, {0x33,0x33,0x99,0xFF}, {0x33,0x33,0xCC,0xFF}, {0x33,0x33,0xFF,0xFF},
+    {0x33,0x66,0x00,0xFF}, {0x33,0x66,0x33,0xFF}, {0x33,0x66,0x66,0xFF}, {0x33,0x66,0x99,0xFF}, {0x33,0x66,0xCC,0xFF}, {0x33,0x66,0xFF,0xFF},
+    {0x33,0x99,0x00,0xFF}, {0x33,0x99,0x33,0xFF}, {0x33,0x99,0x66,0xFF}, {0x33,0x99,0x99,0xFF}, {0x33,0x99,0xCC,0xFF}, {0x33,0x99,0xFF,0xFF},
+    {0x33,0xCC,0x00,0xFF}, {0x33,0xCC,0x33,0xFF}, {0x33,0xCC,0x66,0xFF}, {0x33,0xCC,0x99,0xFF}, {0x33,0xCC,0xCC,0xFF}, {0x33,0xCC,0xFF,0xFF},
+    {0x33,0xFF,0x00,0xFF}, {0x33,0xFF,0x33,0xFF}, {0x33,0xFF,0x66,0xFF}, {0x33,0xFF,0x99,0xFF}, {0x33,0xFF,0xCC,0xFF}, {0x33,0xFF,0xFF,0xFF},
+    {0x66,0x00,0x00,0xFF}, {0x66,0x00,0x33,0xFF}, {0x66,0x00,0x66,0xFF}, {0x66,0x00,0x99,0xFF}, {0x66,0x00,0xCC,0xFF}, {0x66,0x00,0xFF,0xFF},
+    {0x66,0x33,0x00,0xFF}, {0x66,0x33,0x33,0xFF}, {0x66,0x33,0x66,0xFF}, {0x66,0x33,0x99,0xFF}, {0x66,0x33,0xCC,0xFF}, {0x66,0x33,0xFF,0xFF},
+    {0x66,0x66,0x00,0xFF}, {0x66,0x66,0x33,0xFF}, {0x66,0x66,0x66,0xFF}, {0x66,0x66,0x99,0xFF}, {0x66,0x66,0xCC,0xFF}, {0x66,0x66,0xFF,0xFF},
+    {0x66,0x99,0x00,0xFF}, {0x66,0x99,0x33,0xFF}, {0x66,0x99,0x66,0xFF}, {0x66,0x99,0x99,0xFF}, {0x66,0x99,0xCC,0xFF}, {0x66,0x99,0xFF,0xFF},
+    {0x66,0xCC,0x00,0xFF}, {0x66,0xCC,0x33,0xFF}, {0x66,0xCC,0x66,0xFF}, {0x66,0xCC,0x99,0xFF}, {0x66,0xCC,0xCC,0xFF}, {0x66,0xCC,0xFF,0xFF},
+    {0x66,0xFF,0x00,0xFF}, {0x66,0xFF,0x33,0xFF}, {0x66,0xFF,0x66,0xFF}, {0x66,0xFF,0x99,0xFF}, {0x66,0xFF,0xCC,0xFF}, {0x66,0xFF,0xFF,0xFF},
+    {0x99,0x00,0x00,0xFF}, {0x99,0x00,0x33,0xFF}, {0x99,0x00,0x66,0xFF}, {0x99,0x00,0x99,0xFF}, {0x99,0x00,0xCC,0xFF}, {0x99,0x00,0xFF,0xFF},
+    {0x99,0x33,0x00,0xFF}, {0x99,0x33,0x33,0xFF}, {0x99,0x33,0x66,0xFF}, {0x99,0x33,0x99,0xFF}, {0x99,0x33,0xCC,0xFF}, {0x99,0x33,0xFF,0xFF},
+    {0x99,0x66,0x00,0xFF}, {0x99,0x66,0x33,0xFF}, {0x99,0x66,0x66,0xFF}, {0x99,0x66,0x99,0xFF}, {0x99,0x66,0xCC,0xFF}, {0x99,0x66,0xFF,0xFF},
+    {0x99,0x99,0x00,0xFF}, {0x99,0x99,0x33,0xFF}, {0x99,0x99,0x66,0xFF}, {0x99,0x99,0x99,0xFF}, {0x99,0x99,0xCC,0xFF}, {0x99,0x99,0xFF,0xFF},
+    {0x99,0xCC,0x00,0xFF}, {0x99,0xCC,0x33,0xFF}, {0x99,0xCC,0x66,0xFF}, {0x99,0xCC,0x99,0xFF}, {0x99,0xCC,0xCC,0xFF}, {0x99,0xCC,0xFF,0xFF},
+    {0x99,0xFF,0x00,0xFF}, {0x99,0xFF,0x33,0xFF}, {0x99,0xFF,0x66,0xFF}, {0x99,0xFF,0x99,0xFF}, {0x99,0xFF,0xCC,0xFF}, {0x99,0xFF,0xFF,0xFF},
+    {0xCC,0x00,0x00,0xFF}, {0xCC,0x00,0x33,0xFF}, {0xCC,0x00,0x66,0xFF}, {0xCC,0x00,0x99,0xFF}, {0xCC,0x00,0xCC,0xFF}, {0xCC,0x00,0xFF,0xFF},
+    {0xCC,0x33,0x00,0xFF}, {0xCC,0x33,0x33,0xFF}, {0xCC,0x33,0x66,0xFF}, {0xCC,0x33,0x99,0xFF}, {0xCC,0x33,0xCC,0xFF}, {0xCC,0x33,0xFF,0xFF},
+    {0xCC,0x66,0x00,0xFF}, {0xCC,0x66,0x33,0xFF}, {0xCC,0x66,0x66,0xFF}, {0xCC,0x66,0x99,0xFF}, {0xCC,0x66,0xCC,0xFF}, {0xCC,0x66,0xFF,0xFF},
+    {0xCC,0x99,0x00,0xFF}, {0xCC,0x99,0x33,0xFF}, {0xCC,0x99,0x66,0xFF}, {0xCC,0x99,0x99,0xFF}, {0xCC,0x99,0xCC,0xFF}, {0xCC,0x99,0xFF,0xFF},
+    {0xCC,0xCC,0x00,0xFF}, {0xCC,0xCC,0x33,0xFF}, {0xCC,0xCC,0x66,0xFF}, {0xCC,0xCC,0x99,0xFF}, {0xCC,0xCC,0xCC,0xFF}, {0xCC,0xCC,0xFF,0xFF},
+    {0xCC,0xFF,0x00,0xFF}, {0xCC,0xFF,0x33,0xFF}, {0xCC,0xFF,0x66,0xFF}, {0xCC,0xFF,0x99,0xFF}, {0xCC,0xFF,0xCC,0xFF}, {0xCC,0xFF,0xFF,0xFF},
+    {0xFF,0x00,0x00,0xFF}, {0xFF,0x00,0x33,0xFF}, {0xFF,0x00,0x66,0xFF}, {0xFF,0x00,0x99,0xFF}, {0xFF,0x00,0xCC,0xFF}, {0xFF,0x00,0xFF,0xFF},
+    {0xFF,0x33,0x00,0xFF}, {0xFF,0x33,0x33,0xFF}, {0xFF,0x33,0x66,0xFF}, {0xFF,0x33,0x99,0xFF}, {0xFF,0x33,0xCC,0xFF}, {0xFF,0x33,0xFF,0xFF},
+    {0xFF,0x66,0x00,0xFF}, {0xFF,0x66,0x33,0xFF}, {0xFF,0x66,0x66,0xFF}, {0xFF,0x66,0x99,0xFF}, {0xFF,0x66,0xCC,0xFF}, {0xFF,0x66,0xFF,0xFF},
+    {0xFF,0x99,0x00,0xFF}, {0xFF,0x99,0x33,0xFF}, {0xFF,0x99,0x66,0xFF}, {0xFF,0x99,0x99,0xFF}, {0xFF,0x99,0xCC,0xFF}, {0xFF,0x99,0xFF,0xFF},
+    {0xFF,0xCC,0x00,0xFF}, {0xFF,0xCC,0x33,0xFF}, {0xFF,0xCC,0x66,0xFF}, {0xFF,0xCC,0x99,0xFF}, {0xFF,0xCC,0xCC,0xFF}, {0xFF,0xCC,0xFF,0xFF},
+    {0xFF,0xFF,0x00,0xFF}, {0xFF,0xFF,0x33,0xFF}, {0xFF,0xFF,0x66,0xFF}, {0xFF,0xFF,0x99,0xFF}, {0xFF,0xFF,0xCC,0xFF}, {0xFF,0xFF,0xFF,0xFF},
+
+    {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, 
+    {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, 
+    {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, 
+    {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, 
+    {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, 
+    {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, 
+    {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, {0x00,0x00,0x00,0xFF}, 
+};
+
+#define sqr(a) (double)((a) * (a))
+
+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));
+    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));
+        if (thisDiff < bestDiff) {
+            bestDiff = thisDiff;
+            bestNdx = i;
+        }
+    }
+    return bestNdx;
+}
+
 RA8875::RA8875(PinName mosi, PinName miso, PinName sclk, PinName csel, PinName reset, 
     const char *name)
     : GraphicsDisplay(name)
@@ -2241,7 +2310,8 @@
     }
 }
 
-RetCode_t RA8875::PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP)
+
+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;
     BITMAPINFOHEADER BMP_Info;
@@ -2249,33 +2319,49 @@
     color_t * pixelBuffer = NULL;
     color_t * pixelBuffer2 = NULL;
     
-    INFO("(%d,%d) - (%d,%d) %s", x,y,w,h,Name_BMP);
+    INFO("(%d,%d)-(%d,%d)x%d %s", x,y,w,h,bitsPerPixel,Name_BMP);
     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);
@@ -2329,7 +2415,16 @@
 
         HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info));
         fwrite(&BMP_Info, sizeof(char), sizeof(BMP_Info), Image);
-
+        
+        if (bitsPerPixel != 24) {
+            HexDump("Palette", (uint8_t *)&WebColorPalette, sizeof(WebColorPalette));
+            fwrite(&WebColorPalette, sizeof(char), sizeof(WebColorPalette), Image);
+            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);
+            }
+        }
         //color_t transparency = GetBackgroundTransparencyColor();
         LayerMode_T ltpr0 = GetLayerMode();
 
@@ -2366,7 +2461,7 @@
                 }
             }
             INFO("Line: %3d", j);
-            HexDump("Raster", (uint8_t *)pixelBuffer, w * sizeof(color_t));
+            //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++) {
@@ -2382,25 +2477,36 @@
                     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("Line", lineBuffer, lineBufSize);
+            //    HexDump("Line", lineBuffer, lineBufSize);
             //}
             // Write to disk
             fwrite(lineBuffer, sizeof(char), lineBufSize, Image);