Skip to content

Conversation

@TripleWhy
Copy link
Contributor

@TripleWhy TripleWhy commented Jan 14, 2024

I was playing around with some rainbow effects and was wondering why there was no real yellow color. Cyan and magenta are also mysteriously underrepresented. I think rainbow effects should use the full rainbow spectrum.

If you agree, that is what this PR does.
Here are two images displaying the Rainbow effect on 256 LEDs, captured using the web UI:

rainbows

Top: 0_15 (874b24f)
Bottom: mine (760a1d4)

This works by replacing the linear transitions R -> G -> B in color_wheel by the HSV transition 0° -> 360°.

Summary by CodeRabbit

  • New Features

    • Updated the color wheel to provide smoother and more consistent color transitions by rotating through HSV hues.
  • Bug Fixes

    • Removed the "Use 'rainbow' color wheel" option from the LED settings in the user interface to streamline configuration.
  • Refactor

    • Simplified color handling by removing the rainbow color wheel setting and related configuration options.

@blazoncek
Copy link
Collaborator

Bravo! That boggled me as well.
Approved.

@blazoncek
Copy link
Collaborator

One more thing: As to avoid angering certain users please make the new color wheel calculation optional.
Make an entry in LED settings (something like "Use HSV transition for color wheel") and a global selector (WLED_GLOBAL bool hsvColorWheel _INIT(false); ).

@blazoncek
Copy link
Collaborator

Update: Please check colors.cpp and function colorHStoRGB(). You could optimize the code to reuse that function (which itself could be optimised to not use float).

@blazoncek
Copy link
Collaborator

Tested this today but have to say that I fail to see any real difference on my LEDs.

@blazoncek blazoncek requested a review from Aircoookie January 18, 2024 14:45
@TripleWhy
Copy link
Contributor Author

Hm. You are right. There is a difference for me, but I can't really say that one better than the other. My version certainly is a bit brighter (obviously, now that I think about it). I have the cheapest LEDs I could find though.

Possibly there might be a greater difference with higher quality or future LEDs or setups. I mean there clearly is a difference on an LCD screen.

@TripleWhy
Copy link
Contributor Author

Update: Please check colors.cpp and function colorHStoRGB(). You could optimize the code to reuse that function (which itself could be optimised to not use float).

I did actually look at that when I worked on color_wheel and decided against it:

  1. As you said, colorHStoRGB is far from optimal.
  2. colorHStoRGB doesn't preserve the W value... I think?
  3. The computations I used are highly optimized to work with the given assumptions. The computations are reduced so far they are not the direct result of math transformations anymore, they are new formulas that happen to produce the correct result for every possible input. These assumptions that can't be made when colorHStoRGB is used, even if I managed to optimize colorHStoRGB a bit.

If you wish, (and if you want to keep my version in the first place,) I can have a look at what's possible, but it won't be as optimal. It might result in an ever so slightly smaller binary though.
But for that size goal I'd first decide on one version and only keep one.

@blazoncek
Copy link
Collaborator

I've already updated code to utilize both as an option. Please review and comment.

@TripleWhy
Copy link
Contributor Author

I saw that. Some more explicit feedback:

  • I think I wouldn't keep both versions at the same time.
  • Configuration option: I have no idea how this works in WLED, so I can't really comment on that.
  • The setting itself is pretty non-descriptive, so I'd want some more information as a user.
  • colorHStoRGB(): Looks good. Probably doesn't change much though ^^

@TripleWhy
Copy link
Contributor Author

Another option would be to keep the original function for ESP8266, and use the hsv function for ESP32.

I made some comparisons between the color computation of these functions:

D1 Mini

original hsv delta %
exec/ns 429.43 546.26 116.83 127.21 %
flash/bytes 874987 875035 48 100.01 %

WT32-ETH01

original hsv delta %
exec/ns 159.56 170.03 10.47 106.56 %
flash/bytes 1290933 1290957 24 100.00 %

@blazoncek
Copy link
Collaborator

I made some comparisons between the color computation of these functions

Are you talking about color_wheel() and colorHStoRGB() or about old vs. new color_wheel()?

@TripleWhy
Copy link
Contributor Author

TripleWhy commented Jan 19, 2024

color_wheel original vs. mine. The versions of the function I benchmarked didn't contain the first two lines that read palette and currentColor, that's why I said this is about the color computation only.

@blazoncek
Copy link
Collaborator

Perhaps change % 256 into & 0xFF and test again. It should provide same result.

@TripleWhy
Copy link
Contributor Author

According to godbolt's compiler explorer, that produces the same binary

@blazoncek
Copy link
Collaborator

blazoncek commented Jan 19, 2024

According to godbolt's compiler explorer, that produces the same binary

Nice to learn something new. Quite a different ASM to Z80. ;)

So simpler C code produces 27% overhead. Who would've thought.

imeszaros pushed a commit to imeszaros/ledclock that referenced this pull request Jan 20, 2024
@blazoncek blazoncek added the keep This issue will never become stale/closed automatically label Apr 4, 2024
@netmindz netmindz changed the base branch from 0_15 to main December 20, 2024 14:07
@TripleWhy
Copy link
Contributor Author

Is this still PR needed? It looks like there is now an alternative implementation with the same intention in place. However there are some key differences:

  • The implementation in main has a configuration option. So does this PR in the current state, but not in the original state.
  • The implementation in main uses a more generic approach and may result in smaller image size (assuming both versions use the configuration option).
  • The implementation in main is probably far less optimized for speed.
  • The implementation in main inverts the hue, so instead of r->g->b you suddenly get r->b->g when you change the configuration option; while this PR aims to have both rainbows go in the same direction.

@DedeHai
Copy link
Collaborator

DedeHai commented Jul 31, 2025

what is wrong with using fastled HSVtoRGB? I wrote an optimized version of that, stuck in PR limbo.

@TripleWhy
Copy link
Contributor Author

Apart from the direction of H?
Nothing, but this version can skip a lot of steps because it can assume S=V=1.

@DedeHai
Copy link
Collaborator

DedeHai commented Jul 31, 2025

Then I still dont understand why adding another function that does the same is needed? Is it used in any effects where the gained speed matters? If so why not use rainbow palette (IIRC that is fewer operations)?

@TripleWhy
Copy link
Contributor Author

It's not adding a full function, just some specialized code.
But I was asking an honest question. Is this still needed/wanted or should the PR be closed?

@DedeHai
Copy link
Collaborator

DedeHai commented Jul 31, 2025

is the initial assesment still true? i.e. are the colorwheel colors bad?

@TripleWhy
Copy link
Contributor Author

In the default configuration, yes. With the rainbow color wheel option enabled, it now uses an hsv conversion with the caveats described above.

@TripleWhy
Copy link
Contributor Author

If so why not use rainbow palette (IIRC that is fewer operations)?

I forgot to address that: The rainbow color palette simply looks different. If you look at the actual values, it also isn't really an hsv sweep (or at least it wasn't when I last looked at it).

@DedeHai
Copy link
Collaborator

DedeHai commented Jul 31, 2025

I checked this and IMHO yes this is still relevant. However I think adding another version of a rainbow is not a good solution, it should just use fastled HSV to RGB and not add another option for users to choose: 0.16 changes color handling significantly and reading the comments above, the difference is minute in reality (please correct me if I am wrong).
edit:
I see that that is already implemented. In order to not add that config option to not change existing setups: simply changing
hsv2rgb_rainbow(CHSV(pos, 255, 255), rgb);
to
hsv2rgb_rainbow(CHSV(255-pos, 255, 255), rgb);
and removing the old version would render this PR obsolete. right?
edit2:
if you agree with the above @TripleWhy can you provide a new PR with that change including removing the checkmark from the config?

@blazoncek
Copy link
Collaborator

In all honesty I was using code from this PR for several months and though I tried I never really noticed huge difference on displays I used. So I forgot about it.

However at some point @DedeHai came up with this topic and it turned out FastLED had "rainbow" color wheel for a long time. So reusing it seemed natural. I do not expect there are thousands of users that would want three variants of color wheel as the difference might be imperceptible on many LEDs. But I am not against giving users the option since the code is relatively compact and small.

If you can integrate current implementation and add your take (perhaps via dropdown "Select color wheel: Standard/Rainbow/Colorful" or radio button) I think it can be integrated.

@TripleWhy
Copy link
Contributor Author

TripleWhy commented Aug 5, 2025

I believe a quick recap is in order.

  • There are now 3 alternative implementations of color_wheel, let's call them original, rainbow and PR.
  • All of them try to achieve the same thing, as far as I can tell.
  • Therefore, I don't think anyone asks for a configuration switch between 3 versions.
  1. original does a linear transition from R to G to B to R. Fast.
  2. rainbow handles the input as HSV hue and uses fastled to convert from an hsv color to an rgb color. This (looks like it) is by far the slowest version.
  3. PR interprets the input as HSV hue and skips most of the HSV conversion steps. This is slightly slower than original, but (likely) magnitudes faster than rainbow.

At the time, this PR was not merged because of performance considerations. Instead the much slower rainbow was added at some point.

So much for what happened so far. So no, I don't think an option to choose between 3 versions is a good idea. Instead we should decide on one. I have no problem closing this PR. But I would also like to find the best rainbow. :)

 

Now for some new insights. Because there are now 3 versions, I wanted to create an update of the image in the original PR description, and noticed a few issues:

rainbows3

The first (single) line is what gimp thinks a hue sweep should look like.

The other double lines are original, rainbow, PR, in that order. The first single ("raw") line of each double line are the raw rgb colors, that each function produces, saved as srgb png. The second single ("UI") line of each double line is a screenshot of the peek line in the wled UI. It doesn't matter if gamma correction is enabled or not, the line will look the same in the UI. Is there is some other color transformation going on?

Conclusions from this image: of the raw lines, only PR produces all 6 pure colors, and it is basically identical to the gimp version.
Of the UI lines, original looks closest to the gimp version, but it fails to produce pure yellow, cyan, magenta. rainbow produces all pure colors, but its center is skewed to the right, and the transition from cyan to blue looks a bit funky to me. PR produces all pure colors, but the mixed ones are too wide.

So I made a version that looks perfect in the UI
  const uint32_t h = (pos * 3) / 128;
  const uint32_t f = ((pos * 6) % 256) * 7 / 12;
  switch (h) {
    case 0: return RGBW32(255    , f      , 0      , w);
    case 1: return RGBW32(148 - f, 255    , 0      , w);
    case 2: return RGBW32(0      , 255    , f      , w);
    case 3: return RGBW32(0      , 148 - f, 255    , w);
    case 4: return RGBW32(f      , 0      , 255    , w);
    case 5: return RGBW32(255    , 0      , 148 - f, w);
    default: return 0;
  }
but on real world LEDs it looks like you would expect the code, so I'm going to assume that the peek UI is not a reliable source of information.

@DedeHai
Copy link
Collaborator

DedeHai commented Aug 5, 2025

nice comparison. I assume you read the fastled article about why they do it that way?

@TripleWhy
Copy link
Contributor Author

No, otherwise I wouldn't have wondered about it so much I assume ^^

Where is that article?

@DedeHai
Copy link
Collaborator

DedeHai commented Aug 5, 2025

@TripleWhy
Copy link
Contributor Author

I see, thanks. I would say they fail their stated goals. The yellow is even more dull than the one in original. (After all, the absence of yellow in both default and rainbow palettes is what prompted me to look into this in the first place.) And the off-center cyan looks just broken to me in physical setups. But I guess that's just an opinion.

Anyway, that fastled hsv rainbow is actually exactly the rainbow palette. (or at least what it used to be? I think I read something about gamma and modified palettes recently)

So I would argue that there is no need for a hsv2rgb_rainbow-based color_wheel.

@TripleWhy
Copy link
Contributor Author

TripleWhy commented Aug 5, 2025

Oh btw. if this is what fastled uses for "spectrum" hsv<->rgb conversions:

fastled hsv

that also disagrees with what wikipedia says and what PR implements:

fastled hsv

@DedeHai
Copy link
Collaborator

DedeHai commented Aug 6, 2025

you are raising some good points.
I would suggest this:

  • use rainbow palette in colorwheel as it is the one looking more natural and less technical, at least from your comparison above, assuming it does look the same as the fastled rainbow in non-dulled version
  • replace the fastled hsv2rgb with the proper implementation (which I already did, see colors.cpp and improved in Full fastled replacement #4615)

the fastled hsv rainbow version was created for LED use without gamma correction, hence why you see it all dull when applying gamma to it, so we should now ditch that entirely.

edit:
on another note:
I think my suggestion in the other issue to make the new gamma correction optional would be a good way to mitigate some of the issues arising with it. I will add that to the PR if I can find a way to properly do it.

@TripleWhy
Copy link
Contributor Author

Well, I want a technical looking palette, that's the whole point of this PR. ^^

For a more natural one there is always the rainbow palette. I therefore wouldn't get rid of it.

Adding options for gamma correction, and even more gamma correction, and then for where to apply it is nice, but if you need a certain set of options enabled for one palette to look good, and then another set of options enabled for a different palette to look good, it doesn't help, does it. That would only work if those options were parts of the preset instead of the configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 6, 2025

Walkthrough

The changes remove the "rainbow color wheel" feature from the codebase. This includes deleting the useRainbowWheel configuration variable, its UI controls, serialization/deserialization logic, and all related code paths. The Segment::color_wheel function is refactored to always use HSV-based color calculation, removing conditional logic for the previous feature.

Changes

Cohort / File(s) Change Summary
Feature Removal: Rainbow Color Wheel Logic
wled00/FX_fcn.cpp
Refactored Segment::color_wheel to always use HSV-based calculation; removed conditional branches and useRainbowWheel logic.
Configuration Handling Cleanup
wled00/cfg.cpp, wled00/set.cpp, wled00/wled.h
Removed all handling, serialization, and declaration of the useRainbowWheel variable from settings processing, configuration, and global declarations.
User Interface Cleanup
wled00/data/settings_leds.htm, wled00/xml.cpp
Removed the UI checkbox and related form logic for the "rainbow color wheel" option from the settings HTML and XML generation code.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~7 minutes

Suggested reviewers

  • blazoncek

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 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 2f4e300 and 5b261d5.

📒 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
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.
  • 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.

Support

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

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 generate unit tests to generate unit tests for 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.

@blazoncek
Copy link
Collaborator

@TripleWhy please start afresh with new PR. Keep both existing "rainbows" however pleasing they may look to you.
And, please, do not force-push in the future.

In the end it is only this that matters:

const uint32_t h = (pos * 3) / 128;
const uint32_t f = (pos * 6) % 256;
switch (h) {
  case  0: return RGBW32(255    , f      , 0      , w);
  case  1: return RGBW32(255 - f, 255    , 0      , w);
  case  2: return RGBW32(0      , 255    , f      , w);
  case  3: return RGBW32(0      , 255 - f, 255    , w);
  case  4: return RGBW32(f      , 0      , 255    , w);
  case  5: return RGBW32(255    , 0      , 255 - f, w);
  default: return 0;
}

Everything else is cosmetics.

@TripleWhy
Copy link
Contributor Author

Well force-pushing was the cleanest way to get this PR up to date, because it contained commits from yourself that were not supposed to be merged anymore.

As I said, both rainbows still exist, one in the form of an hue sweep (color_wheel), the other in the form of the rainbow palette, which is (or used to be) identical to hsv2rgb_rainbow.

I don't see a reason for a new PR, but I can of course create one if that makes you happy. I would however first like to know if we can agree on a solution, otherwise I don't need to open yet another PR.

blazoncek added a commit to blazoncek/WLED that referenced this pull request Aug 6, 2025
@DedeHai
Copy link
Collaborator

DedeHai commented Aug 6, 2025

Well, I want a technical looking palette, that's the whole point of this PR. ^^

"I was playing around with some rainbow effects and was wondering why there was no real yellow color" was your initial statement, that is what the rainbow palette provides and the technical HSV2RGB does not, at least from your images shown above.

Adding options for gamma correction, and even more gamma correction, and then for where to apply it is nice, but if you need a certain set of options enabled for one palette to look good, and then another set of options enabled for a different palette to look good, it doesn't help, does it.

that is not what I was proposing. I will try to implement it.

@DedeHai
Copy link
Collaborator

DedeHai commented Aug 7, 2025

I ran some tests on this matter and here are my insights:

  • the comparisons shown above are a valid representation on what it looks like on actual LEDs
  • hsv2rgb_rainbow is a very close match to the rainbow palette, the differences are negligible
  • the proposed hsv2rgb produces a more "technical" rainbow with evenly distributed colorbands

my code from #4798 has a too aggressive hue preservation, if I fix that, the gamma correction works very well in all cases, I currently see no need for the "apply gamma after effects" option I proposed earlier.

Bottom line is: I do agree with the overall proposed changes in this PR:

  • remove the option Use "rainbow" color wheel as it is virtually identical to rainbow palette which can be saved in presets rather than the settings, making it more versatile
  • use hsv2rgb as the new default colorwheel as it produces more evenly spread color-bands compared to "original"

I would propose one change: instead of "copying" the already existing hsv2rgb code just use the function. Its slightly slower but in practice I would not expect it to matter much as its at least as fast as color_from_palette()

Here is my proposed solution:

uint32_t Segment::color_wheel(uint8_t pos) const {
  if (palette) return color_from_palette(pos, false, false, 0); // only wrap if "always wrap" is set
  pos = 255 - pos; // legacy color order
  uint8_t w = W(getCurrentColor(0));
  uint32_t rgb;
  hsv2rgb(CHSV32(pos, 255, 255), rgb);
  return rgb | (w << 24); // add white channel
}

Also corrected the comment about wrapping.

@TripleWhy
Copy link
Contributor Author

Sounds good to me, assuming that version of hsv2rgb does the same thing I do here... Should I update the PR or would you like add that code yourself?

However, the direction of the hue gradient should match the original color_wheel, not the rainbow color wheel IMO. I.e. remove pos = 255 - pos;. (Should that line be necessary to match the original color_wheel, I believe hsv2rgb is wrong. :)

As a side note I just noticed CHSV32 with the 16 bit hue for the first time, and immediately questioned the call with 8 bit pos. I do see that there are two constructors, one for 16 bit hue and one for 8 bit hue, and I find that a questionable construct, but that's unrelated to this PR.

@DedeHai
Copy link
Collaborator

DedeHai commented Aug 7, 2025

you can update this PR if you like, since its already 95% there.

I believe its correct the way it is now. But please test it.

since when is a constructor overload a questionable construct?

This is the current result of the discussion in wled#3681
@TripleWhy
Copy link
Contributor Author

TripleWhy commented Aug 7, 2025

Done, tested, looks fine to me.

Anything that makes a reader stop and wonder or look something up is questionable.

An overload isn't questionable on its own, but providing more than one overload for an integer type is problematic, especially if both expect different value ranges. If both expected the range 0-255 it would be fine, but there would also be no point in providing both. If we had strong type guarantees that would also be fine, but c++ casts freely and implicitly between many primitive types. You could of course provide some 8 and 16 bit range types that don't allow implicit casting, to make this safe, but that would just complicate things. Here are some examples where it's not immediately obvious or even misleading which function is called:

CHSV32(255, s, v);

int h;
CHSV32(h, s, v);

uint8_t h;
CHSV32(2*h, s, v);

float h;
CHSV32(h * 255, s, v);

@DedeHai
Copy link
Collaborator

DedeHai commented Aug 7, 2025

Done, tested, looks fine to me.

did you also test the color order against the original?

re: overload: ah, I see. what's the best alternative? a wrapper? or leave it to the caller and not provide it at all? IIRC my idea was to be 1:1 compatible to CHSV but that may have been a bad idea to start with.

@TripleWhy
Copy link
Contributor Author

TripleWhy commented Aug 7, 2025

did you also test the color order against the original?

yes, it's the same order

re: overload: ah, I see. what's the best alternative? a wrapper?

I just noticed that none of the above examples compile, precisely because they are ambiguous, but I guess you get the gist ^^
There is no great alternative. You either provide just the one constructor with more features, and leave the rest up to the user, (however that would make the code above actually compile... I suppose you could explicitly delete other overloads). Optionally you can also provide a static CHSV32::from8Bit (or similar). Or you provide no public constructor, just CHSV32::from16Bit and CHSV32::from8Bit for maximum consistency and clarity.

Edit: you could also provide just the 16 bit constructor and allow implicit casting from CHSV, but I don't think that would improve anything

@DedeHai
Copy link
Collaborator

DedeHai commented Aug 7, 2025

yes, it's the same order

compared against main? I remember it being flipped. That would mean hsv2rgb is also flipped against the _rainbow version of fastled. Or I remember incorrectly.

So I think I will remove the ambiguous overload at one point. Can you therefore please provide a 16bit value so its one less thing to clean up later?

@TripleWhy
Copy link
Contributor Author

TripleWhy commented Aug 7, 2025

yes, it's the same order

compared against main? I remember it being flipped. That would mean hsv2rgb is also flipped against the _rainbow version of fastled. Or I remember incorrectly.

the rainbow color wheel was flipped, because the pos = 255 - pos; line that belongs to the old conversion was left unconditional before the if, instead of moving it with the old conversion into the else. That means that the original color wheel was r>g>b, and the rainbow wheel was r>b>g. The version I just pushed does not use that line and is therefore r>g>b, the same as the original wheel.

So I think I will remove the ambiguous overload at one point. Can you therefore please provide a 16bit value so its one less thing to clean up later?

Ok ^^

@blazoncek
Copy link
Collaborator

@DedeHai you are being inconsistent. In #4798 you are arguing for speed and reimplementing color_fade() when the code is used in a single pass over entire strip, while here you are suggesting the use of hsv2rgb() adding unnecessary computations for function that is called for each pixel which may be painted over several times.

If you insist on preferring speed over compact code, please be consistent. @TripleWhy 's implementation of HSV to RGB was faster as it didn't deal with S & V.

@DedeHai
Copy link
Collaborator

DedeHai commented Aug 7, 2025

I know I am being inconsistend and I gave the reason why I think its acceptable. Please read it again.
If you think its not acceptable, please give me some numbers.

@DedeHai DedeHai merged commit b8b59b2 into wled:main Aug 15, 2025
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effect keep This issue will never become stale/closed automatically

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants