Skip to content

Commit 4ca03d8

Browse files
committed
Epoch.
0 parents  commit 4ca03d8

File tree

5 files changed

+482
-0
lines changed

5 files changed

+482
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ff-sort
2+
*.png

COPYING

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
ISC License
2+
3+
Copyright (c) 2018, Adrian "vifino" Pistol
4+
5+
Permission to use, copy, modify, and/or distribute this software for any
6+
purpose with or without fee is hereby granted, provided that the above
7+
copyright notice and this permission notice appear in all copies.
8+
9+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Makefile

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CC ?= cc
2+
CFLAGS ?= -Os
3+
CPPLAGS += -pedantic -Wall -Wextra
4+
5+
DESTDIR ?= /usr/local
6+
7+
BINS=ff-sort
8+
all: $(BINS)
9+
10+
ff-sort: ff-sort.c
11+
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $^
12+
13+
install: $(BINS)
14+
install $(BINS) $(DESTDIR)/bin
15+
16+
clean:
17+
rm -f $(BINS)

conversion.h

+174
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
// Small library for color conversion.
2+
// All with alpha channel.
3+
// Uses doubles for conversion.
4+
// Not fast at all, but simple.
5+
#include <stdint.h>
6+
#include <math.h>
7+
8+
// I know, I know, not standardized.
9+
// But painless fallback.
10+
#if defined(__linux__)
11+
#include <endian.h>
12+
#if __BYTE_ORDER != __BIG_ENDIAN
13+
#define DOCONVERT
14+
#endif
15+
#else
16+
#define DOCONVERT
17+
#include <arpa/inet.h>
18+
#define be32toh ntohl
19+
#define htobe32 htonl
20+
#define be16toh ntohs
21+
#define htobe16 htons
22+
#endif
23+
24+
#ifndef FP
25+
#define FP double
26+
#endif
27+
28+
#if FP == float
29+
#define FPOW powf
30+
#define FMOD fmodf
31+
#define FMIN fmin
32+
#define FMAX fmax
33+
#else
34+
#define FPOW pow
35+
#define FMOD fmod
36+
#define FMIN fminf
37+
#define FMAX fmaxf
38+
#endif
39+
40+
// BE uint16_t <-> NE uint16_t
41+
static inline void qbeush2ush(uint16_t* src, uint16_t* dst) {
42+
dst[0] = be16toh(src[0]);
43+
dst[1] = be16toh(src[1]);
44+
dst[2] = be16toh(src[2]);
45+
dst[3] = be16toh(src[3]);
46+
}
47+
static inline void qush2beush(uint16_t* src, uint16_t* dst) {
48+
dst[0] = htobe16(src[0]);
49+
dst[1] = htobe16(src[1]);
50+
dst[2] = htobe16(src[2]);
51+
dst[3] = htobe16(src[3]);
52+
}
53+
54+
// uint16 <-> FP 0..1
55+
#define USH2FP(chan) (((FP) (chan)) / UINT16_MAX)
56+
#define FP2USH(chan) ((uint16_t) (chan * UINT16_MAX))
57+
58+
static inline void qush2fp(uint16_t* src, FP* dst) {
59+
dst[0] = USH2FP(src[0]);
60+
dst[1] = USH2FP(src[1]);
61+
dst[2] = USH2FP(src[2]);
62+
dst[3] = USH2FP(src[3]);
63+
}
64+
static inline void qfp2ush(FP* src, uint16_t* dst) {
65+
dst[0] = FP2USH(src[0]);
66+
dst[1] = FP2USH(src[1]);
67+
dst[2] = FP2USH(src[2]);
68+
dst[3] = FP2USH(src[3]);
69+
}
70+
71+
// SRGB <-> Linear RGB
72+
#define SRGB_THRES ((FP) 0.0031306684425217108)
73+
#define SRGB2RGB(s) ((s <= (SRGB_THRES * 12.92)) ? s / 12.92 : FPOW((s + 0.055) / 1.055, 2.4))
74+
#define RGB2SRGB(l) ((l <= SRGB_THRES) ? l * 12.92 : 1.055 * FPOW(l, 1.0/2.4) - 0.055)
75+
76+
static inline void srgb2rgb(FP* src, FP* dst) {
77+
dst[0] = SRGB2RGB(src[0]);
78+
dst[1] = SRGB2RGB(src[1]);
79+
dst[2] = SRGB2RGB(src[2]);
80+
dst[3] = src[3]; // yep. very complicated.
81+
}
82+
static inline void rgb2srgb(FP* src, FP* dst) {
83+
dst[0] = RGB2SRGB(src[0]);
84+
dst[1] = RGB2SRGB(src[1]);
85+
dst[2] = RGB2SRGB(src[2]);
86+
dst[3] = src[3]; // yep. very complicated.
87+
}
88+
89+
// RGB <-> HSV
90+
// Definitly stolen off the internet.
91+
static inline void rgb2hsv(FP* src, FP* dst) {
92+
FP r = src[0];
93+
FP g = src[1];
94+
FP b = src[2];
95+
96+
FP max = FMAX(FMAX(r, g), b);
97+
FP min = FMIN(FMIN(r, g), b);
98+
FP d = max - min;
99+
100+
FP h = (max == min) ? 0 : max;
101+
FP s = (max == 0) ? 0 : d / max;
102+
FP v = max;
103+
104+
if (r == max) {
105+
h = (g - b) / d + (g < b ? 6 : 0);
106+
} else if (g == max) {
107+
h = (b - r) / d + 2;
108+
} else {
109+
h = (r - g) / d + 4;
110+
}
111+
112+
dst[0] = h;
113+
dst[1] = s;
114+
dst[2] = v;
115+
dst[3] = src[3]; // copy alpha;
116+
}
117+
118+
static inline void hsv2rgb(FP* src, FP* dst) {
119+
FP i = floor(src[0] * 6);
120+
FP f = src[0] * 6 - i;
121+
FP p = src[3] * (1 - src[1]);
122+
FP q = src[3] * (1 - f * src[1]);
123+
FP t = src[3] * (1 - (1 - f) * src[1]);
124+
125+
switch((int) FMOD(i, 6)){
126+
case 0: dst[0] = src[2], dst[1] = t, dst[2] = p; break;
127+
case 1: dst[0] = q, dst[1] = src[2], dst[2] = p; break;
128+
case 2: dst[0] = p, dst[1] = src[2], dst[2] = t; break;
129+
case 3: dst[0] = p, dst[1] = q, dst[2] = src[2]; break;
130+
case 4: dst[0] = t, dst[1] = p, dst[2] = src[2]; break;
131+
case 5: dst[0] = src[2], dst[1] = p, dst[2] = q; break;
132+
}
133+
dst[3] = src[3];
134+
}
135+
136+
// Linear RGB <-> CIE XYZ
137+
#define MAT3MUL(s, v1, v2, v3) (s[0] * (FP)(v1) + s[1] * (FP)(v2) + s[2] * (FP)(v3))
138+
139+
#define MAT3M3MUL(s, d, scale, r1m1, r1m2, r1m3, r2m1, r2m2, r2m3, r3m1, r3m2, r3m3) \
140+
(d)[0] = MAT3MUL((s), r1m1, r1m2, r1m3) * (FP)(scale); \
141+
(d)[1] = MAT3MUL((s), r2m1, r2m2, r2m3) * (FP)(scale); \
142+
(d)[2] = MAT3MUL((s), r3m1, r3m2, r3m3) * (FP)(scale);
143+
144+
static inline void rgb2xyz(FP* src, FP* dst) {
145+
// table stolen from blind.
146+
// seems to be a bit too bright?
147+
MAT3M3MUL(src, dst, 1,
148+
0.412457445582367576708548995157,
149+
0.357575865245515878143578447634,
150+
0.180437247826399665973085006954,
151+
0.212673370378408277403536885686,
152+
0.715151730491031756287156895269,
153+
0.072174899130559869164791564344,
154+
0.019333942761673460208893260415,
155+
0.119191955081838593666354597644,
156+
0.950302838552371742508739771438);
157+
158+
dst[3] = src[3]; // yep. very complicated.
159+
}
160+
161+
static inline void xyz2rgb(FP* src, FP* dst) {
162+
// table stolen from blind.
163+
MAT3M3MUL(src, dst, 1,
164+
3.240446254647737500675930277794,
165+
-1.537134761820080575134284117667,
166+
-0.498530193022728718155178739835,
167+
-0.969266606244679751469561779231,
168+
1.876011959788370209167851498933,
169+
0.041556042214430065351304932619,
170+
0.055643503564352832235773149705,
171+
-0.204026179735960239147729566866,
172+
1.057226567722703292062647051353);
173+
dst[3] = src[3];
174+
}

0 commit comments

Comments
 (0)