[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");
}
}