1 /* babl - dynamically extendable universal pixel fish 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 "babl-internal.h"
21 #ifdef HAVE_LCMS
22 #include "lcms2.h"
23 #endif
24 
25 
26 static Babl *
assert_conversion_find(const void * source,const void * destination)27 assert_conversion_find (const void *source,
28                         const void *destination)
29 {
30   Babl *ret = babl_conversion_find (source, destination);
31 
32   if (!ret)
33     babl_fatal ("failed finding conversion between %s and %s aborting",
34                 babl_get_name (source), babl_get_name (destination));
35 
36   return ret;
37 }
38 
39 static int
create_name_internal(char * buf,size_t maxlen,const Babl * source,const Babl * destination,int is_reference)40 create_name_internal (char *buf,
41                       size_t maxlen,
42                       const Babl *source,
43                       const Babl *destination,
44                       int   is_reference)
45 {
46   return snprintf (buf, maxlen, "%s %p %p",
47                    is_reference ? "ref "
48                    : "",
49                    source, destination);
50 }
51 
52 #ifdef HAVE_TLS
53 
54 static __thread char buf[1024];
55 
56 static char *
create_name(const Babl * source,const Babl * destination,int is_reference)57 create_name (const Babl *source,
58              const Babl *destination,
59              int         is_reference)
60 {
61   int size = 0;
62 
63   size = create_name_internal (buf, sizeof(buf), source, destination, is_reference);
64 
65   if (size < 0)
66     return NULL;
67 
68   return buf;
69 }
70 
71 
72 #else
73 
74 static char *
create_name(const Babl * source,const Babl * destination,int is_reference)75 create_name (const Babl *source,
76              const Babl *destination,
77              int         is_reference)
78 {
79   int size = 0;
80   char *buf = NULL;
81 
82   size = create_name_internal (buf, size, source, destination, is_reference);
83 
84   if (size < 0)
85     return NULL;
86 
87   size++;             /* For '\0' */
88   buf = malloc (size);
89   if (buf == NULL)
90     return NULL;
91 
92   size = create_name_internal (buf, size, source, destination, is_reference);
93 
94   if (size < 0)
95     {
96       free (buf);
97       return NULL;
98     }
99 
100   return buf;
101 }
102 
103 #endif
104 
105 /* need an internal version that only ever does double,
106  * for use in path evaluation? and perhaps even self evaluation of float code path?
107  */
108 Babl *
babl_fish_reference(const Babl * source,const Babl * destination)109 babl_fish_reference (const Babl *source,
110                      const Babl *destination)
111 {
112   Babl *babl = NULL;
113   char *name = create_name (source, destination, 1);
114 
115   babl_assert (name);
116 
117   babl = babl_db_exist_by_name (babl_fish_db (), name);
118   if (babl)
119     {
120       /* There is an instance already registered by the required name,
121        * returning the preexistent one instead.
122        */
123 #ifndef HAVE_TLS
124       free (name);
125 #endif
126       _babl_fish_rig_dispatch (babl);
127       return babl;
128     }
129 
130   babl_assert (BABL_IS_BABL (source));
131   babl_assert (BABL_IS_BABL (destination));
132 
133   babl_assert (source->class_type == BABL_FORMAT);
134   babl_assert (destination->class_type == BABL_FORMAT);
135 
136   babl = babl_calloc (1, sizeof (BablFishReference) +
137                       strlen (name) + 1);
138   babl->class_type    = BABL_FISH_REFERENCE;
139   babl->instance.id   = babl_fish_get_id (source, destination);
140   babl->instance.name = ((char *) babl) + sizeof (BablFishReference);
141   strcpy (babl->instance.name, name);
142   babl->fish.source      = source;
143   babl->fish.destination = destination;
144 
145   babl->fish.pixels      = 0;
146   babl->fish.error       = 0.0;  /* assuming the provided reference conversions for types
147                                     and models are as exact as possible
148                                   */
149   _babl_fish_rig_dispatch (babl);
150 
151   /* Since there is not an already registered instance by the required
152    * name, inserting newly created class into database.
153    */
154   babl_db_insert (babl_fish_db (), babl);
155 #ifndef HAVE_TLS
156   free (name);
157 #endif
158   return babl;
159 }
160 
161 
162 static void
convert_to_double(BablFormat * source_fmt,const char * source_buf,char * double_buf,int n)163 convert_to_double (BablFormat      *source_fmt,
164                    const char      *source_buf,
165                    char            *double_buf,
166                    int              n)
167 {
168   int        i;
169 
170   BablImage *src_img;
171   BablImage *dst_img;
172 
173   src_img = (BablImage *) babl_image_new (
174     babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
175   dst_img = (BablImage *) babl_image_new (
176     babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
177 
178   dst_img->type[0]  = (BablType *) babl_type_from_id (BABL_DOUBLE);
179   dst_img->pitch[0] =
180     (dst_img->type[0]->bits / 8) * source_fmt->model->components;
181   dst_img->stride[0] = 0;
182 
183   src_img->type[0]   = (BablType *) babl_type_from_id (BABL_DOUBLE);
184   src_img->pitch[0]  = source_fmt->bytes_per_pixel;
185   src_img->stride[0] = 0;
186 
187   {
188   /* i is dest position */
189   for (i = 0; i < source_fmt->model->components; i++)
190     {
191       int j;
192       int found = 0;
193 
194       dst_img->data[0] =
195         double_buf + (dst_img->type[0]->bits / 8) * i;
196 
197       src_img->data[0] = (char *)source_buf;
198 
199       /* j is source position */
200       for (j = 0; j < source_fmt->components; j++)
201         {
202           src_img->type[0] = source_fmt->type[j];
203 
204           if (source_fmt->component[j] ==
205               source_fmt->model->component[i])
206             {
207               babl_conversion_process (assert_conversion_find (src_img->type[0], dst_img->type[0]),
208                                        (void*)src_img, (void*)dst_img, n);
209               found = 1;
210               break;
211             }
212 
213           src_img->data[0] += src_img->type[0]->bits / 8;
214         }
215 
216       if (!found)
217         {
218           char *dst_ptr = dst_img->data[0];
219           double value;
220 
221           value = source_fmt->model->component[i]->instance.id == BABL_ALPHA ? 1.0 : 0.0;
222 
223           for (j = 0; j < n; j++)
224             {
225               double *dst_component = (double *) dst_ptr;
226 
227               *dst_component = value;
228               dst_ptr += dst_img->pitch[0];
229             }
230         }
231     }
232   }
233   babl_free (src_img);
234   babl_free (dst_img);
235 }
236 
237 
238 static void
convert_from_double(BablFormat * source_fmt,BablFormat * destination_fmt,char * destination_double_buf,char * destination_buf,int n)239 convert_from_double (BablFormat *source_fmt,
240                      BablFormat *destination_fmt,
241                      char       *destination_double_buf,
242                      char       *destination_buf,
243                      int         n)
244 {
245   int        i;
246 
247   BablImage *src_img;
248   BablImage *dst_img;
249 
250   src_img = (BablImage *) babl_image_new (
251     babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
252   dst_img = (BablImage *) babl_image_new (
253     babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
254 
255   src_img->type[0]   = (BablType *) babl_type_from_id (BABL_DOUBLE);
256   src_img->pitch[0]  = (src_img->type[0]->bits / 8) * destination_fmt->model->components;
257   src_img->stride[0] = 0;
258 
259   dst_img->data[0]  = destination_buf;
260   dst_img->pitch[0] = destination_fmt->bytes_per_pixel;
261   dst_img->stride[0] = 0;
262 
263   for (i = 0; i < destination_fmt->components; i++)
264     {
265       int j;
266       int can_be_used = 1;
267 
268       dst_img->type[0] = destination_fmt->type[i];
269 
270       if (source_fmt->model == destination_fmt->model)
271       {
272         can_be_used = 0;
273         for (j = 0; j < source_fmt->components; j++)
274         {
275           if (destination_fmt->component[i] == source_fmt->component[j])
276           {
277             can_be_used = 1;
278           }
279         }
280       }
281       else
282       {
283       }
284          //fprintf (stderr, "%s %s %i\n", babl_get_name (source_fmt), babl_get_name (destination_fmt), can_be_used);
285 
286       if (can_be_used)
287       for (j = 0; j < destination_fmt->model->components; j++)
288         {
289           if (destination_fmt->component[i] ==
290               destination_fmt->model->component[j])
291             {
292               src_img->data[0] =
293                 destination_double_buf + (src_img->type[0]->bits / 8) * j;
294 
295               babl_conversion_process (assert_conversion_find (src_img->type[0],
296                                        dst_img->type[0]),
297                                        (void*)src_img, (void*)dst_img, n);
298               break;
299             }
300         }
301 
302       dst_img->data[0] += dst_img->type[0]->bits / 8;
303     }
304   babl_free (src_img);
305   babl_free (dst_img);
306 }
307 
308 
309 static void
ncomponent_convert_to_double(BablFormat * source_fmt,char * source_buf,char * source_double_buf,int n)310 ncomponent_convert_to_double (BablFormat       *source_fmt,
311                               char             *source_buf,
312                               char             *source_double_buf,
313                               int               n)
314 {
315   BablImage *src_img;
316   BablImage *dst_img;
317 
318   src_img = (BablImage *) babl_image_new (
319     babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
320   dst_img = (BablImage *) babl_image_new (
321     babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
322 
323   dst_img->type[0]  = (BablType *) babl_type_from_id (BABL_DOUBLE);
324   dst_img->pitch[0] = (dst_img->type[0]->bits / 8);
325   dst_img->stride[0] = 0;
326 
327   src_img->data[0] = source_buf;
328   src_img->type[0] = source_fmt->type[0];
329   src_img->pitch[0] = source_fmt->type[0]->bits / 8;
330   src_img->stride[0] = 0;
331 
332   dst_img->data[0] = source_double_buf;
333 
334   babl_conversion_process (
335     assert_conversion_find (src_img->type[0], dst_img->type[0]),
336     (void*)src_img, (void*)dst_img,
337     n * source_fmt->components);
338   babl_free (src_img);
339   babl_free (dst_img);
340 }
341 
342 static void
ncomponent_convert_from_double(BablFormat * destination_fmt,char * destination_double_buf,char * destination_buf,int n)343 ncomponent_convert_from_double (BablFormat *destination_fmt,
344                                 char       *destination_double_buf,
345                                 char       *destination_buf,
346                                 int         n)
347 {
348   BablImage *src_img;
349   BablImage *dst_img;
350 
351   src_img = (BablImage *) babl_image_new (
352     babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
353   dst_img = (BablImage *) babl_image_new (
354     babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
355 
356   src_img->type[0]   = (BablType *) babl_type_from_id (BABL_DOUBLE);
357   src_img->pitch[0]  = (src_img->type[0]->bits / 8);
358   src_img->stride[0] = 0;
359 
360   dst_img->data[0]  = destination_buf;
361   dst_img->pitch[0] = destination_fmt->type[0]->bits/8;
362   dst_img->stride[0] = 0;
363 
364   dst_img->type[0] = destination_fmt->type[0];
365   src_img->data[0] = destination_double_buf;
366 
367   babl_conversion_process (
368     assert_conversion_find (src_img->type[0], dst_img->type[0]),
369     (void*)src_img, (void*)dst_img,
370     n * destination_fmt->components);
371 
372   dst_img->data[0] += dst_img->type[0]->bits / 8;
373   babl_free (src_img);
374   babl_free (dst_img);
375 }
376 
377 
378 static int
process_to_n_component(const Babl * babl,const char * source,char * destination,long n)379 process_to_n_component (const Babl  *babl,
380                         const char *source,
381                         char       *destination,
382                         long        n)
383 {
384   void *double_buf;
385 #ifndef MAX
386 #define MAX(a, b) ((a) > (b) ? (a) : (b))
387 #endif
388   int components = MAX(BABL (babl->fish.source)->format.model->components,
389                        BABL (babl->fish.source)->format.components);
390   components = MAX(components, BABL (babl->fish.destination)->format.components);
391   components = MAX(components, BABL (babl->fish.destination)->model.components);
392 
393   double_buf = babl_malloc (sizeof (double) * n * components);
394       memset (double_buf, 0,sizeof (double) * n * components);
395 
396  /* a single precision path could be added here*/
397     {
398       ncomponent_convert_to_double (
399         (BablFormat *) BABL (babl->fish.source),
400         (char *) source,
401         double_buf,
402         n
403       );
404 
405       ncomponent_convert_from_double (
406         (BablFormat *) BABL (babl->fish.destination),
407         double_buf,
408         (char *) destination,
409         n
410       );
411     }
412 
413   babl_free (double_buf);
414   return 0;
415 }
416 
compatible_components(const BablFormat * a,const BablFormat * b)417 static int compatible_components (const BablFormat *a,
418                                   const BablFormat *b)
419 {
420   int i;
421   if (a->components != b->components)
422     return 0;
423   for (i = 0; i < a->components; i++)
424    if (a->component[i] != b->component[i])
425      return 0;
426   return 1;
427 }
428 
429 static void
ncomponent_convert_to_float(BablFormat * source_fmt,char * source_buf,char * source_float_buf,int n)430 ncomponent_convert_to_float (BablFormat       *source_fmt,
431                              char             *source_buf,
432                              char             *source_float_buf,
433                              int               n)
434 {
435   BablImage *src_img;
436   BablImage *dst_img;
437 
438   src_img = (BablImage *) babl_image_new (
439     babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
440   dst_img = (BablImage *) babl_image_new (
441     babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
442 
443   dst_img->type[0]  = (BablType *) babl_type_from_id (BABL_FLOAT);
444   dst_img->pitch[0] = (dst_img->type[0]->bits / 8);
445   dst_img->stride[0] = 0;
446 
447   src_img->data[0] = source_buf;
448   src_img->type[0] = source_fmt->type[0];
449   src_img->pitch[0] = source_fmt->type[0]->bits / 8;
450   src_img->stride[0] = 0;
451 
452   dst_img->data[0] = source_float_buf;
453 
454   babl_conversion_process (
455     assert_conversion_find (src_img->type[0], dst_img->type[0]),
456     (void*)src_img, (void*)dst_img,
457     n * source_fmt->components);
458   babl_free (src_img);
459   babl_free (dst_img);
460 }
461 
462 static void
ncomponent_convert_from_float(BablFormat * source_fmt,BablFormat * destination_fmt,char * destination_float_buf,char * destination_buf,int n)463 ncomponent_convert_from_float (BablFormat *source_fmt,
464                                BablFormat *destination_fmt,
465                                char       *destination_float_buf,
466                                char       *destination_buf,
467                                int         n)
468 {
469   BablImage *src_img;
470   BablImage *dst_img;
471 
472   src_img = (BablImage *) babl_image_new (
473     babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
474   dst_img = (BablImage *) babl_image_new (
475     babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
476 
477   src_img->type[0]   = (BablType *) babl_type_from_id (BABL_FLOAT);
478   src_img->pitch[0]  = (src_img->type[0]->bits / 8);
479   src_img->stride[0] = 0;
480 
481   dst_img->data[0]  = destination_buf;
482   dst_img->pitch[0] = destination_fmt->type[0]->bits/8;
483   dst_img->stride[0] = 0;
484 
485   dst_img->type[0] = destination_fmt->type[0];
486   src_img->data[0] = destination_float_buf;
487 
488   babl_conversion_process (
489     assert_conversion_find (src_img->type[0], dst_img->type[0]),
490     (void*)src_img, (void*)dst_img,
491     n * destination_fmt->components);
492 
493   dst_img->data[0] += dst_img->type[0]->bits / 8;
494   babl_free (src_img);
495   babl_free (dst_img);
496 }
497 
498 static void
convert_to_float(BablFormat * source_fmt,const char * source_buf,char * float_buf,int n)499 convert_to_float (BablFormat *source_fmt,
500                   const char *source_buf,
501                   char       *float_buf,
502                   int         n)
503 {
504   int        i;
505 
506   BablImage *src_img;
507   BablImage *dst_img;
508 
509   src_img = (BablImage *) babl_image_new (
510     babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
511   dst_img = (BablImage *) babl_image_new (
512     babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
513 
514   dst_img->type[0]  = (BablType *) babl_type_from_id (BABL_FLOAT);
515   dst_img->pitch[0] =
516     (dst_img->type[0]->bits / 8) * source_fmt->model->components;
517   dst_img->stride[0] = 0;
518 
519   src_img->type[0]   = (BablType *) babl_type_from_id (BABL_FLOAT);
520   src_img->pitch[0]  = source_fmt->bytes_per_pixel;
521   src_img->stride[0] = 0;
522 
523   {
524   /* i is dest position */
525   for (i = 0; i < source_fmt->model->components; i++)
526     {
527       int j;
528       int found = 0;
529 
530       dst_img->data[0] =
531         float_buf + (dst_img->type[0]->bits / 8) * i;
532 
533       src_img->data[0] = (char *)source_buf;
534 
535       /* j is source position */
536       for (j = 0; j < source_fmt->components; j++)
537         {
538           src_img->type[0] = source_fmt->type[j];
539 
540           if (source_fmt->component[j] ==
541               source_fmt->model->component[i])
542             {
543               babl_conversion_process (assert_conversion_find (src_img->type[0], dst_img->type[0]),
544                                        (void*)src_img, (void*)dst_img, n);
545               found = 1;
546               break;
547             }
548 
549           src_img->data[0] += src_img->type[0]->bits / 8;
550         }
551 
552       if (!found)
553         {
554           char *dst_ptr = dst_img->data[0];
555           float value;
556 
557           value = source_fmt->model->component[i]->instance.id == BABL_ALPHA ? 1.0 : 0.0;
558 
559           for (j = 0; j < n; j++)
560             {
561               float *dst_component = (float *) dst_ptr;
562 
563               *dst_component = value;
564               dst_ptr += dst_img->pitch[0];
565             }
566         }
567     }
568   }
569   babl_free (src_img);
570   babl_free (dst_img);
571 }
572 
573 
574 static void
convert_from_float(BablFormat * source_fmt,BablFormat * destination_fmt,char * destination_float_buf,char * destination_buf,int n)575 convert_from_float (BablFormat *source_fmt,
576                     BablFormat *destination_fmt,
577                      char      *destination_float_buf,
578                      char      *destination_buf,
579                      int        n)
580 {
581   int        i;
582 
583   BablImage *src_img;
584   BablImage *dst_img;
585 
586   src_img = (BablImage *) babl_image_new (
587     babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
588   dst_img = (BablImage *) babl_image_new (
589     babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
590 
591   src_img->type[0]   = (BablType *) babl_type_from_id (BABL_FLOAT);
592   src_img->pitch[0]  = (src_img->type[0]->bits / 8) * destination_fmt->model->components;
593   src_img->stride[0] = 0;
594 
595   dst_img->data[0]  = destination_buf;
596   dst_img->type[0]  = (BablType *) babl_type_from_id (BABL_FLOAT);
597   dst_img->pitch[0] = destination_fmt->bytes_per_pixel;
598   dst_img->stride[0] = 0;
599 
600   for (i = 0; i < destination_fmt->components; i++)
601     {
602       int j;
603       int can_be_used = 1;
604 
605       dst_img->type[0] = destination_fmt->type[i];
606 
607       if (source_fmt->model == destination_fmt->model)
608       {
609         can_be_used = 0;
610         for (j = 0; j < source_fmt->components; j++)
611         {
612           if (destination_fmt->component[i] == source_fmt->component[j])
613           {
614             can_be_used = 1;
615           }
616         }
617       }
618 
619       if (can_be_used)
620       for (j = 0; j < destination_fmt->model->components; j++)
621         {
622           if (destination_fmt->component[i] ==
623               destination_fmt->model->component[j])
624             {
625               src_img->data[0] =
626                 destination_float_buf + (src_img->type[0]->bits / 8) * j;
627 
628               babl_conversion_process (assert_conversion_find (src_img->type[0],
629                                        dst_img->type[0]),
630                                        (void*)src_img, (void*)dst_img, n);
631               break;
632             }
633         }
634 
635       dst_img->data[0] += dst_img->type[0]->bits / 8;
636     }
637   babl_free (src_img);
638   babl_free (dst_img);
639 }
640 
641 
642 
643 static void
process_same_model(const Babl * babl,const char * source,char * destination,long n)644 process_same_model (const Babl  *babl,
645                     const char *source,
646                     char       *destination,
647                     long        n)
648 {
649   const void *type_float = babl_type_from_id (BABL_FLOAT);
650 #define MAX(a, b) ((a) > (b) ? (a) : (b))
651 
652   if ((babl->fish.source->format.type[0]->bits < 32 ||
653        babl->fish.source->format.type[0] == type_float) &&
654       (babl->fish.destination->format.type[0]->bits < 32 ||
655        babl->fish.destination->format.type[0] == type_float))
656   {
657      void *float_buf = babl_malloc (sizeof (float) * n *
658                             MAX (BABL (babl->fish.source)->format.model->components,
659                                  BABL (babl->fish.source)->format.components));
660     if (compatible_components ((void*)babl->fish.source,
661                                (void*)babl->fish.destination))
662     {
663         ncomponent_convert_to_float (
664           (BablFormat *) BABL (babl->fish.source),
665           (char *) source,
666           float_buf,
667           n);
668         ncomponent_convert_from_float (
669           (BablFormat *) BABL (babl->fish.source),
670           (BablFormat *) BABL (babl->fish.destination),
671           float_buf,
672           (char *) destination,
673           n);
674     }
675     else
676     {
677         convert_to_float (
678           (BablFormat *) BABL (babl->fish.source),
679           (char *) source,
680           float_buf,
681           n);
682 
683         convert_from_float (
684           (BablFormat *) BABL (babl->fish.source),
685           (BablFormat *) BABL (babl->fish.destination),
686           float_buf,
687           (char *) destination,
688           n);
689     }
690     babl_free (float_buf);
691   }
692   else
693   {
694      void *double_buf = babl_malloc (sizeof (double) * n *
695                             MAX (BABL (babl->fish.source)->format.model->components,
696                                  BABL (babl->fish.source)->format.components));
697 #undef MAX
698     if (compatible_components ((void*)babl->fish.source,
699                                (void*)babl->fish.destination))
700     {
701         ncomponent_convert_to_double (
702           (BablFormat *) BABL (babl->fish.source),
703           (char *) source,
704           double_buf,
705           n);
706         ncomponent_convert_from_double (
707           (BablFormat *) BABL (babl->fish.destination),
708           double_buf,
709           (char *) destination,
710           n);
711     }
712     else
713     {
714         convert_to_double (
715           (BablFormat *) BABL (babl->fish.source),
716           (char *) source,
717           double_buf,
718           n);
719 
720         convert_from_double (
721           (BablFormat *) BABL (babl->fish.source),
722           (BablFormat *) BABL (babl->fish.destination),
723           double_buf,
724           (char *) destination,
725           n);
726     }
727     babl_free (double_buf);
728   }
729 }
730 
731 typedef enum _Kind Kind;
732 enum _Kind { KIND_RGB, KIND_CMYK};
733 
format_has_cmyk_model(const Babl * format)734 static int format_has_cmyk_model (const Babl *format)
735 {
736   return format->format.model->flags & BABL_MODEL_FLAG_CMYK;
737 }
738 
739 static void
babl_fish_reference_process_double(const Babl * babl,const char * source,char * destination,long n,void * data)740 babl_fish_reference_process_double (const Babl *babl,
741                                     const char *source,
742                                     char       *destination,
743                                     long        n,
744                                     void       *data)
745 {
746   Kind  source_kind             = KIND_RGB;
747   Kind  destination_kind        = KIND_RGB;
748   Babl *source_image            = NULL;
749   Babl *rgba_image              = NULL;
750   Babl *cmyka_image             = NULL;
751   Babl *destination_image       = NULL;
752 
753 
754 
755   void *source_double_buf_alloc = NULL;
756   void *source_double_buf       = NULL;
757   void *rgba_double_buf_alloc   = NULL;
758   void *rgba_double_buf         = NULL;
759   void *cmyka_double_buf_alloc  = NULL;
760   void *cmyka_double_buf        = NULL;
761   void *destination_double_buf_alloc = NULL;
762   void *destination_double_buf;
763   const void *type_double  = babl_type_from_id (BABL_DOUBLE);
764 
765   const Babl *source_space = BABL (BABL ((babl->fish.source))->format.space);
766   const Babl *destination_space = BABL (BABL ((babl->fish.destination))->format.space);
767 
768   /* This is not the full/only condition XXX */
769 
770   /* XXX : sometimes is_cmyk is neither 0 or 1 */
771 
772   if (format_has_cmyk_model (babl->fish.source))
773     source_kind = KIND_CMYK;
774   if (format_has_cmyk_model (babl->fish.destination))
775     destination_kind = KIND_CMYK;
776 
777   if (babl->fish.source->format.type[0] == type_double &&
778       BABL(babl->fish.source)->format.components ==
779       BABL(babl->fish.source)->format.model->components)
780   {
781     source_double_buf = (void*)source;
782     source_image = babl_image_from_linear (
783        source_double_buf, BABL (BABL ((babl->fish.source))->format.model));
784   }
785   else
786   {
787     source_double_buf =
788     source_double_buf_alloc = babl_malloc (sizeof (double) * n *
789                                 BABL (babl->fish.source)->format.model->components);
790 
791     source_image = babl_image_from_linear (
792       source_double_buf, BABL (BABL ((babl->fish.source))->format.model));
793     convert_to_double (
794       (BablFormat *) BABL (babl->fish.source),
795       source,
796       source_double_buf,
797       n
798     );
799   }
800 
801   babl_mutex_lock (babl_reference_mutex);
802   switch (source_kind)
803   {
804     case KIND_RGB:
805      {
806        Babl *conv = assert_conversion_find (
807            BABL (babl->fish.source)->format.model,
808        babl_remodel_with_space (babl_model_from_id (BABL_RGBA),
809                          source_space));
810 
811        rgba_double_buf       =
812        rgba_double_buf_alloc = babl_malloc (sizeof (double) * n * 4);
813 
814        rgba_image = babl_image_from_linear (
815           rgba_double_buf, babl_remodel_with_space (babl_model_from_id (BABL_RGBA), source_space));
816 
817        if (conv->class_type == BABL_CONVERSION_PLANAR)
818        {
819           babl_conversion_process (conv,
820                (void*)source_image, (void*)rgba_image, n);
821        }
822        else if (conv->class_type == BABL_CONVERSION_LINEAR)
823        {
824          babl_conversion_process (conv, source_double_buf, rgba_double_buf, n);
825        }
826        else babl_fatal ("oops");
827       }
828       break;
829     case KIND_CMYK:
830       if (babl_model_is ((void*)babl->fish.source->format.model, "cmykA"))
831       {
832         cmyka_double_buf = source_double_buf;
833         cmyka_image = babl_image_from_linear (cmyka_double_buf,
834                                 (void*)babl->fish.source->format.model);
835       }
836       else
837       {
838         Babl *conv = assert_conversion_find (
839                    BABL (babl->fish.source)->format.model,
840                    babl_remodel_with_space (babl_model ("cmykA"),
841                          source_space));
842 
843         cmyka_double_buf       =
844         cmyka_double_buf_alloc = babl_malloc (sizeof (double) * n * 5);
845 
846         cmyka_image = babl_image_from_linear (
847           cmyka_double_buf, babl_remodel_with_space (babl_model ("cmykA"),
848           source_space));
849 
850         if (conv->class_type == BABL_CONVERSION_PLANAR)
851         {
852           babl_conversion_process (conv,
853            (void*)source_image, (void*)cmyka_image, n);
854         }
855         else if (conv->class_type == BABL_CONVERSION_LINEAR)
856         {
857           babl_conversion_process (conv,source_double_buf, cmyka_double_buf, n);
858         }
859         else babl_fatal ("oops");
860       }
861       break;
862   }
863 
864   if (source_kind      == KIND_RGB &&
865       destination_kind == KIND_RGB)
866   {
867     if (source_space != destination_space)
868     {
869       double matrix[9];
870       double *rgba = rgba_double_buf;
871       babl_matrix_mul_matrix (
872         destination_space->space.XYZtoRGB,
873         source_space->space.RGBtoXYZ,
874         matrix);
875 
876       babl_matrix_mul_vector_buf4 (matrix, rgba, rgba, n);
877     }
878   }
879   else if (source_kind      == KIND_RGB &&
880            destination_kind == KIND_CMYK)
881   {
882     cmyka_double_buf        =
883     cmyka_double_buf_alloc  = babl_malloc (sizeof (double) * n * 5);
884     cmyka_image = babl_image_from_linear (
885         cmyka_double_buf, babl_remodel_with_space (babl_model ("cmykA"),
886         destination_space));
887 
888 #if HAVE_LCMS
889     if (destination_space->space.cmyk.lcms_profile)
890     {
891       /* lcms expect floats with normalized range 0.0-100.0 for CMYK data,
892          we also do our inversion from profile here.
893        */
894       double *rgba=rgba_double_buf;
895       double *cmyka=cmyka_double_buf;
896       int i;
897       /* use lcms for doing conversion from RGBA */
898       cmsDoTransform (destination_space->space.cmyk.lcms_from_rgba,
899          rgba_double_buf, cmyka_double_buf, n);
900 
901       for (i = 0; i < n; i++)
902       {
903         cmyka[i * 5 + 0] = 1.0-(cmyka[i * 5 + 0])/100.0;
904         cmyka[i * 5 + 1] = 1.0-(cmyka[i * 5 + 1])/100.0;
905         cmyka[i * 5 + 2] = 1.0-(cmyka[i * 5 + 2])/100.0;
906         cmyka[i * 5 + 3] = 1.0-(cmyka[i * 5 + 3])/100.0;
907         cmyka[i * 5 + 4] = rgba[i * 4 + 3];
908       }
909     }
910     else
911 #endif
912     {
913       double *rgba=rgba_double_buf;
914       double *cmyka=cmyka_double_buf;
915       int i;
916       for (i = 0; i < n; i++)
917       {
918         /* A very naive conversion - but it is usable */
919         double key=1.0;
920         cmyka[i * 5 + 0] = 1.0 - rgba[i * 4 + 0];
921         cmyka[i * 5 + 1] = 1.0 - rgba[i * 4 + 1];
922         cmyka[i * 5 + 2] = 1.0 - rgba[i * 4 + 2];
923 
924         if (cmyka[i * 5 + 0] < key) key = cmyka[i*5+0];
925         if (cmyka[i * 5 + 1] < key) key = cmyka[i*5+1];
926         if (cmyka[i * 5 + 2] < key) key = cmyka[i*5+2];
927 
928         key *= 1.0; // pullout - XXX tune default pullout?;
929 
930         if (key < 1.0)
931         {
932           cmyka[i * 5 + 0] = (cmyka[i * 5 + 0] - key) / (1.0-key);
933           cmyka[i * 5 + 1] = (cmyka[i * 5 + 1] - key) / (1.0-key);
934           cmyka[i * 5 + 2] = (cmyka[i * 5 + 2] - key) / (1.0-key);
935         }
936         cmyka[i * 5 + 0] = 1.0-cmyka[i * 5 + 0];
937         cmyka[i * 5 + 1] = 1.0-cmyka[i * 5 + 1];
938         cmyka[i * 5 + 2] = 1.0-cmyka[i * 5 + 2];
939         cmyka[i * 5 + 3] = 1.0-key;
940         cmyka[i * 5 + 4] = rgba[i * 4 + 3];
941       }
942     }
943  }
944  else if (source_kind      == KIND_CMYK &&
945           destination_kind == KIND_RGB)
946  {
947     /* */
948     rgba_double_buf_alloc  = babl_malloc (sizeof (double) * n * 4);
949     rgba_double_buf        = rgba_double_buf_alloc;
950     rgba_image = babl_image_from_linear (
951         rgba_double_buf, babl_remodel_with_space (babl_model_from_id (BABL_RGBA),
952         destination_space));
953 
954 #if HAVE_LCMS
955     if (source_space->space.cmyk.lcms_profile)
956     {
957     {
958       /* lcms expect floats with normalized range 0.0-100.0 for CMYK data,
959          we also do our inversion from profile here.
960        */
961       double *cmyka=cmyka_double_buf;
962       int i;
963       for (i = 0; i < n; i++)
964       {
965         cmyka[i * 5 + 0] = (1.0-cmyka[i * 5 + 0])*100.0;
966         cmyka[i * 5 + 1] = (1.0-cmyka[i * 5 + 1])*100.0;
967         cmyka[i * 5 + 2] = (1.0-cmyka[i * 5 + 2])*100.0;
968         cmyka[i * 5 + 3] = (1.0-cmyka[i * 5 + 3])*100.0;
969       }
970     }
971     /* use lcms for doing conversion to RGBA */
972     cmsDoTransform (source_space->space.cmyk.lcms_to_rgba,
973        cmyka_double_buf, rgba_double_buf, n);
974 
975     {
976       double *rgba=rgba_double_buf;
977       double *cmyka=cmyka_double_buf;
978       int i;
979       for (i = 0; i < n; i++)
980       {
981         rgba[i * 4 + 3] = cmyka[i * 5 + 4];
982       }
983     }
984     }
985     else
986 #endif
987     {
988       double *rgba=rgba_double_buf;
989       double *cmyka=cmyka_double_buf;
990       int i;
991       for (i = 0; i < n; i++)
992       {
993         /* A very naive conversion - but it is usable */
994         rgba[i * 4 + 0] = cmyka[i * 5 + 0]*cmyka[i*5+3];
995         rgba[i * 4 + 1] = cmyka[i * 5 + 1]*cmyka[i*5+3];
996         rgba[i * 4 + 2] = cmyka[i * 5 + 2]*cmyka[i*5+3];
997         rgba[i * 4 + 3] = cmyka[i * 5 + 4];
998       }
999     }
1000 
1001     /* color space conversions */
1002      if ((babl_space ("scRGB")!=
1003         ((babl->fish.destination)->format.space)))
1004     {
1005       double matrix[9];
1006       double *rgba = rgba_double_buf;
1007       babl_matrix_mul_matrix (
1008         (babl->fish.destination)->format.space->space.XYZtoRGB,
1009         babl_space("scRGB")->space.RGBtoXYZ,
1010         matrix);
1011 
1012       babl_matrix_mul_vector_buf4 (matrix, rgba, rgba, n);
1013     }
1014  }
1015  else if (source_kind      == KIND_CMYK &&
1016           destination_kind == KIND_CMYK)
1017  {
1018     if (source_space != destination_space
1019 #if HAVE_LCMS
1020         && source_space->space.cmyk.lcms_profile
1021         && destination_space->space.cmyk.lcms_profile
1022 #endif
1023  )
1024     {
1025 #if HAVE_LCMS
1026 
1027 #define MAX_CMYK_CMYK  64
1028      static int cmyk_cmyk_count = 0;
1029      static const Babl *cmyk_cmyk_source[MAX_CMYK_CMYK];
1030      static const Babl *cmyk_cmyk_destination[MAX_CMYK_CMYK];
1031      static cmsHTRANSFORM cmyk_cmyk_transform[MAX_CMYK_CMYK];
1032 
1033      int cmyk_cmyk_no;
1034       double *cmyka = cmyka_double_buf;
1035      for (cmyk_cmyk_no = 0; cmyk_cmyk_no < cmyk_cmyk_count; cmyk_cmyk_no++)
1036      {
1037        if (cmyk_cmyk_source[cmyk_cmyk_no] == source_space &&
1038            cmyk_cmyk_destination[cmyk_cmyk_no] == destination_space)
1039          break;
1040      }
1041 
1042 /* these are not defined by lcms2.h we hope that following the existing pattern of pixel-format definitions work */
1043 #ifndef TYPE_CMYKA_DBL
1044 #define TYPE_CMYKA_DBL      (FLOAT_SH(1)|COLORSPACE_SH(PT_CMYK)|EXTRA_SH(1)|CHANNELS_SH(4)|BYTES_SH(0))
1045 #endif
1046 
1047      if (cmyk_cmyk_no >= cmyk_cmyk_count)
1048      {
1049        cmsHPROFILE src_profile = cmsOpenProfileFromMem(source_space->space.icc_profile, source_space->space.icc_length);
1050        cmsHPROFILE dst_profile = cmsOpenProfileFromMem(destination_space->space.icc_profile, source_space->space.icc_length);
1051 
1052        cmyk_cmyk_source[cmyk_cmyk_no] = source_space;
1053        cmyk_cmyk_destination[cmyk_cmyk_no] = destination_space;
1054        cmyk_cmyk_transform[cmyk_cmyk_no] = cmsCreateTransform(src_profile, TYPE_CMYKA_DBL,
1055   dst_profile, TYPE_CMYKA_DBL,
1056   INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_BLACKPOINTCOMPENSATION);
1057        cmsCloseProfile (src_profile);
1058        cmsCloseProfile (dst_profile);
1059 
1060        cmyk_cmyk_count ++;
1061      }
1062       for (int i = 0; i < n; i++)
1063       {
1064         cmyka[i * 5 + 0] = (1.0-cmyka[i * 5 + 0])*100.0;
1065         cmyka[i * 5 + 1] = (1.0-cmyka[i * 5 + 1])*100.0;
1066         cmyka[i * 5 + 2] = (1.0-cmyka[i * 5 + 2])*100.0;
1067         cmyka[i * 5 + 3] = (1.0-cmyka[i * 5 + 3])*100.0;
1068       }
1069 
1070      cmsDoTransform (cmyk_cmyk_transform[cmyk_cmyk_no],
1071                      cmyka_double_buf, cmyka_double_buf, n);
1072 
1073       for (int i = 0; i < n; i++)
1074       {
1075         cmyka[i * 5 + 0] = 1.0-(cmyka[i * 5 + 0])/100.0;
1076         cmyka[i * 5 + 1] = 1.0-(cmyka[i * 5 + 1])/100.0;
1077         cmyka[i * 5 + 2] = 1.0-(cmyka[i * 5 + 2])/100.0;
1078         cmyka[i * 5 + 3] = 1.0-(cmyka[i * 5 + 3])/100.0;
1079       }
1080 
1081 #endif
1082      }
1083  }
1084 
1085 
1086   switch (destination_kind) /* XXX: the cases can share logic */
1087   {
1088     case KIND_CMYK:
1089       {
1090         const Babl *destination_cmyka_format =
1091           babl_remodel_with_space (babl_model ("cmykA"), destination_space);
1092         if(BABL (babl->fish.destination)->format.model == (void*)destination_cmyka_format)
1093         {
1094            destination_double_buf = cmyka_double_buf;
1095         }
1096         else
1097         {
1098           Babl *conv =
1099             assert_conversion_find (destination_cmyka_format,
1100                              BABL (babl->fish.destination)->format.model);
1101           destination_double_buf =
1102           destination_double_buf_alloc = babl_malloc (sizeof (double) * n *
1103                                           BABL (babl->fish.destination)->format.model->components);
1104           if (conv->class_type == BABL_CONVERSION_PLANAR)
1105           {
1106             destination_image = babl_image_from_linear (
1107               destination_double_buf, BABL (BABL ((babl->fish.destination))->format.model));
1108             babl_conversion_process (conv,
1109               (void*)cmyka_image, (void*)destination_image, n);
1110           }
1111           else if (conv->class_type == BABL_CONVERSION_LINEAR)
1112           {
1113             babl_conversion_process (conv,
1114                            cmyka_double_buf, destination_double_buf, n);
1115           }
1116           else
1117           {
1118             babl_fatal ("oops");
1119           }
1120         }
1121      }
1122      break;
1123   case KIND_RGB:
1124       {
1125         const Babl *destination_rgba_format =
1126           babl_remodel_with_space (babl_model_from_id (BABL_RGBA),
1127                destination_space);
1128 
1129         if(BABL (babl->fish.destination)->format.model == (void*)destination_rgba_format)
1130         {
1131            destination_double_buf = rgba_double_buf;
1132         }
1133         else
1134         {
1135         Babl *conv =
1136           assert_conversion_find (destination_rgba_format,
1137              BABL (babl->fish.destination)->format.model);
1138            destination_double_buf_alloc = babl_malloc (sizeof (double) * n *
1139                                             BABL (babl->fish.destination)->format.model->components);
1140            destination_double_buf = destination_double_buf_alloc;
1141 
1142         if (conv->class_type == BABL_CONVERSION_PLANAR)
1143           {
1144             destination_image = babl_image_from_linear (
1145               destination_double_buf, BABL (BABL ((babl->fish.destination))->format.model));
1146             babl_conversion_process (
1147               conv,
1148               (void*)rgba_image, (void*)destination_image,
1149               n);
1150           }
1151         else if (conv->class_type == BABL_CONVERSION_LINEAR)
1152           {
1153             babl_conversion_process (
1154               conv,
1155               rgba_double_buf, destination_double_buf,
1156               n);
1157           }
1158         else
1159           {
1160             babl_fatal ("oops");
1161           }
1162         }
1163      }
1164    break;
1165   }
1166   babl_mutex_unlock (babl_reference_mutex);
1167 
1168  /* convert from double model backing target pixel format to final representation */
1169   convert_from_double (
1170     (BablFormat *) BABL (babl->fish.source),
1171     (BablFormat *) BABL (babl->fish.destination),
1172     destination_double_buf,
1173     destination,
1174     n
1175   );
1176 
1177   if (destination_double_buf_alloc)
1178     babl_free (destination_double_buf_alloc);
1179   if (rgba_double_buf_alloc)
1180     babl_free (rgba_double_buf_alloc);
1181   if (cmyka_double_buf_alloc)
1182     babl_free (cmyka_double_buf_alloc);
1183   if (source_double_buf_alloc)
1184     babl_free (source_double_buf_alloc);
1185   if (source_image)
1186     babl_free (source_image);
1187   if (rgba_image)
1188     babl_free (rgba_image);
1189   if (cmyka_image)
1190     babl_free (cmyka_image);
1191   if (destination_image)
1192     babl_free (destination_image);
1193 }
1194 
1195 static void
babl_fish_reference_process_float(const Babl * babl,const char * source,char * destination,long n,void * data)1196 babl_fish_reference_process_float (const Babl *babl,
1197                                    const char *source,
1198                                    char       *destination,
1199                                    long        n,
1200                                    void       *data)
1201 {
1202   const void *type_float = babl_type_from_id (BABL_FLOAT);
1203     Babl *source_image = NULL;
1204     Babl *rgba_image = NULL;
1205     Babl *destination_image = NULL;
1206     void *source_float_buf_alloc = NULL;
1207     void *source_float_buf;
1208     void *rgba_float_buf_alloc = NULL;
1209     void *rgba_float_buf;
1210     void *destination_float_buf_alloc = NULL;
1211     void *destination_float_buf;
1212     const Babl *destination_float_format;
1213     Babl *conv_to_rgba;
1214     Babl *conv_from_rgba;
1215     char dst_name[256];
1216 
1217 
1218     {
1219     char src_name[256];
1220     sprintf (src_name, "%s float", babl_get_name((void*)babl->fish.source->format.model));
1221     conv_to_rgba =
1222         babl_conversion_find (
1223         babl_format_with_space (src_name,
1224                    BABL (BABL ((babl->fish.source))->format.space)),
1225         babl_format_with_space ("RGBA float",
1226                    BABL (BABL ((babl->fish.source))->format.space)));
1227     }
1228     {
1229       sprintf (dst_name, "%s float", babl_get_name((void*)babl->fish.destination->format.model));
1230       destination_float_format =
1231         babl_format_with_space (dst_name,
1232                    BABL (BABL ((babl->fish.destination))->format.space));
1233       conv_from_rgba  =
1234         babl_conversion_find (
1235         babl_format_with_space ("RGBA float",
1236                    BABL (BABL ((babl->fish.destination))->format.space)),
1237                    destination_float_format);
1238     }
1239 
1240     if (!conv_to_rgba || !conv_from_rgba)
1241     {
1242       /* needed float conversions not found, using double code path instead */
1243       babl_fish_reference_process_double (babl, source, destination, n, data);
1244       return;
1245     }
1246 
1247     babl_mutex_lock (babl_reference_mutex);
1248     if (babl->fish.source->format.type[0] == type_float &&
1249         BABL(babl->fish.source)->format.components ==
1250         BABL(babl->fish.source)->format.model->components && 0)
1251     {
1252       source_float_buf = (void*)source;
1253       source_image = babl_image_from_linear (
1254          source_float_buf,
1255          babl_format_with_model_as_type ((void*)((babl->fish.source))->format.model,
1256          type_float));
1257     }
1258     else
1259     {
1260       /* the +1 is to mask a valgrind 'invalid read of size 16' false positive  */
1261       source_float_buf_alloc = babl_malloc (sizeof (float) * (n+1) *
1262                                   (BABL (babl->fish.source)->format.model->components));
1263 
1264       source_float_buf = source_float_buf_alloc;
1265       source_image = babl_image_from_linear (
1266         source_float_buf,
1267       babl_format_with_model_as_type (BABL(BABL ((babl->fish.source))->format.model),
1268          type_float));
1269       convert_to_float (
1270         (BablFormat *) BABL (babl->fish.source),
1271         source,
1272         source_float_buf,
1273         n
1274       );
1275     }
1276 
1277     if (babl_model_is ((void*)babl->fish.source->format.model, "RGBA") && 0)
1278     {
1279       rgba_float_buf = source_float_buf;
1280       rgba_image = babl_image_from_linear (
1281           rgba_float_buf,
1282           (void*)babl->fish.source->format.model);
1283     }
1284     else
1285     {
1286       rgba_float_buf_alloc  = babl_malloc (sizeof (float) * n * 4);
1287       rgba_float_buf        = rgba_float_buf_alloc;
1288 
1289       rgba_image = babl_image_from_linear (
1290           rgba_float_buf,
1291         babl_format_with_space ("RGBA float",
1292                    BABL (BABL ((babl->fish.source))->format.space)));
1293 
1294 
1295     if (conv_to_rgba->class_type == BABL_CONVERSION_PLANAR)
1296       {
1297         babl_conversion_process (
1298           conv_to_rgba,
1299           (void*)source_image, (void*)rgba_image,
1300           n);
1301       }
1302     else if (conv_to_rgba->class_type == BABL_CONVERSION_LINEAR)
1303       {
1304         babl_conversion_process (
1305           conv_to_rgba,
1306           source_float_buf, rgba_float_buf,
1307           n);
1308       }
1309     }
1310     babl_mutex_unlock (babl_reference_mutex);
1311 
1312     if (((babl->fish.source)->format.space !=
1313         ((babl->fish.destination)->format.space)))
1314     {
1315       float matrix[9];
1316       float *rgba = rgba_float_buf;
1317       babl_matrix_mul_matrixf (
1318         (babl->fish.destination)->format.space->space.XYZtoRGBf,
1319         (babl->fish.source)->format.space->space.RGBtoXYZf,
1320         matrix);
1321 
1322       babl_matrix_mul_vectorff_buf4 (matrix, rgba, rgba, n);
1323     }
1324 
1325     {
1326       if(babl_format_with_space ("RGBA float",
1327                    BABL (BABL ((babl->fish.destination))->format.space)) ==
1328          babl_format_with_space (dst_name,
1329                    BABL (BABL ((babl->fish.destination))->format.space)))
1330       {
1331         destination_float_buf = rgba_float_buf;
1332       }
1333       else
1334       {
1335         destination_float_buf_alloc = babl_malloc (sizeof (float) * n *
1336                                         BABL (babl->fish.destination)->format.model->components);
1337         destination_float_buf = destination_float_buf_alloc;
1338 
1339         if (conv_from_rgba->class_type == BABL_CONVERSION_PLANAR)
1340         {
1341            destination_image = babl_image_from_linear (
1342              destination_float_buf, destination_float_format);
1343              babl_conversion_process (
1344                conv_from_rgba,
1345                (void*)rgba_image, (void*)destination_image,
1346              n);
1347         }
1348         else if (conv_from_rgba->class_type == BABL_CONVERSION_LINEAR)
1349         {
1350           babl_conversion_process (conv_from_rgba, rgba_float_buf,
1351                                    destination_float_buf, n);
1352         }
1353       }
1354     }
1355 
1356     convert_from_float (
1357       (BablFormat *) BABL (babl->fish.source),
1358       (BablFormat *) BABL (babl->fish.destination),
1359       destination_float_buf,
1360       destination,
1361       n
1362     );
1363 
1364     if (destination_float_buf_alloc)
1365       babl_free (destination_float_buf_alloc);
1366     if (rgba_float_buf_alloc)
1367       babl_free (rgba_float_buf_alloc);
1368     if (source_float_buf_alloc)
1369       babl_free (source_float_buf_alloc);
1370     if (source_image)
1371       babl_free (source_image);
1372     if (rgba_image)
1373       babl_free (rgba_image);
1374     if (destination_image)
1375       babl_free (destination_image);
1376 }
1377 
1378 void
babl_fish_reference_process(const Babl * babl,const char * source,char * destination,long n,void * data)1379 babl_fish_reference_process (const Babl *babl,
1380                              const char *source,
1381                              char       *destination,
1382                              long        n,
1383                              void       *data)
1384 {
1385   static const void *type_float = NULL;
1386   static int allow_float_reference = -1;
1387 
1388   if (!type_float) type_float = babl_type_from_id (BABL_FLOAT);
1389 
1390   /* same format in source/destination */
1391   if (BABL (babl->fish.source) == BABL (babl->fish.destination))
1392   {
1393     if (source == destination)
1394     {
1395       memcpy (destination, source, n * babl->fish.source->format.bytes_per_pixel);
1396     }
1397     return;
1398   }
1399 
1400   /* same model and space, only convert type */
1401   if ((BABL (babl->fish.source)->format.model ==
1402        BABL (babl->fish.destination)->format.model) &&
1403       (BABL (babl->fish.source)->format.space ==
1404        BABL (babl->fish.destination)->format.space)
1405       )
1406   {
1407     process_same_model (babl, source, destination, n);
1408     return;
1409   }
1410 
1411   /* we're converting to a n_component format - special case   */
1412   if (babl_format_is_format_n (BABL (babl->fish.destination)))
1413   {
1414     process_to_n_component (babl, source, destination, n);
1415     return;
1416   }
1417 
1418   if (format_has_cmyk_model (babl->fish.source) ||
1419       format_has_cmyk_model (babl->fish.destination))
1420   {
1421     babl_fish_reference_process_double (babl, source, destination, n, data);
1422     return;
1423   }
1424 
1425   if (allow_float_reference == -1)
1426     allow_float_reference = getenv ("BABL_REFERENCE_NOFLOAT") ? 0 : 1;
1427 
1428   /* both source and destination are either single precision float or <32bit component,
1429      we then do a similar to the double reference - using the first registered
1430      float conversions - note that this makes the first registered float conversion of
1431      a given type a reference, and we thus rely on the *first* float conversion regsitered
1432      to be correct, this will be the case if the code paths are duplicated and we register
1433      either a planar or linear conversion to and from "RGBA float" at the same time as
1434      registering conversions for double. When needed conversions do not exist, we defer
1435      to the double code paths
1436    */
1437   if (allow_float_reference &&
1438       (babl->fish.source->format.type[0]->bits < 32 ||
1439       babl->fish.source->format.type[0] == type_float) &&
1440       (babl->fish.destination->format.type[0]->bits < 32 ||
1441       babl->fish.destination->format.type[0] == type_float) &&
1442       !babl_format_is_palette (babl->fish.source) &&
1443       !babl_format_is_palette (babl->fish.destination))
1444   {
1445     babl_fish_reference_process_float (babl, source, destination, n, data);
1446   }
1447   else /*   double  */
1448   {
1449     babl_fish_reference_process_double (babl, source, destination, n, data);
1450   }
1451 
1452 }
1453