diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index 96e131d5..24e5a003 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -49,7 +49,7 @@ bool openGif(const char *filename) { // side-effect: updates "file" } static Segment* activeSeg; -static uint16_t gifWidth, gifHeight; // these two must stay uint16_t, because they are passed by reference +static uint16_t gifWidth = 0, gifHeight = 0; // these two must stay uint16_t, because they are passed by reference static unsigned segCols = 1; static unsigned segRows = 1; static unsigned segLen = 1; // for 1D and 1DExpand support @@ -107,6 +107,29 @@ void drawPixelCallback2D(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8 } } +// calculate image scaling; updates scaling factors and sets the best pixel drawing callback +static void calculateScaling() { + if (gifDecodeFailed) return; + if ((gifWidth > 0 && gifHeight > 0)) { + if (activeSeg->is2D()) { + perPixelX = (segCols + gifWidth -1) / gifWidth; + perPixelY = (segRows + gifHeight-1) / gifHeight; + if (segCols != gifWidth || segRows != gifHeight) { + decoder.setDrawPixelCallback(drawPixelCallback2D); // use 2D callback with scaling + } else { + decoder.setDrawPixelCallback(drawPixelCallbackNoScale2D); // use 2D callback without scaling + } + } else { + int totalImgPix = (int)gifWidth * gifHeight; + if (totalImgPix - segLen == 1) totalImgPix--; // handle off-by-one: skip last pixel instead of first (gifs constructed from 1D input pad last pixel if length is odd) + perPixelX = (segLen + totalImgPix-1) / totalImgPix; + if (totalImgPix != segLen) { + decoder.setDrawPixelCallback(drawPixelCallback1D); // use 1D callback with scaling + } + } + } +} + #define IMAGE_ERROR_NONE 0 #define IMAGE_ERROR_NO_NAME 1 #define IMAGE_ERROR_SEG_LIMIT 2 @@ -192,24 +215,7 @@ byte renderImageToSegment(Segment &seg) { USER_PRINTF("Invalid GIF dimensions: %dx%d\n", gifWidth, gifHeight); return IMAGE_ERROR_GIF_DECODE; } - if (activeSeg->is2D()) { - perPixelX = (segCols + gifWidth -1) / gifWidth; - perPixelY = (segRows + gifHeight-1) / gifHeight; - if (segCols != gifWidth || segRows != gifHeight) { - decoder.setDrawPixelCallback(drawPixelCallback2D); // use 2D callback with scaling - //DEBUG_PRINTLN(F("scaling image")); - } else { - decoder.setDrawPixelCallback(drawPixelCallbackNoScale2D); // use 2D callback without scaling - } - } else { - int totalImgPix = (int)gifWidth * gifHeight; - if (totalImgPix - segLen == 1) totalImgPix--; // handle off-by-one: skip last pixel instead of first (gifs constructed from 1D input pad last pixel if length is odd) - perPixelX = (segLen + totalImgPix-1) / totalImgPix; - if (totalImgPix != segLen) { - decoder.setDrawPixelCallback(drawPixelCallback1D); // use 1D callback with scaling - //DEBUG_PRINTLN(F("scaling image")); - } - } + calculateScaling(); } if (gifDecodeFailed) return IMAGE_ERROR_PREV; @@ -227,6 +233,9 @@ byte renderImageToSegment(Segment &seg) { unsigned td0 = millis(); while (strip.isUpdating() && (millis() - td0 < 20)) delay(1); // wait up to 20ms for LED output to finish + // WLEDMM experimental: segment options might change (mirror, transpose, grouping, spacing) at any time + calculateScaling(); // --> re-calculate scaling for each frame + int result = decoder.decodeFrame(false); if (result < 0) { USER_PRINTF("GIF Decoding error %d in decodeFrame().\n", result); @@ -247,6 +256,7 @@ void endImagePlayback(Segment *seg) { if (!activeSeg || activeSeg != seg) return; if (file) file.close(); decoder.dealloc(); + gifWidth = 0; gifHeight = 0; // WLEDMM clear cached image dimensions gifDecodeFailed = false; activeSeg = nullptr; strcpy(lastFilename, "/"); // reset filename