Thanks for the program.
I have use it to draw a series of 3 x 3 jpeg map tiles, 256 x 256 pixel, each on a 320 x 480 TFT.
By adding the following line : if ((mcu_x >= 0) && (mcu_y >= 0)) // SL add
I was able to use negative xpos, ypos number to center the 3x3 tiles collection on the screen, and remove the excedent of the image.
`/ 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 jpegRender(int xpos, int ypos) {
// 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 = jpg_min(mcu_w, max_x % mcu_w);
uint32_t min_h = jpg_min(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; // largeur de l'image + position initial si different de 0
max_y += ypos;
// Fetch data from the file, decode and display
while (JpegDec.read()) { // While there is more data in the file
pImg = JpegDec.pImage; // Decode a MCU (Minimum Coding Unit, typically a 8x8 or 16x16 pixel block)
// Calculate coordinates of top left corner of current MCU
int mcu_x = JpegDec.MCUx * mcu_w + xpos;
int mcu_y = JpegDec.MCUy * mcu_h + ypos;
//Serial.println( String( "Top left mcu_x : " + String(mcu_x) + " mcu_y : " + String(mcu_y)) );
if ((mcu_x >= 0) && (mcu_y >= 0)) // SL add
{
// 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++;
}
}
}
// calculate how many pixels must be drawn
uint32_t mcu_pixels = win_w * win_h;
// 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.pushImage(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
}
}
tft.setSwapBytes(swapBytes);
showTime(millis() - drawTime); // These lines are for sketch testing only
}
Thanks for the program.
I have use it to draw a series of 3 x 3 jpeg map tiles, 256 x 256 pixel, each on a 320 x 480 TFT. By adding the following line : if ((mcu_x >= 0) && (mcu_y >= 0)) // SL add
I was able to use negative xpos, ypos number to center the 3x3 tiles collection on the screen, and remove the excedent of the image.
`/ 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 jpegRender(int xpos, int ypos) {
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;
//Serial.println( String( "mcu_w : " + String(mcu_w) + " mcu_h : " + String(mcu_h))); //Serial.println( String( "max_x : " + String(max_x) + " max_y : " + String(max_y)));
//17:43:35.502 -> mcu_w : 16 mcu_h : 16 // 17:43:35.502 -> max_x : 256 max_y : 256
bool swapBytes = tft.getSwapBytes(); tft.setSwapBytes(true);
// 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 = jpg_min(mcu_w, max_x % mcu_w); uint32_t min_h = jpg_min(mcu_h, max_y % mcu_h);
//Serial.println( String( "min_w : " + String(min_w) + " min_h : " + String(min_h)) ); // 17:43:35.502 -> min_w : 0 min_h : 0*/
// 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; // largeur de l'image + position initial si different de 0 max_y += ypos;
// Fetch data from the file, decode and display while (JpegDec.read()) { // While there is more data in the file pImg = JpegDec.pImage; // Decode a MCU (Minimum Coding Unit, typically a 8x8 or 16x16 pixel block)
}
tft.setSwapBytes(swapBytes);
showTime(millis() - drawTime); // These lines are for sketch testing only }
`