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