[gimp/wip/alxsa/mypaint-brush-v2] get_color_pigment function implemented



commit 624380c92fde87fe5aaab228cbbf01b3c3f825da
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]