Coverage Report

Created: 2026-09-14 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvips/libvips/colour/colour.c
Line
Count
Source
1
/* base class for all colour operations
2
 */
3
4
/*
5
6
  This file is part of VIPS.
7
8
  VIPS is free software; you can redistribute it and/or modify
9
  it under the terms of the GNU Lesser General Public License as published by
10
  the Free Software Foundation; either version 2 of the License, or
11
  (at your option) any later version.
12
13
  This program is distributed in the hope that it will be useful,
14
  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
  GNU Lesser General Public License for more details.
17
18
  You should have received a copy of the GNU Lesser General Public License
19
  along with this program; if not, write to the Free Software
20
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21
  02110-1301  USA
22
23
 */
24
25
/*
26
27
  These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
28
29
 */
30
31
/*
32
#define DEBUG
33
 */
34
35
#ifdef HAVE_CONFIG_H
36
#include <config.h>
37
#endif /*HAVE_CONFIG_H*/
38
#include <glib/gi18n-lib.h>
39
40
#include <stdio.h>
41
#include <stdlib.h>
42
#include <math.h>
43
44
#include <vips/vips.h>
45
#include <vips/internal.h>
46
47
#include "pcolour.h"
48
49
/* Areas under curves for Dxx. 2 degree observer.
50
 */
51
52
/**
53
 * VIPS_D93_X0:
54
 *
55
 * Areas under curves for D93, 2 degree observer.
56
 */
57
58
/**
59
 * VIPS_D75_X0:
60
 *
61
 * Areas under curves for D75, 2 degree observer.
62
 */
63
64
/**
65
 * VIPS_D65_X0:
66
 *
67
 * Areas under curves for D65, 2 degree observer.
68
 */
69
70
/**
71
 * VIPS_D55_X0:
72
 *
73
 * Areas under curves for D55, 2 degree observer.
74
 */
75
76
/**
77
 * VIPS_D50_X0:
78
 *
79
 * Areas under curves for D50, 2 degree observer.
80
 */
81
82
/**
83
 * VIPS_A_X0:
84
 *
85
 * Areas under curves for illuminant A (2856K), 2 degree observer.
86
 */
87
88
/**
89
 * VIPS_B_X0:
90
 *
91
 * Areas under curves for illuminant B (4874K), 2 degree observer.
92
 */
93
94
/**
95
 * VIPS_C_X0:
96
 *
97
 * Areas under curves for illuminant C (6774K), 2 degree observer.
98
 */
99
100
/**
101
 * VIPS_E_X0:
102
 *
103
 * Areas under curves for equal energy illuminant E.
104
 */
105
106
/**
107
 * VIPS_D3250_X0:
108
 *
109
 * Areas under curves for black body at 3250K, 2 degree observer.
110
 */
111
112
200
G_DEFINE_ABSTRACT_TYPE(VipsColour, vips_colour, VIPS_TYPE_OPERATION);
113
200
114
200
/* Maximum number of input images -- why not?
115
200
 */
116
288k
#define MAX_INPUT_IMAGES (64)
117
118
static int
119
vips_colour_gen(VipsRegion *out_region,
120
  void *seq, void *a, void *b, gboolean *stop)
121
296k
{
122
296k
  VipsRegion **ir = (VipsRegion **) seq;
123
296k
  VipsColour *colour = VIPS_COLOUR(b);
124
296k
  VipsColourClass *class = VIPS_COLOUR_GET_CLASS(colour);
125
296k
  VipsRect *r = &out_region->valid;
126
127
296k
  int i, y;
128
296k
  VipsPel *p[MAX_INPUT_IMAGES], *q;
129
130
  /*
131
  printf("vips_colour_gen: %s, "
132
       "left = %d, top = %d, width = %d, height = %d\n",
133
    VIPS_OBJECT_CLASS(class)->nickname,
134
    r->left, r->top, r->width, r->height);
135
  */
136
137
296k
  if (vips_reorder_prepare_many(out_region->im, ir, r))
138
160k
    return -1;
139
140
296k
  VIPS_GATE_START("vips_colour_gen: work");
141
142
4.51M
  for (y = 0; y < r->height; y++) {
143
8.75M
    for (i = 0; ir[i]; i++)
144
4.37M
      p[i] = VIPS_REGION_ADDR(ir[i], r->left, r->top + y);
145
4.37M
    p[i] = NULL;
146
4.37M
    q = VIPS_REGION_ADDR(out_region, r->left, r->top + y);
147
148
4.37M
    class->process_line(colour, q, p, r->width);
149
4.37M
  }
150
151
136k
  VIPS_GATE_STOP("vips_colour_gen: work");
152
153
136k
  VIPS_COUNT_PIXELS(out_region, VIPS_OBJECT_GET_CLASS(colour)->nickname);
154
155
136k
  return 0;
156
296k
}
157
158
static int
159
vips_colour_build(VipsObject *object)
160
288k
{
161
288k
  VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(object);
162
288k
  VipsColour *colour = VIPS_COLOUR(object);
163
164
288k
  VipsImage **in;
165
288k
  VipsImage **extra_bands;
166
288k
  VipsImage *out;
167
168
#ifdef DEBUG
169
  printf("vips_colour_build: ");
170
  vips_object_print_name(object);
171
  printf("\n");
172
#endif /*DEBUG*/
173
174
288k
  if (VIPS_OBJECT_CLASS(vips_colour_parent_class)->build(object))
175
0
    return -1;
176
177
288k
  if (colour->n > MAX_INPUT_IMAGES) {
178
0
    vips_error(class->nickname, "%s", _("too many input images"));
179
0
    return -1;
180
0
  }
181
577k
  for (int i = 0; i < colour->n; i++)
182
288k
    if (vips_image_pio_input(colour->in[i]))
183
0
      return -1;
184
185
  /* colour->in[] must be NULL-terminated, we can use it as an arg to
186
   * vips_start_many().
187
   */
188
288k
  g_assert(!colour->in[colour->n]);
189
190
288k
  in = colour->in;
191
288k
  extra_bands = (VipsImage **) vips_object_local_array(object, colour->n);
192
193
  /* If there are more than @input_bands bands, we detach and reattach
194
   * after processing.
195
   */
196
288k
  if (colour->input_bands > 0) {
197
288k
    VipsImage **new_in = (VipsImage **)
198
288k
      vips_object_local_array(object, colour->n);
199
200
577k
    for (int i = 0; i < colour->n; i++) {
201
288k
      if (vips_check_bands_atleast(class->nickname,
202
288k
          in[i], colour->input_bands))
203
6
        return -1;
204
205
288k
      if (in[i]->Bands > colour->input_bands) {
206
60.0k
        if (vips_extract_band(in[i], &new_in[i], 0,
207
60.0k
            "n", colour->input_bands,
208
60.0k
            NULL))
209
0
          return -1;
210
60.0k
      }
211
228k
      else {
212
228k
        new_in[i] = in[i];
213
228k
        g_object_ref(new_in[i]);
214
228k
      }
215
216
288k
      if (in[i]->Bands > colour->input_bands)
217
60.0k
        if (vips_extract_band(in[i], &extra_bands[i],
218
60.0k
            colour->input_bands,
219
60.0k
            "n", in[i]->Bands - colour->input_bands,
220
60.0k
            NULL))
221
0
          return -1;
222
288k
    }
223
224
288k
    in = new_in;
225
288k
  }
226
227
288k
  out = vips_image_new();
228
288k
  if (vips_image_pipeline_array(out,
229
288k
      VIPS_DEMAND_STYLE_THINSTRIP, in)) {
230
0
    g_object_unref(out);
231
0
    return -1;
232
0
  }
233
288k
  out->Coding = colour->coding;
234
288k
  out->Type = colour->interpretation;
235
288k
  out->BandFmt = colour->format;
236
288k
  out->Bands = colour->bands;
237
238
288k
  if (colour->profile_filename &&
239
633
    vips__profile_set(out, colour->profile_filename))
240
0
    return -1;
241
242
288k
  if (vips_image_generate(out,
243
288k
      vips_start_many, vips_colour_gen, vips_stop_many,
244
288k
      in, colour)) {
245
0
    VIPS_UNREF(out);
246
0
    return -1;
247
0
  }
248
249
  /* Reattach higher bands, if necessary. If we have more than one input
250
   * image, just use the first extra bands.
251
   */
252
517k
  for (int i = 0; i < colour->n; i++)
253
288k
    if (extra_bands[i]) {
254
60.0k
      VipsImage **t = (VipsImage **) vips_object_local_array(object, 3);
255
256
60.0k
      double max_alpha_before =
257
60.0k
        vips_interpretation_max_alpha(extra_bands[i]->Type);
258
60.0k
      double max_alpha_after =
259
60.0k
        vips_interpretation_max_alpha(out->Type);
260
261
60.0k
      VipsImage *alpha;
262
263
60.0k
      alpha = extra_bands[i];
264
265
      /* Rescale, if the alpha scale has changed.
266
       */
267
60.0k
      if (max_alpha_before != max_alpha_after) {
268
36.5k
        if (vips_linear1(alpha, &t[0],
269
36.5k
          max_alpha_after / max_alpha_before, 0.0, NULL)) {
270
0
          VIPS_UNREF(out);
271
0
          return -1;
272
0
        }
273
36.5k
        alpha = t[0];
274
36.5k
      }
275
276
60.0k
      if (vips_cast(alpha, &t[1], out->BandFmt, NULL)) {
277
0
        VIPS_UNREF(out);
278
0
        return -1;
279
0
      }
280
60.0k
      alpha = t[1];
281
282
60.0k
      if (vips_bandjoin2(out, alpha, &t[2], NULL)) {
283
0
        VIPS_UNREF(out);
284
0
        return -1;
285
0
      }
286
60.0k
      g_object_unref(out);
287
60.0k
      out = t[2];
288
60.0k
      t[2] = NULL;
289
290
60.0k
      break;
291
60.0k
    }
292
293
288k
  g_object_set(colour, "out", out, NULL);
294
295
288k
  return 0;
296
288k
}
297
298
static void
299
vips_colour_class_init(VipsColourClass *class)
300
20
{
301
20
  GObjectClass *gobject_class = G_OBJECT_CLASS(class);
302
20
  VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS(class);
303
20
  VipsOperationClass *operation_class = VIPS_OPERATION_CLASS(class);
304
305
20
  gobject_class->set_property = vips_object_set_property;
306
20
  gobject_class->get_property = vips_object_get_property;
307
308
20
  vobject_class->nickname = "colour";
309
20
  vobject_class->description = _("color operations");
310
20
  vobject_class->build = vips_colour_build;
311
312
20
  operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
313
314
20
  VIPS_ARG_IMAGE(class, "out", 100,
315
20
    _("Output"),
316
20
    _("Output image"),
317
20
    VIPS_ARGUMENT_REQUIRED_OUTPUT,
318
20
    G_STRUCT_OFFSET(VipsColour, out));
319
20
}
320
321
static void
322
vips_colour_init(VipsColour *colour)
323
290k
{
324
290k
  colour->coding = VIPS_CODING_NONE;
325
290k
  colour->interpretation = VIPS_INTERPRETATION_sRGB;
326
290k
  colour->format = VIPS_FORMAT_UCHAR;
327
290k
  colour->bands = 3;
328
290k
  colour->input_bands = -1;
329
290k
}
330
331
560
G_DEFINE_ABSTRACT_TYPE(VipsColourTransform, vips_colour_transform,
332
560
  VIPS_TYPE_COLOUR);
333
560
334
560
static int
335
560
vips_colour_transform_build(VipsObject *object)
336
153k
{
337
153k
  VipsColour *colour = VIPS_COLOUR(object);
338
153k
  VipsColourTransform *transform = VIPS_COLOUR_TRANSFORM(object);
339
153k
  VipsImage **t = (VipsImage **) vips_object_local_array(object, 1);
340
341
  /* We only process float.
342
   */
343
153k
  if (transform->in &&
344
153k
    transform->in->BandFmt != VIPS_FORMAT_FLOAT) {
345
2.87k
    if (vips_cast_float(transform->in, &t[0], NULL))
346
0
      return -1;
347
2.87k
  }
348
150k
  else {
349
150k
    t[0] = transform->in;
350
150k
    g_object_ref(t[0]);
351
150k
  }
352
353
  /* We always do 3 bands -> 3 bands.
354
   */
355
153k
  colour->input_bands = 3;
356
357
153k
  colour->n = 1;
358
153k
  colour->in = t;
359
360
153k
  if (VIPS_OBJECT_CLASS(vips_colour_transform_parent_class)->build(object))
361
3
    return -1;
362
363
153k
  return 0;
364
153k
}
365
366
static void
367
vips_colour_transform_class_init(VipsColourTransformClass *class)
368
20
{
369
20
  GObjectClass *gobject_class = G_OBJECT_CLASS(class);
370
20
  VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS(class);
371
372
20
  gobject_class->set_property = vips_object_set_property;
373
20
  gobject_class->get_property = vips_object_get_property;
374
375
20
  vobject_class->nickname = "space";
376
20
  vobject_class->description = _("color space transformations");
377
20
  vobject_class->build = vips_colour_transform_build;
378
379
20
  VIPS_ARG_IMAGE(class, "in", 1,
380
20
    _("Input"),
381
20
    _("Input image"),
382
20
    VIPS_ARGUMENT_REQUIRED_INPUT,
383
20
    G_STRUCT_OFFSET(VipsColourTransform, in));
384
20
}
385
386
static void
387
vips_colour_transform_init(VipsColourTransform *space)
388
154k
{
389
154k
  VipsColour *colour = (VipsColour *) space;
390
391
  /* What we write. interpretation should be overwritten in subclass
392
   * builds.
393
   */
394
154k
  colour->coding = VIPS_CODING_NONE;
395
154k
  colour->interpretation = VIPS_INTERPRETATION_LAB;
396
154k
  colour->format = VIPS_FORMAT_FLOAT;
397
154k
  colour->bands = 3;
398
154k
}
399
400
640
G_DEFINE_ABSTRACT_TYPE(VipsColourCode, vips_colour_code, VIPS_TYPE_COLOUR);
401
640
402
640
static int
403
640
vips_colour_code_build(VipsObject *object)
404
135k
{
405
135k
  VipsColour *colour = VIPS_COLOUR(object);
406
135k
  VipsColourCode *code = VIPS_COLOUR_CODE(object);
407
135k
  VipsColourCodeClass *class = VIPS_COLOUR_CODE_GET_CLASS(object);
408
135k
  VipsImage **t = (VipsImage **) vips_object_local_array(object, 6);
409
410
135k
  VipsImage *in;
411
412
135k
  in = code->in;
413
414
  /* We want labq, rad etc. all decoded (unlike colour_build).
415
   */
416
135k
  if (in &&
417
135k
    code->input_coding == VIPS_CODING_NONE &&
418
133k
    in->Coding != code->input_coding) {
419
13
    if (vips_image_decode(in, &t[0]))
420
0
      return -1;
421
13
    in = t[0];
422
13
  }
423
424
135k
  if (in &&
425
135k
    vips_check_coding(VIPS_OBJECT_CLASS(class)->nickname,
426
135k
      in, code->input_coding))
427
1
    return -1;
428
429
135k
  if (in &&
430
135k
    code->input_coding == VIPS_CODING_NONE &&
431
133k
    code->input_format != VIPS_FORMAT_NOTSET &&
432
133k
    in->BandFmt != code->input_format) {
433
6.77k
    if (vips_cast(in, &t[3], code->input_format, NULL))
434
0
      return -1;
435
6.77k
    in = t[3];
436
6.77k
  }
437
438
135k
  if (in &&
439
135k
    code->input_coding == VIPS_CODING_NONE &&
440
133k
    code->input_interpretation != VIPS_INTERPRETATION_ERROR &&
441
5.31k
    in->Type != code->input_interpretation) {
442
67
    if (vips_colourspace(in, &t[4],
443
67
        code->input_interpretation, NULL))
444
0
      return -1;
445
67
    in = t[4];
446
67
  }
447
448
135k
  colour->n = 1;
449
135k
  colour->in = VIPS_ARRAY(object, 2, VipsImage *);
450
135k
  colour->in[0] = in;
451
135k
  colour->in[1] = NULL;
452
453
135k
  if (VIPS_OBJECT_CLASS(vips_colour_code_parent_class)->build(object))
454
3
    return -1;
455
456
135k
  return 0;
457
135k
}
458
459
static void
460
vips_colour_code_class_init(VipsColourCodeClass *class)
461
20
{
462
20
  GObjectClass *gobject_class = G_OBJECT_CLASS(class);
463
20
  VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS(class);
464
465
20
  gobject_class->set_property = vips_object_set_property;
466
20
  gobject_class->get_property = vips_object_get_property;
467
468
20
  vobject_class->nickname = "code";
469
20
  vobject_class->description = _("change color coding");
470
20
  vobject_class->build = vips_colour_code_build;
471
472
20
  VIPS_ARG_IMAGE(class, "in", 1,
473
20
    _("Input"),
474
20
    _("Input image"),
475
20
    VIPS_ARGUMENT_REQUIRED_INPUT,
476
20
    G_STRUCT_OFFSET(VipsColourCode, in));
477
20
}
478
479
static void
480
vips_colour_code_init(VipsColourCode *code)
481
135k
{
482
135k
  code->input_coding = VIPS_CODING_NONE;
483
135k
  code->input_interpretation = VIPS_INTERPRETATION_ERROR;
484
135k
  code->input_format = VIPS_FORMAT_NOTSET;
485
135k
}
486
487
120
G_DEFINE_ABSTRACT_TYPE(VipsColourDifference, vips_colour_difference,
488
120
  VIPS_TYPE_COLOUR);
489
120
490
120
static int
491
120
vips_colour_difference_build(VipsObject *object)
492
120
{
493
69
  VipsColour *colour = VIPS_COLOUR(object);
494
69
  VipsColourDifference *difference = VIPS_COLOUR_DIFFERENCE(object);
495
496
69
  VipsImage **t;
497
69
  VipsImage *left;
498
69
  VipsImage *right;
499
500
69
  t = (VipsImage **) vips_object_local_array(object, 12);
501
502
69
  left = difference->left;
503
69
  right = difference->right;
504
505
69
  if (left) {
506
69
    if (vips_image_decode(left, &t[0]))
507
0
      return -1;
508
69
    left = t[0];
509
69
  }
510
511
69
  if (right) {
512
69
    if (vips_image_decode(right, &t[1]))
513
0
      return -1;
514
69
    right = t[1];
515
69
  }
516
517
  /* Detach and reattach any extra bands.
518
   */
519
69
  colour->input_bands = 3;
520
521
69
  if (left &&
522
69
    left->Type != difference->interpretation) {
523
68
    if (vips_colourspace(left, &t[6],
524
68
        difference->interpretation, NULL))
525
0
      return -1;
526
68
    left = t[6];
527
68
  }
528
529
69
  if (right &&
530
69
    right->Type != difference->interpretation) {
531
68
    if (vips_colourspace(right, &t[7],
532
68
        difference->interpretation, NULL))
533
0
      return -1;
534
68
    right = t[7];
535
68
  }
536
537
  /* We only process float.
538
   */
539
69
  if (left &&
540
69
    left->BandFmt != VIPS_FORMAT_FLOAT) {
541
0
    if (vips_cast_float(left, &t[8], NULL))
542
0
      return -1;
543
0
    left = t[8];
544
0
  }
545
546
69
  if (right &&
547
69
    right->BandFmt != VIPS_FORMAT_FLOAT) {
548
0
    if (vips_cast_float(right, &t[9], NULL))
549
0
      return -1;
550
0
    right = t[9];
551
0
  }
552
553
69
  if (vips__sizealike(left, right, &t[10], &t[11]))
554
0
    return -1;
555
69
  left = t[10];
556
69
  right = t[11];
557
558
69
  colour->n = 2;
559
69
  colour->in = VIPS_ARRAY(object, 3, VipsImage *);
560
69
  colour->in[0] = left;
561
69
  colour->in[1] = right;
562
69
  colour->in[2] = NULL;
563
564
69
  return VIPS_OBJECT_CLASS(vips_colour_difference_parent_class)->
565
69
    build(object);
566
69
}
567
568
static void
569
vips_colour_difference_class_init(VipsColourDifferenceClass *class)
570
20
{
571
20
  GObjectClass *gobject_class = G_OBJECT_CLASS(class);
572
20
  VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS(class);
573
574
20
  gobject_class->set_property = vips_object_set_property;
575
20
  gobject_class->get_property = vips_object_get_property;
576
577
20
  vobject_class->nickname = "difference";
578
20
  vobject_class->description = _("calculate color difference");
579
20
  vobject_class->build = vips_colour_difference_build;
580
581
20
  VIPS_ARG_IMAGE(class, "left", 1,
582
20
    _("Left"),
583
20
    _("Left-hand input image"),
584
20
    VIPS_ARGUMENT_REQUIRED_INPUT,
585
20
    G_STRUCT_OFFSET(VipsColourDifference, left));
586
587
20
  VIPS_ARG_IMAGE(class, "right", 2,
588
20
    _("Right"),
589
20
    _("Right-hand input image"),
590
20
    VIPS_ARGUMENT_REQUIRED_INPUT,
591
20
    G_STRUCT_OFFSET(VipsColourDifference, right));
592
20
}
593
594
static void
595
vips_colour_difference_init(VipsColourDifference *difference)
596
91
{
597
91
  VipsColour *colour = VIPS_COLOUR(difference);
598
599
91
  colour->coding = VIPS_CODING_NONE;
600
91
  colour->interpretation = VIPS_INTERPRETATION_B_W;
601
91
  colour->format = VIPS_FORMAT_FLOAT;
602
91
  colour->bands = 1;
603
91
}
604
605
/* Called from iofuncs to init all operations in this dir. Use a plugin system
606
 * instead?
607
 */
608
void
609
vips_colour_operation_init(void)
610
40
{
611
40
  extern GType vips_colourspace_get_type(void);
612
40
  extern GType vips_Lab2XYZ_get_type(void);
613
40
  extern GType vips_XYZ2Lab_get_type(void);
614
40
  extern GType vips_Lab2LCh_get_type(void);
615
40
  extern GType vips_LCh2Lab_get_type(void);
616
40
  extern GType vips_LCh2CMC_get_type(void);
617
40
  extern GType vips_CMC2LCh_get_type(void);
618
40
  extern GType vips_Yxy2XYZ_get_type(void);
619
40
  extern GType vips_XYZ2Yxy_get_type(void);
620
40
  extern GType vips_LabQ2Lab_get_type(void);
621
40
  extern GType vips_Lab2LabQ_get_type(void);
622
40
  extern GType vips_LabQ2LabS_get_type(void);
623
40
  extern GType vips_LabS2LabQ_get_type(void);
624
40
  extern GType vips_LabS2Lab_get_type(void);
625
40
  extern GType vips_Lab2LabS_get_type(void);
626
40
  extern GType vips_rad2float_get_type(void);
627
40
  extern GType vips_float2rad_get_type(void);
628
40
  extern GType vips_LabQ2sRGB_get_type(void);
629
40
  extern GType vips_XYZ2sRGB_get_type(void);
630
40
  extern GType vips_sRGB2scRGB_get_type(void);
631
40
  extern GType vips_sRGB2HSV_get_type(void);
632
40
  extern GType vips_HSV2sRGB_get_type(void);
633
40
  extern GType vips_scRGB2XYZ_get_type(void);
634
40
  extern GType vips_scRGB2BW_get_type(void);
635
40
  extern GType vips_XYZ2scRGB_get_type(void);
636
40
  extern GType vips_scRGB2sRGB_get_type(void);
637
40
  extern GType vips_CMYK2XYZ_get_type(void);
638
40
  extern GType vips_XYZ2CMYK_get_type(void);
639
40
  extern GType vips_XYZ2Oklab_get_type(void);
640
40
  extern GType vips_Oklab2XYZ_get_type(void);
641
40
  extern GType vips_Oklab2Oklch_get_type(void);
642
40
  extern GType vips_Oklch2Oklab_get_type(void);
643
40
  extern GType vips_uhdr2scRGB_get_type(void);
644
40
  extern GType vips_CICP2scRGB_get_type(void);
645
40
  extern GType vips_scRGB2CICP_get_type(void);
646
40
  extern GType vips_profile_load_get_type(void);
647
40
#ifdef HAVE_LCMS2
648
40
  extern GType vips_icc_import_get_type(void);
649
40
  extern GType vips_icc_export_get_type(void);
650
40
  extern GType vips_icc_transform_get_type(void);
651
40
#endif
652
40
  extern GType vips_dE76_get_type(void);
653
40
  extern GType vips_dE00_get_type(void);
654
40
  extern GType vips_dECMC_get_type(void);
655
656
40
  vips_colourspace_get_type();
657
40
  vips_Oklab2Oklch_get_type();
658
40
  vips_Oklch2Oklab_get_type();
659
40
  vips_Oklab2XYZ_get_type();
660
40
  vips_XYZ2Oklab_get_type();
661
40
  vips_Lab2XYZ_get_type();
662
40
  vips_XYZ2Lab_get_type();
663
40
  vips_Lab2LCh_get_type();
664
40
  vips_LCh2Lab_get_type();
665
40
  vips_LCh2CMC_get_type();
666
40
  vips_CMC2LCh_get_type();
667
40
  vips_XYZ2Yxy_get_type();
668
40
  vips_Yxy2XYZ_get_type();
669
40
  vips_LabQ2Lab_get_type();
670
40
  vips_Lab2LabQ_get_type();
671
40
  vips_LabQ2LabS_get_type();
672
40
  vips_LabS2LabQ_get_type();
673
40
  vips_LabS2Lab_get_type();
674
40
  vips_Lab2LabS_get_type();
675
40
  vips_rad2float_get_type();
676
40
  vips_float2rad_get_type();
677
40
  vips_LabQ2sRGB_get_type();
678
40
  vips_sRGB2scRGB_get_type();
679
40
  vips_scRGB2XYZ_get_type();
680
40
  vips_scRGB2BW_get_type();
681
40
  vips_sRGB2HSV_get_type();
682
40
  vips_HSV2sRGB_get_type();
683
40
  vips_XYZ2scRGB_get_type();
684
40
  vips_scRGB2sRGB_get_type();
685
40
  vips_CMYK2XYZ_get_type();
686
40
  vips_XYZ2CMYK_get_type();
687
40
  vips_uhdr2scRGB_get_type();
688
40
  vips_CICP2scRGB_get_type();
689
40
  vips_scRGB2CICP_get_type();
690
40
  vips_profile_load_get_type();
691
40
#ifdef HAVE_LCMS2
692
40
  vips_icc_import_get_type();
693
40
  vips_icc_export_get_type();
694
40
  vips_icc_transform_get_type();
695
40
#endif
696
40
  vips_dE76_get_type();
697
40
  vips_dE00_get_type();
698
40
  vips_dECMC_get_type();
699
40
}