From 13414b50373f157a6b9d695054d4d041cb5ca475 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Wed, 14 Dec 2022 17:50:50 +0000 Subject: [PATCH] JPEGDEC: Clip drawing to iWidthUsed. Corrects clipping width using new iWidthUsed value, noticable particularly on smaller jpegs and those that aren't a multiple of the MCU sized. Fixes #573 --- libraries/jpegdec/JPEGDEC.h | 1 + libraries/jpegdec/jpeg.inl | 5 ++++- micropython/modules/jpegdec/jpegdec.cpp | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/libraries/jpegdec/JPEGDEC.h b/libraries/jpegdec/JPEGDEC.h index f49cd3b5..a3f55b8e 100644 --- a/libraries/jpegdec/JPEGDEC.h +++ b/libraries/jpegdec/JPEGDEC.h @@ -108,6 +108,7 @@ typedef struct jpeg_draw_tag { int x, y; // upper left corner of current MCU int iWidth, iHeight; // size of this MCU + int iWidthUsed; // clipped size for odd/edges int iBpp; // bit depth of the pixels (8 or 16) uint16_t *pPixels; // 16-bit pixels void *pUser; diff --git a/libraries/jpegdec/jpeg.inl b/libraries/jpegdec/jpeg.inl index 57c9261e..be792a25 100644 --- a/libraries/jpegdec/jpeg.inl +++ b/libraries/jpegdec/jpeg.inl @@ -3454,10 +3454,13 @@ static int DecodeJPEG(JPEGIMAGE *pJPEG) if (xoff == iPitch || x == cx-1) // time to draw { xoff = 0; - jd.iWidth = iPitch; // width of each LCD block group + jd.iWidth = jd.iWidthUsed = iPitch; // width of each LCD block group jd.pUser = pJPEG->pUser; if (pJPEG->ucPixelType > EIGHT_BIT_GRAYSCALE) // dither to 4/2/1 bits JPEGDither(pJPEG, cx * mcuCX, mcuCY); + if ((x+1)*mcuCX > pJPEG->iWidth) { // right edge has clipped pixels + jd.iWidthUsed = iPitch - (cx*mcuCX - pJPEG->iWidth); + } if ((jd.y - pJPEG->iYOffset + mcuCY) > (pJPEG->iHeight>>iScaleShift)) { // last row needs to be trimmed jd.iHeight = (pJPEG->iHeight>>iScaleShift) - (jd.y - pJPEG->iYOffset); } diff --git a/micropython/modules/jpegdec/jpegdec.cpp b/micropython/modules/jpegdec/jpegdec.cpp index 57e9c59d..6153368e 100644 --- a/micropython/modules/jpegdec/jpegdec.cpp +++ b/micropython/modules/jpegdec/jpegdec.cpp @@ -95,6 +95,7 @@ MICROPY_EVENT_POLL_HOOK uint8_t *pixel = (uint8_t *)pDraw->pPixels; for(int y = 0; y < pDraw->iHeight; y++) { for(int x = 0; x < pDraw->iWidth; x++) { + if(x >= pDraw->iWidthUsed) break; // Clip to the used width current_graphics->set_pen((uint8_t)(*pixel >> 4)); current_graphics->set_pixel({pDraw->x + x, pDraw->y + y}); pixel++; @@ -104,6 +105,7 @@ MICROPY_EVENT_POLL_HOOK uint8_t *pixels = (uint8_t *)pDraw->pPixels; for(int y = 0; y < pDraw->iHeight; y++) { for(int x = 0; x < pDraw->iWidth; x++) { + if(x >= pDraw->iWidthUsed) break; // Clip to the used width int i = y * pDraw->iWidth + x; uint8_t p = pixels[i / 2]; p >>= (i & 0b1) ? 0 : 4; @@ -116,6 +118,7 @@ MICROPY_EVENT_POLL_HOOK uint8_t *pixels = (uint8_t *)pDraw->pPixels; for(int y = 0; y < pDraw->iHeight; y++) { for(int x = 0; x < pDraw->iWidth; x++) { + if(x >= pDraw->iWidthUsed) break; // Clip to the used width int i = y * pDraw->iWidth + x; uint8_t p = pixels[i / 8]; p >>= 7 - (i & 0b111); @@ -127,6 +130,7 @@ MICROPY_EVENT_POLL_HOOK } else { for(int y = 0; y < pDraw->iHeight; y++) { for(int x = 0; x < pDraw->iWidth; x++) { + if(x >= pDraw->iWidthUsed) break; // Clip to the used width int i = y * pDraw->iWidth + x; if (current_graphics->pen_type == PicoGraphics::PEN_RGB332) { if (current_flags & FLAG_NO_DITHER) {