Allowing the user to choose the color of control points in VoronoiDiagramEffect and CellsEffect#1696
Allowing the user to choose the color of control points in VoronoiDiagramEffect and CellsEffect#1696cameronwhite merged 25 commits into
VoronoiDiagramEffect and CellsEffect#1696Conversation
|
The easiest case to look at here is drawing the points with semi-transparent green in the cells effect, and having the cell color scheme use the palette with the primary color set to fully opaque green The result of this should be fully opaque green. (https://en.wikipedia.org/wiki/Alpha_compositing#Straight_versus_premultiplied) But the result has a darker green - the eyedropper tool produces ColorBgra.Lerp, using the alpha of the destination color, produces the expected result, and same for setting the layer blend mode which does the blend operation through Cairo
|
For premultiplied alpha
|
@cameronwhite I tried to implement and thoroughly explain the logic of the "normal" blend op (see new I don't know if we should try to match the blending behavior of Cairo at this stage. There are many things that go into it that we would need to investigate, like whether or not Cairo does gamma correction. Perhaps we should look at these algorithms as completely independent at first, and later on we could allow for different settings. The commits after this message break down the rounding logic in different ways, and we could choose which commits to discard depending on the desired style. |
|
👍 The implementation looks reasonable to me A couple thoughts:
|
This reverts commit f01880e.
|
@cameronwhite I just replaced the body of A few notes:
|
… `CellsEffect`" This reverts commit 64d9f1c.
This looks good to merge, but it would be great to also add a test for the blend op first |
|
I just created a test setup for the blend ops, and test cases for the normal blend op @cameronwhite. There are two different commits:
I don't know if any existing tool uses invalid color values. I don't want to break stuff that is working, but perhaps if it's using invalid colors it should be failing loudly. |
|
Thanks! I was thinking it would be good to have some visual tests for these too, something like https://www.pinta-project.com/user-guide/edit/#apply-blend-mode where it's easier to see what effect is produced I'm very uneasy about validating colors here for a couple reasons:
|
This reverts commit 6e6245d.
|
@cameronwhite yeah, that's understandable. I just reverted it. In any case, the inputs with invalid colors are clearly separated in the code, so they should be easy to remove in the future if we are absolutely sure. And performance is another very good point. I'm not sure that the JIT could do much there, so maybe the validation code belongs elsewhere and the blending methods should assume that the inputs are valid. I am now going to create some visual tests. |
|
@cameronwhite I just added visual tests. The images used were generated from scratch so that we don't have to deal with any licensing or copyright issues. Unfortunately I didn't find information about the import numpy as np
from PIL import Image
TARGET_SIZE = 250
SCALE_FACTOR = 4
SUPER_SIZE = TARGET_SIZE * SCALE_FACTOR
def get_arr_a(y, x, ss):
arr = np.stack([255*(ss-x)/ss, 255*(x+y)/(2*ss), 255*y/ss, 255*(ss-y)/ss], -1)
cx, cy, r = ss//2, ss//2, ss//4
arr[(x-cx)**2 + (y-cy)**2 < r**2] = [255, 255, 0, 200]
return arr
def get_arr_b(y, x, ss):
cx, cy, arr = ss//2, ss//2, np.zeros((ss, ss, 4), 'u1')
arr[..., 3] = 255
arr[..., 2] = 255 * (1 - np.clip(np.hypot(x-cx, y-cy) / (ss*2**-0.5), 0, 1))
bw = ss//8
arr[:,ss//4-bw:ss//4] = [255,0,0,180]
arr[:,ss//2-bw:ss//2] = [0,255,0,180]
arr[:,3*ss//4-bw:3*ss//4] = [0,0,255,180]
tsize = ss//16
in_zone = (x > cx) & (y > cy)
is_black = ((x // tsize + y // tsize) % 2).astype(bool)
arr[in_zone & is_black], arr[in_zone & ~is_black] = [0,0,0,255], 255
return arr
content_factories = {'a': get_arr_a, 'b': get_arr_b}
for name, generator_func in content_factories.items():
y, x = np.mgrid[0:SUPER_SIZE, 0:SUPER_SIZE]
arr = generator_func(y, x, SUPER_SIZE)
img = Image.fromarray(np.clip(arr, 0, 255).astype('u1'), 'RGBA').resize((TARGET_SIZE, TARGET_SIZE), Image.Resampling.LANCZOS)
img.save(filename := f"visual_{name}.png")
print(f"Saved '{filename}'")The best part is that I generated the blended output image with Pinta layers (not through the re-written blend op). So it appears that the blend op works the same as Cairo's! And as a sanity check to verify that the tests are actually testing the image, I altered the blended version in 3af4819, and reverted it afterwards. |
|
Thanks! Those tests look good, and generating the output with the regular layer blending is great to make sure they match as closely as possible |

This is a follow-up on #1641.
I was thinking I could just use
UserBlendOps.NormalBlendOp. However, I am a bit doubtful. Look at what happens when one chooses the color of the points to be (say) pure green with an alpha of 128 (that is, (B:0, G:255, R:0, A:128)):Shouldn't these points look closer to light green? It seems like they are being darkened at times even if the cell is of a light color.
Let's look at what happens if I generate the control points in a solid color, on a different layer, and blend that layer with 50% opacity:
If you want to try generating the points yourself, I would suggest using the cells effect with a "transparent" edge behavior and a cell radius of just 1. Or you could use this image:
P.S. This relates to #1553