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 #include "config.h"
20 #include <string.h>
21 #include <stdarg.h>
22 #include <math.h>
23 
24 #define NEEDS_BABL_DB
25 #include "babl-internal.h"
26 #include "babl-db.h"
27 #include "babl-ref-pixels.h"
28 
29 
30 static int
babl_format_destruct(void * babl)31 babl_format_destruct (void *babl)
32 {
33   BablFormat *format = babl;
34   if (format->image_template != NULL)
35     {
36       babl_set_destructor (format->image_template, NULL);
37       /* with no destructor set, the circular reference is no problem */
38       babl_free (format->image_template);
39       format->image_template = NULL;
40     }
41   if (format->from_list)
42     babl_free (format->from_list);
43   return 0;
44 }
45 
46 static Babl *
format_new(const char * name,int id,int planar,int components,BablModel * model,const Babl * space,BablComponent ** component,BablSampling ** sampling,const BablType ** type,const char * doc)47 format_new (const char      *name,
48             int              id,
49             int              planar,
50             int              components,
51             BablModel       *model,
52             const Babl      *space,
53             BablComponent  **component,
54             BablSampling   **sampling,
55             const BablType **type,
56             const char      *doc)
57 {
58   Babl *babl;
59 
60   /* i is destination position */
61   int i, j, component_found = 0;
62   for (i = 0; i < model->components; i++)
63     {
64       for (j = 0; j < components; j++)
65         {
66           if (component[j] == model->component[i])
67             {
68               component_found = 1;
69               break;
70             }
71         }
72       if (!component_found)
73         {
74           component_found = 0;
75 #if 0 /* since babl does the right thing, let it happen */
76           babl_fatal("matching source component for %s in model %s not found",
77                       model->component[i]->instance.name, model->instance.name);
78 #endif
79         }
80     }
81 
82   /* allocate all memory in one chunk */
83   babl = babl_malloc (sizeof (BablFormat) +
84                       strlen (name) + 1 +
85                       sizeof (BablComponent *) * (components) +
86                       sizeof (BablSampling *) * (components) +
87                       sizeof (BablType *) * (components) +
88                       sizeof (int) * (components) +
89                       sizeof (int) * (components));
90 
91   babl_set_destructor (babl, babl_format_destruct);
92 
93   babl->format.from_list = NULL;
94   babl->format.component = (void *) (((char *) babl) + sizeof (BablFormat));
95   babl->format.type      = (void *) (((char *) babl->format.component) + sizeof (BablComponent *) * (components));
96   babl->format.sampling  = (void *) (((char *) babl->format.type) + sizeof (BablType *) * (components));
97   babl->instance.name    = ((char *) babl->format.sampling) + sizeof (BablSampling *) * (components);
98 
99   babl->class_type  = BABL_FORMAT;
100   babl->instance.id = id;
101 
102   strcpy (babl->instance.name, name);
103 
104   babl->format.components = components;
105 
106   if (space == babl_space ("sRGB"))
107     babl->format.model      = model;
108   else
109     babl->format.model      = (void*)babl_remodel_with_space ((void*)model, space);
110 
111   memcpy (babl->format.component, component, sizeof (BablComponent *) * components);
112   memcpy (babl->format.type, type, sizeof (BablType *) * components);
113   memcpy (babl->format.sampling, sampling, sizeof (BablSampling *) * components);
114 
115   babl->format.planar = planar;
116 
117   babl->format.bytes_per_pixel = 0;
118   {
119     int i;
120     for (i = 0; i < components; i++)
121       babl->format.bytes_per_pixel += type[i]->bits / 8;
122   }
123 
124   babl->format.loss = -1.0;
125   babl->format.visited = 0;
126   babl->format.image_template = NULL;
127   babl->format.format_n = 0;
128   babl->format.palette = 0;
129 
130   babl->format.space = (void*)space;
131   babl->format.encoding = NULL;
132   babl->instance.doc = doc;
133 
134   return babl;
135 }
136 
137 Babl *
format_new_from_format_with_space(const Babl * format,const Babl * space)138 format_new_from_format_with_space (const Babl *format,
139                                    const Babl *space)
140 {
141   Babl *ret;
142   char new_name[256];
143   snprintf (new_name, sizeof (new_name), "%s-%s", babl_get_name ((void*)format),
144                                                   babl_get_name ((void*)space));
145   ret = babl_db_find (babl_format_db(), new_name);
146   if (ret)
147     return ret;
148 
149   ret = format_new (new_name,
150                     0,
151                     format->format.planar, format->format.components,
152                     (void*)babl_remodel_with_space (BABL(format->format.model), space),
153                     space,
154                     format->format.component, format->format.sampling, (void*)format->format.type, NULL);
155 
156   ret->format.encoding = babl_get_name(format);
157   babl_db_insert (db, (void*)ret);
158   return ret;
159 }
160 
161 
162 static char *
create_name(const BablModel * model,int components,BablComponent ** component,const BablType ** type)163 create_name (const BablModel *model,
164              int              components,
165              BablComponent  **component,
166              const BablType **type)
167 {
168   char            buf[512] = "";
169   char           *p = &buf[0];
170   ssize_t         left;
171   int             i;
172   int             same_types = 1;
173   const BablType**t          = type;
174   const BablType *first_type = *type;
175   BablComponent **c1         = component;
176   BablComponent **c2         = model->component;
177 
178   left = 512;
179   snprintf (p, left, "%s ", model->instance.name);
180   p += strlen (model->instance.name) + 1;
181   left -= strlen (model->instance.name) + 1;
182   babl_assert (left >= 0);
183 
184   i = components;
185   while (i--)
186     {
187       if (first_type != *t)
188         {
189           same_types = 0;
190           break;
191         }
192       t++;
193     }
194 
195   if (same_types &&
196       components != model->components)
197     same_types = 0;
198 
199   i = components;
200   while (same_types && i--)
201     {
202       if (*c1 != *c2)
203         {
204           same_types = 0;
205           break;
206         }
207       c1++;
208       c2++;
209     }
210 
211 
212   if (same_types)
213     {
214       snprintf (p, left, "%s", first_type->instance.name);
215       return babl_strdup (buf);
216     }
217 
218   i = components;
219 
220   while (i--)
221     {
222       snprintf (p, left, "(%s as %s) ",
223                (*component)->instance.name,
224                (*type)->instance.name);
225       p += strlen ((*component)->instance.name) +
226            strlen ((*type)->instance.name) + strlen ("( as ) ");
227       left -= strlen ((*component)->instance.name) +
228               strlen ((*type)->instance.name) + strlen ("( as ) ");
229       babl_assert (left >= 0);
230       component++;
231       type++;
232     }
233   return babl_strdup (buf);
234 }
235 
236 static char *
ncomponents_create_name(const Babl * type,int components)237 ncomponents_create_name (const Babl *type,
238                          int         components)
239 {
240   char buf[512];
241   snprintf (buf, sizeof (buf), "%s[%i] ", type->instance.name, components);
242   return babl_strdup (buf);
243 }
244 
245 static void
babl_format_set_is_format_n(Babl * format)246 babl_format_set_is_format_n (Babl *format)
247 {
248   if (format->class_type == BABL_FORMAT)
249     {
250       format->format.format_n = 1;
251     }
252 }
253 
254 const Babl *
babl_format_n(const Babl * btype,int components)255 babl_format_n (const Babl *btype,
256                int   components)
257 {
258   int            i;
259   Babl          *babl;
260   int            id         = 0;
261   int            planar     = 0;
262   BablModel     *model      = (BablModel *)babl_model ("Y");
263   BablComponent *component [components];
264   BablSampling  *sampling  [components];
265   const BablType *type      [components];
266   char          *name       = NULL;
267 
268   for (i = 0; i<components; i++)
269     {
270       component[i] = model->component[0];
271       type[i] = &btype->type;
272       sampling[i] = (BablSampling *) babl_sampling (1, 1);
273     }
274 
275   name = ncomponents_create_name (btype, components);
276   babl = babl_db_exist (db, id, name);
277   if (babl)
278     {
279       /* There is an instance already registered by the required id/name,
280        * returning the preexistent one instead.
281        */
282       babl_free (name);
283       return babl;
284     }
285 
286   babl = format_new (name,
287                      id,
288                      planar, components, model,
289                      babl_space("sRGB"),
290                      component, sampling, type, NULL);
291 
292   babl_format_set_is_format_n (babl);
293 
294   babl_db_insert (db, babl);
295   babl_free (name);
296   return babl;
297 }
298 
299 int
babl_format_is_format_n(const Babl * format)300 babl_format_is_format_n (const Babl *format)
301 {
302   if (format->class_type == BABL_FORMAT)
303     {
304       return format->format.format_n;
305     }
306 
307   return 0;
308 }
309 
310 static int
is_format_duplicate(Babl * babl,int planar,int components,BablModel * model,const Babl * space,BablComponent ** component,BablSampling ** sampling,const BablType ** type)311 is_format_duplicate (Babl            *babl,
312                      int              planar,
313                      int              components,
314                      BablModel       *model,
315                      const Babl      *space,
316                      BablComponent  **component,
317                      BablSampling   **sampling,
318                      const BablType **type)
319 {
320   int i;
321 
322   if (babl->format.planar     != planar     ||
323       babl->format.components != components ||
324       babl->format.model      != model      ||
325       babl->format.space      != (void*)space)
326     return 0;
327 
328   for (i = 0; i < components; i++)
329     {
330       if (babl->format.component[i] != component[i] ||
331           babl->format.sampling[i]  != sampling[i]  ||
332           babl->format.type[i]      != type[i])
333         return 0;
334     }
335   return 1;
336 }
337 
338 const Babl *
babl_format_new(const void * first_arg,...)339 babl_format_new (const void *first_arg,
340                  ...)
341 {
342   va_list        varg;
343   Babl          *babl;
344   int            id         = 0;
345   int            planar     = 0;
346   int            components = 0;
347   BablModel     *model      = NULL;
348   const Babl    *space      = babl_space ("sRGB");
349   const char    *doc        = NULL;
350   BablComponent *component [BABL_MAX_COMPONENTS];
351   BablSampling  *sampling  [BABL_MAX_COMPONENTS];
352   const BablType*type      [BABL_MAX_COMPONENTS];
353 
354   BablSampling  *current_sampling = (BablSampling *) babl_sampling (1, 1);
355   BablType      *current_type     = (BablType *) babl_type_from_id (BABL_DOUBLE);
356   char          *name             = NULL;
357   const void    *arg              = first_arg;
358 
359   va_start (varg, first_arg);
360 
361   while (1)
362     {
363       /* first, we assume arguments to be strings */
364       if (!strcmp (arg, "id"))
365         {
366           id = va_arg (varg, int);
367         }
368 
369       else if (!strcmp (arg, "name"))
370         {
371           name = babl_strdup (va_arg (varg, char *));
372         }
373 
374       else if (!strcmp (arg, "doc"))
375         {
376           doc = babl_strdup (va_arg (varg, const char *));
377         }
378 
379       else if (!strcmp (arg, "packed"))
380         {
381           planar = 0;
382         }
383 
384       else if (!strcmp (arg, "planar"))
385         {
386           planar = 1;
387         }
388 
389       /* if we didn't point to a known string, we assume argument to be babl */
390       else if (BABL_IS_BABL (arg))
391         {
392           Babl *babl = (Babl *) arg;
393 
394           switch (babl->class_type)
395             {
396               case BABL_TYPE:
397               case BABL_TYPE_FLOAT:
398               case BABL_TYPE_INTEGER:
399                 current_type = (BablType *) babl;
400                 break;
401 
402               case BABL_COMPONENT:
403                 if (!model)
404                   {
405                     babl_fatal ("no model specified before component %s",
406                                 babl->instance.name);
407                   }
408                 component [components] = (BablComponent *) babl;
409                 type      [components] = current_type;
410                 sampling  [components] = current_sampling;
411                 components++;
412 
413                 if (components >= BABL_MAX_COMPONENTS)
414                   {
415                     babl_fatal ("maximum number of components (%i) exceeded for %s",
416                                 BABL_MAX_COMPONENTS, name);
417                   }
418                 break;
419 
420               case BABL_SAMPLING:
421                 current_sampling = (BablSampling *) arg;
422                 break;
423 
424               case BABL_SPACE:
425                 space = (Babl*) arg;
426                 break;
427 
428               case BABL_MODEL:
429                 if (model)
430                   {
431                     babl_log ("args=(%s): model %s already requested",
432                               babl->instance.name, model->instance.name);
433                   }
434                 model = (BablModel *) arg;
435                 break;
436 
437               case BABL_INSTANCE:
438               case BABL_FORMAT:
439               case BABL_CONVERSION:
440               case BABL_CONVERSION_LINEAR:
441               case BABL_CONVERSION_PLANE:
442               case BABL_CONVERSION_PLANAR:
443               case BABL_FISH:
444               case BABL_FISH_REFERENCE:
445               case BABL_FISH_SIMPLE:
446               case BABL_FISH_PATH:
447               case BABL_IMAGE:
448               case BABL_EXTENSION:
449                 babl_log ("%s unexpected",
450                           babl_class_name (babl->class_type));
451                 break;
452 
453               case BABL_SKY: /* shut up compiler */
454                 break;
455             }
456         }
457 
458       else
459         {
460           babl_fatal ("unhandled argument '%s' for format '%s'", arg, name);
461         }
462 
463       arg = va_arg (varg, char *);
464       if (!arg)
465         break;
466     }
467 
468   va_end (varg);
469 
470   if (!name)
471     {
472       name = create_name (model, components, component, type);
473 
474       if (space != babl_space ("sRGB"))
475         {
476           char *new_name = babl_malloc (strlen (name) +
477                                         strlen (babl_get_name ((Babl*)space)) + 1);
478           sprintf (new_name, "%s-%s", name, babl_get_name ((Babl*)space));
479           babl_free (name);
480           name = new_name;
481         }
482     }
483 
484   if (!model)
485     {
486       babl_log ("no model specified for format '%s'", name);
487       babl_free(name);
488       return NULL;
489     }
490 
491   if (!components)
492     {
493       babl_log ("no components specified for format '%s'", name);
494       babl_free(name);
495       return NULL;
496     }
497 
498   babl = babl_db_exist (db, id, name);
499   if (id && !babl && babl_db_exist (db, 0, name))
500     babl_fatal ("Trying to reregister BablFormat '%s' with different id!", name);
501 
502   if (babl)
503     {
504       /* There is an instance already registered by the required id/name,
505        * returning the preexistent one instead if it doesn't differ.
506        */
507       if(0)if (!is_format_duplicate (babl, planar, components, model, space,
508                                 component, sampling, type))
509         babl_fatal ("BablFormat '%s' already registered "
510                     "with different content!", name);
511 
512       babl_free (name);
513       return babl;
514     }
515 
516   babl = format_new ((void*)name,
517                      id,
518                      planar, components, model, space,
519                      component, sampling, type, doc);
520 
521   babl_db_insert (db, babl);
522   babl_free (name);
523   return babl;
524 }
525 
526 int
babl_formats_count(void)527 babl_formats_count (void)
528 {
529   return babl_db_count (db);
530 }
531 
532 int
babl_format_has_alpha(const Babl * format)533 babl_format_has_alpha (const Babl *format)
534 {
535   int n = babl_format_get_n_components (format);
536   int i;
537 
538   for (i = 0; i < n; i++)
539     {
540       if (format->format.component[i]->alpha)
541         {
542           return 1;
543         }
544     }
545 
546   return 0;
547 }
548 
549 int
babl_format_get_bytes_per_pixel(const Babl * format)550 babl_format_get_bytes_per_pixel (const Babl *format)
551 {
552   if (format->class_type == BABL_FORMAT)
553     {
554       return format->format.bytes_per_pixel;
555     }
556 
557   return 0;
558 }
559 
560 int
babl_format_get_n_components(const Babl * format)561 babl_format_get_n_components (const Babl *format)
562 {
563   if (format->class_type == BABL_FORMAT)
564     {
565       return format->format.components;
566     }
567 
568   return 0;
569 }
570 
571 const Babl *
babl_format_get_type(const Babl * format,int component_index)572 babl_format_get_type (const Babl *format,
573                       int         component_index)
574 {
575   if (format->class_type == BABL_FORMAT &&
576       component_index >= 0 &&
577       component_index < format->format.components)
578     {
579       return (Babl *)format->format.type[component_index];
580     }
581 
582   return NULL;
583 }
584 
585 const Babl *
babl_format_with_model_as_type(const Babl * model,const Babl * type)586 babl_format_with_model_as_type (const Babl *model,
587                                 const Babl *type)
588 {
589   BablComponent *component[10];
590   int            i;
591 
592   for (i = 0; i < model->model.components; i++)
593     {
594       component[i] = model->model.component[i];
595     }
596   component[i] = NULL;
597 
598   return babl_format_new (
599            model,
600            type,
601            component[0],
602            component[1],
603            component[2],
604            component[3],
605            component[4],
606            component[5],
607            component[6],
608            component[7],
609            component[8],
610            component[9],
611            NULL
612   );
613 }
614 
615 double
babl_format_loss(const Babl * babl)616 babl_format_loss (const Babl *babl)
617 {
618   double  loss = 0.0;
619   void   *original;
620   double *clipped;
621   void   *destination;
622   double *transformed;
623 
624   const Babl *ref_fmt;
625   const Babl *fmt;
626   Babl       *fish_to;
627   Babl       *fish_from;
628 
629   const double *test = babl_get_format_test_pixels ();
630   const int     test_pixels = babl_get_num_format_test_pixels ();
631 
632   ref_fmt = babl_format_new (
633     babl_model ("RGBA"),
634     babl_type ("double"),
635     babl_component ("R"),
636     babl_component ("G"),
637     babl_component ("B"),
638     babl_component ("A"),
639     NULL);
640 
641   if (babl->format.loss != -1.0)
642     return babl->format.loss;
643 
644   fmt       = babl;
645   fish_to   = babl_fish_reference (ref_fmt, fmt);
646   fish_from = babl_fish_reference (fmt, ref_fmt);
647 
648   original    = babl_calloc (test_pixels, fmt->format.bytes_per_pixel);
649   clipped     = babl_calloc (test_pixels, ref_fmt->format.bytes_per_pixel);
650   destination = babl_calloc (test_pixels, fmt->format.bytes_per_pixel);
651   transformed = babl_calloc (test_pixels, ref_fmt->format.bytes_per_pixel);
652 
653   babl_process (fish_to, test, original, test_pixels);
654   babl_process (fish_from, original, clipped, test_pixels);
655   babl_process (fish_to, clipped, destination, test_pixels);
656   babl_process (fish_from, destination, transformed, test_pixels);
657 
658   loss = babl_rel_avg_error (clipped, test, test_pixels * 4);
659 
660   fish_to->fish.pixels        -= test_pixels * 2;
661   fish_from->fish.pixels      -= test_pixels * 2;
662 
663   babl_free (original);
664   babl_free (clipped);
665   babl_free (destination);
666   babl_free (transformed);
667 
668   ((Babl*)babl)->format.loss = loss;
669   return loss;
670 }
671 
672 
673 void *
babl_get_user_data(const Babl * babl)674 babl_get_user_data (const Babl *babl)
675 {
676   switch (babl->instance.class_type)
677     {
678       case BABL_MODEL:
679         return babl->model.data;
680       case BABL_FORMAT:
681         return babl->format.model->data;
682       default:
683         babl_fatal ("babl_get_user_data called on non-model/format");
684     }
685   babl_fatal ("eeeek");
686   return NULL;
687 }
688 
689 void
babl_set_user_data(const Babl * cbabl,void * data)690 babl_set_user_data (const Babl *cbabl,
691                     void       *data)
692 {
693   Babl *babl = (Babl*) cbabl;
694   switch (cbabl->instance.class_type)
695     {
696       case BABL_MODEL:
697         babl->model.data = data;
698         break;
699       case BABL_FORMAT:
700         babl->format.model->data = data;
701         break;
702       default:
703         babl_fatal ("babl_set_user_data called on non-model/format");
704     }
705 }
706 
707 const Babl *
babl_format_get_model(const Babl * format)708 babl_format_get_model (const Babl *format)
709 {
710   if (format->class_type == BABL_FORMAT)
711     {
712       return (Babl*)format->format.model;
713     }
714   return NULL;
715 }
716 
babl_format_get_space(const Babl * format)717 const Babl * babl_format_get_space      (const Babl *format)
718 {
719   if (format->class_type == BABL_FORMAT)
720     {
721       return (Babl*)format->format.space;
722     }
723   return NULL;
724 }
725 
BABL_CLASS_IMPLEMENT(format)726 BABL_CLASS_IMPLEMENT (format)
727 
728 const char *
729 babl_format_get_encoding (const Babl *babl)
730 {
731   if (!babl) return NULL;
732   if (babl->format.encoding) return babl->format.encoding;
733   return babl_get_name (babl);
734 }
735 
736 const Babl *
babl_format_with_space(const char * encoding,const Babl * space)737 babl_format_with_space (const char *encoding, const Babl *space)
738 {
739   const Babl *example_format = (void*) encoding;
740   if (!encoding) return NULL;
741 
742   if (BABL_IS_BABL (example_format))
743   {
744     encoding = babl_get_name (example_format);
745     if (babl_format_get_space (example_format) != babl_space ("sRGB"))
746     {
747       encoding = babl_format_get_encoding (example_format);
748     }
749   }
750 
751   if (!space)
752     space = babl_space ("sRGB");
753 
754   if (space->class_type == BABL_FORMAT)
755   {
756     space = space->format.space;
757   }
758   else if (space->class_type == BABL_MODEL)
759   {
760     space = space->model.space;
761   }
762   else if (space->class_type != BABL_SPACE)
763   {
764     return NULL;
765   }
766   example_format = babl_format (encoding);
767 
768   if (space == babl_space("sRGB"))
769     return example_format;
770 
771   if (babl_format_is_palette (example_format))
772   {
773     /* XXX we should allocate a new palette name, and
774            duplicate the path data, converted for new space
775      */
776     return example_format;
777   }
778 
779   return format_new_from_format_with_space (example_format, space);
780 }
781 
782 int
babl_format_exists(const char * name)783 babl_format_exists (const char *name)
784 {
785   if (babl_db_exist_by_name (db, name))
786     return 1;
787   return 0;
788 }
789 
790 
791 
792