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