mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-04 04:06:06 -05:00
hsl: add our own implementations of rgb-to-hsl and hsl-to-rgb
* New function: rgb_to_hsl() * New function: hsl_to_rgb() * Replace XTerm’s hls_to_rgb() with our own, hsl_to_rgb(). * Ensure hue/lum/sat values are within range before calling hsl_to_rgb() Note that sixels’ use the following primary hues: * blue: 0° * red: 120 * green: 240° While “standard” HSL uses: * red: 0° * green: 120° * blue: 240° Thus, we need to adjust the sixel’s hue value before calling hsl_to_rgb().
This commit is contained in:
parent
8e779b356e
commit
e0297daa1f
6 changed files with 124 additions and 136 deletions
89
hsl.c
Normal file
89
hsl.c
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#include "hsl.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
void
|
||||
rgb_to_hsl(uint32_t rgb, int *hue, int *sat, int *lum)
|
||||
{
|
||||
double r = (double)((rgb >> 16) & 0xff) / 255.;
|
||||
double g = (double)((rgb >> 8) & 0xff) / 255.;
|
||||
double b = (double)((rgb >> 0) & 0xff) / 255.;
|
||||
|
||||
double x_max = max(max(r, g), b);
|
||||
double x_min = min(min(r, g), b);
|
||||
double V = x_max;
|
||||
|
||||
double C = x_max - x_min;
|
||||
double L = (x_max + x_min) / 2.;
|
||||
|
||||
*lum = 100 * L;
|
||||
|
||||
if (C == 0.0)
|
||||
*hue = 0;
|
||||
else if (V == r)
|
||||
*hue = 60. * (0. + (g - b) / C);
|
||||
else if (V == g)
|
||||
*hue = 60. * (2. + (b - r) / C);
|
||||
else if (V == b)
|
||||
*hue = 60. * (4. + (r - g) / C);
|
||||
if (*hue < 0)
|
||||
*hue += 360;
|
||||
|
||||
double S = C == 0.0
|
||||
? 0
|
||||
: C / (1. - fabs(2. * L - 1.));
|
||||
*sat = 100 * S;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
hsl_to_rgb(int hue, int sat, int lum)
|
||||
{
|
||||
double L = lum / 100.0;
|
||||
double S = sat / 100.0;
|
||||
double C = (1. - fabs(2. * L - 1.)) * S;
|
||||
|
||||
double X = C * (1. - fabs(fmod((double)hue / 60., 2.) - 1.));
|
||||
double m = L - C / 2.;
|
||||
|
||||
double r, g, b;
|
||||
if (hue >= 0 && hue <= 60) {
|
||||
r = C;
|
||||
g = X;
|
||||
b = 0.;
|
||||
} else if (hue >= 60 && hue <= 120) {
|
||||
r = X;
|
||||
g = C;
|
||||
b = 0.;
|
||||
} else if (hue >= 120 && hue <= 180) {
|
||||
r = 0.;
|
||||
g = C;
|
||||
b = X;
|
||||
} else if (hue >= 180 && hue <= 240) {
|
||||
r = 0.;
|
||||
g = X;
|
||||
b = C;
|
||||
} else if (hue >= 240 && hue <= 300) {
|
||||
r = X;
|
||||
g = 0.;
|
||||
b = C;
|
||||
} else if (hue >= 300 && hue <= 360) {
|
||||
r = C;
|
||||
g = 0.;
|
||||
b = X;
|
||||
} else {
|
||||
r = 0.;
|
||||
g = 0.;
|
||||
b = 0.;
|
||||
}
|
||||
|
||||
r += m;
|
||||
g += m;
|
||||
b += m;
|
||||
|
||||
return (
|
||||
(int)round(r * 255.) << 16 |
|
||||
(int)round(g * 255.) << 8 |
|
||||
(int)round(b * 255.) << 0);
|
||||
}
|
||||
6
hsl.h
Normal file
6
hsl.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void rgb_to_hsl(uint32_t rgb, int *hue, int *sat, int *lum);
|
||||
uint32_t hsl_to_rgb(int hue, int sat, int lum);
|
||||
|
|
@ -111,6 +111,7 @@ executable(
|
|||
'extract.c', 'extract.h',
|
||||
'fdm.c', 'fdm.h',
|
||||
'grid.c', 'grid.h',
|
||||
'hsl.c', 'hsl.h',
|
||||
'input.c', 'input.h',
|
||||
'log.c', 'log.h',
|
||||
'macros.h',
|
||||
|
|
@ -125,7 +126,6 @@ executable(
|
|||
'server.c', 'server.h',
|
||||
'shm.c', 'shm.h',
|
||||
'sixel.c', 'sixel.h',
|
||||
'sixel-hls.c', 'sixel-hls.h',
|
||||
'slave.c', 'slave.h',
|
||||
'spawn.c', 'spawn.h',
|
||||
'terminal.c', 'terminal.h',
|
||||
|
|
|
|||
117
sixel-hls.c
117
sixel-hls.c
|
|
@ -1,117 +0,0 @@
|
|||
// sixel.c (part of mintty)
|
||||
// this function is derived from a part of graphics.c
|
||||
// in Xterm pl#310 originally written by Ross Combs.
|
||||
//
|
||||
// Copyright 2013,2014 by Ross Combs
|
||||
//
|
||||
// All Rights Reserved
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// Except as contained in this notice, the name(s) of the above copyright
|
||||
// holders shall not be used in advertising or otherwise to promote the
|
||||
// sale, use or other dealings in this Software without prior written
|
||||
// authorization.
|
||||
|
||||
#include "sixel-hls.h"
|
||||
|
||||
#define SIXEL_RGB(r, g, b) (((r) << 16) + ((g) << 8) + (b))
|
||||
|
||||
int
|
||||
hls_to_rgb(int hue, int lum, int sat)
|
||||
{
|
||||
double hs = (hue + 240) % 360;
|
||||
double hv = hs / 360.0;
|
||||
double lv = lum / 100.0;
|
||||
double sv = sat / 100.0;
|
||||
double c, x, m, c2;
|
||||
double r1, g1, b1;
|
||||
int r, g, b;
|
||||
int hpi;
|
||||
|
||||
if (sat == 0) {
|
||||
r = g = b = lum * 255 / 100;
|
||||
return SIXEL_RGB(r, g, b);
|
||||
}
|
||||
|
||||
if ((c2 = ((2.0 * lv) - 1.0)) < 0.0) {
|
||||
c2 = -c2;
|
||||
}
|
||||
c = (1.0 - c2) * sv;
|
||||
hpi = (int) (hv * 6.0);
|
||||
x = (hpi & 1) ? c : 0.0;
|
||||
m = lv - 0.5 * c;
|
||||
|
||||
switch (hpi) {
|
||||
case 0:
|
||||
r1 = c;
|
||||
g1 = x;
|
||||
b1 = 0.0;
|
||||
break;
|
||||
case 1:
|
||||
r1 = x;
|
||||
g1 = c;
|
||||
b1 = 0.0;
|
||||
break;
|
||||
case 2:
|
||||
r1 = 0.0;
|
||||
g1 = c;
|
||||
b1 = x;
|
||||
break;
|
||||
case 3:
|
||||
r1 = 0.0;
|
||||
g1 = x;
|
||||
b1 = c;
|
||||
break;
|
||||
case 4:
|
||||
r1 = x;
|
||||
g1 = 0.0;
|
||||
b1 = c;
|
||||
break;
|
||||
case 5:
|
||||
r1 = c;
|
||||
g1 = 0.0;
|
||||
b1 = x;
|
||||
break;
|
||||
default:
|
||||
return SIXEL_RGB(255, 255, 255);
|
||||
}
|
||||
|
||||
r = (int) ((r1 + m) * 100.0 + 0.5);
|
||||
g = (int) ((g1 + m) * 100.0 + 0.5);
|
||||
b = (int) ((b1 + m) * 100.0 + 0.5);
|
||||
|
||||
if (r < 0) {
|
||||
r = 0;
|
||||
} else if (r > 100) {
|
||||
r = 100;
|
||||
}
|
||||
if (g < 0) {
|
||||
g = 0;
|
||||
} else if (g > 100) {
|
||||
g = 100;
|
||||
}
|
||||
if (b < 0) {
|
||||
b = 0;
|
||||
} else if (b > 100) {
|
||||
b = 100;
|
||||
}
|
||||
return SIXEL_RGB(r * 255 / 100, g * 255 / 100, b * 255 / 100);
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
* Primary color hues:
|
||||
* blue: 0 degrees
|
||||
* red: 120 degrees
|
||||
* green: 240 degrees
|
||||
*/
|
||||
int hls_to_rgb(int hue, int lum, int sat);
|
||||
37
sixel.c
37
sixel.c
|
|
@ -7,7 +7,7 @@
|
|||
#define LOG_ENABLE_DBG 0
|
||||
#include "log.h"
|
||||
#include "render.h"
|
||||
#include "sixel-hls.h"
|
||||
#include "hsl.h"
|
||||
#include "util.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
|
|
@ -1052,23 +1052,42 @@ decgci(struct terminal *term, uint8_t c)
|
|||
|
||||
if (nparams > 4) {
|
||||
unsigned format = term->sixel.params[1];
|
||||
unsigned c1 = term->sixel.params[2];
|
||||
unsigned c2 = term->sixel.params[3];
|
||||
unsigned c3 = term->sixel.params[4];
|
||||
int c1 = term->sixel.params[2];
|
||||
int c2 = term->sixel.params[3];
|
||||
int c3 = term->sixel.params[4];
|
||||
|
||||
switch (format) {
|
||||
case 1: { /* HLS */
|
||||
uint32_t rgb = hls_to_rgb(c1, c2, c3);
|
||||
int hue = min(c1, 360);
|
||||
int lum = min(c2, 100);
|
||||
int sat = min(c3, 100);
|
||||
|
||||
/*
|
||||
* Sixel’s HLS use the following primary color hues:
|
||||
* blue: 0°
|
||||
* red: 120°
|
||||
* green: 240°
|
||||
*
|
||||
* While “standard” HSL uses:
|
||||
* red: 0°
|
||||
* green: 120°
|
||||
* blue: 240°
|
||||
*/
|
||||
hue = (hue + 240) % 360;
|
||||
|
||||
uint32_t rgb = hsl_to_rgb(hue, sat, lum);
|
||||
|
||||
LOG_DBG("setting palette #%d = HLS %hhu/%hhu/%hhu (0x%06x)",
|
||||
term->sixel.color_idx, c1, c2, c3, rgb);
|
||||
term->sixel.color_idx, hue, lum, sat, rgb);
|
||||
|
||||
term->sixel.palette[term->sixel.color_idx] = rgb;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: { /* RGB */
|
||||
uint8_t r = 255 * c1 / 100;
|
||||
uint8_t g = 255 * c2 / 100;
|
||||
uint8_t b = 255 * c3 / 100;
|
||||
uint8_t r = 255 * min(c1, 100) / 100;
|
||||
uint8_t g = 255 * min(c2, 100) / 100;
|
||||
uint8_t b = 255 * min(c3, 100) / 100;
|
||||
|
||||
LOG_DBG("setting palette #%d = RGB %hhu/%hhu/%hhu",
|
||||
term->sixel.color_idx, r, g, b);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue