#################################################################################################### Draw a JPEG on the TFT, images will be cropped on the right/bottom sides if they do not fit #################################################################################################### from: https://github.com/Bodmer/TFT_eSPI/blob/master/examples/Generic/ESP32_SDcard_jpeg/ESP32_SDcard_jpeg.
| 1159 | // This function assumes xpos,ypos is a valid screen coordinate. For convenience images that do not |
| 1160 | // fit totally on the screen are cropped to the nearest MCU size and may leave right/bottom borders. |
| 1161 | void jpegRender(int xpos, int ypos) { |
| 1162 | |
| 1163 | // jpegInfo(); // Print information from the JPEG file (could comment this line out) |
| 1164 | |
| 1165 | uint16_t *pImg; |
| 1166 | uint16_t mcu_w = JpegDec.MCUWidth; |
| 1167 | uint16_t mcu_h = JpegDec.MCUHeight; |
| 1168 | uint32_t max_x = JpegDec.width; |
| 1169 | uint32_t max_y = JpegDec.height; |
| 1170 | |
| 1171 | bool swapBytes = tft.getSwapBytes(); |
| 1172 | tft.setSwapBytes(true); |
| 1173 | |
| 1174 | // Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs) |
| 1175 | // Typically these MCUs are 16x16 pixel blocks |
| 1176 | // Determine the width and height of the right and bottom edge image blocks |
| 1177 | uint32_t min_w = jpg_min(mcu_w, max_x % mcu_w); |
| 1178 | uint32_t min_h = jpg_min(mcu_h, max_y % mcu_h); |
| 1179 | |
| 1180 | // save the current image block size |
| 1181 | uint32_t win_w = mcu_w; |
| 1182 | uint32_t win_h = mcu_h; |
| 1183 | |
| 1184 | // save the coordinate of the right and bottom edges to assist image cropping |
| 1185 | // to the screen size |
| 1186 | max_x += xpos; |
| 1187 | max_y += ypos; |
| 1188 | |
| 1189 | // Fetch data from the file, decode and display |
| 1190 | tft.fillRect(xpos, ypos, JpegDec.width, JpegDec.height, TFT_BLACK); |
| 1191 | while (JpegDec.read()) { // While there is more data in the file |
| 1192 | pImg = JpegDec.pImage; // Decode a MCU (Minimum Coding Unit, typically a 8x8 or 16x16 pixel block) |
| 1193 | |
| 1194 | // Calculate coordinates of top left corner of current MCU |
| 1195 | int mcu_x = JpegDec.MCUx * mcu_w + xpos; |
| 1196 | int mcu_y = JpegDec.MCUy * mcu_h + ypos; |
| 1197 | |
| 1198 | // check if the image block size needs to be changed for the right edge |
| 1199 | if (mcu_x + mcu_w <= max_x) win_w = mcu_w; |
| 1200 | else win_w = min_w; |
| 1201 | |
| 1202 | // check if the image block size needs to be changed for the bottom edge |
| 1203 | if (mcu_y + mcu_h <= max_y) win_h = mcu_h; |
| 1204 | else win_h = min_h; |
| 1205 | |
| 1206 | // copy pixels into a contiguous block |
| 1207 | if (win_w != mcu_w) { |
| 1208 | uint16_t *cImg; |
| 1209 | int p = 0; |
| 1210 | cImg = pImg + win_w; |
| 1211 | for (int h = 1; h < win_h; h++) { |
| 1212 | p += mcu_w; |
| 1213 | for (int w = 0; w < win_w; w++) { |
| 1214 | *cImg = *(pImg + w + p); |
| 1215 | cImg++; |
| 1216 | } |
| 1217 | } |
| 1218 | } |
no test coverage detected