-
Notifications
You must be signed in to change notification settings - Fork 89
Description
Here I have a patch:
diff --git a/brushmodes.c b/brushmodes.c
index f0c68b6..eede454 100644
--- a/brushmodes.c
+++ b/brushmodes.c
@@ -70,6 +70,12 @@ void draw_dab_pixels_BlendMode_Normal (uint16_t * mask,
}
};
+inline int color_direct_mixable(uint16_t r, uint16_t g, uint16_t b, uint16_t* rgba){
+ return ((rgba[0]==r || r/abs(rgba[0]-r)>50)&&
+ (rgba[1]==g || g/abs(rgba[1]-g)>50)&&
+ (rgba[2]==b || b/abs(rgba[2]-b)>50));
+}
+
void draw_dab_pixels_BlendMode_Normal_Paint (uint16_t * mask,
uint16_t * rgba,
uint16_t color_r,
@@ -91,7 +97,7 @@ void draw_dab_pixels_BlendMode_Normal_Paint (uint16_t * mask,
uint32_t opa_b = (1<<15)-opa_a; // bottomAlpha
// optimization- if background has 0 alpha we can just do normal additive
// blending since there is nothing to mix with.
- if (rgba[3] <= 0) {
+ if (rgba[3] <= 0 || opacity>30000 || color_direct_mixable(color_r, color_g, color_b, rgba)) {
rgba[3] = opa_a + opa_b * rgba[3] / (1<<15);
rgba[0] = (opa_a*color_r + opa_b*rgba[0])/(1<<15);
rgba[1] = (opa_a*color_g + opa_b*rgba[1])/(1<<15);
@@ -351,6 +357,16 @@ void draw_dab_pixels_BlendMode_Normal_and_Eraser_Paint (uint16_t * mask,
for (; mask[0]; mask++, rgba+=4) {
const uint32_t opa_a = mask[0]*(uint32_t)opacity/(1<<15); // topAlpha
const uint32_t opa_b = (1<<15)-opa_a; // bottomAlpha
+
+ if (rgba[3] <= 0 || opacity>30000 || color_direct_mixable(color_r, color_g, color_b, rgba)) {
+ const uint32_t opa_a1 = opa_a * color_a / (1<<15);
+ rgba[3] = opa_a1 + opa_b * rgba[3] / (1<<15);
+ rgba[0] = (opa_a1*color_r + opa_b*rgba[0])/(1<<15);
+ rgba[1] = (opa_a1*color_g + opa_b*rgba[1])/(1<<15);
+ rgba[2] = (opa_a1*color_b + opa_b*rgba[2])/(1<<15);
+ continue;
+ }
+
const uint32_t opa_a2 = opa_a * color_a / (1<<15); // erase-adjusted alpha
const uint32_t opa_out = opa_a2 + opa_b * rgba[3] / (1<<15);
@@ -458,7 +474,7 @@ void draw_dab_pixels_BlendMode_LockAlpha_Paint (uint16_t * mask,
uint32_t opa_b = (1<<15)-opa_a; // bottomAlpha
opa_a *= rgba[3];
opa_a /= (1<<15);
- if (rgba[3] <= 0) {
+ if (rgba[3] <= 0 || opacity>30000 || color_direct_mixable(color_r, color_g, color_b, rgba)) {
rgba[0] = (opa_a*color_r + opa_b*rgba[0])/(1<<15);
rgba[1] = (opa_a*color_g + opa_b*rgba[1])/(1<<15);
rgba[2] = (opa_a*color_b + opa_b*rgba[2])/(1<<15);
Because most brushes are dabbed repeatedly around the same spot, so there are a lot overlapping, so if colours are close enough, we don't really need to do spectrum conversion, which greatly speeds up large brushes.
Results are still visually correct:
My original description which I thought it was a bug: (wrong, don't look at it)
Because spectrum mixing is ridiculously slow even with fully opaque brushes, I am looking into the code and found the spectrum switch seems to be controlled by "alpha underneath" instead of "input alpha"? Is this a typo error or am I not understanding the algorithm correctly?
brushmodes.c line 375:
if (spectral_factor && rgba[3] != 0) { // apparently it should be "color_a!=65535" here?
// Convert straightened tile pixel color to a spectral
float spectral_b[10] = {0};
rgb_to_spectral(
(float)rgba[0] / rgba[3],
(float)rgba[1] / rgba[3],
(float)rgba[2] / rgba[3],
spectral_b
);
I'm not sure I understood the code correctly, but I think for opaque brushes there should not be any spectrum mixing? Or if it's a different mindset I'd appreciate a more in-depth explanation.
Thanks and have a great day!
