[gimp/wip/alxsa/mypaint-brush-v2: 61/66] get_color_pigment function implemented
- From: Alx Sa <sawyeralex src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/wip/alxsa/mypaint-brush-v2: 61/66] get_color_pigment function implemented
- Date: Sun, 16 Oct 2022 17:45:30 +0000 (UTC)
commit 319a51d8d61ad762caa526c51549c475a555a440
Author: Alx Sa <cmyk student gmail com>
Date: Fri Oct 7 20:22:36 2022 +0000
get_color_pigment function implemented
app/paint/gimpmybrushoptions.c | 2 +-
app/paint/gimpmybrushsurface.c | 264 ++++++++++++++++-------------------------
2 files changed, 104 insertions(+), 162 deletions(-)
---
diff --git a/app/paint/gimpmybrushoptions.c b/app/paint/gimpmybrushoptions.c
index 73dd1d1a95..2d1d1a57f6 100644
--- a/app/paint/gimpmybrushoptions.c
+++ b/app/paint/gimpmybrushoptions.c
@@ -140,7 +140,7 @@ gimp_mybrush_options_class_init (GimpMybrushOptionsClass *klass)
"posterizenum",
_("Posterize Number"),
NULL,
- 0.0, 1.0, 1.0,
+ 0.0, 1.28, 1.0,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_ERASER,
diff --git a/app/paint/gimpmybrushsurface.c b/app/paint/gimpmybrushsurface.c
index f8a01da1b0..a358ba81ba 100644
--- a/app/paint/gimpmybrushsurface.c
+++ b/app/paint/gimpmybrushsurface.c
@@ -27,6 +27,7 @@
#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
+#include "fastapprox/fastpow.h"
#include "libgimpcolor/gimpcolor.h"
#include "gimpmybrushoptions.h"
@@ -48,13 +49,13 @@ struct _GimpMybrushSurface
struct _GimpMybrushSurface2
{
- MyPaintSurface2 surface;
- GeglBuffer *buffer;
- GeglBuffer *paint_mask;
- gint paint_mask_x;
- gint paint_mask_y;
- GeglRectangle dirty;
- GimpComponentMask component_mask;
+ MyPaintSurface2 surface;
+ GeglBuffer *buffer;
+ GeglBuffer *paint_mask;
+ gint paint_mask_x;
+ gint paint_mask_y;
+ GeglRectangle dirty;
+ GimpComponentMask component_mask;
GimpMybrushOptions *options;
};
@@ -90,24 +91,17 @@ spectral_to_rgb (float *spectral,
float *rgb_);
void
-get_color_pixels_legacy (float *mask,
- float *rgba,
- float *sum_weight,
- float *sum_r,
- float *sum_g,
- float *sum_b,
- float *sum_a);
-void get_color_pixels_accumulate (float *mask,
- float *rgba,
+get_color_pixels_accumulate (float *mask,
+ float *pixel,
float *sum_weight,
float *sum_r,
float *sum_g,
float *sum_b,
float *sum_a,
float paint,
+ float pixel_weight,
uint16_t sample_interval,
- float random_sample_rate
- );
+ float random_sample_rate);
/* --- Taken from mypaint-tiled-surface.c --- */
static inline float
@@ -281,29 +275,29 @@ rgb_to_spectral (float r,
r = r * offset + WGM_EPSILON;
g = g * offset + WGM_EPSILON;
b = b * offset + WGM_EPSILON;
- //upsample rgb to spectral primaries
+ /* upsample rgb to spectral primaries */
- for (int i=0; i < 10; i++) {
+ for (int i = 0; i < 10; i++) {
spec_r[i] = spectral_r_small[i] * r;
}
- for (int i=0; i < 10; i++) {
+ for (int i = 0; i < 10; i++) {
spec_g[i] = spectral_g_small[i] * g;
}
- for (int i=0; i < 10; i++) {
+ for (int i = 0; i < 10; i++) {
spec_b[i] = spectral_b_small[i] * b;
}
//collapse into one spd
- for (int i=0; i<10; i++) {
+ for (int i = 0; i < 10; i++) {
spectral_[i] += spec_r[i] + spec_g[i] + spec_b[i];
}
-
}
void
spectral_to_rgb (float *spectral,
- float *rgb_) {
+ float *rgb_)
+{
float offset = 1.0 - WGM_EPSILON;
- // We need this tmp. array to allow auto vectorization.
+ /* We need this tmp. array to allow auto vectorization. */
float tmp[3] = {0};
for (int i=0; i<10; i++) {
tmp[0] += T_MATRIX_SMALL[0][i] * spectral[i];
@@ -315,137 +309,70 @@ spectral_to_rgb (float *spectral,
}
}
-
/* -- Taken from brushmode.c -- */
void
-get_color_pixels_legacy (float *mask,
- float *rgba,
- float *sum_weight,
- float *sum_r,
- float *sum_g,
- float *sum_b,
- float *sum_a)
+get_color_pixels_accumulate (float *mask,
+ float *pixel,
+ float *sum_weight,
+ float *sum_r,
+ float *sum_g,
+ float *sum_b,
+ float *sum_a,
+ float pixel_weight,
+ float paint,
+ uint16_t sample_interval,
+ float random_sample_rate)
{
- // The sum of a 64x64 tile fits into a 32 bit integer, but the sum
- // of an arbitrary number of tiles may not fit. We assume that we
- // are processing a single tile at a time, so we can use integers.
- // But for the result we need floats.
- uint32_t weight = 0;
- uint32_t r = 0;
- uint32_t g = 0;
- uint32_t b = 0;
- uint32_t a = 0;
-
- //while (1) {
- //for (; mask[0]; mask++, rgba += 4)
- // {
- uint32_t opa = (uint16_t) mask[0];
- weight += opa;
- r += ((uint16_t) rgba[RED])/(1<<15);
- g += ((uint16_t) rgba[GREEN])/(1<<15);
- b += ((uint16_t) rgba[BLUE])/(1<<15);
- //a += rgba[ALPHA]/(1<<15);
- //}
- //if (! ((uint16_t) mask[1]))
- //break;
- rgba += (uint16_t) mask[1];
- mask += 2;
- //}
-
- // convert integer to float outside the performance critical loop
- *sum_weight += weight;
- *sum_r += r;
- *sum_g += g;
- *sum_b += b;
- *sum_a += a;
-};
-
-void
-get_color_pixels_accumulate (float *mask,
- float *rgba,
- float *sum_weight,
- float *sum_r,
- float *sum_g,
- float *sum_b,
- float *sum_a,
- float paint,
- uint16_t sample_interval,
- float random_sample_rate)
-{
- float avg_spectral[10] = {0};
- float avg_rgb[3] = {*sum_r, *sum_g, *sum_b};
- // Rolling counter determining which pixels to sample
- // This sampling _is_ biased (but hopefully not too bad).
- // Ideally, the selection of pixels to be sampled should
- // be determined before this function is called.
- uint16_t interval_counter = 0;
- const int random_sample_threshold = (int)(random_sample_rate * RAND_MAX);
- float spec_rgb[3] = {0};
-
- // Fall back to legacy sampling if using static 0 paint setting
- // Indicated by passing a negative paint factor (normal range 0..1)
- if (paint < 0.0) {
- get_color_pixels_legacy (mask, rgba, sum_weight, sum_r, sum_g, sum_b, sum_a);
- return;
- }
-
- // Sample the canvas as additive and subtractive
- // According to paint parameter
- // Average the results normally
- // Only sample a partially random subset of pixels
-
- if (paint > 0.0f) {
- rgb_to_spectral(*sum_r, *sum_g, *sum_b, avg_spectral);
- }
-
- //while (1) {
- //for (; mask[0]; mask++, rgba+=4) {
- // Sample every n pixels, and a percentage of the rest.
- // At least one pixel (the first) will always be sampled.
- if (interval_counter == 0 || rand() < random_sample_threshold) {
-
- //float a = (float) mask[0] * rgba[ALPHA] / (1 << 30);
- //float alpha_sums = a + *sum_a;
- float fac_a, fac_b;
+ uint16_t interval_counter = 0;
+ const int random_sample_threshold = (int)(random_sample_rate * G_MAXINT);
+ float avg_spectral[10] = {0};
+ float avg_rgb[3] = {*sum_r, *sum_g, *sum_b};
+ float spec_rgb[3] = {0};
+
+ rgb_to_spectral (*sum_r, *sum_g, *sum_b, avg_spectral);
+ if (interval_counter == 0 || rand() < random_sample_threshold)
+ {
+ float fac_a, fac_b;
+ float a = pixel_weight * pixel[ALPHA];
+ float alpha_sums = a + *sum_a;
- *sum_weight += (float) mask[0] / (1 << 15);
+ *sum_weight += pixel_weight;
- fac_a = fac_b = 1.0f;
- //if (alpha_sums > 0.0f) {
- //fac_a = a / alpha_sums;
+ fac_a = fac_b = 1.0f;
+ if (alpha_sums > 0.0f)
+ {
+ fac_a = a / alpha_sums;
fac_b = 1.0 - fac_a;
- //}
+ }
- /*if (paint > 0.0f && rgba[ALPHA] > 0) {
+ if (paint > 0.0f && pixel[ALPHA] > 0)
+ {
float spectral[10] = {0};
- rgb_to_spectral((float)rgba[RED] / rgba[ALPHA], (float)rgba[GREEN] / rgba[ALPHA],
(float)rgba[BLUE] / rgba[ALPHA], spectral);
+ rgb_to_spectral (pixel[RED] / pixel[ALPHA],
+ pixel[GREEN] / pixel[ALPHA],
+ pixel[BLUE] / pixel[ALPHA],
+ spectral);
- for (int i = 0; i < 10; i++) {
- avg_spectral[i] = pow (spectral[i], fac_a) * pow(avg_spectral[i], fac_b);
- }
+ for (int i = 0; i < 10; i++)
+ avg_spectral[i] = fastpow (spectral[i], fac_a) * fastpow (avg_spectral[i], fac_b);
}
- if (paint < 1.0f && rgba[ALPHA] > 0) {
- for (int i = 0; i < 3; i++) {
- avg_rgb[i] = (float)rgba[i] * fac_a / rgba[ALPHA] + (float)avg_rgb[i] * fac_b;
- }
- }*/
- //*sum_a += a;
- }
- interval_counter = (interval_counter + 1) % sample_interval;
- //}
- //if (!mask[1])
- //break;
- rgba += (uint16_t) mask[1];
- mask += 2;
- //}
- // Convert the spectral average to rgb and write the result
- // back weighted with the rgb average.
+
+ if (paint < 1.0f && pixel[ALPHA] > 0)
+ {
+ for (int i = 0; i < 3; i++)
+ avg_rgb[i] = pixel[i] * fac_a / pixel[ALPHA] + avg_rgb[i] * fac_b;
+ }
+
+ *sum_a += a;
+ }
+ interval_counter = (interval_counter + 1) % sample_interval;
+
spectral_to_rgb (avg_spectral, spec_rgb);
- *sum_r = spec_rgb[0] * paint + (1.0 - paint) * avg_rgb[0];
- *sum_g = spec_rgb[1] * paint + (1.0 - paint) * avg_rgb[1];
- *sum_b = spec_rgb[2] * paint + (1.0 - paint) * avg_rgb[2];
-};
+ *sum_r = (float) spec_rgb[0] * paint + (1.0 - paint) * avg_rgb[0];
+ *sum_g = (float) spec_rgb[1] * paint + (1.0 - paint) * avg_rgb[1];
+ *sum_b = (float) spec_rgb[2] * paint + (1.0 - paint) * avg_rgb[2];
+}
/* -- end mypaint code */
static inline float
@@ -850,7 +777,8 @@ gimp_mypaint_surface_draw_dab_2 (MyPaintSurface2 *base_surface,
r_aa_start = MAX (r_aa_start, 0);
r_aa_start = (r_aa_start * r_aa_start) / aspect_ratio;
- normal_mode = opaque * (1.0f - colorize);
+ posterize = CLAMP (posterize, 0.0f, 1.0f);
+ normal_mode = opaque * (1.0f - colorize) * (1.0f - posterize);
colorize = opaque * colorize;
/* FIXME: This should use the real matrix values to trim aspect_ratio dabs */
@@ -1016,7 +944,6 @@ gimp_mypaint_surface_get_color_2 (MyPaintSurface2 *base_surface,
float *color_a,
float paint)
{
- /* Placeholder - eventually implement here */
GimpMybrushSurface2 *surface = (GimpMybrushSurface2 *) base_surface;
GeglRectangle dabRect;
@@ -1081,11 +1008,25 @@ gimp_mypaint_surface_get_color_2 (MyPaintSurface2 *base_surface,
if (mask)
pixel_weight *= *mask;
- get_color_pixels_accumulate (mask, pixel, &sum_weight,
- &sum_r, &sum_g, &sum_b, &sum_a,
- paint, sample_interval,
- random_sample_rate);
-
+ /* Version 1 / Legacy Brushes */
+ if (paint < 0.0f)
+ {
+ sum_r += pixel_weight * pixel[RED];
+ sum_g += pixel_weight * pixel[GREEN];
+ sum_b += pixel_weight * pixel[BLUE];
+ sum_a += pixel_weight * pixel[ALPHA];
+ sum_weight += pixel_weight;
+ }
+ /* Version 2 Brushes */
+ else
+ {
+ #ifdef _OPENMP
+ #pragma omp critical
+ #endif
+ get_color_pixels_accumulate (mask, pixel, &sum_weight,
+ &sum_r, &sum_g, &sum_b, &sum_a, paint,
+ pixel_weight, sample_interval, random_sample_rate);
+ }
pixel += 4;
if (mask)
mask += 1;
@@ -1095,24 +1036,25 @@ gimp_mypaint_surface_get_color_2 (MyPaintSurface2 *base_surface,
if (sum_a > 0.0f && sum_weight > 0.0f)
{
- float demul;
-
- sum_a /= sum_weight;
- if (paint < 0.0)
+ if (paint < 0.0f)
{
sum_r /= sum_weight;
sum_g /= sum_weight;
sum_b /= sum_weight;
}
+ sum_a /= sum_weight;
- demul = paint < 0.0 ? sum_a : 1.0f;
- *color_r = CLAMP(sum_r / demul, 0.0f, 1.0f);
- *color_g = CLAMP(sum_g / demul, 0.0f, 1.0f);
- *color_b = CLAMP(sum_b / demul, 0.0f, 1.0f);
+ sum_r /= sum_a;
+ sum_g /= sum_a;
+ sum_b /= sum_a;
+
+ /* FIXME: Clamping is wrong because GEGL allows alpha > 1, this should probably re-multipy things */
+ *color_r = CLAMP(sum_r, 0.0f, 1.0f);
+ *color_g = CLAMP(sum_g, 0.0f, 1.0f);
+ *color_b = CLAMP(sum_b, 0.0f, 1.0f);
*color_a = CLAMP(sum_a, 0.0f, 1.0f);
}
}
-
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]