Closed multiholle closed 4 years ago
There is no scaling capability built into this library. Simple methods are to skip pixels. Best is to blend NxN pixel blocks to find the average colour and plot as a single pixel.
The TJpg_Decoder library does handle scaling down by pixel skipping and has higher overall performance on 32 bit processors. Sketches are simplified too.
I'm loading the image to display from a web server and would like to scale the image to fit the screen. Simple scaling by 1/2 or 1/4 would be sufficient.
my code
```cpp #include
#include
#include
#include
TFT_eSPI tft = TFT_eSPI();
const char* ssid = "****";
const char* password = "****";
// JPEG decoder library
#include
const int picBufferSize = 640*480;
void *picBuffer = NULL;
// Return the minimum of two values a and b
#define minimum(a,b) (((a) < (b)) ? (a) : (b))
//####################################################################################################
// Draw a JPEG on the TFT, images will be cropped on the right/bottom sides if they do not fit
//####################################################################################################
// This function assumes xpos,ypos is a valid screen coordinate. For convenience images that do not
// fit totally on the screen are cropped to the nearest MCU size and may leave right/bottom borders.
void renderJPEG(int xpos, int ypos) {
// retrieve infomration about the image
uint16_t *pImg;
uint16_t mcu_w = JpegDec.MCUWidth;
uint16_t mcu_h = JpegDec.MCUHeight;
uint32_t max_x = JpegDec.width;
uint32_t max_y = JpegDec.height;
// Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs)
// Typically these MCUs are 16x16 pixel blocks
// Determine the width and height of the right and bottom edge image blocks
uint32_t min_w = minimum(mcu_w, max_x % mcu_w);
uint32_t min_h = minimum(mcu_h, max_y % mcu_h);
// save the current image block size
uint32_t win_w = mcu_w;
uint32_t win_h = mcu_h;
// record the current time so we can measure how long it takes to draw an image
uint32_t drawTime = millis();
// save the coordinate of the right and bottom edges to assist image cropping
// to the screen size
max_x += xpos;
max_y += ypos;
// read each MCU block until there are no more
while (JpegDec.readSwappedBytes()) {
// save a pointer to the image block
pImg = JpegDec.pImage ;
// calculate where the image block should be drawn on the screen
int mcu_x = JpegDec.MCUx * mcu_w + xpos; // Calculate coordinates of top left corner of current MCU
int mcu_y = JpegDec.MCUy * mcu_h + ypos;
// check if the image block size needs to be changed for the right edge
if (mcu_x + mcu_w <= max_x) win_w = mcu_w;
else win_w = min_w;
// check if the image block size needs to be changed for the bottom edge
if (mcu_y + mcu_h <= max_y) win_h = mcu_h;
else win_h = min_h;
// copy pixels into a contiguous block
if (win_w != mcu_w)
{
uint16_t *cImg;
int p = 0;
cImg = pImg + win_w;
for (int h = 1; h < win_h; h++)
{
p += mcu_w;
for (int w = 0; w < win_w; w++)
{
*cImg = *(pImg + w + p);
cImg++;
}
}
}
// 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())
{
tft.pushRect(mcu_x, mcu_y, win_w, win_h, pImg);
}
else if ( (mcu_y + win_h) >= tft.height()) JpegDec.abort(); // Image has run off bottom of screen so abort decoding
}
// calculate how long it took to draw the image
drawTime = millis() - drawTime;
// print the results to the serial port
Serial.print(F( "Total render time was : ")); Serial.print(drawTime); Serial.println(F(" ms"));
Serial.println(F(""));
}
//####################################################################################################
// Draw a JPEG on the TFT pulled from a program memory array
//####################################################################################################
void drawArrayJpeg(const uint8_t arrayname[], uint32_t array_size, int xpos, int ypos) {
int x = xpos;
int y = ypos;
JpegDec.decodeArray(arrayname, array_size);
renderJPEG(x, y);
Serial.println("#########################");
}
void setup(void) {
Serial.begin(115200);
tft.init();
tft.fillScreen(TFT_BLACK);
delay(10);
Serial.println();
Serial.println();
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());
picBuffer = malloc(picBufferSize);
HTTPClient http;
http.begin("https://placebear.com/128/128"); //Specify the URL
int httpCode = http.GET(); //Make the request
if (httpCode > 0) { //Check for the returning code
//String payload = http.getString();
Serial.println(httpCode);
//Serial.println(payload);
int len = http.getSize();
Serial.printf("[HTTP] size: %d\n", len);
WiFiClient * stream = http.getStreamPtr();
// read all data from server
uint8_t* p = (uint8_t*) picBuffer;
int l = len;
while (http.connected() && (l > 0 || len == -1))
{
// get available data size
size_t size = stream->available();
if (size)
{
int c = stream->readBytes(p, size);
p += size;
Serial.printf("[HTTP] read: %d\n", c);
}
}
Serial.println();
Serial.print("[HTTP] connection closed.\n");
drawArrayJpeg((uint8_t*) picBuffer, len, 0, 16);
}
else {
Serial.println("Error on HTTP request");
}
http.end();
}
void loop(){
}
```