1 /* babl - dynamically extendable universal pixel conversion library.
2 * Copyright (C) 2012, Øyvind Kolås
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 3 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General
15 * Public License along with this library; if not, see
16 * <https://www.gnu.org/licenses/>.
25 #include "babl-cpuaccel.h"
26 #include "extensions/util.h"
27 #include "base/util.h"
31 typedef float (* BablLookupFunction
) (float value
,
33 #define babl_LOOKUP_MAX_ENTRIES (819200)
35 typedef struct BablLookup
37 BablLookupFunction function
;
40 uint32_t positive_min
, positive_max
, negative_min
, negative_max
;
41 uint32_t bitmask
[babl_LOOKUP_MAX_ENTRIES
/32];
47 static BablLookup
*babl_lookup_new (BablLookupFunction function
,
53 static void babl_lookup_free (BablLookup
*lookup
);
59 babl_lookup (BablLookup
*lookup
,
62 union { float f
; uint32_t i
; } u
;
63 union { float f
; uint32_t i
; } ub
;
64 union { float f
; uint32_t i
; } ua
;
70 i
= (u
.i
<< LSHIFT
) >> lookup
->shift
;
72 if (i
> lookup
->positive_min
&& i
< lookup
->positive_max
)
74 ua
.i
= ((i
) << lookup
->shift
) >> LSHIFT
;
75 ub
.i
= ((i
+ 1) << lookup
->shift
) >> LSHIFT
;
77 i
= i
- lookup
->positive_min
;
79 else if (i
> lookup
->negative_min
&& i
< lookup
->negative_max
)
82 ua
.i
= ((i
) << lookup
->shift
) >> LSHIFT
;
83 ub
.i
= ((i
+ 1) << lookup
->shift
) >> LSHIFT
;
85 i
= i
- lookup
->negative_min
+ (lookup
->positive_max
- lookup
->positive_min
);
89 return lookup
->function (number
, lookup
->data
);
93 uint32_t bm
=u
.i
& 0b11110000000000000000000000000000;
97 dx
= (u
.f
-ua
.f
) / (ub
.f
- ua
.f
);
101 if (!(lookup
->bitmask
[i
/32] & (1UL<<(i
& 31))))
103 lookup
->table
[i
]= lookup
->function (ua
.f
, lookup
->data
);
104 lookup
->bitmask
[i
/32] |= (1UL<<(i
& 31));
107 if (i
< lookup
->entries
-2)
109 if (!(lookup
->bitmask
[i
/32] & (1UL<<(i
& 31))))
111 lookup
->table
[i
]= lookup
->function (ub
.f
, lookup
->data
);
112 lookup
->bitmask
[i
/32] |= (1UL<<(i
& 31));
115 return lookup
->table
[i
-1] * (1.0f
-dx
) +
116 lookup
->table
[i
] * (dx
);
120 return lookup
->table
[i
-1];
126 babl_lookup_new (BablLookupFunction function
,
138 int positive_min
, positive_max
, negative_min
, negative_max
;
141 /* normalize input parameters */
149 if (precision
<= 0.000005f
) shift
= 0; /* checked for later */
150 else if (precision
<= 0.000010f
) shift
= 8;
151 else if (precision
<= 0.000020f
) shift
= 9;
152 else if (precision
<= 0.000040f
) shift
= 10;
153 else if (precision
<= 0.000081f
) shift
= 11;
154 else if (precision
<= 0.000161f
) shift
= 12;
155 else if (precision
<= 0.000200f
) shift
= 13;
156 else if (precision
<= 0.000324f
) shift
= 14;
157 else if (precision
<= 0.000649f
) shift
= 15;
158 else shift
= 16; /* a bit better than 8bit sRGB quality */
161 /* Adjust slightly away from 0.0, saving many entries close to 0, this
162 * causes lookups very close to zero to be passed directly to the
170 /* Compute start and */
172 if (start
< 0.0f
|| end
< 0.0f
)
177 positive_max
= (u
.i
<< LSHIFT
) >> shift
;
179 positive_min
= (u
.i
<< LSHIFT
) >> shift
;
180 negative_min
= positive_max
;
181 negative_max
= positive_max
;
186 positive_min
= (u
.i
<< LSHIFT
) >> shift
;
188 positive_max
= (u
.i
<< LSHIFT
) >> shift
;
191 negative_min
= (u
.i
<< LSHIFT
) >> shift
;
193 negative_max
= (u
.i
<< LSHIFT
) >> shift
;
199 positive_min
= (u
.i
<< LSHIFT
) >> shift
;
201 positive_max
= (u
.i
<< LSHIFT
) >> shift
;
202 negative_min
= positive_max
;
203 negative_max
= positive_max
;
206 if (shift
== 0) /* short circuit, do not use ranges */
208 positive_min
= positive_max
= negative_min
= negative_max
= 0;
211 if ((positive_max
-positive_min
) + (negative_max
-negative_min
) > babl_LOOKUP_MAX_ENTRIES
)
213 /* Reduce the size of the cache tables to fit within the bittable
214 * budget (the maximum allocation is around 2.18mb of memory
217 int diff
= (positive_max
-positive_min
) + (negative_max
-negative_min
) - babl_LOOKUP_MAX_ENTRIES
;
219 if (negative_max
- negative_min
> 0)
221 if (negative_max
- negative_min
>= diff
)
223 negative_max
-= diff
;
228 diff
-= negative_max
- negative_min
;
229 negative_max
= negative_min
;
236 lookup
= calloc (sizeof (BablLookup
) + sizeof (float) *
237 ((positive_max
-positive_min
)+
238 (negative_max
-negative_min
)), 1);
240 lookup
->positive_min
= positive_min
;
241 lookup
->positive_max
= positive_max
;
242 lookup
->negative_min
= negative_min
;
243 lookup
->negative_max
= negative_max
;
244 lookup
->shift
= shift
;
245 lookup
->function
= function
;
248 lookup
->entries
= (positive_max
-positive_min
)+
249 (negative_max
-negative_min
);
254 static BablLookup
*fast_pow
= NULL
;
256 static inline float core_lookup (float val
, void *userdata
)
258 return babl_linear_to_gamma_2_2f (val
);
262 linear_to_gamma_2_2_lut (float val
)
264 return babl_lookup (fast_pow
, val
);
267 static BablLookup
*fast_rpow
= NULL
;
269 static inline float core_rlookup (float val
, void *userdata
)
271 return babl_gamma_2_2_to_linearf (val
);
275 gamma_2_2_to_linear_lut (float val
)
277 return babl_lookup (fast_rpow
, val
);
282 babl_lookup_free (BablLookup
*lookup
)
289 conv_rgbaF_linear_rgbAF_gamma (const Babl
*conversion
,
294 float *fsrc
= (float *) src
;
295 float *fdst
= (float *) dst
;
301 float green
= *fsrc
++;
302 float blue
= *fsrc
++;
303 float alpha
= *fsrc
++;
306 *fdst
++ = linear_to_gamma_2_2_lut (red
);
307 *fdst
++ = linear_to_gamma_2_2_lut (green
);
308 *fdst
++ = linear_to_gamma_2_2_lut (blue
);
313 float used_alpha
= babl_epsilon_for_zero_float (alpha
);
314 *fdst
++ = linear_to_gamma_2_2_lut (red
) * used_alpha
;
315 *fdst
++ = linear_to_gamma_2_2_lut (green
) * used_alpha
;
316 *fdst
++ = linear_to_gamma_2_2_lut (blue
) * used_alpha
;
325 conv_rgbaF_linear_rgba8_gamma (const Babl
*conversion
,
330 float *fsrc
= (float *) src
;
331 uint8_t *cdst
= (uint8_t *) dst
;
337 float green
= *fsrc
++;
338 float blue
= *fsrc
++;
339 float alpha
= *fsrc
++;
340 if (alpha
<= 0) /* XXX: we need to drop alpha!! ? */
349 int val
= linear_to_gamma_2_2_lut (red
) * 0xff + 0.5f
;
350 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
351 val
= linear_to_gamma_2_2_lut (green
) * 0xff + 0.5f
;
352 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
353 val
= linear_to_gamma_2_2_lut (blue
) * 0xff + 0.5f
;
354 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
355 val
= alpha
* 0xff + 0.5f
;
356 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
362 conv_rgbaF_linear_rgbA8_gamma (const Babl
*conversion
,
367 float *fsrc
= (float *) src
;
368 uint8_t *cdst
= (uint8_t *) dst
;
374 float green
= *fsrc
++;
375 float blue
= *fsrc
++;
376 float alpha
= *fsrc
++;
379 int val
= linear_to_gamma_2_2_lut (red
) * 0xff + 0.5f
;
380 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
381 val
= linear_to_gamma_2_2_lut (green
) * 0xff + 0.5f
;
382 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
383 val
= linear_to_gamma_2_2_lut (blue
) * 0xff + 0.5f
;
384 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
389 float balpha
= alpha
* 0xff;
390 int val
= linear_to_gamma_2_2_lut (red
) * balpha
+ 0.5f
;
391 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
392 val
= linear_to_gamma_2_2_lut (green
) * balpha
+ 0.5f
;
393 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
394 val
= linear_to_gamma_2_2_lut (blue
) * balpha
+ 0.5f
;
395 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
396 *cdst
++ = balpha
+ 0.5f
;
402 conv_yaF_linear_rgbA8_gamma (const Babl
*conversion
,unsigned char *src
,
406 float *fsrc
= (float *) src
;
407 uint8_t *cdst
= (uint8_t *) dst
;
412 float gray
= *fsrc
++;
413 float alpha
= *fsrc
++;
416 int val
= linear_to_gamma_2_2_lut (gray
) * 0xff + 0.5f
;
417 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
418 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
419 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
422 else if (alpha
<= 0.0f
)
424 *((uint32_t*)(cdst
))=0;
429 float balpha
= alpha
* 0xff;
430 int val
= linear_to_gamma_2_2_lut (gray
) * balpha
+ 0.5f
;
431 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
432 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
433 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
434 *cdst
++ = balpha
+ 0.5f
;
442 conv_rgbaF_linear_rgbA8_gamma_cairo (const Babl
*conversion
,unsigned char *src
,
446 float *fsrc
= (float *) src
;
447 unsigned char *cdst
= (unsigned char *) dst
;
453 float green
= *fsrc
++;
454 float blue
= *fsrc
++;
455 float alpha
= *fsrc
++;
458 int val
= linear_to_gamma_2_2_lut (blue
) * 0xff + 0.5f
;
459 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
460 val
= linear_to_gamma_2_2_lut (green
) * 0xff + 0.5f
;
461 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
462 val
= linear_to_gamma_2_2_lut (red
) * 0xff + 0.5f
;
463 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
468 float balpha
= alpha
* 0xff;
469 int val
= linear_to_gamma_2_2_lut (blue
) * balpha
+ 0.5f
;
470 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
471 val
= linear_to_gamma_2_2_lut (green
) * balpha
+ 0.5f
;
472 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
473 val
= linear_to_gamma_2_2_lut (red
) * balpha
+ 0.5f
;
474 *cdst
++ = val
>= 0xff ? 0xff : val
<= 0 ? 0 : val
;
475 *cdst
++ = balpha
+ 0.5f
;
481 conv_rgbAF_linear_rgbAF_gamma (const Babl
*conversion
,
486 float *fsrc
= (float *) src
;
487 float *fdst
= (float *) dst
;
493 float green
= *fsrc
++;
494 float blue
= *fsrc
++;
495 float alpha
= *fsrc
++;
499 *fdst
++ = linear_to_gamma_2_2_lut (red
);
500 *fdst
++ = linear_to_gamma_2_2_lut (green
);
501 *fdst
++ = linear_to_gamma_2_2_lut (blue
);
506 float alpha_recip
= 1.0f
/ alpha
;
507 *fdst
++ = linear_to_gamma_2_2_lut (red
* alpha_recip
) * alpha
;
508 *fdst
++ = linear_to_gamma_2_2_lut (green
* alpha_recip
) * alpha
;
509 *fdst
++ = linear_to_gamma_2_2_lut (blue
* alpha_recip
) * alpha
;
516 conv_rgbaF_linear_rgbaF_gamma (const Babl
*conversion
,
521 float *fsrc
= (float *) src
;
522 float *fdst
= (float *) dst
;
527 *fdst
++ = linear_to_gamma_2_2_lut (*fsrc
++);
528 *fdst
++ = linear_to_gamma_2_2_lut (*fsrc
++);
529 *fdst
++ = linear_to_gamma_2_2_lut (*fsrc
++);
535 conv_rgbF_linear_rgbF_gamma (const Babl
*conversion
,unsigned char *src
,
539 float *fsrc
= (float *) src
;
540 float *fdst
= (float *) dst
;
545 *fdst
++ = linear_to_gamma_2_2_lut (*fsrc
++);
546 *fdst
++ = linear_to_gamma_2_2_lut (*fsrc
++);
547 *fdst
++ = linear_to_gamma_2_2_lut (*fsrc
++);
553 conv_rgbaF_gamma_rgbaF_linear (const Babl
*conversion
,
558 float *fsrc
= (float *) src
;
559 float *fdst
= (float *) dst
;
564 *fdst
++ = gamma_2_2_to_linear_lut (*fsrc
++);
565 *fdst
++ = gamma_2_2_to_linear_lut (*fsrc
++);
566 *fdst
++ = gamma_2_2_to_linear_lut (*fsrc
++);
572 conv_rgbF_gamma_rgbF_linear (const Babl
*conversion
,
577 float *fsrc
= (float *) src
;
578 float *fdst
= (float *) dst
;
583 *fdst
++ = gamma_2_2_to_linear_lut (*fsrc
++);
584 *fdst
++ = gamma_2_2_to_linear_lut (*fsrc
++);
585 *fdst
++ = gamma_2_2_to_linear_lut (*fsrc
++);
589 #define o(src, dst) \
590 babl_conversion_new (src, dst, "linear", conv_ ## src ## _ ## dst, NULL)
592 #include "babl-verify-cpu.inc"
600 const Babl
*yaF_linear
= babl_format_new (
603 babl_component ("Y"),
604 babl_component ("A"),
607 const Babl
*rgbaF_linear
= babl_format_new (
610 babl_component ("R"),
611 babl_component ("G"),
612 babl_component ("B"),
613 babl_component ("A"),
615 const Babl
*rgbAF_linear
= babl_format_new (
616 babl_model ("RaGaBaA"),
618 babl_component ("Ra"),
619 babl_component ("Ga"),
620 babl_component ("Ba"),
621 babl_component ("A"),
623 const Babl
*rgbaF_gamma
= babl_format_new (
624 babl_model ("R'G'B'A"),
626 babl_component ("R'"),
627 babl_component ("G'"),
628 babl_component ("B'"),
629 babl_component ("A"),
631 const Babl
*rgbAF_gamma
= babl_format_new (
632 babl_model ("R'aG'aB'aA"),
634 babl_component ("R'a"),
635 babl_component ("G'a"),
636 babl_component ("B'a"),
637 babl_component ("A"),
640 const Babl
*rgbA8_gamma
= babl_format_new (
641 babl_model ("R'aG'aB'aA"),
643 babl_component ("R'a"),
644 babl_component ("G'a"),
645 babl_component ("B'a"),
646 babl_component ("A"),
649 const Babl
*rgba8_gamma
= babl_format_new (
650 babl_model ("R'G'B'A"),
652 babl_component ("R'"),
653 babl_component ("G'"),
654 babl_component ("B'"),
655 babl_component ("A"),
658 const Babl
*rgbF_linear
= babl_format_new (
661 babl_component ("R"),
662 babl_component ("G"),
663 babl_component ("B"),
665 const Babl
*rgbF_gamma
= babl_format_new (
666 babl_model ("R'G'B'"),
668 babl_component ("R'"),
669 babl_component ("G'"),
670 babl_component ("B'"),
673 return 0; // XXX: the fast paths registered here doesn't correctly
674 // clamp negative values - disabling for now
679 /* tweaking the precision - does impact speed.. */
680 fast_pow
= babl_lookup_new (core_lookup
, NULL
, 0.0f
, 1.0f
, 0.000199f
);
681 fast_rpow
= babl_lookup_new (core_rlookup
, NULL
, 0.0f
, 1.0f
, 0.000250f
);
683 for (f
= 0.0; f
< 1.0f
; f
+= 0.0000001f
)
685 a
= linear_to_gamma_2_2_lut (f
);
686 a
= gamma_2_2_to_linear_lut (f
);
695 const Babl
*f32
= babl_format_new (
696 "name", "cairo-ARGB32",
697 babl_model ("R'aG'aB'aA"),
699 babl_component ("B'a"),
700 babl_component ("G'a"),
701 babl_component ("R'a"),
702 babl_component ("A"),
707 babl_conversion_new (rgbaF_linear
, f32
, "linear", conv_rgbaF_linear_rgbA8_gamma_cairo
, NULL
);
710 o (rgbaF_linear
, rgbA8_gamma
);
711 o (rgbAF_linear
, rgbAF_gamma
);
712 o (rgbaF_linear
, rgbAF_gamma
);
713 o (rgbaF_linear
, rgbaF_gamma
);
714 o (rgbaF_linear
, rgba8_gamma
);
715 o (rgbaF_gamma
, rgbaF_linear
);
716 o (rgbF_linear
, rgbF_gamma
);
717 o (rgbF_gamma
, rgbF_linear
);
718 o (yaF_linear
, rgbA8_gamma
);