Skip to content

Conversation

@netmindz
Copy link
Collaborator

@netmindz netmindz commented Feb 22, 2025

Pull in GIF support from upstream

Summary by CodeRabbit

  • New Features

    • Introduced an animated GIF image effect, allowing users to display GIFs on LED segments.
  • Chores

    • Added GIF animation and decoding libraries with build configuration updates for enhanced GIF support.

@netmindz netmindz marked this pull request as draft February 22, 2025 12:49
@netmindz
Copy link
Collaborator Author

TODO: tidy up lib_deps and device which builds we include this with

@coderabbitai
Copy link

coderabbitai bot commented Feb 22, 2025

Walkthrough

The changes integrate GIF handling support into the project. The configuration file now includes two new library dependencies and a build flag to enable GIF functionality. The effect system has been updated to include a new image effect mode that renders .gif images from the filesystem, replacing a previous Halloween mode. Additional modifications include function declarations for file operations and the implementation of GIF image loading and playback cleanup within a new file.

Changes

File(s) Change Summary
platformio.ini Added library dependencies (bitbank2/AnimatedGIF@^1.4.7 and GitHub/Aircoookie/GifDecoder#bc3af18) and a new build flag (-D WLED_ENABLE_GIF).
wled00/FX.cpp, wled00/FX.h Introduced a new image effect mode for displaying GIFs; replaced the Halloween mode with the new Image mode (FX_MODE_IMAGE now defined as 53).
wled00/FX_fcn.cpp, wled00/fcn_declare.h Added a conditional call to endImagePlayback during segment resets and declared several new functions for file callbacks and image rendering.
wled00/image_loader.cpp New file implementing GIF loading: includes callbacks for file operations, opening GIF files, rendering images to segments, and ending playback.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant E as ImageEffect
    participant S as Segment
    participant L as ImageLoader
    U->>E: Activate Image Effect
    E->>S: Update segment with GIF mode
    alt GIF enabled
        S->>L: Call openGif(filename)
        L->>S: Render frame via renderImageToSegment()
        S->>L: Reset segment → call endImagePlayback()
    end
Loading

Poem

I'm a rabbit with a code so fine,
GIF magic now dances on each LED line.
Hopping through functions with a cheerful tune,
I light up pixels like a bright, full moon.
Hop along, dear coders, our changes truly shine! 🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cf8aacb and c5a28c2.

📒 Files selected for processing (1)
  • wled00/FX_fcn.cpp (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • wled00/FX_fcn.cpp
⏰ Context from checks skipped due to timeout of 90000ms (20)
  • GitHub Check: Builds (adafruit_matrixportal_esp32s3_tinyUF2)
  • GitHub Check: Builds (esp32s2_PSRAM_M)
  • GitHub Check: Builds (esp8266_4MB_M)
  • GitHub Check: Builds (esp01_1MB_S)
  • GitHub Check: Builds (esp32c3mini_dio_4MB_M)
  • GitHub Check: Builds (esp8266_2MB_S)
  • GitHub Check: Builds (esp32S3_8MB_PSRAM_M)
  • GitHub Check: Builds (esp32_4MB_V4_HUB75_forum)
  • GitHub Check: Builds (esp32S3_4MB_PSRAM_M)
  • GitHub Check: Builds (esp32S3_8MB_M)
  • GitHub Check: Builds (esp32S3_4MB_S)
  • GitHub Check: Builds (esp32_4MB_PSRAM_S)
  • GitHub Check: Builds (esp32S3_8MB_S)
  • GitHub Check: Builds (esp32_4MB_V4_S)
  • GitHub Check: Builds (esp32_4MB_M_debug)
  • GitHub Check: Builds (esp32_16MB_M_eth)
  • GitHub Check: Builds (esp32_4MB_XL)
  • GitHub Check: Builds (esp32_pico_4MB_M)
  • GitHub Check: Builds (esp32_4MB_M)
  • GitHub Check: Builds (esp32_4MB_S)
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@netmindz netmindz marked this pull request as ready for review February 22, 2025 13:30
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
wled00/FX.h (1)

189-189: New effect mode ID assigned to “Image.”
The definition #define FX_MODE_IMAGE 53 correctly introduces the new image effect mode. If backward compatibility with any removed mode is needed, consider using a different ID or implement a migration path.

wled00/FX_fcn.cpp (1)

272-293: Consider adding error handling for GIF cleanup.

While the GIF cleanup integration looks good, consider adding error handling to catch and log any potential failures during GIF cleanup operations.

  #ifdef WLED_ENABLE_GIF
- endImagePlayback(this);
+ if (!endImagePlayback(this)) {
+   // Log error or set error flag
+   DEBUG_PRINTLN(F("Failed to cleanup GIF resources"));
+ }
  #endif
wled00/FX.cpp (1)

4664-4667: Remove commented debug code.

The commented debug print statements should be removed as they are not being used.

-  // if (status != 0 && status != 254 && status != 255) {
-  //   Serial.print("GIF renderer return: ");
-  //   Serial.println(status);
-  // }
platformio.ini (1)

264-265: Review of GIF Library Dependencies Addition:
The two new library entries:
bitbank2/AnimatedGIF@^1.4.7
https://github.com/Aircoookie/GifDecoder#bc3af18
have been added to the global lib_deps section. This change clearly aligns with the PR’s goal to integrate GIF playback support.

  • Compatibility Check: Ensure these library versions are compatible with your other dependencies and target platforms.
  • Conditional Inclusion: Given the comment in the PR about tidying up lib_deps and board-specific builds, consider if these dependencies should be conditionally included only for environments that require GIF support. This might optimize flash size on devices that do not use this feature.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e9d07d6 and 1c414dc.

📒 Files selected for processing (6)
  • platformio.ini (2 hunks)
  • wled00/FX.cpp (2 hunks)
  • wled00/FX.h (1 hunks)
  • wled00/FX_fcn.cpp (1 hunks)
  • wled00/fcn_declare.h (1 hunks)
  • wled00/image_loader.cpp (1 hunks)
🔇 Additional comments (8)
wled00/image_loader.cpp (1)

133-142: Resource cleanup looks correct.
The endImagePlayback() implementation closes the file, deallocates the decoder, and resets state variables. This helps avoid memory leaks or dangling references.

wled00/fcn_declare.h (1)

112-123: Ensure consistent function naming across files.
All newly introduced GIF-related callback prototypes appear consistent with their counterparts in image_loader.cpp. However, confirm that each callback name exactly matches its definition to prevent linkage errors.

wled00/FX_fcn.cpp (2)

290-292: LGTM: GIF cleanup integration looks good.

The addition of the GIF cleanup code in resetIfRequired() is well-placed and properly guarded by the WLED_ENABLE_GIF preprocessor directive. This ensures proper cleanup of GIF resources when a segment is reset.


272-293:

Details

✅ Verification successful

Verify GIF cleanup implementation.

The resetIfRequired() method handles cleanup of various segment resources. Let's verify that the GIF cleanup is properly implemented in the codebase.


🏁 Script executed:

#!/bin/bash
# Description: Check for GIF cleanup implementation
# Look for endImagePlayback implementation and related GIF cleanup code

# Search for endImagePlayback function definition
echo "Searching for endImagePlayback implementation..."
rg "endImagePlayback.*\(.*Segment" -A 5

# Search for GIF-related cleanup code
echo "Searching for GIF cleanup code..."
rg "WLED_ENABLE_GIF.*cleanup" -A 5

Length of output: 844


GIF cleanup confirmed.
The call to endImagePlayback(this) inside the #ifdef WLED_ENABLE_GIF block in wled00/FX_fcn.cpp is correctly implemented. The function definition in wled00/image_loader.cpp shows that it properly handles resource cleanup by closing any open file and deallocating the GIF decoder. No further changes are required for GIF cleanup.

wled00/FX.cpp (3)

9092-9094: LGTM!

The Image effect is properly integrated into the effects list with appropriate conditional compilation.


4657-4668:

Details

❓ Verification inconclusive

Consider the TODO from PR description.

The PR mentions a TODO about organizing lib_deps and device builds. While this file implements the GIF functionality correctly, ensure that the necessary library dependencies and device configurations are properly managed in the build system.


🏁 Script executed:

#!/bin/bash
# Search for library dependencies and build configurations
rg -l 'WLED_ENABLE_GIF' platformio.ini

Length of output: 53


Action: Verify that build configurations and library dependencies for GIF support are fully organized as discussed.

The GIF functionality in the file is implemented correctly with proper conditional compilation. However, the PR’s TODO regarding the organization of lib_deps and device builds still needs your attention. While the grep confirms that platformio.ini includes the WLED_ENABLE_GIF flag, please review and ensure that the build system properly incorporates any additional library dependencies and that device configurations are appropriately updated.


4669-4669:

Details

✅ Verification successful

Verify the effect data string parameters.

The effect data string includes sx=128 which might limit the matrix size. Please verify:

  1. Is 128 the maximum supported size?
  2. What do the "!" parameters represent?

🏁 Script executed:

#!/bin/bash
# Search for documentation or usage of effect data string parameters
rg -A 5 'sx=' wled00/

Length of output: 7424


Re: Verification of effect data string parameters in Image mode

After reviewing the data strings across the codebase, here are the findings:

  • Matrix Size Parameter (sx):
    The value sx=128 in the Image effect is consistent with the arbitrary sizing used in other effects—values range from 24 up to 255 in different modes. This confirms that 128 is not a hard upper limit but simply the configured value for this particular effect.

  • Exclamation Mark (!) Parameters:
    The ! entries appear as placeholders in the effect data strings. They denote parameters that are either not explicitly set or should fall back to default behavior, as evidenced by their consistent usage across multiple effects.

Overall, the current implementation appears intentional, and there is no indication of a limitation imposed by the use of sx=128 or the default markers.

platformio.ini (1)

1113-1113: Build Flag for GIF Support:
The flag -D WLED_ENABLE_GIF has been added in the shared build flags section (build_flags_S), which will conditionally enable GIF-related code in the project.

  • Consistency Check: Please verify that all parts of the codebase implementing GIF playback are correctly guarded by this flag so that the feature compiles only when intended.

Comment on lines +115 to +116
uint32_t wait = currentFrameDelay * 2 - seg.speed * currentFrameDelay / 128;

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Prevent potential integer underflow in frame timing.
When seg.speed is very high, seg.speed * currentFrameDelay / 128 could exceed currentFrameDelay * 2. This may cause underflow upon subtracting, resulting in a large unsigned value for wait and stalling updates.

-  uint32_t wait = currentFrameDelay * 2 - seg.speed * currentFrameDelay / 128;
+  uint32_t speedDelay = seg.speed * currentFrameDelay / 128;
+  uint32_t baseDelay  = currentFrameDelay * 2;
+  uint32_t wait       = (speedDelay >= baseDelay) ? 0 : (baseDelay - speedDelay);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
uint32_t wait = currentFrameDelay * 2 - seg.speed * currentFrameDelay / 128;
uint32_t speedDelay = seg.speed * currentFrameDelay / 128;
uint32_t baseDelay = currentFrameDelay * 2;
uint32_t wait = (speedDelay >= baseDelay) ? 0 : (baseDelay - speedDelay);

Comment on lines +13 to +14
char lastFilename[34] = "/";
GifDecoder<320,320,12,true> decoder;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Consider validating lastFilename length before substring operations.
Storing the segment name at lastFilename + 1 and later relying on strlen(lastFilename) - 4 to verify whether it ends with ".gif" may risk out-of-bounds reads if seg.name is too short. A length check would harden this logic against malformed or truncated segment names.

 if (strncmp(lastFilename +1, seg.name, 32) != 0) {
+  if (strlen(seg.name) < 4) {
+    gifDecodeFailed = true;
+    return IMAGE_ERROR_UNSUPPORTED_FORMAT; 
+  }
   strncpy(lastFilename +1, seg.name, 32);
   ...
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
char lastFilename[34] = "/";
GifDecoder<320,320,12,true> decoder;
if (strncmp(lastFilename + 1, seg.name, 32) != 0) {
if (strlen(seg.name) < 4) {
gifDecodeFailed = true;
return IMAGE_ERROR_UNSUPPORTED_FORMAT;
}
strncpy(lastFilename + 1, seg.name, 32);
// ... rest of the code
}

@byOZN
Copy link

byOZN commented Mar 10, 2025

Please tell me how to upload it .Gif to the file system to try it out?

@netmindz
Copy link
Collaborator Author

Go to http://IP/edit

@byOZN
Copy link

byOZN commented Mar 12, 2025

Go to http://IP/edit

I just tested this with my HUB75 panels. Target: adafruit_matrixportal_esp32s . I connected 3 32x64 panels. When playing the effect, it's as if only the first frame from the gif is displayed on the panel and that's it.. I'll be watching the debugging information.
In debugging, I see the following messages that are repeated
Starting decoding -> Decoding started -> Image playback ended

@netmindz
Copy link
Collaborator Author

Thanks for testing, @byOZN , looks like some changes are needed to make compatible with WLED-MM then

@softhack007

@byOZN
Copy link

byOZN commented Mar 13, 2025

Thanks for testing, @byOZN , looks like some changes are needed to make compatible with WLED-MM then

@softhack007

I commented out the code in the void endImagePlayback(Segment*seg) function and the Gif started displaying normally. I will investigate the problem further.

@netmindz
Copy link
Collaborator Author

endImagePlayback

Thanks for testing, @byOZN , looks like some changes are needed to make compatible with WLED-MM then
@softhack007

I commented out the code in the void endImagePlayback(Segment*seg) function and the Gif started displaying normally. I will investigate the problem further.

Looks like I'm probably calling that method in the wrong place in resetIfRequired then

Should it be inside both ifs @softhack007 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants