Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions examples/http_stream/stream_huge_jpg
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Example for library:
// https://github.com/Bodmer/TJpg_Decoder

// This example if for ESP32, it renders a Jpeg file
// that is streamed from a http url. The test file
// is way to huge (~18mb) and mainly for showing the limits of the library
// if you scale it down with value 8, it's gonna take around 60s
// shown in it's original size, the stream will take around 10s
// for implementation in real life projects, it's recommended
// to catch images in size of the display

// Include the jpeg decoder library
#include <TJpg_Decoder.h>

// Include SD
#include <WiFi.h>


// Include the TFT library https://github.com/Bodmer/TFT_eSPI
#include "SPI.h"
#include <TFT_eSPI.h> // Hardware-specific library
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
const char* ssid ="ssid";//
const char* password = "password";//
char* url = "https://upload.wikimedia.org/wikipedia/commons/0/00/Center_of_the_Milky_Way_Galaxy_IV_%E2%80%93_Composite.jpg";


// This next function will be called during decoding of the jpeg file to
// render each block to the TFT. If you use a different TFT library
// you will need to adapt this function to suit.
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
// Stop further decoding as image is running off bottom of screen
if ( y >= tft.height() ) return 0;

// This function will clip the image block rendering automatically at the TFT boundaries
tft.pushImage(x, y, w, h, bitmap);

// This might work instead if you adapt the sketch to use the Adafruit_GFX library
// tft.drawRGBBitmap(x, y, bitmap, w, h);

// Return 1 to decode next block
return 1;
}


void setup()
{
Serial.begin(115200);
Serial.println("\n\n Testing TJpg_Decoder library");

Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

// Initialise the TFT
tft.begin();
tft.setTextColor(0xFFFF, 0x0000);
tft.fillScreen(TFT_BLACK);
tft.setSwapBytes(true); // We need to swap the colour bytes (endianess)

// The jpeg image can be scaled by a factor of 1, 2, 4, or 8
TJpgDec.setJpgScale(1);

// The decoder must be given the exact name of the rendering function above
TJpgDec.setCallback(tft_output);
}

void loop()
{
tft.fillScreen(TFT_RED);

// Time recorded for test purposes
uint32_t t = millis();

// Get the width and height in pixels of the jpeg if you wish
uint16_t w = 0, h = 0;
TJpgDec.getJpgSizeFromStream(&w, &h, url);
Serial.print("Width = "); Serial.print(w); Serial.print(", height = "); Serial.println(h);

// Draw the image, top left at 0,0
TJpgDec.drawJpgFromStream(0 ,0, url);
//TJpgDec.drawSdJpg(0, 0, "/panda.jpg");

// How much time did rendering take
t = millis() - t;
Serial.print(t); Serial.println(" ms");

// Wait before drawing again
delay(2000);
}
97 changes: 97 additions & 0 deletions examples/http_stream/stream_jpg
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Example for library:
// https://github.com/Bodmer/TJpg_Decoder

// This example if for ESP32, it renders a Jpeg file
// that is streamed from a http url.

// Include the jpeg decoder library
#include <TJpg_Decoder.h>

// Include SD
#include <WiFi.h>


// Include the TFT library https://github.com/Bodmer/TFT_eSPI
#include "SPI.h"
#include <TFT_eSPI.h> // Hardware-specific library
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
const char* ssid ="ssid";
const char* password = "password";
char* url = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/00/Center_of_the_Milky_Way_Galaxy_IV_%E2%80%93_Composite.jpg/320px-Center_of_the_Milky_Way_Galaxy_IV_%E2%80%93_Composite.jpg";


// This next function will be called during decoding of the jpeg file to
// render each block to the TFT. If you use a different TFT library
// you will need to adapt this function to suit.
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
// Stop further decoding as image is running off bottom of screen
if ( y >= tft.height() ) return 0;

// This function will clip the image block rendering automatically at the TFT boundaries
tft.pushImage(x, y, w, h, bitmap);

// This might work instead if you adapt the sketch to use the Adafruit_GFX library
// tft.drawRGBBitmap(x, y, bitmap, w, h);

// Return 1 to decode next block
return 1;
}


void setup()
{
Serial.begin(115200);
Serial.println("\n\n Testing TJpg_Decoder library");

Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

// Initialise the TFT
tft.begin();
tft.setTextColor(0xFFFF, 0x0000);
tft.fillScreen(TFT_BLACK);
tft.setSwapBytes(true); // We need to swap the colour bytes (endianess)

// The jpeg image can be scaled by a factor of 1, 2, 4, or 8
TJpgDec.setJpgScale(1);

// The decoder must be given the exact name of the rendering function above
TJpgDec.setCallback(tft_output);
}

void loop()
{
tft.fillScreen(TFT_RED);

// Time recorded for test purposes
uint32_t t = millis();

// Get the width and height in pixels of the jpeg if you wish
uint16_t w = 0, h = 0;
TJpgDec.getJpgSizeFromStream(&w, &h, url);
Serial.print("Width = "); Serial.print(w); Serial.print(", height = "); Serial.println(h);

// Draw the image, top left at 0,0
TJpgDec.drawJpgFromStream(0 ,0, url);
//TJpgDec.drawSdJpg(0, 0, "/panda.jpg");

// How much time did rendering take
t = millis() - t;
Serial.print(t); Serial.println(" ms");

// Wait before drawing again
delay(2000);
}
118 changes: 118 additions & 0 deletions src/TJpg_Decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,29 @@ unsigned int TJpg_Decoder::jd_input(JDEC* jdec, uint8_t* buf, unsigned int len)
}
}
#endif

#ifdef TJPGD_LOAD_HTTP_LIBRARY
else if (thisPtr->jpg_source == TJPG_STREAM_FILE)
{
if (thisPtr->array_index + len > thisPtr->array_size)
{
len = thisPtr->array_size - thisPtr->array_index;
}

if(thisPtr->jpg_http->connected())
{
uint8_t _buff[len];
WiFiClient* const stream = thisPtr->jpg_http->getStreamPtr();
if (stream->available()) stream->readBytes(_buff, len);
yield();
if (buf)
{
memcpy_P(buf,_buff,len);
}
thisPtr->array_index = thisPtr->array_index + len;
}
}
#endif

return len;
}
Expand Down Expand Up @@ -156,6 +179,101 @@ int TJpg_Decoder::jd_output(JDEC* jdec, void* bitmap, JRECT* jrect)
}


#if defined (TJPGD_LOAD_HTTP_LIBRARY)

/***************************************************************************************
** Function name: drawJpg
** Description: Draw a named jpg file at x,y (name in char array)
***************************************************************************************/

JRESULT TJpg_Decoder::drawJpgFromStream(int32_t x, int32_t y, char* _url) {
JDEC jdec;
JRESULT jresult = JDR_OK;

jpg_source = TJPG_STREAM_FILE;

jpeg_x = x;
jpeg_y = y;
array_size = 0;
array_index = 0;

jdec.swap = _swap;
jpg_http = new HTTPClient;
jpg_http->begin(_url);
long httpCode = jpg_http->GET();
if (httpCode == HTTP_CODE_OK)
{
array_size = jpg_http->getSize();
Serial.println(array_size);
array_index = 0;
}

// Analyse input data
jresult = jd_prepare(&jdec, jd_input, workspace, TJPGD_WORKSPACE_SIZE, 0);

// Extract image and render
if (jresult == JDR_OK)jresult = jd_decomp(&jdec, jd_output, jpgScale);

if(jpg_http->connected())
{
WiFiClient* const stream = jpg_http->getStreamPtr();
stream->stop();
stream->flush();
}
jpg_http->end();
delete jpg_http;
jpg_http = NULL;

return jresult;
}

/***************************************************************************************
** Function name: getJpgSizeFromStream
** Description: Get width and height of a jpg file (name in char array)
***************************************************************************************/
// Generic file call for SD or SPIFFS, uses leading / to distinguish SPIFFS files
JRESULT TJpg_Decoder::getJpgSizeFromStream(uint16_t *w, uint16_t *h, char *_url){

JDEC jdec;
JRESULT jresult = JDR_OK;

*w = 0;
*h = 0;
array_index = 0;

jpg_source = TJPG_STREAM_FILE;

if(!jpg_http||!jpg_http->connected()){
Serial.println("get size");
jpg_http = new HTTPClient;
jpg_http->begin(_url);
long httpCode = jpg_http->GET();
if (httpCode == HTTP_CODE_OK)
{
array_size = jpg_http->getSize();
}
jresult = jd_prepare(&jdec, jd_input, workspace, TJPGD_WORKSPACE_SIZE, 0);

if (jresult == JDR_OK) {
*w = jdec.width;
*h = jdec.height;
}

if(jpg_http->connected())
{
WiFiClient* const stream = jpg_http->getStreamPtr();
stream->stop();
stream->flush();
}
jpg_http->end();
delete jpg_http;
jpg_http = NULL;
}
return jresult;
}

#endif

#if defined (TJPGD_LOAD_SD_LIBRARY) || defined (TJPGD_LOAD_FFS)

/***************************************************************************************
Expand Down
21 changes: 18 additions & 3 deletions src/TJpg_Decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ Latest version here:
#include "Arduino.h"
#include "tjpgd.h"

#if defined (ESP8266) || defined (ESP32)
#if defined (ARDUINO_ARCH_ESP8266) || defined (ESP32)
#if defined (TJPGD_LOAD_HTTP_LIBRARY)
#include <WiFi.h>
#include <HTTPClient.h>
#endif

#include <pgmspace.h>
#include <FS.h>
#include <LittleFS.h>
Expand All @@ -39,7 +44,8 @@ Latest version here:
enum {
TJPG_ARRAY = 0,
TJPG_FS_FILE,
TJPG_SD_FILE
TJPG_SD_FILE,
TJPG_STREAM_FILE
};

//------------------------------------------------------------------------------
Expand All @@ -56,6 +62,10 @@ class TJpg_Decoder {
#ifdef TJPGD_LOAD_FFS
fs::File jpgFile;
#endif

#if defined (TJPGD_LOAD_HTTP_LIBRARY)
HTTPClient* jpg_http = NULL;
#endif

public:

Expand All @@ -76,13 +86,18 @@ class TJpg_Decoder {
JRESULT getJpgSize(uint16_t *w, uint16_t *h, const char *pFilename);
JRESULT getJpgSize(uint16_t *w, uint16_t *h, const String& pFilename);
#endif

#if defined (TJPGD_LOAD_HTTP_LIBRARY)
JRESULT drawJpgFromStream(int32_t x, int32_t y, char* url) ;
JRESULT getJpgSizeFromStream(uint16_t *w, uint16_t *h, char* url);
#endif

#if defined (TJPGD_LOAD_SD_LIBRARY)
JRESULT drawSdJpg (int32_t x, int32_t y, const char *pFilename);
JRESULT drawSdJpg (int32_t x, int32_t y, const String& pFilename);
JRESULT drawSdJpg (int32_t x, int32_t y, File inFile);

JRESULT getSdJpgSize(uint16_t *w, uint16_t *h, const char *pFilename);
JRESULT getSdJpgSize(uint16_t *w, uint16_t *h, const char *pFilename);
JRESULT getSdJpgSize(uint16_t *w, uint16_t *h, const String& pFilename);
JRESULT getSdJpgSize(uint16_t *w, uint16_t *h, File inFile);
#endif
Expand Down
1 change: 1 addition & 0 deletions src/User_Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
#endif

#define TJPGD_LOAD_SD_LIBRARY
#define TJPGD_LOAD_HTTP_LIBRARY