Help identifying compressed image format

Hey y’all,

I have a TJC3224T132_011N display and have been playing around with reverse engineering the mcu firmware as well as the .tft files generated for this display. After figuring out how to decrypt header2 of the .tft files and getting the offsets for the various sections, I’m now trying to figure out how the images are encoded.

Looking at the dumped image in a hex editor, it looks as though it might be some sort of run length encoding, as I can see the 16bit color data inline, however it does not appear to be just the raw pixel data. It looks as though the data is broken up into 5 word (20 byte) chunks with the first word possibly defining how to interpret the next 8 pixel data.

I created a custom tft with the following 64x64 image
four_square_64x64
And here is a link to a hexdump of the image that was extracted from this tft. The pixel data is 1300 bytes with an additional 576 bytes at the end, a palette perhaps?

Anyone happen to know the format of these compressed images?

I think I am on the verge of figuring the encoding scheme out, thanks to having a firmware dump from the mcu and the ability to actually attach a debugger and step through the code.

Pixels appear to be broken up into packets of 5 words. The last 4 are the raw pixel data broken into 2 RGB565 colors per word for a total of 8 colors. The first word is broken up into 8 4-bit nibbles where each nibble corresponds to the number of times the pixel in the corresponding half-word should be repeated.

This is a new way of doing RLE to me but it works.

  do {
    while( true ) {
      while( true ) {
        uVar3 = *puVar2;
        uVar4 = uVar3 & 0xf;
        if (uVar4 != 0xf) break;
        iVar1 = iVar1 + 8;
        GPIOA_BSRR._3_1_ = 0x10;
        GPIOB_ODR = (undefined2)(puVar2[4] >> 0x10);
        GPIOA_BSRR._1_1_ = 0x10;
        puVar2 = puVar2 + 5;
        param_1 = param_1 + -0x14;
        if (param_1 == 0) {
          return CONCAT44(param_2,iVar1);
        }
      }
      if (uVar4 != 0) break;
LAB_080013f4:
      puVar2 = puVar2 + 5;
      param_1 = param_1 + -0x14;
      if (param_1 == 0) {
        return CONCAT44(param_2,iVar1);
      }
    }
    GPIOB_ODR = *(undefined2 *)(puVar2 + 1);
    do {
      GPIOA_BSRR._3_1_ = 0x10;
      GPIOA_BSRR._1_1_ = 0x10;
      iVar1 = iVar1 + 1;
      uVar4 = uVar4 - 1;
    } while (uVar4 != 0);
    uVar4 = uVar3 >> 4 & 0xf;
    if (uVar4 == 0) goto LAB_080013f4;
    GPIOB_ODR = *(undefined2 *)((int)puVar2 + 6);
    do {
      GPIOA_BSRR._3_1_ = 0x10;
      GPIOA_BSRR._1_1_ = 0x10;
      iVar1 = iVar1 + 1;
      uVar4 = uVar4 - 1;
    } while (uVar4 != 0);
    uVar4 = uVar3 >> 8 & 0xf;
    if (uVar4 == 0) goto LAB_080013f4;
    GPIOB_ODR = *(undefined2 *)(puVar2 + 2);
    do {
      GPIOA_BSRR._3_1_ = 0x10;
      GPIOA_BSRR._1_1_ = 0x10;
      iVar1 = iVar1 + 1;
      uVar4 = uVar4 - 1;
    } while (uVar4 != 0);
    uVar4 = uVar3 >> 0xc & 0xf;
    if (uVar4 == 0) goto LAB_080013f4;
    GPIOB_ODR = *(undefined2 *)((int)puVar2 + 10);
    do {
      iVar1 = iVar1 + 1;
      uVar4 = uVar4 - 1;
    } while (uVar4 != 0);
    uVar4 = uVar3 >> 0x10 & 0xf;
    if (uVar4 != 0) {
      GPIOB_ODR = *(undefined2 *)(puVar2 + 3);
      do {
        iVar1 = iVar1 + 1;
        uVar4 = uVar4 - 1;
      } while (uVar4 != 0);
      uVar4 = uVar3 >> 0x14 & 0xf;
      if (uVar4 != 0) {
        GPIOB_ODR = *(undefined2 *)((int)puVar2 + 0xe);
        do {
          iVar1 = iVar1 + 1;
          uVar4 = uVar4 - 1;
        } while (uVar4 != 0);
        uVar4 = uVar3 >> 0x18 & 0xf;
        if (uVar4 != 0) {
          GPIOB_ODR = *(undefined2 *)(puVar2 + 4);
          do {
            iVar1 = iVar1 + 1;
            uVar4 = uVar4 - 1;
          } while (uVar4 != 0);
          uVar3 = uVar3 >> 0x1c;
          if (uVar3 != 0) {
            GPIOB_ODR = *(undefined2 *)((int)puVar2 + 0x12);
            do {
              iVar1 = iVar1 + 1;
              uVar3 = uVar3 - 1;
            } while (uVar3 != 0);
          }
        }
      }
    }
    GPIOA_BSRR._3_1_ = 0x10;
    GPIOA_BSRR._1_1_ = 0x10;
    puVar2 = puVar2 + 5;
    param_1 = param_1 + -0x14;
    if (param_1 == 0) {
      return CONCAT44(param_2,iVar1);
    }
  } while( true );

Wrote a little python script that does this image decoding :wink: