1 /* babl - dynamically extendable universal pixel conversion library.
2 * Copyright (C) 2005, Øyvind Kolås.
3 *
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.
8 *
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.
13 *
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/>.
17 */
18
19 #ifndef _BABL_INTERNAL_H
20 #define _BABL_INTERNAL_H
21
22 #ifndef BABL_LIBRARY
23 #error "config.h must be included prior to babl-internal.h"
24 #endif
25
26 #ifdef _BABL_H
27 #error babl-internal.h included after babl.h
28 #endif
29
30 #define BABL_MAX_COMPONENTS 32
31 #define BABL_CONVERSIONS 5
32
33
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <math.h>
38 #include "assert.h"
39
40 #undef _BABL_INTERNAL_H
41 #include "babl.h"
42 #define _BABL_INTERNAL_H
43
44 #include "babl-classes.h"
45 #include "babl-introspect.h"
46 #include "babl-class.h"
47 #include "babl-list.h"
48 #include "babl-hash-table.h"
49 #include "babl-db.h"
50 #include "babl-ids.h"
51 #include "babl-util.h"
52 #include "babl-memory.h"
53 #include "babl-mutex.h"
54 #include "babl-cpuaccel.h"
55 #include "babl-polynomial.h"
56
57 /* fallback to floor function when rint is not around */
58 #ifndef HAVE_RINT
59 # define rint(f) (floor (((double) (f)) + 0.5))
60 #endif
61
62 #ifdef __ANDROID_API__
63 #include <android/log.h>
64 #endif
65
66 Babl * babl_conversion_find (const void *source,
67 const void *destination);
68 double babl_conversion_error (BablConversion *conversion);
69 long babl_conversion_cost (BablConversion *conversion);
70
71 Babl * babl_extension_base (void);
72
73 Babl * babl_extender (void);
74 void babl_set_extender (Babl *new_extender);
75
76 Babl * babl_extension_quiet_log (void);
77 void babl_extension_deinit (void);
78
79 void babl_fish_reference_process (const Babl *babl,
80 const char *source,
81 char *destination,
82 long n,
83 void *data); // data is ignored
84
85 Babl * babl_fish_reference (const Babl *source,
86 const Babl *destination);
87 Babl * babl_fish_simple (BablConversion *conversion);
88 Babl * babl_fish_path (const Babl *source,
89 const Babl *destination);
90
91 int babl_fish_get_id (const Babl *source,
92 const Babl *destination);
93
94 double babl_format_loss (const Babl *babl);
95 Babl * babl_image_from_linear (char *buffer,
96 const Babl *format);
97 Babl * babl_image_double_from_image (const Babl *source);
98
99 double babl_model_is_symmetric (const Babl *babl);
100 void babl_die (void);
101 int babl_sanity (void);
102
103 void babl_doc (const Babl *babl,
104 const char *doc);
105
106 const char * babl_get_doc (const Babl *babl);
107
108 void babl_core_init (void);
109 const Babl *babl_format_with_model_as_type (const Babl *model,
110 const Babl *type);
111 int babl_formats_count (void); /* should maybe be templated? */
112 int babl_type_is_symmetric (const Babl *babl);
113
114 /**** LOGGER ****/
115 #include <stdarg.h>
116
117 int babl_backtrack (void);
118
119 static inline void
real_babl_log_va(const char * file,int line,const char * function,const char * fmt,va_list varg)120 real_babl_log_va(const char *file,
121 int line,
122 const char *function,
123 const char *fmt,
124 va_list varg)
125 {
126 Babl *extender = babl_extender();
127
128 if (extender != babl_extension_quiet_log())
129 {
130 if (babl_extender())
131 {
132 #ifdef __ANDROID_API__
133 __android_log_print (ANDROID_LOG_DEBUG, "BABL",
134 "When loading %s:\n\t", babl_extender()->instance.name);
135 #else
136 fprintf (stderr, "When loading %s:\n\t", babl_extender()->instance.name);
137 #endif
138 }
139
140 #ifdef __ANDROID_API__
141 __android_log_print (ANDROID_LOG_DEBUG, "BABL",
142 "%s:%i %s()", file, line, function);
143 #else
144 fprintf (stderr, "%s:%i %s()\n\t", file, line, function);
145 #endif
146 }
147
148 #ifdef __ANDROID_API__
149 __android_log_vprint (ANDROID_LOG_DEBUG, "BABL",
150 fmt, varg);
151 #else
152 vfprintf (stderr, fmt, varg);
153 fprintf (stderr, "\n");
154 fflush (NULL);
155 #endif
156 return;
157 }
158
159 static inline void
real_babl_log(const char * file,int line,const char * function,const char * fmt,...)160 real_babl_log (const char *file,
161 int line,
162 const char *function,
163 const char *fmt, ...)
164 {
165 va_list varg;
166
167 va_start (varg, fmt);
168 real_babl_log_va (file, line, function, fmt, varg);
169 va_end (varg);
170 }
171
172 /* Provide a string identifying the current function, non-concatenatable */
173 #ifndef G_STRFUNC
174 #if defined (__GNUC__)
175 # define G_STRFUNC ((const char*) (__PRETTY_FUNCTION__))
176 #elif defined (G_HAVE_ISO_VARARGS)
177 # define G_STRFUNC ((const char*) (__func__))
178 #else
179 # define G_STRFUNC ((const char*) ("???"))
180 #endif
181 #endif
182
183 #if defined(__cplusplus) && defined(BABL_ISO_CXX_VARIADIC_MACROS)
184 # define BABL_ISO_VARIADIC_MACROS 1
185 #endif
186
187 #if defined(BABL_ISO_VARIADIC_MACROS)
188
189 #define babl_log(...) \
190 real_babl_log(__FILE__, __LINE__, G_STRFUNC, __VA_ARGS__)
191
192 #define babl_fatal(...) do{ \
193 real_babl_log(__FILE__, __LINE__, G_STRFUNC, __VA_ARGS__); \
194 babl_die();} \
195 while(0)
196
197 #elif defined(BABL_GNUC_VARIADIC_MACROS)
198
199 #define babl_log(args...) \
200 real_babl_log(__FILE__, __LINE__, G_STRFUNC, args)
201
202 #define babl_fatal(args...) do{ \
203 real_babl_log(__FILE__, __LINE__, G_STRFUNC, args); \
204 babl_die();} \
205 while(0)
206
207 #else
208
209 static inline void
babl_log(const char * format,...)210 babl_log (const char *format, ...)
211 {
212 va_list args;
213 va_start (args, format);
214 real_babl_log_va (__FILE__, __LINE__, G_STRFUNC, format, args);
215 va_end (args);
216 }
217 static inline void
babl_fatal(const char * format,...)218 babl_fatal (const char *format, ...)
219 {
220 va_list args;
221 va_start (args, format);
222 real_babl_log_va (__FILE__, __LINE__, G_STRFUNC, format, args);
223 va_end (args);
224 babl_die();
225 }
226
227 #endif
228
229
230 #define babl_assert(expr) do{ \
231 if(!(expr)) \
232 { \
233 real_babl_log(__FILE__, __LINE__, G_STRFUNC, "Eeeeek! Assertion failed: `" #expr "`"); \
234 assert(expr); \
235 } \
236 }while(0)
237 /***** LOGGER (end)**/
238
239 #define BABL_CLASS_TYPE_IS_VALID(klass_type) \
240 ( ((klass_type)>=BABL_INSTANCE ) && ((klass_type)<=BABL_SKY) ?1:0 )
241
242 #define BABL_IS_BABL(obj) \
243 (NULL==(obj)?0 \
244 :BABL_CLASS_TYPE_IS_VALID(((Babl*)(obj))->class_type) \
245 )
246
247 extern int babl_hmpf_on_name_lookups;
248 extern int babl_in_fish_path;
249 extern BablMutex *babl_format_mutex;
250 extern BablMutex *babl_fish_mutex;
251 extern BablMutex *babl_reference_mutex;
252 extern BablMutex *babl_space_mutex;
253
254 #define BABL_DEBUG_MEM 0
255 #if BABL_DEBUG_MEM
256 extern BablMutex *babl_debug_mutex;
257 #endif
258
259 const char *babl_class_name (BablClassType klass);
260 void babl_internal_init (void);
261 void babl_internal_destroy (void);
262
263
264 /* this template is expanded in the files including babl-internal.h,
265 * generating code, the declarations for these functions are found in
266 * the BABL_CLASS expansions done in babl.h as well, thus babl.h needs
267 * to be kept in sync with the C files.
268 */
269
270 #define BABL_CLASS_MINIMAL_IMPLEMENT(klass) \
271 \
272 BablDb * \
273 babl_##klass##_db (void) \
274 { \
275 if (!db) \
276 db=babl_db_init (); \
277 return db; \
278 } \
279 \
280 void \
281 babl_##klass##_class_for_each (BablEachFunction each_fun, \
282 void *user_data) \
283 { \
284 babl_db_each (db, each_fun, user_data); \
285 } \
286
287 #define BABL_CLASS_IMPLEMENT(klass) \
288 BABL_CLASS_MINIMAL_IMPLEMENT(klass) \
289 \
290 const Babl * \
291 babl_##klass (const char *name) \
292 { \
293 Babl *babl; \
294 \
295 if (babl_hmpf_on_name_lookups) \
296 { \
297 babl_log ("%s(\"%s\"): looking up", G_STRFUNC, name); \
298 } \
299 if (!db) \
300 { \
301 babl_fatal ("%s(\"%s\"): you must call babl_init first", G_STRFUNC, name); \
302 } \
303 babl = babl_db_exist_by_name (db, name); \
304 \
305 if (!babl) \
306 { \
307 babl_fatal ("%s(\"%s\"): not found", G_STRFUNC, name); \
308 } \
309 return babl; \
310 } \
311 \
312 const Babl * \
313 babl_##klass##_from_id (int id) \
314 { \
315 Babl *babl; \
316 babl = babl_db_exist_by_id (db, id); \
317 if (!babl) \
318 { \
319 babl_fatal ("%s(%i): not found", G_STRFUNC, id); \
320 } \
321 return babl; \
322 } \
323
324 #define BABL(obj) ((Babl*)(obj))
325
babl_parse_double(const char * str)326 static inline double babl_parse_double (const char *str)
327 {
328 double result = 0;
329 if (!str)
330 return 0.0;
331 result = atoi (str);
332 if (strchr (str, '.'))
333 {
334 char *p = strchr (str, '.') + 1;
335 double d = 10;
336 for (;*p && *p >= '0' && *p <= '9';p++, d *= 10)
337 {
338 if (result >= 0)
339 result += (*p - '0') / d;
340 else
341 result -= (*p - '0') / d;
342 }
343 }
344 return result;
345 }
346
347 const Babl *
348 babl_remodel_with_space (const Babl *model, const Babl *space);
349 Babl *
350 _conversion_new (const char *name,
351 int id,
352 const Babl *source,
353 const Babl *destination,
354 BablFuncLinear linear,
355 BablFuncPlane plane,
356 BablFuncPlanar planar,
357 void *user_data,
358 int allow_collision);
359
360 double _babl_legal_error (void);
361 void babl_init_db (void);
362 void babl_store_db (void);
363 int _babl_max_path_len (void);
364
365
366 const Babl *
367 babl_trc_new (const char *name,
368 BablTRCType type,
369 double gamma,
370 int n_lut,
371 float *lut);
372
373 void babl_space_to_xyz (const Babl *space, const double *rgb, double *xyz);
374 void babl_space_from_xyz (const Babl *space, const double *xyz, double *rgb);
375
376 const Babl *babl_trc_lut_find (float *lut, int lut_size);
377 const Babl *babl_trc_lut (const char *name, int n, float *entries);
378
379 Babl * format_new_from_format_with_space (const Babl *format, const Babl *space);
380
381 int babl_list_destroy (void *data);
382
383 const char *
384 babl_conversion_create_name (Babl *source, Babl *destination, int type,
385 int allow_collision);
386
387 void _babl_space_add_universal_rgb (const Babl *space);
388 const Babl *
389 babl_trc_formula_srgb (double gamma, double a, double b, double c, double d, double e, double f);
390 const Babl *
391 babl_trc_formula_cie (double gamma, double a, double b, double c);
392
393
394 const Babl *babl_space_match_trc_matrix (const Babl *trc_red,
395 const Babl *trc_green,
396 const Babl *trc_blue,
397 float rx, float ry, float rz,
398 float gx, float gy, float gz,
399 float bx, float by, float bz);
400
401
402
403
404 int _babl_file_get_contents (const char *path,
405 char **contents,
406 long *length,
407 void *error);
408
409
410
411 /* babl_space_get_rgbtoxyz:
412
413 Returns the double-precision 3x3 matrix used to convert linear
414 RGB data to CIE XYZ.
415 */
416 const double * babl_space_get_rgbtoxyz (const Babl *space);
417
418 /* babl_space_to_xyz:
419 *
420 * converts a double triplet from linear RGB to CIE XYZ.
421 */
422 void babl_space_to_xyz (const Babl *space, const double *rgb, double *xyz);
423
424 /* babl_space_from_xyz:
425 *
426 * converts double triplet from CIE XYZ to linear RGB
427 */
428 void babl_space_from_xyz (const Babl *space, const double *xyz, double *rgb);
429
430 extern int _babl_instrument;
431
432 static inline void
babl_conversion_process(const Babl * babl,const char * source,char * destination,long n)433 babl_conversion_process (const Babl *babl,
434 const char *source,
435 char *destination,
436 long n)
437 {
438 BablConversion *conversion = (BablConversion *) babl;
439 if (_babl_instrument)
440 conversion->pixels += n;
441 conversion->dispatch (babl, source, destination, n, conversion->data);
442 }
443
444 void _babl_fish_missing_fast_path_warning (const Babl *source,
445 const Babl *destination);
446 void _babl_fish_rig_dispatch (Babl *babl);
447 void _babl_fish_prepare_bpp (Babl *babl);
448
449
450 /* babl_space_to_icc:
451 *
452 * Creates an ICCv2 RGB matrix profile for a babl space. The profiles strive to
453 * be as small and compact as possible, TRCs are stored as 1024 entry LUT(s).
454 *
455 * the result is allocated with malloc and you should free it when done.
456 */
457
458 typedef enum {
459 BABL_ICC_DEFAULTS = 0,
460 BABL_ICC_COMPACT_TRC_LUT = 1,
461 } BablICCFlags;
462
463 char *babl_space_to_icc (const Babl *space,
464 const char *description,
465 const char *copyright,
466 BablICCFlags flags,
467 int *icc_length);
468 Babl *
469 _babl_space_for_lcms (const char *icc_data, int icc_length); // XXX pass profile for dedup?
470
471 #endif
472