@@ -11,6 +11,8 @@ bool ImageDecoder::decodeToBW(const char* path, uint8_t* outBuffer, uint16_t tar
1111 ctx.outBuffer = outBuffer;
1212 ctx.targetWidth = targetWidth;
1313 ctx.targetHeight = targetHeight;
14+ ctx.offsetX = 0 ;
15+ ctx.offsetY = 0 ;
1416 ctx.success = false ;
1517 g_ctx = &ctx;
1618
@@ -22,7 +24,7 @@ bool ImageDecoder::decodeToBW(const char* path, uint8_t* outBuffer, uint16_t tar
2224 File f = SD .open (path);
2325 if (!f) return false ;
2426
25- // Use the simpler open() with callbacks to avoid linkage issues with File-based open
27+ // Use manual callback-based open to avoid linkage issues with File-based open
2628 int rc = jpeg.open ((void *)&f, (int )f.size (), [](void *p) { /* close */ },
2729 [](JPEGFILE *pfn, uint8_t *pBuf, int32_t iLen) -> int32_t {
2830 if (!pfn->fHandle ) return -1 ;
@@ -35,16 +37,28 @@ bool ImageDecoder::decodeToBW(const char* path, uint8_t* outBuffer, uint16_t tar
3537
3638 if (rc) {
3739 jpeg.setUserPointer (&ctx);
38- // We want to fit the image to the screen
40+
3941 int scale = 0 ;
40- if (jpeg.getWidth () > targetWidth || jpeg.getHeight () > targetHeight) {
41- // Simplified scaling (JPEGDEC supports 1/2, 1/4, 1/8)
42- if (jpeg.getWidth () > targetWidth * 4 ) scale = JPEG_SCALE_EIGHTH ;
43- else if (jpeg.getWidth () > targetWidth * 2 ) scale = JPEG_SCALE_QUARTER ;
44- else scale = JPEG_SCALE_HALF ;
42+ int iw = jpeg.getWidth ();
43+ int ih = jpeg.getHeight ();
44+
45+ // Determine scaling factor (JPEGDEC supports 1/2, 1/4, 1/8)
46+ if (iw > targetWidth * 4 || ih > targetHeight * 4 ) {
47+ scale = JPEG_SCALE_EIGHTH ;
48+ iw >>= 3 ; ih >>= 3 ;
49+ } else if (iw > targetWidth * 2 || ih > targetHeight * 2 ) {
50+ scale = JPEG_SCALE_QUARTER ;
51+ iw >>= 2 ; ih >>= 2 ;
52+ } else if (iw > targetWidth || ih > targetHeight) {
53+ scale = JPEG_SCALE_HALF ;
54+ iw >>= 1 ; ih >>= 1 ;
4555 }
56+
57+ // Calculate centering offsets
58+ ctx.offsetX = (targetWidth - iw) / 2 ;
59+ ctx.offsetY = (targetHeight - ih) / 2 ;
4660
47- if (jpeg.decode (0 , 0 , scale)) {
61+ if (jpeg.decode (ctx. offsetX , ctx. offsetY , scale)) {
4862 ctx.success = true ;
4963 }
5064 jpeg.close ();
@@ -87,6 +101,10 @@ bool ImageDecoder::decodeToBW(const char* path, uint8_t* outBuffer, uint16_t tar
87101 });
88102
89103 if (rc == PNG_SUCCESS ) {
104+ // PNGdec doesn't have built-in scaling, so it will be drawn top-left or cropped
105+ ctx.offsetX = (targetWidth - png.getWidth ()) / 2 ;
106+ ctx.offsetY = (targetHeight - png.getHeight ()) / 2 ;
107+
90108 rc = png.decode (&ctx, 0 );
91109 if (rc == PNG_SUCCESS ) {
92110 ctx.success = true ;
@@ -106,7 +124,7 @@ int ImageDecoder::JPEGDraw(JPEGDRAW *pDraw) {
106124 DecodeContext *ctx = (DecodeContext *)pDraw->pUser ;
107125
108126 const int destStride = (ctx->targetWidth + 7 ) / 8 ;
109- Serial.printf (" JPEGDraw: x=%d, y=%d, w=%d, h=%d, destStride=%d\n " , pDraw->x , pDraw->y , pDraw->iWidth , pDraw->iHeight , destStride);
127+ // Serial.printf("JPEGDraw: x=%d, y=%d, w=%d, h=%d, destStride=%d\n", pDraw->x, pDraw->y, pDraw->iWidth, pDraw->iHeight, destStride);
110128
111129 for (int y = 0 ; y < pDraw->iHeight ; y++) {
112130 int targetY = pDraw->y + y;
@@ -130,11 +148,11 @@ int ImageDecoder::JPEGDraw(JPEGDRAW *pDraw) {
130148 int bitIdx = 7 - (targetX % 8 );
131149
132150 if (lum < 128 ) {
133- // Black pixel (1 in E-Ink/SSD1677)
134- ctx->outBuffer [byteIdx] |= (1 << bitIdx);
135- } else {
136- // White pixel (0 in E-Ink/SSD1677)
151+ // Black pixel (0 in E-Ink/SSD1677 based on EInkDisplay.cpp)
137152 ctx->outBuffer [byteIdx] &= ~(1 << bitIdx);
153+ } else {
154+ // White pixel (1 in E-Ink/SSD1677 based on EInkDisplay.cpp)
155+ ctx->outBuffer [byteIdx] |= (1 << bitIdx);
138156 }
139157 }
140158 }
@@ -150,14 +168,13 @@ void ImageDecoder::PNGDraw(PNGDRAW *pDraw) {
150168 currentPNG->getLineAsRGB565 (pDraw, usPixels, PNG_RGB565_LITTLE_ENDIAN , 0xffffffff );
151169
152170 const int destStride = (ctx->targetWidth + 7 ) / 8 ;
153- // Serial.printf("PNGDraw: y=%d, w=%d, destStride=%d\n", pDraw->y, pDraw->iWidth, destStride);
154171
155- int targetY = pDraw->y ;
156- if (targetY >= ctx->targetHeight ) return ;
172+ int targetY = pDraw->y + ctx-> offsetY ;
173+ if (targetY < 0 || targetY >= ctx->targetHeight ) return ;
157174
158175 for (int x = 0 ; x < pDraw->iWidth ; x++) {
159- int targetX = x;
160- if (targetX >= ctx->targetWidth ) break ;
176+ int targetX = x + ctx-> offsetX ;
177+ if (targetX < 0 || targetX >= ctx->targetWidth ) continue ;
161178
162179 uint16_t pixel = usPixels[x];
163180 uint8_t r = (pixel >> 11 ) & 0x1F ;
@@ -170,11 +187,11 @@ void ImageDecoder::PNGDraw(PNGDRAW *pDraw) {
170187 int bitIdx = 7 - (targetX % 8 );
171188
172189 if (lum < 128 ) {
173- // Black pixel (1 in E-Ink/SSD1677)
174- ctx->outBuffer [byteIdx] |= (1 << bitIdx);
175- } else {
176- // White pixel (0 in E-Ink/SSD1677)
190+ // Black pixel (0 in E-Ink/SSD1677)
177191 ctx->outBuffer [byteIdx] &= ~(1 << bitIdx);
192+ } else {
193+ // White pixel (1 in E-Ink/SSD1677)
194+ ctx->outBuffer [byteIdx] |= (1 << bitIdx);
178195 }
179196 }
180197}
0 commit comments