fast_thumbhash 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ruby-version +1 -0
- data/Gemfile.lock +2 -1
- data/ext/fast_thumbhash/fast_thumbhash.c +73 -45
- data/ext/fast_thumbhash/fast_thumbhash.h +18 -20
- data/lib/fast_thumbhash/version.rb +1 -1
- data/lib/fast_thumbhash.rb +3 -4
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '029bcedcfcff9aeabbd3d052759f165228798ba5a4599747866b80c0e7cb2267'
|
4
|
+
data.tar.gz: c0284c796f2541a68ba0ce5d5f6d39362abc487d443ea92fe34f1cae84e49da2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8305727fad3e3d55f31265f05f3bad5931f6a6cb90787e896a8aacde19d3fa5aa75c122a3d6a7a977b0f0703c95323556527401816641148f69c25001b5b30e9
|
7
|
+
data.tar.gz: 77e126d32164ec0531b0ee450a950e59e7f872ca18d2fbb46e5544171f35f44066835817fb0f6cccce2625e806e5af9a280c238e7bd104de2125065e6b6e3cb8
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.7.8
|
data/Gemfile.lock
CHANGED
@@ -67,14 +67,20 @@ encoded_channel encode_channel(double *channel, uint8_t nx, uint8_t ny, uint8_t
|
|
67
67
|
return (encoded_channel){dc, ac, ac_length, scale};
|
68
68
|
}
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
70
|
+
uint8_t write_varying_factors(double *ac, int ac_size, uint8_t *thumbhash, uint8_t *ac_index)
|
71
|
+
{
|
72
|
+
uint8_t index;
|
73
|
+
|
74
|
+
for (int i = 0; i < ac_size; i++)
|
75
|
+
{
|
76
|
+
index = (*ac_index) >> 1;
|
77
|
+
thumbhash[index] |= (uint8_t)roundf(15.0 * ac[i]) << (((*ac_index)++ & 1) << 2);
|
74
78
|
}
|
79
|
+
|
80
|
+
return index;
|
75
81
|
}
|
76
82
|
|
77
|
-
|
83
|
+
uint8_t rgba_to_thumbhash(uint8_t w, uint8_t h, uint8_t *rgba, uint8_t *thumbhash)
|
78
84
|
{
|
79
85
|
assert(w <= 100);
|
80
86
|
assert(h <= 100);
|
@@ -143,28 +149,44 @@ void rgba_to_thumbhash(uint8_t w, uint8_t h, uint8_t *rgba, uint8_t *thumbhash)
|
|
143
149
|
thumbhash[3] = (uint8_t)(header16 & 0xff);
|
144
150
|
thumbhash[4] = (uint8_t)(header16 >> 8);
|
145
151
|
|
146
|
-
if (has_alpha)
|
147
|
-
|
152
|
+
if (has_alpha)
|
153
|
+
{
|
154
|
+
thumbhash[5] = (uint8_t)roundf(15.0 * ea.dc) | ((uint8_t)roundf(15.0 * ea.scale) << 4);
|
148
155
|
}
|
149
156
|
|
150
157
|
uint8_t ac_start = has_alpha ? 6 : 5;
|
151
158
|
uint8_t ac_index = 0;
|
152
159
|
|
153
|
-
|
154
|
-
|
155
|
-
write_varying_factors(
|
160
|
+
uint8_t max_written_indexes[] = {0, 0, 0, 0};
|
161
|
+
|
162
|
+
max_written_indexes[0] = write_varying_factors(el.ac, el.ac_size, thumbhash + ac_start, &ac_index);
|
163
|
+
max_written_indexes[1] = write_varying_factors(ep.ac, ep.ac_size, thumbhash + ac_start, &ac_index);
|
164
|
+
max_written_indexes[2] = write_varying_factors(eq.ac, eq.ac_size, thumbhash + ac_start, &ac_index);
|
156
165
|
|
157
|
-
if (has_alpha)
|
158
|
-
|
166
|
+
if (has_alpha)
|
167
|
+
{
|
168
|
+
max_written_indexes[3] = write_varying_factors(ea.ac, ea.ac_size, thumbhash + ac_start, &ac_index);
|
159
169
|
}
|
160
170
|
|
161
171
|
free(el.ac);
|
162
172
|
free(ep.ac);
|
163
173
|
free(eq.ac);
|
164
174
|
|
165
|
-
if (has_alpha)
|
175
|
+
if (has_alpha)
|
176
|
+
{
|
166
177
|
free(ea.ac);
|
167
178
|
}
|
179
|
+
|
180
|
+
// store the largest number at max_written_indexes[0]
|
181
|
+
for (int i = 1; i < 4; ++i)
|
182
|
+
{
|
183
|
+
if (max_written_indexes[0] < max_written_indexes[i])
|
184
|
+
{
|
185
|
+
max_written_indexes[0] = max_written_indexes[i];
|
186
|
+
}
|
187
|
+
}
|
188
|
+
|
189
|
+
return max_written_indexes[0] + ac_start + 1;
|
168
190
|
}
|
169
191
|
|
170
192
|
double *decode_channel(uint8_t nx, uint8_t ny, double scale, uint8_t *hash, uint8_t ac_start, uint8_t *ac_index)
|
@@ -321,15 +343,14 @@ void hsv2rgb(float *hsv, uint8_t *rgb)
|
|
321
343
|
* Decodes a ThumbHash to an RGBA image. RGB is not be premultiplied by A.
|
322
344
|
*/
|
323
345
|
void thumbhash_to_rgba(
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
)
|
346
|
+
uint8_t *hash,
|
347
|
+
uint8_t w,
|
348
|
+
uint8_t h,
|
349
|
+
enum FillMode fill_mode,
|
350
|
+
uint8_t *fill_color,
|
351
|
+
double *homogeneous_transform,
|
352
|
+
int saturation,
|
353
|
+
uint8_t *rgba)
|
333
354
|
{
|
334
355
|
// Read the constants
|
335
356
|
u_int32_t header24 = hash[0] | (hash[1] << 8) | (hash[2] << 16);
|
@@ -343,7 +364,8 @@ void thumbhash_to_rgba(
|
|
343
364
|
double q_scale = (double)((header16 >> 9) & 63) / 63;
|
344
365
|
bool is_landscape = (header16 >> 15) != 0;
|
345
366
|
uint8_t lx = fmax(3, is_landscape ? has_alpha ? 5 : 7 : header16 & 7);
|
346
|
-
uint8_t ly = fmax(3, is_landscape ? header16 & 7 : has_alpha ? 5
|
367
|
+
uint8_t ly = fmax(3, is_landscape ? header16 & 7 : has_alpha ? 5
|
368
|
+
: 7);
|
347
369
|
double a_dc = (double)has_alpha ? (hash[5] & 15) / 15 : 1;
|
348
370
|
double a_scale = (double)(hash[5] >> 4) / 15;
|
349
371
|
|
@@ -380,7 +402,8 @@ void thumbhash_to_rgba(
|
|
380
402
|
|
381
403
|
double r, g, b, a;
|
382
404
|
|
383
|
-
if (fill_mode == CLAMP || fill_mode == BLUR)
|
405
|
+
if (fill_mode == CLAMP || fill_mode == BLUR)
|
406
|
+
{
|
384
407
|
if (x < 0)
|
385
408
|
{
|
386
409
|
x = 0;
|
@@ -401,7 +424,8 @@ void thumbhash_to_rgba(
|
|
401
424
|
|
402
425
|
bool inside_image = x >= 0 && x <= 1.0 && y >= 0 && y <= 1.0;
|
403
426
|
|
404
|
-
if (inside_image)
|
427
|
+
if (inside_image)
|
428
|
+
{
|
405
429
|
double l = l_dc, p = p_dc, q = q_dc;
|
406
430
|
a = a_dc;
|
407
431
|
|
@@ -455,7 +479,9 @@ void thumbhash_to_rgba(
|
|
455
479
|
b = l - 2.0 / 3.0 * p;
|
456
480
|
r = (3.0 * l - b + q) / 2.0;
|
457
481
|
g = r - q;
|
458
|
-
}
|
482
|
+
}
|
483
|
+
else
|
484
|
+
{
|
459
485
|
r = 255;
|
460
486
|
g = 255;
|
461
487
|
b = 255;
|
@@ -463,35 +489,37 @@ void thumbhash_to_rgba(
|
|
463
489
|
}
|
464
490
|
|
465
491
|
uint_fast8_t top[4] = {
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
double top_a = (double)
|
474
|
-
double fill_color_a = (double)
|
492
|
+
fmax(0, 255 * fmin(1, r)),
|
493
|
+
fmax(0, 255 * fmin(1, g)),
|
494
|
+
fmax(0, 255 * fmin(1, b)),
|
495
|
+
fmax(0, 255 * fmin(1, a))};
|
496
|
+
|
497
|
+
if (fill_color && fill_color[3] > 0)
|
498
|
+
{
|
499
|
+
double top_a = (double)top[3] / 255.0;
|
500
|
+
double fill_color_a = (double)fill_color[3] / 255.0;
|
475
501
|
double inverse_top_a = 1.0 - top_a;
|
476
502
|
double sum_a = top_a + fill_color_a * inverse_top_a;
|
477
503
|
|
478
504
|
// Alpha compositing (top over fill_color)
|
479
|
-
rgba[i]
|
480
|
-
rgba[i+1] = roundf(((double)
|
481
|
-
rgba[i+2] = roundf(((double)
|
482
|
-
rgba[i+3] = roundf(sum_a * 255.0);
|
483
|
-
}
|
484
|
-
|
485
|
-
|
486
|
-
rgba[i
|
487
|
-
rgba[i+
|
505
|
+
rgba[i] = roundf(((double)top[0] * top_a + (double)fill_color[0] * fill_color_a * inverse_top_a) / sum_a);
|
506
|
+
rgba[i + 1] = roundf(((double)top[1] * top_a + (double)fill_color[1] * fill_color_a * inverse_top_a) / sum_a);
|
507
|
+
rgba[i + 2] = roundf(((double)top[2] * top_a + (double)fill_color[2] * fill_color_a * inverse_top_a) / sum_a);
|
508
|
+
rgba[i + 3] = roundf(sum_a * 255.0);
|
509
|
+
}
|
510
|
+
else
|
511
|
+
{
|
512
|
+
rgba[i] = top[0];
|
513
|
+
rgba[i + 1] = top[1];
|
514
|
+
rgba[i + 2] = top[2];
|
515
|
+
rgba[i + 3] = top[3];
|
488
516
|
}
|
489
517
|
|
490
518
|
if (saturation)
|
491
519
|
{
|
492
520
|
float hsv[3] = {0};
|
493
521
|
rgb2hsv(rgba + i, hsv);
|
494
|
-
float mult = ((float)
|
522
|
+
float mult = ((float)saturation + 100.0f) / 200.0f * 1.4f;
|
495
523
|
hsv[1] = fminf(fmaxf(hsv[1] * mult, 0), 1.0f);
|
496
524
|
hsv2rgb(hsv, rgba + i);
|
497
525
|
}
|
@@ -3,34 +3,32 @@
|
|
3
3
|
|
4
4
|
#include <stdint.h>
|
5
5
|
|
6
|
-
enum FillMode
|
6
|
+
enum FillMode
|
7
|
+
{
|
7
8
|
SOLID = 0,
|
8
9
|
BLUR = 1,
|
9
10
|
CLAMP = 2,
|
10
11
|
};
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
);
|
13
|
+
uint8_t rgba_to_thumbhash(
|
14
|
+
uint8_t w,
|
15
|
+
uint8_t h,
|
16
|
+
uint8_t *rgba,
|
17
|
+
uint8_t *thumbhash);
|
18
18
|
|
19
19
|
void thumb_size(
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
);
|
20
|
+
uint8_t *hash,
|
21
|
+
uint8_t max_size,
|
22
|
+
uint8_t *size);
|
24
23
|
|
25
24
|
void thumbhash_to_rgba(
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
);
|
25
|
+
uint8_t *hash,
|
26
|
+
uint8_t w,
|
27
|
+
uint8_t h,
|
28
|
+
enum FillMode fill_mode,
|
29
|
+
uint8_t *fill_color,
|
30
|
+
double *homogeneous_transform,
|
31
|
+
int saturation,
|
32
|
+
uint8_t *rgba);
|
35
33
|
|
36
34
|
#endif
|
data/lib/fast_thumbhash.rb
CHANGED
@@ -155,10 +155,9 @@ module FastThumbhash
|
|
155
155
|
|
156
156
|
thumbhash_pointer = FFI::MemoryPointer.new(:uint8, 25)
|
157
157
|
|
158
|
-
Library.rgba_to_thumbhash(width, height, rgba_pointer, thumbhash_pointer)
|
158
|
+
length = Library.rgba_to_thumbhash(width, height, rgba_pointer, thumbhash_pointer)
|
159
159
|
|
160
|
-
result = thumbhash_pointer.read_array_of_uint8(
|
161
|
-
result.pop while result.last.zero?
|
160
|
+
result = thumbhash_pointer.read_array_of_uint8(length)
|
162
161
|
|
163
162
|
result.pack("C*")
|
164
163
|
ensure
|
@@ -178,6 +177,6 @@ module FastThumbhash
|
|
178
177
|
|
179
178
|
attach_function :thumb_size, %i[pointer uint8 pointer], :size_t
|
180
179
|
attach_function :thumbhash_to_rgba, %i[pointer uint8 uint8 fill_mode pointer pointer int pointer], :void
|
181
|
-
attach_function :rgba_to_thumbhash, %i[uint8 uint8 pointer pointer], :
|
180
|
+
attach_function :rgba_to_thumbhash, %i[uint8 uint8 pointer pointer], :uint8
|
182
181
|
end
|
183
182
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fast_thumbhash
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stefano Verna
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -35,6 +35,7 @@ extra_rdoc_files: []
|
|
35
35
|
files:
|
36
36
|
- ".rspec"
|
37
37
|
- ".rubocop.yml"
|
38
|
+
- ".ruby-version"
|
38
39
|
- CODE_OF_CONDUCT.md
|
39
40
|
- Gemfile
|
40
41
|
- Gemfile.lock
|