Scaling an interpolation routine

Sorry, I can’t guess how those error messages relate to your program, although the failure seems to pop up while doing I/O. Why have you not posted ALL the code?

At what point will math calculated rgb’s outperform a LUT?

Never, in terms of execution time. Lookup is always faster, but the table takes up memory.

Why am I only seeing 10-15 different colors at any one time?

I have no idea what you are “seeing”.

Can you please explain your modified version of the Adafuit example more thoroughly?

Instead of storing the interpolated value in an array, I output it directly to the display. I don’t know how I could make that more clear. Here is the entirety of the modified version of set_point():

void set_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y, float f) {
//    p[y * cols + x] = f;  //was, for output array

// send blocks of points to display (global boxsize)
  int colorTemp;
  uint8_t colorIndex, x1, y1, x2, y2;
  if ((x < 0) || (x >= cols)) return;
  if ((y < 0) || (y >= rows)) return;
  
  x1=x*boxsize;
  x2=x1+boxsize-1;
  y1=y*boxsize;
  y2=y1+boxsize-1;

  if(f >= MAXTEMP) colorTemp = MAXTEMP;
      else if(f <= MINTEMP) colorTemp = MINTEMP;
      else colorTemp = f;
      
      colorIndex = map(colorTemp, MINTEMP, MAXTEMP, 0, 255);
      colorIndex = constrain(colorIndex, 0, 255);
      colorTemp=camColors[colorIndex];
      OLED_DrawRectangle(x1, y1, x2, y2, colorTemp);
}

It seems you have moved some functions from interpolation.cpp to the main .ino file.

Don’t confuse the Arduino .ino main code (posted as the first entry in Reply #11) with the independent Code::Blocks test program, which runs on a PC (posted as the second entry in Reply #11).

For the Arduino program, I renamed interpolation.cpp to interp.h and used #include “interp.h” to bring it into the .ino file.

Ok, I will take another look, I think i was getting the examples mixed up.

I have opened a new topic in programming questions regarding the crash, as it seems to be more related to my hardware and program, rather than the interpolation itsself, and I dont want to veer to far off topic here.
I hope this was the correct thing to do.

I have posted a copy of my code in the new topic here

I dont understand how this is supposed to work, everything is defined in the .ino, so when i replace set_point() in interpolation.cpp i get a buch of errors because nothing is defined (for example; boxsize, maxtemp, mintemp, and so on)

I already mentioned this before testing and you just kind of brushed it off. There are also extra lines in my copy of interpolation.cpp that arent there in your sample.
Is it possible this code of your is based off of an older version of the adafruit example?

So, now I have moved set_point() to the main program (.ino) and code will compile and run, even with rows and columns more than 41.

But… i just get a purple box on my screen. It looks like maybe the picture is huge and I am only seeing one corner of it?

Here is my code:

#include "Test_GSLC.h"
#include <Adafruit_AMG88xx.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <inttypes.h>


#define MINTEMP 25
#define MAXTEMP 35

//the colors we will be using
const uint16_t camColors[] = {0x480F,
0x400F,0x400F,0x400F,0x4010,0x3810,0x3810,0x3810,0x3810,0x3010,0x3010,
0x3010,0x2810,0x2810,0x2810,0x2810,0x2010,0x2010,0x2010,0x1810,0x1810,
0x1811,0x1811,0x1011,0x1011,0x1011,0x0811,0x0811,0x0811,0x0011,0x0011,
0x0011,0x0011,0x0011,0x0031,0x0031,0x0051,0x0072,0x0072,0x0092,0x00B2,
0x00B2,0x00D2,0x00F2,0x00F2,0x0112,0x0132,0x0152,0x0152,0x0172,0x0192,
0x0192,0x01B2,0x01D2,0x01F3,0x01F3,0x0213,0x0233,0x0253,0x0253,0x0273,
0x0293,0x02B3,0x02D3,0x02D3,0x02F3,0x0313,0x0333,0x0333,0x0353,0x0373,
0x0394,0x03B4,0x03D4,0x03D4,0x03F4,0x0414,0x0434,0x0454,0x0474,0x0474,
0x0494,0x04B4,0x04D4,0x04F4,0x0514,0x0534,0x0534,0x0554,0x0554,0x0574,
0x0574,0x0573,0x0573,0x0573,0x0572,0x0572,0x0572,0x0571,0x0591,0x0591,
0x0590,0x0590,0x058F,0x058F,0x058F,0x058E,0x05AE,0x05AE,0x05AD,0x05AD,
0x05AD,0x05AC,0x05AC,0x05AB,0x05CB,0x05CB,0x05CA,0x05CA,0x05CA,0x05C9,
0x05C9,0x05C8,0x05E8,0x05E8,0x05E7,0x05E7,0x05E6,0x05E6,0x05E6,0x05E5,
0x05E5,0x0604,0x0604,0x0604,0x0603,0x0603,0x0602,0x0602,0x0601,0x0621,
0x0621,0x0620,0x0620,0x0620,0x0620,0x0E20,0x0E20,0x0E40,0x1640,0x1640,
0x1E40,0x1E40,0x2640,0x2640,0x2E40,0x2E60,0x3660,0x3660,0x3E60,0x3E60,
0x3E60,0x4660,0x4660,0x4E60,0x4E80,0x5680,0x5680,0x5E80,0x5E80,0x6680,
0x6680,0x6E80,0x6EA0,0x76A0,0x76A0,0x7EA0,0x7EA0,0x86A0,0x86A0,0x8EA0,
0x8EC0,0x96C0,0x96C0,0x9EC0,0x9EC0,0xA6C0,0xAEC0,0xAEC0,0xB6E0,0xB6E0,
0xBEE0,0xBEE0,0xC6E0,0xC6E0,0xCEE0,0xCEE0,0xD6E0,0xD700,0xDF00,0xDEE0,
0xDEC0,0xDEA0,0xDE80,0xDE80,0xE660,0xE640,0xE620,0xE600,0xE5E0,0xE5C0,
0xE5A0,0xE580,0xE560,0xE540,0xE520,0xE500,0xE4E0,0xE4C0,0xE4A0,0xE480,
0xE460,0xEC40,0xEC20,0xEC00,0xEBE0,0xEBC0,0xEBA0,0xEB80,0xEB60,0xEB40,
0xEB20,0xEB00,0xEAE0,0xEAC0,0xEAA0,0xEA80,0xEA60,0xEA40,0xF220,0xF200,
0xF1E0,0xF1C0,0xF1A0,0xF180,0xF160,0xF140,0xF100,0xF0E0,0xF0C0,0xF0A0,
0xF080,0xF060,0xF040,0xF020,0xF800,};

Adafruit_AMG88xx amg;
unsigned long delayTime;

#define AMG_COLS 8
#define AMG_ROWS 8
#define INTERPOLATED_COLS 32
#define INTERPOLATED_ROWS 32
#define DISPLAY_COLS 240
#define DISPLAY_ROWS 180

float pixels[AMG_COLS * AMG_ROWS];
int npix = AMG88xx_PIXEL_ARRAY_SIZE;
float value;
float value2;
float r,g,b;

float x, y;
int i;
int boxsize;
float dest_2d;

float get_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
void set_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y, float f);
void get_adjacents_1d(float *src, float *dest, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
void get_adjacents_2d(float *src, float *dest, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
float cubicInterpolate(float p[], float x);
float bicubicInterpolate(float p[], float x, float y);
void interpolate_image(float *src, uint8_t src_rows, uint8_t src_cols, 
                       float *dest, uint8_t dest_rows, uint8_t dest_cols);
                       
gslc_tsElemRef* homeBtn           = NULL;
gslc_tsElemRef* thermalBtn        = NULL;
static int16_t DebugOut(char ch) { if (ch == (char)'\n') Serial.println(""); else Serial.write(ch); return 0; }
bool CbBtnCommon(void* pvGui,void *pvElemRef,gslc_teTouch eTouch,int16_t nX,int16_t nY)
{
  gslc_tsGui*     pGui     = (gslc_tsGui*)(pvGui);
  gslc_tsElemRef* pElemRef = (gslc_tsElemRef*)(pvElemRef);
  gslc_tsElem*    pElem    = gslc_GetElemFromRef(pGui,pElemRef);

  if ( eTouch == GSLC_TOUCH_UP_IN ) {
    switch (pElem->nId) {
      case TERMAL_BTN:
        gslc_SetPageCur(&m_gui, E_PG2);
        break;
      case HOME_BTN:
        gslc_SetPageCur(&m_gui, E_PG_MAIN);
        break;
      default:
        break;
    }
  }
  return true;
}
void setup()
{
  Serial.begin(9600);
  gslc_InitDebug(&DebugOut);
  InitGUIslice_gen();
  amg.begin();
  boxsize = min(3, 4);

}
void loop()
{
if (gslc_GetPageCur(&m_gui) == E_PG2){
  x=y=0.0;
  amg.readPixels(pixels);
  for (i = 1; i <= npix; i++) {
    if (y < pixels[i - 1]) y = pixels[i - 1]; //get max
    x += pixels[i - 1]; //calc average
  }
  x /= (float)npix;
  y = y - x; //subtract max (NOT USED atm)
  for (i = 1; i <= npix; i++) {
    y = pixels[i - 1] - x;
    if (y < 0.0) y = 0.0;
    if (y > MAXTEMP) y = MAXTEMP;
    pixels[i - 1] = y;
  }
  interpolate_image(&pixels[0], AMG_ROWS, AMG_COLS, &dest_2d, INTERPOLATED_ROWS, INTERPOLATED_COLS);
}
  gslc_Update(&m_gui);  
}

  void set_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y,
               float f) {
//  if ((x < 0) || (x >= cols))
  //  return;
  //if ((y < 0) || (y >= rows))
    //return;
  //p[y * cols + x] = f;
  // send blocks of points to display (global boxsize)
  int colorTemp;
  uint8_t colorIndex, x1, y1, x2, y2;
  if ((x < 0) || (x >= cols)) return;
  if ((y < 0) || (y >= rows)) return;
 
  x1=x*boxsize;
  x2=x1+boxsize-1;
  y1=y*boxsize;
  y2=y1+boxsize-1;

  if(f >= MAXTEMP) colorTemp = MAXTEMP;
      else if(f <= MINTEMP) colorTemp = MINTEMP;
      else colorTemp = f;
     
      colorIndex = map(colorTemp, MINTEMP, MAXTEMP, 0, 255);
      colorIndex = constrain(colorIndex, 0, 255);
      colorTemp=camColors[colorIndex];
      //OLED_DrawRectangle(x1, y1, x2, y2, colorTemp);  //fill must be set by pensize()

      gslc_tsRect rCamRect = {
                           x1,
                           y1,
                           x2,
                           y2};
      uint16_t     nCamColor_rgb565 = camColors[colorIndex];
      gslc_tsColor nCamCol_rgb888;
      nCamCol_rgb888.r =  (((nCamColor_rgb565  )>> 11)*255)/31  ; 
      nCamCol_rgb888.g =  (((nCamColor_rgb565 & 0x7e0) >> 5)*255)/63  ;
      nCamCol_rgb888.b =  ((nCamColor_rgb565 & 0x1F)*255)/31;
      
      gslc_DrvDrawFillRect(&m_gui, rCamRect, nCamCol_rgb888);
}

Can you spot any obvious problems?

Here is a copy of my interpolation.cpp (minus set_point() )

#include <Arduino.h>

float get_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
void set_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y,
               float f);
void get_adjacents_1d(float *src, float *dest, uint8_t rows, uint8_t cols,
                      int8_t x, int8_t y);
void get_adjacents_2d(float *src, float *dest, uint8_t rows, uint8_t cols,
                      int8_t x, int8_t y);
float cubicInterpolate(float p[], float x);
float bicubicInterpolate(float p[], float x, float y);
void interpolate_image(float *src, uint8_t src_rows, uint8_t src_cols,
                       float *dest, uint8_t dest_rows, uint8_t dest_cols);

float get_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y) {
  if (x < 0)
    x = 0;
  if (y < 0)
    y = 0;
  if (x >= cols)
    x = cols - 1;
  if (y >= rows)
    y = rows - 1;
  return p[y * cols + x];
}



// src is a grid src_rows * src_cols
// dest is a pre-allocated grid, dest_rows*dest_cols
void interpolate_image(float *src, uint8_t src_rows, uint8_t src_cols,
                       float *dest, uint8_t dest_rows, uint8_t dest_cols) {
  float mu_x = (src_cols - 1.0) / (dest_cols - 1.0);
  float mu_y = (src_rows - 1.0) / (dest_rows - 1.0);

  float adj_2d[16]; // matrix for storing adjacents

  for (uint8_t y_idx = 0; y_idx < dest_rows; y_idx++) {
    for (uint8_t x_idx = 0; x_idx < dest_cols; x_idx++) {
      float x = x_idx * mu_x;
      float y = y_idx * mu_y;
      // Serial.print("("); Serial.print(y_idx); Serial.print(", ");
      // Serial.print(x_idx); Serial.print(") = "); Serial.print("(");
      // Serial.print(y); Serial.print(", "); Serial.print(x); Serial.print(") =
      // ");
      get_adjacents_2d(src, adj_2d, src_rows, src_cols, x, y);
      /*
      Serial.print("[");
      for (uint8_t i=0; i<16; i++) {
        Serial.print(adj_2d[i]); Serial.print(", ");
      }
      Serial.println("]");
      */
      float frac_x = x - (int)x; // we only need the ~delta~ between the points
      float frac_y = y - (int)y; // we only need the ~delta~ between the points
      float out = bicubicInterpolate(adj_2d, frac_x, frac_y);
      // Serial.print("\tInterp: "); Serial.println(out);
      set_point(dest, dest_rows, dest_cols, x_idx, y_idx, out);
    }
  }
}

// p is a list of 4 points, 2 to the left, 2 to the right
float cubicInterpolate(float p[], float x) {
  float r = p[1] + (0.5 * x *
                    (p[2] - p[0] +
                     x * (2.0 * p[0] - 5.0 * p[1] + 4.0 * p[2] - p[3] +
                          x * (3.0 * (p[1] - p[2]) + p[3] - p[0]))));
  /*
    Serial.print("interpolating: [");
    Serial.print(p[0],2); Serial.print(", ");
    Serial.print(p[1],2); Serial.print(", ");
    Serial.print(p[2],2); Serial.print(", ");
    Serial.print(p[3],2); Serial.print("] w/"); Serial.print(x); Serial.print("
    = "); Serial.println(r);
  */
  return r;
}

// p is a 16-point 4x4 array of the 2 rows & columns left/right/above/below
float bicubicInterpolate(float p[], float x, float y) {
  float arr[4] = {0, 0, 0, 0};
  arr[0] = cubicInterpolate(p + 0, x);
  arr[1] = cubicInterpolate(p + 4, x);
  arr[2] = cubicInterpolate(p + 8, x);
  arr[3] = cubicInterpolate(p + 12, x);
  return cubicInterpolate(arr, y);
}

// src is rows*cols and dest is a 4-point array passed in already allocated!
void get_adjacents_1d(float *src, float *dest, uint8_t rows, uint8_t cols,
                      int8_t x, int8_t y) {
  // Serial.print("("); Serial.print(x); Serial.print(", "); Serial.print(y);
  // Serial.println(")");
  // pick two items to the left
  dest[0] = get_point(src, rows, cols, x - 1, y);
  dest[1] = get_point(src, rows, cols, x, y);
  // pick two items to the right
  dest[2] = get_point(src, rows, cols, x + 1, y);
  dest[3] = get_point(src, rows, cols, x + 2, y);
}

// src is rows*cols and dest is a 16-point array passed in already allocated!
void get_adjacents_2d(float *src, float *dest, uint8_t rows, uint8_t cols,
                      int8_t x, int8_t y) {
  // Serial.print("("); Serial.print(x); Serial.print(", "); Serial.print(y);
  // Serial.println(")");
  float arr[4];
  for (int8_t delta_y = -1; delta_y < 3; delta_y++) { // -1, 0, 1, 2
    float *row = dest + 4 * (delta_y + 1); // index into each chunk of 4
    for (int8_t delta_x = -1; delta_x < 3; delta_x++) { // -1, 0, 1, 2
      row[delta_x + 1] = get_point(src, rows, cols, x + delta_x, y + delta_y);
    }
  }
}

I hav also tried changing it to a .h file, but I get the following error message:

AppData\Local\Temp\arduino_build_859993\sketch\JremingtonTest.ino.cpp.o:(.literal._Z4loopv+0x24): undefined reference to `interpolate_image(float*, unsigned char, unsigned char, float*, unsigned char, unsigned char)'
AppData\Local\Temp\arduino_build_859993\sketch\JremingtonTest.ino.cpp.o: In function `loop()':
Documents\Arduino\JremingtonTest/JremingtonTest.ino:165: undefined reference to `interpolate_image(float*, unsigned char, unsigned char, float*, unsigned char, unsigned char)'
collect2.exe: error: ld returned 1 exit status

undefined reference to `interpolate_image (float * …

Did you forget to #include “interp.h”?

i get a buch of errors because nothing is defined (for example; boxsize, maxtemp, mintemp

All of those variables are clearly defined in the Arduino .ino file that I posted back in reply #11. Did you miss that?

Here it that .ino again. For completeness, I’ve attached the required interp.h and the OLED driver, which makes the complete running example for Arduino. The latter two files should be in the same folder as the .ino file.

Note the required lines #include “interp.h” and #include “oled160drv.h” below.

#define INPUT_COLS 8
#define INPUT_ROWS 8
#define INPUT_PIXEL_ARRAY_SIZE (INPUT_ROWS*INPUT_COLS)
#define INTERPOLATED_COLS 32
#define INTERPOLATED_ROWS 32
#define DISPLAY_COLS 128
#define DISPLAY_ROWS 128
#define MINTEMP 0.
#define MAXTEMP 10.

#include <Wire.h>
#include <Adafruit_AMG88xx.h>

Adafruit_AMG88xx amg;

float pixels[AMG88xx_PIXEL_ARRAY_SIZE];
int npix = AMG88xx_PIXEL_ARRAY_SIZE;

//TX = 9, RX=8, reset_display=7
#include <AltSoftSerial.h>
AltSoftSerial altSerial;

float dest_2d;  //output value for box fill
int boxsize; //pixel blocksize for output

#include "oled160drv.h"
#include "interp.h"

char powerup = 1; //OLED display powered up

// timeout set to four minutes
#define SCREENSAVER 4*60*1000UL

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("test interp");
  altSerial.begin(19200);
  OLED_Init();
  OLED_Clear();  //have to set font size first or row spacing doesn't work properly
  OLED_Pensize(0); //  fill rectangles
  bool status;

  // initialize thermal sensor with defaults
  status = amg.begin();
  if (!status) {
    Serial.println("Could not find thermal sensor.");
    while (1);
  }

  boxsize = min(DISPLAY_COLS / INTERPOLATED_COLS, DISPLAY_ROWS / INTERPOLATED_COLS);
  Serial.print("Box size = ");
  Serial.println(boxsize);
  delay(100); // sensor is still booting
}

float x, y;
int i;
int counter = 0;

void loop() {
  counter++;

  if ( (millis() > SCREENSAVER) && powerup) {
    Serial.println("screensaver activated, power down");
    powerup = 0;
    OLED_PowerDn();
    while (1);
  }
  Serial.print("image ");
  Serial.println(counter);

  //read all the pixels, bottom to top
  
  x=y=0.0;
  amg.readPixels(pixels);

  for (i = 1; i <= npix; i++) {
    if (y < pixels[i - 1]) y = pixels[i - 1]; //get max
    x += pixels[i - 1]; //calc average
  }
  x /= (float)npix;
  y = y - x; //subtract max (NOT USED atm)

  for (i = 1; i <= npix; i++) {
    y = pixels[i - 1] - x;
    if (y < 0.0) y = 0.0;
    if (y > MAXTEMP) y = MAXTEMP;
    pixels[i - 1] = y;
  }

  interpolate_image(&pixels[0], INPUT_ROWS, INPUT_COLS, &dest_2d, INTERPOLATED_ROWS, INTERPOLATED_COLS);

}

I know nothing about your display, so can’t comment on the code that sends data to it.

interp.h (6.76 KB)

oled160drv.h (5.77 KB)

Unfortunately its not working for me.
I am having some problems with the following piece of code:

x1 = x * boxsize;
  x2 = x1 + boxsize - 1;
  y1 = y * boxsize;
  y2 = y1 + boxsize - 1;

When I use these to draw my rect I end up with a massive picture. It results in the box size being the size the picture should be.
Apart from that I am not getting any colors, just a purple picture.

This is what GUIslice needs to perform drawFillRect :

bool gslc_DrvDrawFillRect	(	gslc_tsGui * 	pGui,
gslc_tsRect 	rRect,
gslc_tsColor 	nCol 
)		
Draw a filled rectangle.

Parameters
[in]	pGui	Pointer to GUI
[in]	rRect	Rectangular region to fill
[in]	nCol	Color RGB value to fill



gslc_tsRect Struct Reference
Rectangular region. Defines X,Y corner coordinates plus dimensions.

Data Fields
int16_t 	x
 	X coordinate of corner.
 
int16_t 	y
 	Y coordinate of corner.
 
uint16_t 	w
 	Width of region. 
 
uint16_t 	h
 	Height of region. 
 
Detailed Description
Rectangular region. Defines X,Y corner coordinates plus dimensions.

If i use x1 and y1 as my coordinates and boxsize as my width and height i get a picture of the expected size, but only one singular functioning box. The rest of the picture is purple with a few random colored boxes that dont change.

Is there any straightforward way to get this working?

I have the adafruit example working with more than 41 rows columns, however when I set it to the desired resolution (example 56x56 or 60x60) it is quite slow, much slower than the 70x70 interpolation from Kris' code, even when using an array instead of using your color map function.

I assume its because the code from Kris uses linear Interpolation, wheras the Adafruit code uses some very fancy interpolation routine?

I have also done some tests with Kris' code, and there was no visable difference when using his rgb math or using an array. His math is very simple and can be executed quickly.

I appreciate your help alot, there is alot of great code and great tips here, but I cant get the Adafruit code running fast enough with the same level of interpolation.

I am considering continuing with the code from Kris, unless you have any tips to speed up the adafruit code when doing the higher resolution interpolation?

When I use these to draw my rect I end up with a massive picture. It results in the box size being the size the picture should be.

To determine why that happens, put in a print statement to see the values of boxsize and the x and y variables.

The Adafruit code does bicubic interpolation, which is much smoother but several times slower than bilinear interpolation. My choice for using a 32x32 output image, and to display 128x128 with 4x4 boxes, is a tradeoff between speed and smoothness. I can't see the box edges, so I'm happy with it.

If you are happy with the results of linear interpolation, that could replace the bicubic interpolation in the adafruit code. Consider it a programming challenge!

I took a look at Kris' code and see the problem. It is really hard coded for 70x70 output, with lots of arbitrary numeric constants scattered through the code, based on that choice. It would be difficult to generalize.

Your dilemma is exactly the reason that experienced programmers so strongly recommend to avoid using numeric constants (and the assumptions that go with them) in the code.

A search for "bilinear interpolation 2D array C code" turns up several examples of more general code.

The best results so far have been adapting Kris' RGB math to the adafruit example. (Once you notice to real difference between linear interpolation and bicubic you can't unsee it :frowning: )

I have tried alot of different arrays, even one with 433 colors (no doubled colors!) and I still wasnt happy with the results, you could easily see the steps in color.

With Kris' RGB math the color transition is flawless! Speed is somewhat compromised, but the resulting color palet more than makes up for it. I have even rewritten the math to produce the ironbow color pallet rather than the normal blue green yellow red color pallet.

Its a bit more pixelated than the 70x70 due to having to run a smaller interpolation to get the same frame rate, but the bicubic interpolation looks a bit nicer than the linear.

I will post the code shortly, I reccomend you give it a try If you still have your thermal cam laying around.

I have linearised the rgb values for the Ironbow pallet


Here is a copy of the code, It takes the existing val from the Adafruit example and uses it co calculate RGB.
Some extra variables and an extra function is needed.

#define MINTEMP 21
#define MAXTEMP 29
Adafruit_AMG88xx amg;
#define AMG_COLS 8
#define AMG_ROWS 8
float pixels[AMG_COLS * AMG_ROWS];
#define INTERPOLATED_COLS 36      
#define INTERPOLATED_ROWS 36
int boxWidth = 7;
int boxHeight = 5;
byte red, green, blue;
float a,b,c,d;
float dest_2d[INTERPOLATED_ROWS * INTERPOLATED_COLS];
float get_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
void set_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y, float f);
void get_adjacents_1d(float *src, float *dest, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
void get_adjacents_2d(float *src, float *dest, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
float cubicInterpolate(float p[], float x);
float bicubicInterpolate(float p[], float x, float y);
void interpolate_image(float *src, uint8_t src_rows, uint8_t src_cols,
                       float *dest, uint8_t dest_rows, uint8_t dest_cols);

void setup()
{
Getabcd();
  amg.begin();
}

void loop()
{
  amg.readPixels(pixels);
  interpolate_image(pixels, AMG_ROWS, AMG_COLS, dest_2d, INTERPOLATED_ROWS, INTERPOLATED_COLS);
  drawpixels(dest_2d, INTERPOLATED_ROWS, INTERPOLATED_COLS, boxWidth, boxHeight, false);
}

void drawpixels(float *p, uint8_t rows, uint8_t cols, uint8_t boxWidth, uint8_t boxHeight, boolean showVal) { //From Adafruit example
  int colorTemp;
  for (int y = 0; y < rows; y++) {
    for (int x = 0; x < cols; x++) {
      float val = get_point(p, rows, cols, x, y);
      red = constrain(255.0 / (c - MINTEMP) * val - ((MINTEMP * 255.0) / (c - MINTEMP)), 0, 255);
      green = constrain(255.0 / (MAXTEMP - b) * val - ((b * 255.0) / (MAXTEMP - b)), 0, 255);
      if ( val <= a) { //finished
        blue = constrain(160.0 / (a - MINTEMP) * val - (160.0 * MINTEMP) / (a - MINTEMP), 20, 160);
      }
      if ((val >= a) & (val <= b)) {
        blue = 160;
      }
      else if ((val >= b) & (val <= c)) { //finished
        blue = constrain(160.0 / (b - c) * val - (c * 160.0) / (b - c), 0, 160);
      }
      else if ((val >= c) & (val <= d)) { //finished
        blue = 0;
      }
      else if (val >= d) { //finished
        blue = constrain(225.0 / (MAXTEMP - d) * val - (d * 225.0) / (MAXTEMP - d), 0, 225);
      }
      gslc_tsRect rCamRect = {
        boxWidth * x,
        boxHeight * y,
        boxWidth,
        boxHeight
      };
      gslc_tsColor nCamCol_rgb = { red, green, blue};
      gslc_DrvDrawFillRect(&m_gui, rCamRect, nCamCol_rgb);


    }

  }
}

void Getabcd() {
  a = MINTEMP + (MAXTEMP - MINTEMP) * 0.2;
  b = MINTEMP + (MAXTEMP - MINTEMP) * 0.4;
  c = MINTEMP + (MAXTEMP - MINTEMP) * 0.6;
  d = MINTEMP + (MAXTEMP - MINTEMP) * 0.8;
}

Sounds like it is working to your satisfaction. Congrats, it is indeed an effort!

The linearized Ironbow pallet is a helpful contribution, thanks. It takes quite a lot of experimentation to get sensible heatmap (and other) color gradients. This is an interesting discussion:

Lookup table for ironbow from FLIR (24 bit):

var iron_palette = ["#00000a","#000014","#00001e","#000025","#00002a","#00002e","#000032","#000036","#00003a","#00003e","#000042","#000046","#00004a","#00004f","#000052","#010055","#010057","#020059","#02005c","#03005e","#040061","#040063","#050065","#060067","#070069","#08006b","#09006e","#0a0070","#0b0073","#0c0074","#0d0075","#0d0076","#0e0077","#100078","#120079","#13007b","#15007c","#17007d","#19007e","#1b0080","#1c0081","#1e0083","#200084","#220085","#240086","#260087","#280089","#2a0089","#2c008a","#2e008b","#30008c","#32008d","#34008e","#36008e","#38008f","#390090","#3b0091","#3c0092","#3e0093","#3f0093","#410094","#420095","#440095","#450096","#470096","#490096","#4a0096","#4c0097","#4e0097","#4f0097","#510097","#520098","#540098","#560098","#580099","#5a0099","#5c0099","#5d009a","#5f009a","#61009b","#63009b","#64009b","#66009b","#68009b","#6a009b","#6c009c","#6d009c","#6f009c","#70009c","#71009d","#73009d","#75009d","#77009d","#78009d","#7a009d","#7c009d","#7e009d","#7f009d","#81009d","#83009d","#84009d","#86009d","#87009d","#89009d","#8a009d","#8b009d","#8d009d","#8f009c","#91009c","#93009c","#95009c","#96009b","#98009b","#99009b","#9b009b","#9c009b","#9d009b","#9f009b","#a0009b","#a2009b","#a3009b","#a4009b","#a6009a","#a7009a","#a8009a","#a90099","#aa0099","#ab0099","#ad0099","#ae0198","#af0198","#b00198","#b00198","#b10197","#b20197","#b30196","#b40296","#b50295","#b60295","#b70395","#b80395","#b90495","#ba0495","#ba0494","#bb0593","#bc0593","#bd0593","#be0692","#bf0692","#bf0692","#c00791","#c00791","#c10890","#c10990","#c20a8f","#c30a8e","#c30b8e","#c40c8d","#c50c8c","#c60d8b","#c60e8a","#c70f89","#c81088","#c91187","#ca1286","#ca1385","#cb1385","#cb1484","#cc1582","#cd1681","#ce1780","#ce187e","#cf187c","#cf197b","#d01a79","#d11b78","#d11c76","#d21c75","#d21d74","#d31e72","#d32071","#d4216f","#d4226e","#d5236b","#d52469","#d62567","#d72665","#d82764","#d82862","#d92a60","#da2b5e","#da2c5c","#db2e5a","#db2f57","#dc2f54","#dd3051","#dd314e","#de324a","#de3347","#df3444","#df3541","#df363d","#e0373a","#e03837","#e03933","#e13a30","#e23b2d","#e23c2a","#e33d26","#e33e23","#e43f20","#e4411d","#e4421c","#e5431b","#e54419","#e54518","#e64616","#e74715","#e74814","#e74913","#e84a12","#e84c10","#e84c0f","#e94d0e","#e94d0d","#ea4e0c","#ea4f0c","#eb500b","#eb510a","#eb520a","#eb5309","#ec5409","#ec5608","#ec5708","#ec5808","#ed5907","#ed5a07","#ed5b06","#ee5c06","#ee5c05","#ee5d05","#ee5e05","#ef5f04","#ef6004","#ef6104","#ef6204","#f06303","#f06403","#f06503","#f16603","#f16603","#f16703","#f16803","#f16902","#f16a02","#f16b02","#f16b02","#f26c01","#f26d01","#f26e01","#f36f01","#f37001","#f37101","#f37201","#f47300","#f47400","#f47500","#f47600","#f47700","#f47800","#f47a00","#f57b00","#f57c00","#f57e00","#f57f00","#f68000","#f68100","#f68200","#f78300","#f78400","#f78500","#f78600","#f88700","#f88800","#f88800","#f88900","#f88a00","#f88b00","#f88c00","#f98d00","#f98d00","#f98e00","#f98f00","#f99000","#f99100","#f99200","#f99300","#fa9400","#fa9500","#fa9600","#fb9800","#fb9900","#fb9a00","#fb9c00","#fc9d00","#fc9f00","#fca000","#fca100","#fda200","#fda300","#fda400","#fda600","#fda700","#fda800","#fdaa00","#fdab00","#fdac00","#fdad00","#fdae00","#feaf00","#feb000","#feb100","#feb200","#feb300","#feb400","#feb500","#feb600","#feb800","#feb900","#feb900","#feba00","#febb00","#febc00","#febd00","#febe00","#fec000","#fec100","#fec200","#fec300","#fec400","#fec500","#fec600","#fec700","#fec800","#fec901","#feca01","#feca01","#fecb01","#fecc02","#fecd02","#fece03","#fecf04","#fecf04","#fed005","#fed106","#fed308","#fed409","#fed50a","#fed60a","#fed70b","#fed80c","#fed90d","#ffda0e","#ffda0e","#ffdb10","#ffdc12","#ffdc14","#ffdd16","#ffde19","#ffde1b","#ffdf1e","#ffe020","#ffe122","#ffe224","#ffe226","#ffe328","#ffe42b","#ffe42e","#ffe531","#ffe635","#ffe638","#ffe73c","#ffe83f","#ffe943","#ffea46","#ffeb49","#ffeb4d","#ffec50","#ffed54","#ffee57","#ffee5b","#ffee5f","#ffef63","#ffef67","#fff06a","#fff06e","#fff172","#fff177","#fff17b","#fff280","#fff285","#fff28a","#fff38e","#fff492","#fff496","#fff49a","#fff59e","#fff5a2","#fff5a6","#fff6aa","#fff6af","#fff7b3","#fff7b6","#fff8ba","#fff8bd","#fff8c1","#fff8c4","#fff9c7","#fff9ca","#fff9cd","#fffad1","#fffad4","#fffbd8","#fffcdb","#fffcdf","#fffde2","#fffde5","#fffde8","#fffeeb","#fffeee","#fffef1","#fffef4","#fffff6"];

Yes, I am quite happy with the results.

jremington:
Lookup table for ironbow from FLIR (24 bit):

var iron_palette = ["#00000a","#000014","#00001e","#000025","#00002a","#00002e","#000032","#000036","#00003a","#00003e","#000042","#000046","#00004a","#00004f","#000052","#010055","#010057","#020059","#02005c","#03005e","#040061","#040063","#050065","#060067","#070069","#08006b","#09006e","#0a0070","#0b0073","#0c0074","#0d0075","#0d0076","#0e0077","#100078","#120079","#13007b","#15007c","#17007d","#19007e","#1b0080","#1c0081","#1e0083","#200084","#220085","#240086","#260087","#280089","#2a0089","#2c008a","#2e008b","#30008c","#32008d","#34008e","#36008e","#38008f","#390090","#3b0091","#3c0092","#3e0093","#3f0093","#410094","#420095","#440095","#450096","#470096","#490096","#4a0096","#4c0097","#4e0097","#4f0097","#510097","#520098","#540098","#560098","#580099","#5a0099","#5c0099","#5d009a","#5f009a","#61009b","#63009b","#64009b","#66009b","#68009b","#6a009b","#6c009c","#6d009c","#6f009c","#70009c","#71009d","#73009d","#75009d","#77009d","#78009d","#7a009d","#7c009d","#7e009d","#7f009d","#81009d","#83009d","#84009d","#86009d","#87009d","#89009d","#8a009d","#8b009d","#8d009d","#8f009c","#91009c","#93009c","#95009c","#96009b","#98009b","#99009b","#9b009b","#9c009b","#9d009b","#9f009b","#a0009b","#a2009b","#a3009b","#a4009b","#a6009a","#a7009a","#a8009a","#a90099","#aa0099","#ab0099","#ad0099","#ae0198","#af0198","#b00198","#b00198","#b10197","#b20197","#b30196","#b40296","#b50295","#b60295","#b70395","#b80395","#b90495","#ba0495","#ba0494","#bb0593","#bc0593","#bd0593","#be0692","#bf0692","#bf0692","#c00791","#c00791","#c10890","#c10990","#c20a8f","#c30a8e","#c30b8e","#c40c8d","#c50c8c","#c60d8b","#c60e8a","#c70f89","#c81088","#c91187","#ca1286","#ca1385","#cb1385","#cb1484","#cc1582","#cd1681","#ce1780","#ce187e","#cf187c","#cf197b","#d01a79","#d11b78","#d11c76","#d21c75","#d21d74","#d31e72","#d32071","#d4216f","#d4226e","#d5236b","#d52469","#d62567","#d72665","#d82764","#d82862","#d92a60","#da2b5e","#da2c5c","#db2e5a","#db2f57","#dc2f54","#dd3051","#dd314e","#de324a","#de3347","#df3444","#df3541","#df363d","#e0373a","#e03837","#e03933","#e13a30","#e23b2d","#e23c2a","#e33d26","#e33e23","#e43f20","#e4411d","#e4421c","#e5431b","#e54419","#e54518","#e64616","#e74715","#e74814","#e74913","#e84a12","#e84c10","#e84c0f","#e94d0e","#e94d0d","#ea4e0c","#ea4f0c","#eb500b","#eb510a","#eb520a","#eb5309","#ec5409","#ec5608","#ec5708","#ec5808","#ed5907","#ed5a07","#ed5b06","#ee5c06","#ee5c05","#ee5d05","#ee5e05","#ef5f04","#ef6004","#ef6104","#ef6204","#f06303","#f06403","#f06503","#f16603","#f16603","#f16703","#f16803","#f16902","#f16a02","#f16b02","#f16b02","#f26c01","#f26d01","#f26e01","#f36f01","#f37001","#f37101","#f37201","#f47300","#f47400","#f47500","#f47600","#f47700","#f47800","#f47a00","#f57b00","#f57c00","#f57e00","#f57f00","#f68000","#f68100","#f68200","#f78300","#f78400","#f78500","#f78600","#f88700","#f88800","#f88800","#f88900","#f88a00","#f88b00","#f88c00","#f98d00","#f98d00","#f98e00","#f98f00","#f99000","#f99100","#f99200","#f99300","#fa9400","#fa9500","#fa9600","#fb9800","#fb9900","#fb9a00","#fb9c00","#fc9d00","#fc9f00","#fca000","#fca100","#fda200","#fda300","#fda400","#fda600","#fda700","#fda800","#fdaa00","#fdab00","#fdac00","#fdad00","#fdae00","#feaf00","#feb000","#feb100","#feb200","#feb300","#feb400","#feb500","#feb600","#feb800","#feb900","#feb900","#feba00","#febb00","#febc00","#febd00","#febe00","#fec000","#fec100","#fec200","#fec300","#fec400","#fec500","#fec600","#fec700","#fec800","#fec901","#feca01","#feca01","#fecb01","#fecc02","#fecd02","#fece03","#fecf04","#fecf04","#fed005","#fed106","#fed308","#fed409","#fed50a","#fed60a","#fed70b","#fed80c","#fed90d","#ffda0e","#ffda0e","#ffdb10","#ffdc12","#ffdc14","#ffdd16","#ffde19","#ffde1b","#ffdf1e","#ffe020","#ffe122","#ffe224","#ffe226","#ffe328","#ffe42b","#ffe42e","#ffe531","#ffe635","#ffe638","#ffe73c","#ffe83f","#ffe943","#ffea46","#ffeb49","#ffeb4d","#ffec50","#ffed54","#ffee57","#ffee5b","#ffee5f","#ffef63","#ffef67","#fff06a","#fff06e","#fff172","#fff177","#fff17b","#fff280","#fff285","#fff28a","#fff38e","#fff492","#fff496","#fff49a","#fff59e","#fff5a2","#fff5a6","#fff6aa","#fff6af","#fff7b3","#fff7b6","#fff8ba","#fff8bd","#fff8c1","#fff8c4","#fff9c7","#fff9ca","#fff9cd","#fffad1","#fffad4","#fffbd8","#fffcdb","#fffcdf","#fffde2","#fffde5","#fffde8","#fffeeb","#fffeee","#fffef1","#fffef4","#fffff6"];

This is the same LUT I tried, I still found the steps in color to be too large, I could only count about 10 different colors at any one time on the screen. With RGB generation there are many more, often a seamless transition between colors.
I am becoming quite familiar with this particular piece of code, it is well thought out and excecutes well.
It does negatively affect speed, but not by a large amount. The advantage is one can have many different maps available without using much memory.
I have already recreated a few of the FLIR maps.
Ironbow:

      red = constrain(255.0 / (c - MINTEMP) * val - ((MINTEMP * 255.0) / (c - MINTEMP)), 0, 255);
      green = constrain(255.0 / (MAXTEMP - b) * val - ((b * 255.0) / (MAXTEMP - b)), 0, 255);
      if ( val <= a) { 
        blue = constrain(160.0 / (a - MINTEMP) * val - (160.0 * MINTEMP) / (a - MINTEMP), 20, 160);    
      }
      if ((val >= a) & (val <= b)) {
        blue = 160;
      }
      else if ((val >= b) & (val <= c)) {
        blue = constrain(160.0 / (b - c) * val - (c * 160.0) / (b - c), 0, 160);
      }    
      else if ((val >= c) & (val <= d)) {
        blue = 0;
      }
      else if (val >= d) {
        blue = constrain(225.0 / (MAXTEMP - d) * val - (d * 225.0) / (MAXTEMP - d), 0, 225);
      }

Black hot:

      red = constrain(255.0 / (MINTEMP - MAXTEMP) * val - ((MAXTEMP * 255.0) / (MINTEMP - MAXTEMP)), 0, 255);
      
      green = constrain(255.0 / (MINTEMP - MAXTEMP) * val - ((MAXTEMP * 255.0) / (MINTEMP - MAXTEMP)), 0, 255);
      
      blue = constrain(255.0 / (MINTEMP - MAXTEMP) * val - ((MAXTEMP * 255.0) / (MINTEMP - MAXTEMP)), 0, 255);

White hot:

red = constrain(255.0 / (MAXTEMP - MINTEMP) * val - ((MINTEMP * 255.0) / (MAXTEMP - MINTEMP)), 0, 255);
      
      green = constrain(255.0 / (MAXTEMP - MINTEMP) * val - ((MINTEMP * 255.0) / (MAXTEMP - MINTEMP)), 0, 255);
      
      blue = constrain(255.0 / (MAXTEMP - MINTEMP) * val - ((MINTEMP * 255.0) / (MAXTEMP - MINTEMP)), 0, 255);

Outdoor Alert:

      if (val <= c) {
        red = constrain(245.0 / (MINTEMP - c) * val - ((c * 245.0) / (MINTEMP - c)), 10, 255);

        green = constrain(245.0 / (MINTEMP - c) * val - ((c * 245.0) / (MINTEMP - c)), 10, 255);

        blue = constrain(245.0 / (MINTEMP - c) * val - ((c * 245.0) / (MINTEMP - c)), 10, 255);
      }

        else if ((val >= c) & (val <= d)) {

          red = constrain(215.0 / (d - c) * val - ((c * 215.0) / (d - c)), 10, 225);

          green = constrain(30.0 / (d - c) * val - ((c * 30.0) / (d - c)), 10, 40);

          blue = constrain(30.0 / (d - c) * val - ((c * 30.0) / (d - c)), 10, 40);
        }
        else if (val >= d) {
          
          red = constrain(30.0 / (MAXTEMP - d) * val - ((d * 30.0) / (MAXTEMP - d)), 225, 255);

          green = constrain(180.0 / (MAXTEMP - d) * val - ((d * 180.0) / (MAXTEMP - d)), 40, 220);

          blue = constrain(35.0 / (MAXTEMP - d) * val - ((d * 35.0) / (MAXTEMP - d)), 5, 40);
        }

The color maps can be further refined by altering the values in Getabcd(). This could easily be done during runtime in some kind of a setting menu with some sliders or similar.

Do you think an STM32 would be better suited for this task? (would it produce more FPS, or more interpolation wit the same FPS?)
At first I was very impressed with the ESP32, but now im starting to see the limitations

I could only count about 10 different colors

That can't be right. Did you translate the 24 bit table to 16 bits? Perhaps you did that incorrectly.

The Teensy 4.x runs at 600 MHz, for about $20. It is the fastest micro currently on the market, and the support at PJRC is excellent.

Yes, I accounted for 24 bit.
I changed the array to uint32_t
And i converted the hex to RGB

gslc_tsRect rCamRect = { (col * 4) + 76, (row * 3) + 12,  BoxHeight, BoxWidth};
          uint32_t     nCamColor_rgb565 = camColors[colorIndex];
          gslc_tsColor nCamCol_rgb888;
      nCamCol_rgb888.r = ((nCamColor_rgb565 >> 16) & 0xFF);
      nCamCol_rgb888.g = ((nCamColor_rgb565 >> 8) & 0xFF);
      nCamCol_rgb888.b = ((nCamColor_rgb565) & 0xFF) ;
          //gslc_tsColor nCamCol_rgb = { red, green, blue};
          gslc_DrvDrawFillRect(&m_gui, rCamRect, nCamCol_rgb888);
        }

The color transitions were not as good as the RGB math, there were clear steps between each shade/color. As I said, I could only see about 8-10 different shades/colors at any one time.

I dont think it is normally so noticable, but I am using a 2.8" display, my picture size is about 180 x 240 depending how many rows/columns/box size.

I think with a picture size of 128 x 128 it wouldnt be as noticable.

jremington:
The Teensy 4.x runs at 600 MHz, for about $20. It is the fastest micro currently on the market, and the support at PJRC is excellent.

I will look into it, hopefully there is some kind of UNO board that allows the use of UNO shields (this was a huge bonus with the ESP32, there is an UNO style board available)
Thanks for the tip.

Here is the array

const uint32_t camColors[] = {
0x00000a,0x000014,0x00001e,0x000025,0x00002a,0x00002e,0x000032,0x000036,0x00003a,0x00003e,0x000042,0x000046,0x00004a,0x00004f,0x000052,0x010055,0x010057,
0x020059,0x02005c,0x03005e,0x040061,0x040063,0x050065,0x060067,0x070069,0x08006b,0x09006e,0x0a0070,0x0b0073,0x0c0074,0x0d0075,0x0d0076,0x0e0077,0x100078,
0x120079,0x13007b,0x15007c,0x17007d,0x19007e,0x1b0080,0x1c0081,0x1e0083,0x200084,0x220085,0x240086,0x260087,0x280089,0x2a0089,0x2c008a,0x2e008b,0x30008c,
0x32008d,0x34008e,0x36008e,0x38008f,0x390090,0x3b0091,0x3c0092,0x3e0093,0x3f0093,0x410094,0x420095,0x440095,0x450096,0x470096,0x490096,0x4a0096,0x4c0097,
0x4e0097,0x4f0097,0x510097,0x520098,0x540098,0x560098,0x580099,0x5a0099,0x5c0099,0x5d009a,0x5f009a,0x61009b,0x63009b,0x64009b,0x66009b,0x68009b,0x6a009b,
0x6c009c,0x6d009c,0x6f009c,0x70009c,0x71009d,0x73009d,0x75009d,0x77009d,0x78009d,0x7a009d,0x7c009d,0x7e009d,0x7f009d,0x81009d,0x83009d,0x84009d,0x86009d,
0x87009d,0x89009d,0x8a009d,0x8b009d,0x8d009d,0x8f009c,0x91009c,0x93009c,0x95009c,0x96009b,0x98009b,0x99009b,0x9b009b,0x9c009b,0x9d009b,0x9f009b,0xa0009b,
0xa2009b,0xa3009b,0xa4009b,0xa6009a,0xa7009a,0xa8009a,0xa90099,0xaa0099,0xab0099,0xad0099,0xae0198,0xaf0198,0xb00198,0xb00198,0xb10197,0xb20197,0xb30196,
0xb40296,0xb50295,0xb60295,0xb70395,0xb80395,0xb90495,0xba0495,0xba0494,0xbb0593,0xbc0593,0xbd0593,0xbe0692,0xbf0692,0xbf0692,0xc00791,0xc00791,0xc10890,
0xc10990,0xc20a8f,0xc30a8e,0xc30b8e,0xc40c8d,0xc50c8c,0xc60d8b,0xc60e8a,0xc70f89,0xc81088,0xc91187,0xca1286,0xca1385,0xcb1385,0xcb1484,0xcc1582,0xcd1681,
0xce1780,0xce187e,0xcf187c,0xcf197b,0xd01a79,0xd11b78,0xd11c76,0xd21c75,0xd21d74,0xd31e72,0xd32071,0xd4216f,0xd4226e,0xd5236b,0xd52469,0xd62567,0xd72665,
0xd82764,0xd82862,0xd92a60,0xda2b5e,0xda2c5c,0xdb2e5a,0xdb2f57,0xdc2f54,0xdd3051,0xdd314e,0xde324a,0xde3347,0xdf3444,0xdf3541,0xdf363d,0xe0373a,0xe03837,
0xe03933,0xe13a30,0xe23b2d,0xe23c2a,0xe33d26,0xe33e23,0xe43f20,0xe4411d,0xe4421c,0xe5431b,0xe54419,0xe54518,0xe64616,0xe74715,0xe74814,0xe74913,0xe84a12,
0xe84c10,0xe84c0f,0xe94d0e,0xe94d0d,0xea4e0c,0xea4f0c,0xeb500b,0xeb510a,0xeb520a,0xeb5309,0xec5409,0xec5608,0xec5708,0xec5808,0xed5907,0xed5a07,0xed5b06,
0xee5c06,0xee5c05,0xee5d05,0xee5e05,0xef5f04,0xef6004,0xef6104,0xef6204,0xf06303,0xf06403,0xf06503,0xf16603,0xf16603,0xf16703,0xf16803,0xf16902,0xf16a02,
0xf16b02,0xf16b02,0xf26c01,0xf26d01,0xf26e01,0xf36f01,0xf37001,0xf37101,0xf37201,0xf47300,0xf47400,0xf47500,0xf47600,0xf47700,0xf47800,0xf47a00,0xf57b00,
0xf57c00,0xf57e00,0xf57f00,0xf68000,0xf68100,0xf68200,0xf78300,0xf78400,0xf78500,0xf78600,0xf88700,0xf88800,0xf88800,0xf88900,0xf88a00,0xf88b00,0xf88c00,
0xf98d00,0xf98d00,0xf98e00,0xf98f00,0xf99000,0xf99100,0xf99200,0xf99300,0xfa9400,0xfa9500,0xfa9600,0xfb9800,0xfb9900,0xfb9a00,0xfb9c00,0xfc9d00,0xfc9f00,
0xfca000,0xfca100,0xfda200,0xfda300,0xfda400,0xfda600,0xfda700,0xfda800,0xfdaa00,0xfdab00,0xfdac00,0xfdad00,0xfdae00,0xfeaf00,0xfeb000,0xfeb100,0xfeb200,
0xfeb300,0xfeb400,0xfeb500,0xfeb600,0xfeb800,0xfeb900,0xfeb900,0xfeba00,0xfebb00,0xfebc00,0xfebd00,0xfebe00,0xfec000,0xfec100,0xfec200,0xfec300,0xfec400,
0xfec500,0xfec600,0xfec700,0xfec800,0xfec901,0xfeca01,0xfeca01,0xfecb01,0xfecc02,0xfecd02,0xfece03,0xfecf04,0xfecf04,0xfed005,0xfed106,0xfed308,0xfed409,
0xfed50a,0xfed60a,0xfed70b,0xfed80c,0xfed90d,0xffda0e,0xffda0e,0xffdb10,0xffdc12,0xffdc14,0xffdd16,0xffde19,0xffde1b,0xffdf1e,0xffe020,0xffe122,0xffe224,
0xffe226,0xffe328,0xffe42b,0xffe42e,0xffe531,0xffe635,0xffe638,0xffe73c,0xffe83f,0xffe943,0xffea46,0xffeb49,0xffeb4d,0xffec50,0xffed54,0xffee57,0xffee5b,
0xffee5f,0xffef63,0xffef67,0xfff06a,0xfff06e,0xfff172,0xfff177,0xfff17b,0xfff280,0xfff285,0xfff28a,0xfff38e,0xfff492,0xfff496,0xfff49a,0xfff59e,0xfff5a2,
0xfff5a6,0xfff6aa,0xfff6af,0xfff7b3,0xfff7b6,0xfff8ba,0xfff8bd,0xfff8c1,0xfff8c4,0xfff9c7,0xfff9ca,0xfff9cd,0xfffad1,0xfffad4,0xfffbd8,0xfffcdb,0xfffcdf,
0xfffde2,0xfffde5,0xfffde8,0xfffeeb,0xfffeee,0xfffef1,0xfffef4,0xfffff6,};

Did you take into account that that lookup table has 433 entries?

Here is the 16 bit, 565 version. In looking over my notes, I had forgotten that I implemented this one on another processor, which is why it wasn't in the code posted earlier.

// 433 entries
 uint16_t ironbow[]=
{1,2,3,4,5,5,6,6,7,7,
8,8,9,9,10,10,10,11,11,11,
12,12,12,12,13,2061,2061,2062,2062,2062,
2062,2062,2062,4111,4111,4111,4111,4111,6159,6160,
6160,6160,8208,8208,8208,8208,10257,10257,10257,10257,
12305,12305,12305,12305,14353,14354,14354,14354,14354,14354,
16402,16402,16402,16402,16402,18450,18450,18450,18450,18450,
20498,20499,20499,20499,22547,22547,22547,22547,22547,24595,
24595,24595,24595,26643,26643,26643,26643,26643,28691,28691,
28691,28691,28691,30739,30739,30739,30739,30739,32787,32787,
32787,32787,32787,34835,34835,34835,34835,34835,36883,36883,
36883,36883,38931,38931,38931,38931,38931,38931,40979,40979,
40979,40979,40979,40979,43027,43027,43027,43027,43027,43027,
43027,45075,45075,45074,45074,45074,45074,45074,45074,45074,
47122,47154,47154,47154,47154,47154,47154,47154,47154,47154,
49202,49202,49234,49234,49233,49233,49233,49265,49265,49265,
49265,49265,51345,51344,51344,51344,51344,51376,51376,51376,
51376,51407,51407,51407,53455,53455,53486,53486,53486,53486,
53518,53517,53517,53517,53549,53548,53548,55596,55628,55628,
55627,55659,55659,55658,55658,55690,55689,55689,55688,55720,
55720,55719,57767,57798,57798,57798,57797,57829,57828,57828,
57828,57859,57859,57859,57891,57891,57890,57890,57922,57922,
59970,60002,60001,60001,60001,60001,60001,60033,60033,60033,
60033,60065,60065,60065,60097,60096,60096,60096,60128,60128,
60128,60128,60128,60160,60160,60160,62208,62240,62240,62240,
62240,62240,62272,62272,62272,62272,62272,62304,62304,62304,
62304,62336,62336,62336,62336,62368,62368,62368,62368,62400,
62400,62400,62432,62432,62432,62464,62464,62464,62464,62496,
62496,62496,64544,64576,64576,64576,64576,64576,64608,64608,
64608,64608,64608,64640,64640,64640,64640,64672,64672,64672,
64704,64704,64704,64736,64736,64736,64768,64768,64768,64768,
64800,64800,64800,64832,64832,64832,64864,64864,64864,64864,
64896,64896,64896,64896,64928,64928,64928,64960,64960,64960,
64960,64960,64992,64992,64992,65024,65024,65024,65024,65056,
65056,65056,65056,65088,65088,65088,65088,65088,65120,65120,
65120,65120,65120,65152,65152,65153,65185,65185,65185,65185,
65217,65217,65217,65217,65218,65250,65250,65250,65251,65251,
65251,65284,65284,65284,65284,65285,65317,65317,65318,65318,
65319,65319,65351,65352,65352,65353,65353,65386,65386,65386,
65387,65387,65388,65388,65421,65421,65422,65422,65423,65424,
65424,65425,65425,65458,65458,65459,65459,65460,65460,65461,
65461,65462,65462,65495,65495,65496,65496,65496,65497,65497,
65498,65498,65499,65531,65531,65532,65532,65533,65533,65533,
65534,65534,65534};

Yes, I had also changed the following:

if(val >= MaxTemp) colorTemp = MaxTemp;
      else if(val <= MinTemp) colorTemp = MinTemp;
      else colorTemp = val;
      
      uint32_t colorIndex = map(colorTemp, MinTemp, MaxTemp, 0, 432);
      colorIndex = constrain(colorIndex, 0, 432);

Was there anything else that needed to be changed? perhaps I missed something?

I just realised its because colorTemp is an int, not a float, and the colorIndex map doesnt help the situation.
This means I was getting a different color for every full degree celcius, hence only 10 or so colors on screen as there was only a difference of about 10 or so degrees.

I changed colorTemp to a float and changed the colorIndex map like so:

int colorIndex = map(colorTemp * 1000, MINTEMP * 1000, MAXTEMP * 1000, 0, 432);

I am now using all availabe colors.