emacs-elpa-diffs
[Top][All Lists]
Advanced

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

[nongnu] elpa/pdf-tools 2ce864be00 3/5: Add hue contribution of backgrou


From: ELPA Syncer
Subject: [nongnu] elpa/pdf-tools 2ce864be00 3/5: Add hue contribution of background color to inverted midnight mode
Date: Sat, 10 Jun 2023 13:01:46 -0400 (EDT)

branch: elpa/pdf-tools
commit 2ce864be00f5e34232ff33d2376b3219cdf66649
Author: Zach Kost-Smith <smithzv@crouton.localdomain>
Commit: Vedang Manerikar <ved.manerikar@gmail.com>

    Add hue contribution of background color to inverted midnight mode
    
    From the comments in the PR, @smithzvk explains the changes:
    
     > I was bugged that it didn't pick up the hue from the background,
     > however, so I made the all color a/b parameters start from the a/b
     > parameters of the BG color. This makes the PDF background (white)
     > map to your BG color and PDF foreground (black) map to your FG
     > color, which can be set to your theme background making it seem
     > pretty seamless. Note that if you set your BG and FG to a color
     > theme without zero saturation (a gray tone of some sort), then you
     > recover the original behavior.
     >
     > I also reinstated the cached transforms for background and the last
     > color computed.
     >
     > I also refactored the loop to move the switch statement outside of
     > the loop. It is more repetitive, but it was needed to get rid of
     > some warnings about potentially uninitialized variables. It should
     > also be faster as the branch was removed from the loop.
     >
     > I also ditched the gamma correction as it seemed to be doing the
     > wrong thing and I never had a theoretical reasoning for it. I can
     > get similar results if I just set my BG color to something like
     > gray5 instead of black. Barely a difference in background but the
     > hinting on the fonts is showing again. The root of my issue may
     > have always been some kind of display calibration issue.
    
    Closes: #197
---
 server/epdfinfo.c | 131 ++++++++++++++++++++++++++++++++----------------------
 1 file changed, 78 insertions(+), 53 deletions(-)

diff --git a/server/epdfinfo.c b/server/epdfinfo.c
index ef14e41e57..6d3e14efd5 100644
--- a/server/epdfinfo.c
+++ b/server/epdfinfo.c
@@ -473,15 +473,19 @@ image_recolor (cairo_surface_t * surface, const 
PopplerColor * fg,
 {
   /* Performs one of two kinds of image recoloring depending on the value of 
usecolors:
 
-     1 -> uses a representation of a rgb color as follows:
-          - a lightness scalar (between 0,1), which is a weighted average of 
r, g, b,
-          - a hue vector, which indicates a radian direction from the grey 
axis,
-            inside the equal lightness plane.
-          - a saturation scalar between 0,1. It is 0 when grey, 1 when the 
color is
-            in the boundary of the rgb cube.
-
-     2 -> Invert the perceived lightness in the image while maintaining hue.
-   */
+     1 -> Bg-Fg Interpolation: maps source document colors to colors
+          interpolated between the background and foreground values in
+          pdf-view-midnight-colors via the lightness of the source color.  This
+          discards hue information but allows you to fit your color theme
+          perfectly.
+
+     2 -> Hue-Preserving interpolation: same as above, similar to above, but
+          attempts to preserve hue while still respecting the background and
+          foreground colors.  This is done by matching source document white 
and
+          black to the specified background and foreground as above, but mixes
+          hue/saturation with the background color.  This preserves hue but is
+          more expensive.
+  */
 
   const unsigned int page_width = cairo_image_surface_get_width (surface);
   const unsigned int page_height = cairo_image_surface_get_height (surface);
@@ -508,41 +512,28 @@ image_recolor (cairo_surface_t * surface, const 
PopplerColor * fg,
     .g = rgb_bg.g - rgb_fg.g,
     .b = rgb_bg.b - rgb_fg.b
   };
-  const double fg_l = a[0] * rgb_fg.r + a[1] * rgb_fg.g + a[2] * rgb_fg.b;
-  const double bg_l = a[0] * rgb_bg.r + a[1] * rgb_bg.g + a[2] * rgb_bg.b;
-  const double diff_l = fg_l - bg_l;
-
-  /* The Oklab transform is expensive, precompute white->black and have a 
single
-     entry cache to speed up computation */
-  struct color white = {.r = 1.0, .g = 1.0, .b = 1.0};
-  struct color black = {.r = 0.0, .g = 0.0, .b = 0.0};
-  struct color precomputed_rgb = white;
-  struct color precomputed_inv_rgb = black;
 
-  unsigned int y;
-  for (y = 0; y < page_height * rowstride; y += rowstride)
+  switch (usecolors)
     {
-      unsigned char *data = image + y;
+    case 0:
+      break;
+    case 1:
+      {
+        unsigned int y;
+        for (y = 0; y < page_height * rowstride; y += rowstride)
+          {
+            unsigned char *data = image + y;
 
-      unsigned int x;
-      for (x = 0; x < page_width; x++, data += 4)
-        {
-          /* Careful. data color components blue, green, red. */
-          struct color rgb = {
-            .r = (double) data[2] / 256.,
-            .g = (double) data[1] / 256.,
-            .b = (double) data[0] / 256.
-          };
-
-          switch (usecolors)
-            {
-            case 0:
-              /* No image recoloring requested.  Do nothing in this case.
-                 Should never be called as we should never call with unless
-                 usecolors != 0. */
-              break;
-            case 1:
+            unsigned int x;
+            for (x = 0; x < page_width; x++, data += 4)
               {
+                /* Careful. data color components blue, green, red. */
+                struct color rgb = {
+                  .r = (double) data[2] / 256.,
+                  .g = (double) data[1] / 256.,
+                  .b = (double) data[0] / 256.
+                };
+
                 /* Linear interpolation between bg and fg based on the
                    perceptual lightness measure l */
                 /* compute h, s, l data   */
@@ -557,14 +548,44 @@ image_recolor (cairo_surface_t * surface, const 
PopplerColor * fg,
                 data[0] =
                   (unsigned char) round (255. * (l * rgb_diff.b + rgb_fg.b));
               }
-              break;
-            case 2:
+          }
+      }
+      break;
+    case 2:
+      {
+        /* If using the Oklab transform, it is relatively expensive.  
Precompute
+           white->background and black->foreground and have a single entry 
cache to
+           speed up computation */
+        const struct color white = {.r = 1.0, .g = 1.0, .b = 1.0};
+        struct color precomputed_rgb = white;
+        struct color precomputed_inv_rgb = rgb_bg;
+
+        /* Must match the transformation of colors below. */
+        struct color oklab_fg = rgb2oklab(rgb_fg);
+        struct color oklab_bg = rgb2oklab(rgb_bg);
+
+        const double oklab_diff_l = oklab_fg.l - oklab_bg.l;
+
+        unsigned int y;
+        for (y = 0; y < page_height * rowstride; y += rowstride)
+          {
+            unsigned char *data = image + y;
+
+            unsigned int x;
+            for (x = 0; x < page_width; x++, data += 4)
               {
+                /* Careful. data color components blue, green, red. */
+                struct color rgb = {
+                  .r = (double) data[2] / 256.,
+                  .g = (double) data[1] / 256.,
+                  .b = (double) data[0] / 256.
+                };
+
                 /* Convert to Oklab coordinates, invert perceived lightness,
                    convert back to RGB. */
                 if (color_equal(white, rgb))
                   {
-                    rgb = black;
+                    rgb = rgb_bg;
                   }
                 else if (color_equal(precomputed_rgb, rgb))
                   {
@@ -575,12 +596,16 @@ image_recolor (cairo_surface_t * surface, const 
PopplerColor * fg,
                     struct color oklab = rgb2oklab(rgb);
                     precomputed_rgb = rgb;
 
-                    /* Gamma correction.  Shouldn't be necessary, but colors
-                     * 'feel' too dark and fonts too thin otherwise. */
-                    oklab.l = pow(oklab.l, 1.8);
-
                     /* Invert the perceived lightness, and scales it */
-                    oklab.l = bg_l + diff_l * (1.0 - oklab.l);
+                    double l = oklab.l;
+                    double inv_l = 1.0 - l;
+                    oklab.l = oklab_bg.l + oklab_diff_l * inv_l;
+
+                    /* Have a and b parameters (which encode hue and 
saturation)
+                       start at the background value and interpolate up to
+                       foreground */
+                    oklab.a = (oklab.a + oklab_bg.a * l + oklab_fg.a * inv_l);
+                    oklab.b = (oklab.b + oklab_bg.b * l + oklab_fg.b * inv_l);
 
                     rgb = oklab2rgb(oklab);
 
@@ -591,11 +616,11 @@ image_recolor (cairo_surface_t * surface, const 
PopplerColor * fg,
                 data[1] = (unsigned char) round(255. * rgb.g);
                 data[0] = (unsigned char) round(255. * rgb.b);
               }
-              break;
-            default:
-              internal_error ("image_recolor switch fell through");
-            }
-        }
+          }
+      }
+      break;
+    default:
+      internal_error ("image_recolor switch fell through");
     }
 }
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]