[gegl] pixel-duster: add another symmetry



commit f9e88057df9bb392731235bab1766c882069fc07
Author: Øyvind Kolås <pippin gimp org>
Date:   Sun Mar 4 20:14:10 2018 +0100

    pixel-duster: add another symmetry

 operations/workshop/enlarge2.c     |   37 ++++++++++++-
 operations/workshop/pixel-duster.h |  101 ++++++++++++++++++++---------------
 2 files changed, 93 insertions(+), 45 deletions(-)
---
diff --git a/operations/workshop/enlarge2.c b/operations/workshop/enlarge2.c
index a8d9318..8bd6c1b 100644
--- a/operations/workshop/enlarge2.c
+++ b/operations/workshop/enlarge2.c
@@ -116,6 +116,33 @@ static void remove_grid (GeglBuffer *in,
       }
 }
 
+static void remove_deviant (GeglBuffer *in,
+                            GeglBuffer *out,
+                            gfloat      scale)
+{
+  GeglRectangle rect;
+  const Babl *format = babl_format ("RGBA float");
+  gint x, y;
+  rect = *gegl_buffer_get_extent (out);
+  for (y = 0; y < rect.height; y++)
+    for (x = 0; x < rect.width; x++)
+      {
+        GeglRectangle r = {x * scale , y * scale, 1, 1};
+        gfloat rgba_in[4] = {0,0,0,0};
+        gfloat rgba_empty[4] = {0,0,0,0};
+        gfloat rgba_out[4] = {0,0,0,0};
+        gegl_buffer_sample (in, x / scale, y / scale, NULL, &rgba_in[0], format, GEGL_SAMPLER_NEAREST, 0);
+        gegl_buffer_sample (out, x, y, NULL, &rgba_out[0], format, GEGL_SAMPLER_NEAREST, 0);
+
+        if (POW2(rgba_in[0]-rgba_out[0])+
+            POW2(rgba_in[1]-rgba_out[1])+
+            POW2(rgba_in[2]-rgba_out[2]) > 14 + 14 + 14)
+        {
+          gegl_buffer_set (out, &r, 0, format, &rgba_empty[0], 0);
+        }
+      }
+}
+
 static gboolean
 process (GeglOperation       *operation,
          GeglBuffer          *input,
@@ -142,12 +169,18 @@ process (GeglOperation       *operation,
   seed_db (duster);
   pixel_duster_add_probes_for_transparent (duster);
   pixel_duster_fill (duster);
-#if 1
+  remove_deviant (input, output, o->scale);
   remove_grid (input, output, o->scale);
   pixel_duster_remove_probes (duster);
   pixel_duster_add_probes_for_transparent (duster);
   pixel_duster_fill (duster);
-#endif
+
+  remove_deviant (input, output, o->scale);
+  pixel_duster_remove_probes (duster);
+  pixel_duster_add_probes_for_transparent (duster);
+  pixel_duster_fill (duster);
+
+  pixel_duster_remove_probes (duster);
   pixel_duster_destroy (duster);
 
   return TRUE;
diff --git a/operations/workshop/pixel-duster.h b/operations/workshop/pixel-duster.h
index babbfe6..c75670f 100644
--- a/operations/workshop/pixel-duster.h
+++ b/operations/workshop/pixel-duster.h
@@ -20,11 +20,11 @@
          for identical entries - thus not losing accurate median computation capabilitiy..
          do median instead of mean for matched pixel components
 
-         store values relative to center pixel instead of center pixel - thus
-         permitting a wider range of neighborhoods to produce valid data - thus will be
-         good at least for superresolution
+         complete code using relative to center pixel instead of center pixel -
+         thus permitting a wider range of neighborhoods to produce valid data - thus
+         will be good at least for superresolution
 
-         add mirroring - thus doubling data
+         add more symmetries mirroring each doubling data
  */
 
 #define POW2(x) ((x)*(x))
@@ -54,34 +54,24 @@ typedef struct
 } PixelDuster;
 
 
-/* todo: create neighbor color histogram - that can
-         be used as neighborhood separation criteria
-         ideally low-enough bits that it can be used
-         as selector.
-         gray axis as separate entity.
-
-         4x4x4
-
-*/
-
 #define MAX_K               1
 #define PIXDUST_REL_DIGEST  0
-#define NEIGHBORHOOD        32
+#define NEIGHBORHOOD        33
 #define PIXDUST_ORDERED     1
 #define MAX_DIR             4
 
-//#define ONLY_DIR 0
+//#define ONLY_DIR            1
 
 typedef struct Probe {
-  int            target_x;
-  int            target_y;
-  int            age;
-  int            k;
-  int            score;
-  int            k_score[MAX_K];
-  int            source_x[MAX_K];
-  int            source_y[MAX_K];
-  guchar        *hay[MAX_K];
+  int     target_x;
+  int     target_y;
+  int     age;
+  int     k;
+  int     score;
+  int     k_score[MAX_K];
+  int     source_x[MAX_K];
+  int     source_y[MAX_K];
+  guchar *hay[MAX_K];
 } Probe;
 
 /* used for hash-table keys */
@@ -173,6 +163,23 @@ static void duster_idx_to_x_y (PixelDuster *duster, int index, int dir, int *x,
       *x =  duster->order[index][1];
       *y =  duster->order[index][0];
       break;
+
+    case 4: /* right */
+      *x =  -duster->order[index][0];
+      *y =   duster->order[index][1];
+      break;
+    case 5: /* left */
+      *x =  duster->order[index][0];
+      *y =  -duster->order[index][1];
+      break;
+    case 6: /* down */
+      *x =  -duster->order[index][1];
+      *y =  duster->order[index][0];
+      break;
+    case 7: /* up */
+      *x =  duster->order[index][1];
+      *y =  -duster->order[index][0];
+      break;
   }
 }
 
@@ -241,7 +248,7 @@ static void extract_site (PixelDuster *duster, GeglBuffer *input, int x, int y,
   static const Babl *yformat = NULL;
   guchar lum[8];
   int bdir, maxlum;
-  uint32_t hist3dmask=0;
+  uint64_t hist3dmask=0;
 
   if (!format){
     format = babl_format ("R'G'B'A u8");
@@ -260,13 +267,24 @@ static void extract_site (PixelDuster *duster, GeglBuffer *input, int x, int y,
  bdir = 0;
 
  maxlum = lum[0*2];
- for (int i = 1; i < MAX_DIR; i++)
+ for (int i = 1; i < MIN(4,MAX_DIR); i++)
    if (lum[i*2] > maxlum)
      {
        bdir = i;
        maxlum = lum[i*2];
      }
 
+ if (MAX_DIR > 4)
+ {
+   switch (bdir)
+   {
+     case 0: if (lum[4] > lum[6]) bdir += 4; break;
+     case 1: if (lum[6] > lum[4]) bdir += 4; break;
+     case 2: if (lum[0] > lum[2]) bdir += 4; break;
+     case 3: if (lum[2] > lum[0]) bdir += 4; break;
+   }
+ }
+
 #ifdef ONLY_DIR
   bdir = ONLY_DIR;
 #endif
@@ -283,16 +301,13 @@ static void extract_site (PixelDuster *duster, GeglBuffer *input, int x, int y,
                         y + dy,
                         NULL, &dst[i*4], format,
                         GEGL_SAMPLER_NEAREST, 0);
-
-
     {
       int hist_r = dst[i*4+0]/80;
       int hist_g = dst[i*4+1]/80;
-      int hist_b = dst[i*4+2]/128;
-      int hist_bit = hist_r * 4 * 2 + hist_g * 2 + hist_b;
+      int hist_b = dst[i*4+2]/80;
+      int hist_bit = hist_r * 4 * 4 + hist_g * 4 + hist_b;
       hist3dmask |= (1 << hist_bit);
     }
-
   }
 #else
   for (int i = 0; i <= NEIGHBORHOOD; i++)
@@ -324,7 +339,7 @@ static void extract_site (PixelDuster *duster, GeglBuffer *input, int x, int y,
  }
 #endif
  dst[0] = bdir;
- *((uint32_t*)(&dst[4*NEIGHBORHOOD])) = hist3dmask;
+ *((uint64_t*)(&dst[4*NEIGHBORHOOD])) = hist3dmask;
 }
 
 static inline int u8_rgb_diff (guchar *a, guchar *b)
@@ -348,16 +363,16 @@ score_site (PixelDuster *duster,
   }
 
   {
-    uint32_t *needle_hist = (void*)&needle[NEIGHBORHOOD * 4];
-    uint32_t *hay_hist    = (void*)&hay[NEIGHBORHOOD * 4];
-    int       diff_hist = *needle_hist ^ *hay_hist;
+    uint64_t *needle_hist = (void*)&needle[NEIGHBORHOOD * 4];
+    uint64_t *hay_hist    = (void*)&hay[NEIGHBORHOOD * 4];
+    uint64_t  diff_hist = *needle_hist ^ *hay_hist;
     int missing = 0;
-  for (i = 0; i < 32; i ++)
+  for (i = 0; i < 64; i ++)
   {
     if (diff_hist & (1 << i)) missing ++;
     //else if ( *needle_hist & (i<<i)) missing ++;
   }
-    if (missing > 5)
+    if (missing > 32)
       return INITIAL_SCORE;
   }
 
@@ -556,7 +571,7 @@ static guchar *ensure_hay (PixelDuster *duster, int x, int y, int subset)
 
   if (!hay)
     {
-      hay = g_malloc (4 * NEIGHBORHOOD + 4);
+      hay = g_malloc (4 * NEIGHBORHOOD + 8);
       extract_site (duster, duster->input, x, y, hay);
       if (subset < 0)
       {
@@ -631,7 +646,7 @@ static void compare_needle (gpointer key, gpointer value, gpointer data)
 static int probe_improve (PixelDuster *duster,
                           Probe       *probe)
 {
-  guchar needle[4 * NEIGHBORHOOD + 4];
+  guchar needle[4 * NEIGHBORHOOD + 8];
   gint  dst_x  = probe->target_x;
   gint  dst_y  = probe->target_y;
   void *ptr[3] = {duster, probe, &needle[0]};
@@ -710,9 +725,9 @@ static inline void pixel_duster_add_probes_for_transparent (PixelDuster *duster)
     while (n_pixels--)
     {
       if (out_pix[3] <= 0.001 ||
-          (out_pix[0] <= 0.01 &&
-           out_pix[1] <= 0.01 &&
-           out_pix[2] <= 0.01))
+          (out_pix[0] <= 0.1 &&
+           out_pix[1] <= 0.1 &&
+           out_pix[2] <= 0.1))
       {
         add_probe (duster, x, y);
       }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]