New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gradient banding #126
Comments
I just realized that you could do the noise thing with a custom sampler. Here's a palette sampler that can apply noise:
and the result with a noise level of +/- 4 (NoiseLevel = 1 / 256 * 4): I think I would prefer the banding. |
first thanks for your answer, I did some tests today
for small components like Button, Progressbar, LED's the Gradient is fine. but for bigger components like a Panel it's not. so it's sucks if i have to rewrite all my components that are using Gradients. Demo file Gradients.zip oh and it's not just in grayscale you can choose any other color combination same result. My Monitor is x2 Dell U2715H (2560x1440) |
@lbWishmaster Your example is flagged by BitDefender as a trojan (Gen:Variant.Ursu.750045) on my system. Probably a false positive. |
I just realized that you are using the polygon gradient functions (
I can fix the problem in |
So I've managed to fix almost all problems in the gradient functions I'm using. It turned out that I had enabled gradient smoothing which means it actually did a cosine gradient instead of a linear gradient. The remaining problems are caused by rounding errors but I'm down to 2-3 duplicate colors in a 256 color gradient. However this doesn't really help you with your problem. I have tried to spot any problems in I'll unassign myself from this issue now since there's nothing more I can do. Angus isn't active in Graphics32 anymore so it's unlikely that he will fix the problem and unless someone else is willing to have a go at it I'm afraid you'll have to try another solution. |
thank you for your help and time. I guess i have to find different solution. but that's one of the reasons why I avoid open source. no official support, the people who wrote a certain code moved on. after that try to find out what they did. and this is a great library (G32) |
And I'm still lurking here though, as Anders correctly states, I'm no longer actively contributing to this library. Nevertheless I'd still be happy to make suggestions except that GR32_ColorGradients has changed so much since my initial contribution that I don't see anything there that resembles what I originally wrote. |
@angus so I wouldn't mind if you can give it a go and help me out ;-) but I have successfully integrated the Gradient part of the pegtop Lib. into my Component Pack. |
Hi @AngusJohnson Yes, I can see from the history that most changes was done by @CWBudde. Maybe he can fix it. I think I've found the spot where the Lerp between the gradient colors takes place:
@lbWishmaster If you've decided to replacethe use of polgon gradients then you might consider using the same gradient functions I'm using. I have already fixed the problem in them and they work with Delphi 10.3.3. They don't support dithering though - yet. |
@andersmelander for sure I can give it a shot. but i have a little more time on the weekend. day job :-( |
@lbWishmaster I've attached the units
You can ignore the "BitmapEditor" stuff and if you're not using Delphi 10.3.3 then you'll have to move the var declarations. |
I have now resolved this problem in my own gradient fill routines (not the same ones used by the polygon gradient filler) by adding optional dithering. I'm documenting the findings I made and the result here for the benefit of whomever tries to fix it in the polygon gradient fill. First of all I discovered that there's a problem in the functions that generate a gradient palette. When creating a 256 entry palette going from black to white the result should be 256 distinct colors. For both Graphics32 and PegTop the generated palette contained less than 256 colors which of course meant that the gradient based on that palette was slightly wrong. Next there's the problem of color depth in the palette. When the colors of the palette are being calculated by interpolating from one color stop to the next, they will be quantized down to 8 bits per channel since the palette stores the colors as TColor32 entries. This isn't a problem if the palette goes from one pure color to another pure color (e.g. black to white) since this transition can be represented in 256 entries without loss, but if the two colors are close (e.g. $7F7F7F to $A0A0A0) then the fractional colors can not be represented and there will be banding in the palette due to rounding errors. PegTop solves this with a 64-bit palette (16-bit per channel) and that is the solution I have used as well. With that out the place I have been able to implement dithering based on the GR32_PaletteSamplers unit (not a part of standard Graphics32). I have implemented the following dithering methods:
Here are the results. I first filled a 512x512 bitmap diagonally with a black to white gradient. I then cropped this bitmap to 64x64 and expanded the dynamic range to make the banding visible. I did the same for a 32x32 bitmap to make it even more visible. Interleaved Gradient Noise dither Edit: I initially uploaded the wrong versions of the blue noise and interleaved gradient images above. I have updated the post with the correct images. While the White and Blue Noise dither may appear similar they differ in the frequency spectrum of the noise they apply. References: |
Thanks Anders.
Very interesting and helpful.
Cheers
A.
…On 28/11/2020 3:54 am, Anders Melander wrote:
I have now resolved this problem in my own gradient fill routines (not
the same ones used by the polygon gradient filler) by adding optional
dithering. I'm documenting the findings I made and the result here for
the benefit of whomever tries to fix it in the polygon gradient fill.
First of all I discovered that there's a problem in the functions that
generate a gradient palette. When creating a 256 entry palette going
from black to white the result should be 256 distinct colors. For both
Graphics32 and PegTop the generated palette contained less than 256
colors which of course meant that the gradient based on that palette
was slightly wrong.
Next there's the problem of color depth in the palette. When the
colors of the palette are being calculated by interpolating from one
color stop to the next, they will be quantized down to 8 bits per
channel since the palette stores the colors as TColor32 entries. This
isn't a problem if the palette goes from one pure color to another
pure color (e.g. black to white) since this transition can be
represented in 256 entries without loss, but if the two colors are
close (e.g. $7F7F7F to $A0A0A0) then the fractional colors can not be
represented and there will be banding in the palette due to rounding
errors. PegTop solves this with a 64-bit palette (16-bit per channel)
and that is the solution I have used as well.
With that out the place I have been able to implement dithering based
on the GR32_PaletteSamplers unit (not a part of standard Graphics32).
I have implemented the following dithering methods:
* Bayer Ordered <https://en.wikipedia.org/wiki/Ordered_dithering> dither
* White Noise <https://en.wikipedia.org/wiki/White_noise> dither
* Blue Noise dither (low and high dynamic range
<https://en.wikipedia.org/wiki/High-dynamic-range_imaging>)^1 <#ref1>
* Interleaved Gradient dither^2 <#ref2>
Here are the results. I first filled a 512x512 bitmap diagonally with
a black to white gradient. I then cropped this bitmap to 64x64 and
expanded the dynamic range
<https://en.wikipedia.org/wiki/Normalization_(image_processing)> to
make the banding visible. I did the same for a 32x32 bitmap to make it
even more visible.
The 512x512 images below are scaled in the HTML to 128x128. Click on
the images to view them at their actual size, without any artifacts
produced by the browser scaling the images.
*No dithering*
<https://user-images.githubusercontent.com/18141921/100469151-08943f80-30d6-11eb-838d-8e9421c69140.png>normal
64x64
<https://user-images.githubusercontent.com/18141921/100472932-76903500-30dd-11eb-814d-a73cecc649d6.png>normal
32x32
<https://user-images.githubusercontent.com/18141921/100472977-93c50380-30dd-11eb-85cc-70609a263a2b.png>
*Bayer Ordered dither*
<https://user-images.githubusercontent.com/18141921/100470395-77729800-30d8-11eb-923a-22b968c0875f.png>bayer
64x64
<https://user-images.githubusercontent.com/18141921/100473009-ac351e00-30dd-11eb-8d7e-d139baf86faf.png>bayer
32x32
<https://user-images.githubusercontent.com/18141921/100473013-ae977800-30dd-11eb-9c45-cebb798cfa5d.png>
*White Noise dither*
<https://user-images.githubusercontent.com/18141921/100470821-40e94d00-30d9-11eb-9dd6-93b312491da5.png>white
noise 64x64
<https://user-images.githubusercontent.com/18141921/100473028-ba833a00-30dd-11eb-952a-ceb508e0644f.png>white
noise 32x32
<https://user-images.githubusercontent.com/18141921/100473034-beaf5780-30dd-11eb-81b9-b91dc921f11b.png>
*Blue Noise (LDR) dither*
<https://user-images.githubusercontent.com/18141921/100471149-f61c0500-30d9-11eb-92fc-4be3dd260f54.png>blue
noise ldr 64x64
<https://user-images.githubusercontent.com/18141921/100473061-cd960a00-30dd-11eb-928a-4be248adc165.png>blue
noise ldr 32x32
<https://user-images.githubusercontent.com/18141921/100473069-d090fa80-30dd-11eb-9126-627d6b5f2506.png>
*Interleaved Gradient Noise dither*
<https://user-images.githubusercontent.com/18141921/100471220-21065900-30da-11eb-938a-c271f79860ff.png>interleaved
noise 64x64
<https://user-images.githubusercontent.com/18141921/100473094-db4b8f80-30dd-11eb-822e-429116a237a7.png>interleaved
noise 32x32
<https://user-images.githubusercontent.com/18141921/100473099-de468000-30dd-11eb-9287-db9320105332.png>
While all the noise based dithers may appear similar they differ in
the frequency spectrum of the noise they apply.
References:
[1] Blue-noise Dithered Sampling, Iliyan Georgiev and Marcos Fajard
<https://www.solidangle.com/research/dither_abstract.pdf>
[2] Next Generation Post Processing in Call of Duty: Advanced Warfare,
Jorge Jimenez
<http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare>
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#126 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABIJHNGFMQ7NU2IOEW435JDSR7RTVANCNFSM4KVB727Q>.
|
I haven't found time to test it, but it looks very useful. |
I don't know if I'm missing something but I can't get the Gradient smooth it just looks nasty.
it has these periodic lines..., Does anybody have an idea on how I can improve it.
The text was updated successfully, but these errors were encountered: