Bodmer / JPEGDecoder

A JPEG decoder library
Other
220 stars 64 forks source link

Adafruit_GFX compatibility lost #37

Closed Bodmer closed 5 years ago

Bodmer commented 5 years ago

The Adafruit_GFX library has been updated and may no longer be compatible with this library.

If the example sketches for the Adafruit library no longer work for you then post details here please.

john-- commented 5 years ago

The issue is due to a breaking change in setAddrWindow. It used to take x1, y1, x2, y2 but now it takes x, y, width, height.

Also it's necessary to preface your write with a startWrite() and end it with an endWrite().

Example:

Before:

    // draw image MCU block only if it will fit on the screen
    if ( ( mcu_x + win_w) <= tft.width() && ( mcu_y + win_h) <= tft.height())
    {
      // Now set a MCU bounding window on the TFT to push pixels into (x, y, x + width - 1, y + height - 1)
      tft.setAddrWindow(mcu_x, mcu_y, mcu_x + win_w - 1, mcu_y + win_h - 1);

      // Write all MCU pixels to the TFT window
      while (mcu_pixels--) tft.pushColor(*pImg++); // Send MCU buffer to TFT 16 bits at a time
    }

After:

    tft.startWrite();

    // draw image MCU block only if it will fit on the screen
    if ( ( mcu_x + win_w) <= tft.width() && ( mcu_y + win_h) <= tft.height())
    {
      // Now set a MCU bounding window on the TFT to push pixels into (x, y, x + width - 1, y + height - 1)
      tft.setAddrWindow(mcu_x, mcu_y, win_w, win_h);

      // Write all MCU pixels to the TFT window
      while (mcu_pixels--) tft.pushColor(*pImg++); // Send MCU buffer to TFT 16 bits at a time
    }

    tft.endWrite();

I tested this and it seems to work on my 1.5" ST7789 Adafruit TFT.

acharyanachiket commented 5 years ago

The issue is due to a breaking change in setAddrWindow. It used to take x1, y1, x2, y2 but now it takes x1, y2, width, height.

Also it's necessary to preface your write with a startWrite() and end it with an endWrite().

Example:

Before:

    // draw image MCU block only if it will fit on the screen
    if ( ( mcu_x + win_w) <= tft.width() && ( mcu_y + win_h) <= tft.height())
  {
      // Now set a MCU bounding window on the TFT to push pixels into (x, y, x + width - 1, y + height - 1)
      tft.setAddrWindow(mcu_x, mcu_y, mcu_x + win_w - 1, mcu_y + win_h - 1);

      // Write all MCU pixels to the TFT window
      while (mcu_pixels--) tft.pushColor(*pImg++); // Send MCU buffer to TFT 16 bits at a time
    }

After:

    tft.startWrite();

    // draw image MCU block only if it will fit on the screen
    if ( ( mcu_x + win_w) <= tft.width() && ( mcu_y + win_h) <= tft.height())
  {
      // Now set a MCU bounding window on the TFT to push pixels into (x, y, x + width - 1, y + height - 1)
      tft.setAddrWindow(mcu_x, mcu_y, win_w, win_h);

      // Write all MCU pixels to the TFT window
      while (mcu_pixels--) tft.pushColor(*pImg++); // Send MCU buffer to TFT 16 bits at a time
    }

    tft.endWrite();

I tested this and it seems to work on my 1.5" ST7789 Adafruit TFT.

Hi John This fix of yours works fine on nodeMCU_Jpeg.ino too, wherein we interface it with ILI9341 driver. Thank you for the update

john-- commented 5 years ago

@acharyanachiket good to hear! I would submit a PR to update the examples, but I just don't have the time to test each of them.

geeksville commented 5 years ago

@acharyanachiket thank you for your note it helped me a lot. (John, if you want a PR I can send one in)

john-- commented 5 years ago

@geeksville it's not my repo but I think the community would find this helpful :) sounds like we've confirmed with enough people that the suggestion seems to resolve the issue.

Bodmer commented 5 years ago

Thanks for your input. I have updated the Adafruit_GFX examples.

The examples also handle the case where the width and height of the image is not an integral number of mcu blocks.

I have implemented the change using drawRGBBitmap(), this may make rendering a bit faster.

trevorbattle commented 3 years ago

The TFT_flash_jpg.ino example can be trivially updated to work with the latest Adafruit_GFX:

Around line 187, replace all of:

      // Now set a MCU bounding window on the TFT to push pixels into (x, y, x + width - 1, y + height - 1)
      tft.setAddrWindow(mcu_x, mcu_y, mcu_x + win_w - 1, mcu_y + win_h - 1);

      // Write all MCU pixels to the TFT window
      while (mcu_pixels--) {
        // Push each pixel to the TFT MCU area
        tft.pushColor(*pImg++);
      }

With:

     tft.drawRGBBitmap(mcu_x, mcu_y, pImg, win_w, win_h);

...I know the library has been deprecated in favour of TJpg_Decoder, but it doesn't support older AVRs anymore. The above patch makes the example work again on Mega2560. (I have only tested with ILI9341 and 320x240, that's all I have handy)

Bodmer commented 3 years ago

The example is for the Arduino TFT library (hence the "#include ") which contains an older (2017) version of Adafruit_GFX, this old version does not provide a drawRGBBitmap() function so the above suggestion will not work without changing the graphics library.

I assume therefore you have made other changes to the sketch to use the Adafruit_GFX and Adafruit_ILI9341 libraries? Please detail these changes.

Edit: My initial thoughs were you meant this example, but perhaps you meant an example in one of my other libraries? If so which library?

trevorbattle commented 3 years ago

The example I am using is:

https://github.com/Bodmer/JPEGDecoder/tree/master/examples/Other%20libraries/Mega%20and%20Due/TFT_flash_jpg

I am using this with Adafruit's TFT-on-a-shield, the capacitive touch version: https://www.adafruit.com/product/1947

The board is an Arduino Mega2560. The jumpers on the Arduino TFT shield were scratched and soldered to use the SPI connection on the ICSP header, as is standard for Leonardo/MEGA. Again I'm sure your new library is better but I wanted it to work on a Mega so I used the older JPEGDecoder.

Starting with the example, I changed the code to instantiate the TFT to:

#include <Adafruit_ILI9341.h>
#define TFT_CS 10
#define TFT_DC 9
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

I only call that one TFT specific include, but inside that file (Adafruit_ILI9341.h) it includes the others:

#include "Adafruit_GFX.h"
...
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <SPI.h>

All of those libraries are up to date on my Arduino IDE. The Adafruit_SPITFT_Macros.h file is empty.

Before the patch, it wouldn't compile because of setWindow.

I switched setWindow to setAddrWindow as-is and it compiled, but the arguments were now all wrong so it didn't draw the image correctly. (it would draw the correct colours but one pixel row at a time rather than a block at a time so it was scrambled but recognizable as the correct colours for the image)

I was crawling through your patches looking for the right way to update arguments from setWindow to setAddrWindow when I saw the use of drawRGBBitmap to do the whole operation in one line.

Plugged that in and it worked.