Coverage Report

Created: 2025-01-28 06:33

/src/libvips/libvips/conversion/composite.cpp
Line
Count
Source (jump to first uncovered line)
1
/* composite an array of images with PDF operators
2
 *
3
 * 25/9/17
4
 *  - from bandjoin.c
5
 * 30/11/17
6
 *  - add composite2 class, to make a nice CLI interface
7
 * 30/1/18
8
 *  - remove number of images limit
9
 *  - allow one mode ... reused for all joins
10
 * 11/8/18 [medakk]
11
 *  - x/y params let you position images
12
 * 27/11/18
13
 *  - don't stop on first non-transparent image [felixbuenemann, GDmac]
14
 * 6/12/18
15
 *  - do our own subimage positioning
16
 * 8/5/19
17
 *  - revise in/out/dest-in/dest-out to make smoother alpha
18
 */
19
20
/*
21
22
  This file is part of VIPS.
23
24
  VIPS is free software; you can redistribute it and/or modify
25
  it under the terms of the GNU Lesser General Public License as published by
26
  the Free Software Foundation; either version 2 of the License, or
27
  (at your option) any later version.
28
29
  This program is distributed in the hope that it will be useful,
30
  but WITHOUT ANY WARRANTY; without even the implied warranty of
31
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32
  GNU Lesser General Public License for more details.
33
34
  You should have received a copy of the GNU Lesser General Public License
35
  along with this program; if not, write to the Free Software
36
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
37
  02110-1301  USA
38
39
 */
40
41
/*
42
43
  These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
44
45
 */
46
47
/*
48
#define VIPS_DEBUG
49
 */
50
51
#ifdef HAVE_CONFIG_H
52
#include <config.h>
53
#endif /*HAVE_CONFIG_H*/
54
#include <glib/gi18n-lib.h>
55
56
#include <stdio.h>
57
#include <string.h>
58
#ifdef _MSC_VER
59
#include <cstdlib>
60
#else
61
#include <stdlib.h>
62
#endif
63
#include <math.h>
64
65
#if defined(HAVE__ALIGNED_MALLOC) || defined(HAVE_MEMALIGN)
66
#include <malloc.h>
67
#endif
68
69
#include <vips/vips.h>
70
#include <vips/internal.h>
71
#include <vips/debug.h>
72
73
#include "pconversion.h"
74
75
/* Maximum number of image bands.
76
 */
77
0
#define MAX_BANDS (64)
78
79
/* Uncomment to disable the vector path ... handy for debugging.
80
#undef HAVE_VECTOR_ARITH
81
 */
82
83
/* We have a vector path with gcc's vector attr.
84
 */
85
#ifdef HAVE_VECTOR_ARITH
86
/* A vector of four floats.
87
 */
88
typedef float v4f __attribute__((vector_size(4 * sizeof(float)), aligned(16)));
89
#endif /*HAVE_VECTOR_ARITH*/
90
91
typedef struct _VipsCompositeBase {
92
  VipsConversion parent_instance;
93
94
  /* The input images.
95
   */
96
  VipsArrayImage *in;
97
98
  /* For N input images, 1 blend mode or N - 1 blend modes.
99
   */
100
  VipsArrayInt *mode;
101
102
  /* Compositing space. This defaults to RGB, or B_W if we only have
103
   * G and GA inputs.
104
   */
105
  VipsInterpretation compositing_space;
106
107
  /* Set if the input images have already been premultiplied.
108
   */
109
  gboolean premultiplied;
110
111
  /* The x and y positions for each image in the stack. There are n - 1
112
   * of these, since image 0 is always positioned at (0, 0). Set by
113
   * subclasses. Can be NULL.
114
   */
115
  int *x_offset;
116
  int *y_offset;
117
118
  /* A rect for the position of each input image. For each output region,
119
   * we composite the set of input images which intersect that area.
120
   */
121
  VipsRect *subimages;
122
123
  /* The number of non-alpha bands we are blending.
124
   */
125
  int bands;
126
127
  /* The maximum value for each band, set from the image interpretation.
128
   * This is used to scale each band to 0 - 1.
129
   */
130
  double max_band[MAX_BANDS + 1];
131
132
  /* TRUE if all our modes are skippable, ie. we can avoid compositing
133
   * the whole stack for every pixel request.
134
   */
135
  gboolean skippable;
136
137
} VipsCompositeBase;
138
139
typedef VipsConversionClass VipsCompositeBaseClass;
140
141
/* We need C linkage for this.
142
 */
143
extern "C" {
144
G_DEFINE_ABSTRACT_TYPE(VipsCompositeBase, vips_composite_base,
145
  VIPS_TYPE_CONVERSION);
146
}
147
148
static void
149
vips_composite_base_dispose(GObject *gobject)
150
0
{
151
0
  VipsCompositeBase *composite = (VipsCompositeBase *) gobject;
152
153
0
  if (composite->in) {
154
0
    vips_area_unref((VipsArea *) composite->in);
155
0
    composite->in = NULL;
156
0
  }
157
0
  if (composite->mode) {
158
0
    vips_area_unref((VipsArea *) composite->mode);
159
0
    composite->mode = NULL;
160
0
  }
161
0
  VIPS_FREE(composite->subimages);
162
163
0
  G_OBJECT_CLASS(vips_composite_base_parent_class)->dispose(gobject);
164
0
}
165
166
/* Our sequence value.
167
 */
168
typedef struct {
169
#ifdef HAVE_VECTOR_ARITH
170
  /* max_band as a vector, for the RGBA case. This must be
171
   * defined first to ensure that the member is aligned
172
   * on a 16-byte boundary.
173
   */
174
  v4f max_band_vec;
175
#endif /*HAVE_VECTOR_ARITH*/
176
177
  VipsCompositeBase *composite;
178
179
  /* Full set of input regions, each made on the corresponding input
180
   * image.
181
   */
182
  VipsRegion **input_regions;
183
184
  /* We then vips_region_prepare_to() to one of this set of regions,
185
   * each defined on the base image.
186
   */
187
  VipsRegion **composite_regions;
188
189
  /* Number of input regions which intersect this request rect.
190
   */
191
  int n;
192
193
  /* For each of @n above (inputs which intersect this request), the
194
   * index of the input image we need. We can use this index to get the
195
   * position, input region and composite region.
196
   */
197
  int *enabled;
198
199
  /* For each enabled image, an input pointer.
200
   */
201
  VipsPel **p;
202
203
} VipsCompositeSequence;
204
205
#ifdef HAVE_VECTOR_ARITH
206
/* Allocate aligned memory. The return value can be released
207
 * by calling the vips_free_aligned() function, for example:
208
 * VIPS_FREEF(vips_free_aligned, ptr);
209
 */
210
static inline void *
211
vips_alloc_aligned(size_t sz, size_t align)
212
0
{
213
0
  g_assert(!(align & (align - 1)));
214
215
#ifdef HAVE__ALIGNED_MALLOC
216
  return _aligned_malloc(sz, align);
217
#elif defined(HAVE_POSIX_MEMALIGN)
218
  void *ptr;
219
0
  if (posix_memalign(&ptr, align, sz))
220
0
    return NULL;
221
0
  return ptr;
222
#elif defined(HAVE_MEMALIGN)
223
  return memalign(align, sz);
224
#else
225
#error Missing aligned alloc implementation
226
#endif
227
0
}
228
229
static inline void
230
vips_free_aligned(void *ptr)
231
0
{
232
#ifdef HAVE__ALIGNED_MALLOC
233
  _aligned_free(ptr);
234
#else /*defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN)*/
235
0
  free(ptr);
236
0
#endif
237
0
}
238
#endif /*HAVE_VECTOR_ARITH*/
239
240
static int
241
vips_composite_stop(void *vseq, void *a, void *b)
242
0
{
243
0
  VipsCompositeSequence *seq = (VipsCompositeSequence *) vseq;
244
245
0
  if (seq->input_regions) {
246
0
    for (int i = 0; seq->input_regions[i]; i++)
247
0
      VIPS_UNREF(seq->input_regions[i]);
248
0
    VIPS_FREE(seq->input_regions);
249
0
  }
250
251
0
  if (seq->composite_regions) {
252
0
    for (int i = 0; seq->composite_regions[i]; i++)
253
0
      VIPS_UNREF(seq->composite_regions[i]);
254
0
    VIPS_FREE(seq->composite_regions);
255
0
  }
256
257
0
  VIPS_FREE(seq->enabled);
258
0
  VIPS_FREE(seq->p);
259
260
0
#ifdef HAVE_VECTOR_ARITH
261
0
  VIPS_FREEF(vips_free_aligned, seq);
262
#else  /*!defined(HAVE_VECTOR_ARITH)*/
263
  VIPS_FREE(seq);
264
#endif /*HAVE_VECTOR_ARITH*/
265
266
0
  return 0;
267
0
}
268
269
static void *
270
vips_composite_start(VipsImage *out, void *a, void *b)
271
0
{
272
0
  VipsImage **in = (VipsImage **) a;
273
0
  VipsCompositeBase *composite = (VipsCompositeBase *) b;
274
275
0
  VipsCompositeSequence *seq;
276
0
  int i, n;
277
278
0
#ifdef HAVE_VECTOR_ARITH
279
  /* Ensure that the memory is aligned on a 16-byte boundary.
280
   */
281
0
  if (!(seq = ((VipsCompositeSequence *) vips_alloc_aligned(
282
0
        sizeof(VipsCompositeSequence), 16))))
283
#else  /*!defined(HAVE_VECTOR_ARITH)*/
284
  if (!(seq = VIPS_NEW(NULL, VipsCompositeSequence)))
285
#endif /*HAVE_VECTOR_ARITH*/
286
0
    return NULL;
287
288
0
  seq->composite = composite;
289
0
  seq->input_regions = NULL;
290
0
  seq->enabled = NULL;
291
0
  seq->p = NULL;
292
293
  /* How many images?
294
   */
295
0
  for (n = 0; in[n]; n++)
296
0
    ;
297
298
  /* Allocate space for region array.
299
   */
300
0
  if (!(seq->input_regions = VIPS_ARRAY(NULL, n + 1, VipsRegion *))) {
301
0
    vips_composite_stop(seq, NULL, NULL);
302
0
    return NULL;
303
0
  }
304
0
  for (i = 0; i < n + 1; i++)
305
0
    seq->input_regions[i] = NULL;
306
307
0
  if (!(seq->composite_regions =
308
0
        VIPS_ARRAY(NULL, n + 1, VipsRegion *))) {
309
0
    vips_composite_stop(seq, NULL, NULL);
310
0
    return NULL;
311
0
  }
312
0
  for (i = 0; i < n + 1; i++)
313
0
    seq->composite_regions[i] = NULL;
314
315
0
  seq->enabled = VIPS_ARRAY(NULL, n, int);
316
0
  seq->p = VIPS_ARRAY(NULL, n, VipsPel *);
317
0
  if (!seq->enabled ||
318
0
    !seq->p) {
319
0
    vips_composite_stop(seq, NULL, NULL);
320
0
    return NULL;
321
0
  }
322
323
  /* Create a set of regions.
324
   */
325
0
  for (i = 0; i < n; i++) {
326
0
    seq->input_regions[i] = vips_region_new(in[i]);
327
0
    seq->composite_regions[i] = vips_region_new(in[0]);
328
329
0
    if (!seq->input_regions[i] ||
330
0
      !seq->composite_regions[i]) {
331
0
      vips_composite_stop(seq, NULL, NULL);
332
0
      return NULL;
333
0
    }
334
0
  }
335
336
0
#ifdef HAVE_VECTOR_ARITH
337
  /* We need a float version for the vector path.
338
   */
339
0
  if (composite->bands == 3)
340
0
    seq->max_band_vec = (v4f){
341
0
      (float) composite->max_band[0],
342
0
      (float) composite->max_band[1],
343
0
      (float) composite->max_band[2],
344
0
      (float) composite->max_band[3]
345
0
    };
346
0
#endif
347
348
0
  return seq;
349
0
}
350
351
/* For each of the supported interpretations, the maximum value of each band.
352
 */
353
static int
354
vips_composite_base_max_band(VipsCompositeBase *composite, double *max_band)
355
0
{
356
0
  double max_alpha;
357
0
  int b;
358
359
0
  max_alpha = vips_interpretation_max_alpha(composite->compositing_space);
360
361
0
  for (b = 0; b <= composite->bands; b++)
362
0
    max_band[b] = max_alpha;
363
364
0
  switch (composite->compositing_space) {
365
0
  case VIPS_INTERPRETATION_XYZ:
366
0
    max_band[0] = VIPS_D65_X0;
367
0
    max_band[1] = VIPS_D65_Y0;
368
0
    max_band[2] = VIPS_D65_Z0;
369
0
    break;
370
371
0
  case VIPS_INTERPRETATION_LAB:
372
0
    max_band[0] = 100;
373
0
    max_band[1] = 128;
374
0
    max_band[2] = 128;
375
0
    break;
376
377
0
  case VIPS_INTERPRETATION_LCH:
378
0
    max_band[0] = 100;
379
0
    max_band[1] = 128;
380
0
    max_band[2] = 360;
381
0
    break;
382
383
0
  case VIPS_INTERPRETATION_CMC:
384
0
    max_band[0] = 100;
385
0
    max_band[1] = 128;
386
0
    max_band[2] = 360;
387
0
    break;
388
389
0
  case VIPS_INTERPRETATION_scRGB:
390
0
    max_band[0] = 1;
391
0
    max_band[1] = 1;
392
0
    max_band[2] = 1;
393
0
    break;
394
395
0
  case VIPS_INTERPRETATION_sRGB:
396
0
    max_band[0] = 255;
397
0
    max_band[1] = 255;
398
0
    max_band[2] = 255;
399
0
    break;
400
401
0
  case VIPS_INTERPRETATION_HSV:
402
0
    max_band[0] = 255;
403
0
    max_band[1] = 255;
404
0
    max_band[2] = 255;
405
0
    break;
406
407
0
  case VIPS_INTERPRETATION_CMYK:
408
0
    max_band[0] = 255;
409
0
    max_band[1] = 255;
410
0
    max_band[2] = 255;
411
0
    max_band[3] = 255;
412
0
    break;
413
414
0
  case VIPS_INTERPRETATION_RGB16:
415
0
    max_band[0] = 65535;
416
0
    max_band[1] = 65535;
417
0
    max_band[2] = 65535;
418
0
    break;
419
420
0
  case VIPS_INTERPRETATION_GREY16:
421
0
    max_band[0] = 65535;
422
0
    break;
423
424
0
  case VIPS_INTERPRETATION_YXY:
425
0
    max_band[0] = 100;
426
0
    max_band[1] = 1;
427
0
    max_band[2] = 1;
428
0
    break;
429
430
0
  case VIPS_INTERPRETATION_B_W:
431
0
    max_band[0] = 255;
432
0
    break;
433
434
0
  default:
435
0
    return -1;
436
0
  }
437
438
0
  return 0;
439
0
}
440
441
/* Find the subset of our input images which intersect this region. If we are
442
 * not in skippable mode, we must enable all layers.
443
 */
444
static void
445
vips_composite_base_select(VipsCompositeSequence *seq, VipsRect *r)
446
0
{
447
0
  VipsCompositeBase *composite = seq->composite;
448
0
  int n = composite->in->area.n;
449
450
0
  seq->n = 0;
451
0
  for (int i = 0; i < n; i++)
452
0
    if (!composite->skippable ||
453
0
      vips_rect_overlapsrect(r,
454
0
        &composite->subimages[i])) {
455
0
      seq->enabled[seq->n] = i;
456
0
      seq->n += 1;
457
0
    }
458
0
}
459
460
/* Cairo naming conventions:
461
 *
462
 * aR alpha of result
463
 * aA alpha of source A (the new pixel)
464
 * aB alpha of source B (the thing we accumulate)
465
 * xR colour band of result
466
 * xA colour band of source A
467
 * xB colour band of source B
468
 */
469
470
/* A is the new pixel coming in, of any non-complex type T.
471
 *
472
 * We must scale incoming pixels to 0 - 1 by dividing by the scale[] vector.
473
 *
474
 * If premultipled is not set, we premultiply incoming pixels before blending.
475
 *
476
 * B is the double pixel we are accumulating.
477
 */
478
template <typename T>
479
static void
480
vips_composite_base_blend(VipsCompositeBase *composite,
481
  VipsBlendMode mode, double *restrict B, T *restrict p)
482
0
{
483
0
  const int bands = composite->bands;
484
485
0
  double A[MAX_BANDS + 1];
486
0
  double aA;
487
0
  double aB;
488
0
  double aR;
489
0
  double t1;
490
0
  double t2;
491
0
  double t3;
492
0
  double f[MAX_BANDS + 1];
493
494
  /* Load and scale the pixel to 0 - 1.
495
   */
496
0
  for (int b = 0; b <= bands; b++)
497
0
    A[b] = p[b] / composite->max_band[b];
498
  /* Not necessary, but it stops a compiler warning.
499
   */
500
0
  for (int b = bands + 1; b < MAX_BANDS + 1; b++)
501
0
    A[b] = 0.0;
502
503
0
  aA = A[bands];
504
0
  aB = B[bands];
505
506
  /* We may need to premultiply A.
507
   */
508
0
  if (!composite->premultiplied)
509
0
    for (int b = 0; b < bands; b++)
510
0
      A[b] *= aA;
511
512
0
  switch (mode) {
513
0
  case VIPS_BLEND_MODE_CLEAR:
514
0
    aR = 0;
515
0
    for (int b = 0; b < bands; b++)
516
0
      B[b] = 0;
517
0
    break;
518
519
0
  case VIPS_BLEND_MODE_SOURCE:
520
0
    aR = aA;
521
0
    for (int b = 0; b < bands; b++)
522
0
      B[b] = A[b];
523
0
    break;
524
525
0
  case VIPS_BLEND_MODE_OVER:
526
0
    aR = aA + aB * (1 - aA);
527
0
    t1 = 1 - aA;
528
0
    for (int b = 0; b < bands; b++)
529
0
      B[b] = A[b] + t1 * B[b];
530
0
    break;
531
532
0
  case VIPS_BLEND_MODE_IN:
533
0
    aR = aA * aB;
534
    // if aA == 0, then aR == 0 and so B will already be 0
535
0
    if (aA != 0)
536
0
      for (int b = 0; b < bands; b++)
537
0
        B[b] = A[b] * aR / aA;
538
0
    break;
539
540
0
  case VIPS_BLEND_MODE_OUT:
541
0
    aR = aA * (1 - aB);
542
    // if aA == 0, then aR == 0 and so B will already be 0
543
0
    if (aA != 0)
544
0
      for (int b = 0; b < bands; b++)
545
0
        B[b] = A[b] * aR / aA;
546
0
    break;
547
548
0
  case VIPS_BLEND_MODE_ATOP:
549
0
    aR = aB;
550
0
    t1 = 1 - aA;
551
0
    for (int b = 0; b < bands; b++)
552
0
      B[b] = A[b] + t1 * B[b];
553
0
    break;
554
555
0
  case VIPS_BLEND_MODE_DEST:
556
0
    aR = aB;
557
    // B = B
558
0
    break;
559
560
0
  case VIPS_BLEND_MODE_DEST_OVER:
561
0
    aR = aB + aA * (1 - aB);
562
0
    t1 = 1 - aB;
563
0
    for (int b = 0; b < bands; b++)
564
0
      B[b] = B[b] + t1 * A[b];
565
0
    break;
566
567
0
  case VIPS_BLEND_MODE_DEST_IN:
568
0
    aR = aA * aB;
569
    // B = B
570
0
    if (aB != 0)
571
0
      for (int b = 0; b < bands; b++)
572
0
        B[b] *= aR / aB;
573
0
    break;
574
575
0
  case VIPS_BLEND_MODE_DEST_OUT:
576
0
    aR = (1 - aA) * aB;
577
    // B = B
578
    // if aB is 0, then B is already 0
579
0
    if (aB != 0)
580
0
      for (int b = 0; b < bands; b++)
581
0
        B[b] *= aR / aB;
582
0
    break;
583
584
0
  case VIPS_BLEND_MODE_DEST_ATOP:
585
0
    aR = aA;
586
0
    t1 = 1 - aB;
587
0
    for (int b = 0; b < bands; b++)
588
0
      B[b] = t1 * A[b] + B[b];
589
0
    break;
590
591
0
  case VIPS_BLEND_MODE_XOR:
592
0
    aR = aA + aB - 2 * aA * aB;
593
0
    t1 = 1 - aB;
594
0
    t2 = 1 - aA;
595
0
    for (int b = 0; b < bands; b++)
596
0
      B[b] = t1 * A[b] + t2 * B[b];
597
0
    break;
598
599
0
  case VIPS_BLEND_MODE_ADD:
600
0
    aR = VIPS_MIN(1, aA + aB);
601
0
    for (int b = 0; b < bands; b++)
602
0
      B[b] = A[b] + B[b];
603
0
    break;
604
605
0
  case VIPS_BLEND_MODE_SATURATE:
606
0
    aR = VIPS_MIN(1, aA + aB);
607
0
    t1 = VIPS_MIN(aA, 1 - aB);
608
0
    for (int b = 0; b < bands; b++)
609
0
      B[b] = t1 * A[b] + B[b];
610
0
    break;
611
612
0
  default:
613
    /* The PDF modes are a bit different.
614
     */
615
0
    aR = aA + aB * (1 - aA);
616
617
0
    switch (mode) {
618
0
    case VIPS_BLEND_MODE_MULTIPLY:
619
0
      for (int b = 0; b < bands; b++)
620
0
        f[b] = A[b] * B[b];
621
0
      break;
622
623
0
    case VIPS_BLEND_MODE_SCREEN:
624
0
      for (int b = 0; b < bands; b++)
625
0
        f[b] = A[b] + B[b] - A[b] * B[b];
626
0
      break;
627
628
0
    case VIPS_BLEND_MODE_OVERLAY:
629
0
      for (int b = 0; b < bands; b++)
630
0
        if (B[b] <= 0.5)
631
0
          f[b] = 2 * A[b] * B[b];
632
0
        else
633
0
          f[b] = 1 - 2 * (1 - A[b]) * (1 - B[b]);
634
0
      break;
635
636
0
    case VIPS_BLEND_MODE_DARKEN:
637
0
      for (int b = 0; b < bands; b++)
638
0
        f[b] = VIPS_MIN(A[b], B[b]);
639
0
      break;
640
641
0
    case VIPS_BLEND_MODE_LIGHTEN:
642
0
      for (int b = 0; b < bands; b++)
643
0
        f[b] = VIPS_MAX(A[b], B[b]);
644
0
      break;
645
646
0
    case VIPS_BLEND_MODE_COLOUR_DODGE:
647
0
      for (int b = 0; b < bands; b++)
648
0
        if (A[b] < 1)
649
0
          f[b] = VIPS_MIN(1, B[b] / (1 - A[b]));
650
0
        else
651
0
          f[b] = 1;
652
0
      break;
653
654
0
    case VIPS_BLEND_MODE_COLOUR_BURN:
655
0
      for (int b = 0; b < bands; b++)
656
0
        if (A[b] > 0)
657
0
          f[b] = 1 - VIPS_MIN(1, (1 - B[b]) / A[b]);
658
0
        else
659
0
          f[b] = 0;
660
0
      break;
661
662
0
    case VIPS_BLEND_MODE_HARD_LIGHT:
663
0
      for (int b = 0; b < bands; b++)
664
0
        if (A[b] <= 0.5)
665
0
          f[b] = 2 * A[b] * B[b];
666
0
        else
667
0
          f[b] = 1 - 2 * (1 - A[b]) * (1 - B[b]);
668
0
      break;
669
670
0
    case VIPS_BLEND_MODE_SOFT_LIGHT:
671
0
      for (int b = 0; b < bands; b++) {
672
0
        double g;
673
674
0
        if (B[b] <= 0.25)
675
0
          g = ((16 * B[b] - 12) * B[b] + 4) * B[b];
676
0
        else
677
0
          g = sqrt(B[b]);
678
679
0
        if (A[b] <= 0.5)
680
0
          f[b] = B[b] - (1 - 2 * A[b]) * B[b] * (1 - B[b]);
681
0
        else
682
0
          f[b] = B[b] + (2 * A[b] - 1) * (g - B[b]);
683
0
      }
684
0
      break;
685
686
0
    case VIPS_BLEND_MODE_DIFFERENCE:
687
0
      for (int b = 0; b < bands; b++)
688
0
        f[b] = fabs(B[b] - A[b]);
689
0
      break;
690
691
0
    case VIPS_BLEND_MODE_EXCLUSION:
692
0
      for (int b = 0; b < bands; b++)
693
0
        f[b] = A[b] + B[b] - 2 * A[b] * B[b];
694
0
      break;
695
696
0
    default:
697
0
      g_assert_not_reached();
698
0
      for (int b = 0; b < bands; b++)
699
0
        B[b] = 0;
700
0
    }
701
702
0
    t1 = 1 - aB;
703
0
    t2 = 1 - aA;
704
0
    t3 = aA * aB;
705
0
    for (int b = 0; b < bands; b++)
706
0
      B[b] = t1 * A[b] + t2 * B[b] + t3 * f[b];
707
0
    break;
708
0
  }
709
710
0
  B[bands] = aR;
711
0
}
Unexecuted instantiation: composite.cpp:void vips_composite_base_blend<unsigned char>(_VipsCompositeBase*, VipsBlendMode, double*, unsigned char*)
Unexecuted instantiation: composite.cpp:void vips_composite_base_blend<signed char>(_VipsCompositeBase*, VipsBlendMode, double*, signed char*)
Unexecuted instantiation: composite.cpp:void vips_composite_base_blend<unsigned short>(_VipsCompositeBase*, VipsBlendMode, double*, unsigned short*)
Unexecuted instantiation: composite.cpp:void vips_composite_base_blend<short>(_VipsCompositeBase*, VipsBlendMode, double*, short*)
Unexecuted instantiation: composite.cpp:void vips_composite_base_blend<unsigned int>(_VipsCompositeBase*, VipsBlendMode, double*, unsigned int*)
Unexecuted instantiation: composite.cpp:void vips_composite_base_blend<int>(_VipsCompositeBase*, VipsBlendMode, double*, int*)
Unexecuted instantiation: composite.cpp:void vips_composite_base_blend<float>(_VipsCompositeBase*, VipsBlendMode, double*, float*)
Unexecuted instantiation: composite.cpp:void vips_composite_base_blend<double>(_VipsCompositeBase*, VipsBlendMode, double*, double*)
712
713
/* We have a vector path with gcc's vector attr.
714
 */
715
#ifdef HAVE_VECTOR_ARITH
716
/* Special path for RGBA with non-double output. This is overwhelmingly the
717
 * most common case, and vectorises easily.
718
 *
719
 * B is the float pixel we are accumulating, A is the new pixel coming
720
 * in from memory.
721
 */
722
template <typename T>
723
static void
724
vips_composite_base_blend3(VipsCompositeSequence *seq,
725
  VipsBlendMode mode, v4f &B, T *restrict p)
726
0
{
727
0
  VipsCompositeBase *composite = seq->composite;
728
729
0
  v4f A;
730
0
  float aA;
731
0
  float aB;
732
0
  float aR;
733
0
  float t1;
734
0
  float t2;
735
0
  float t3;
736
0
  v4f f;
737
0
  v4f g;
738
739
  /* Load and scale the pixel to 0 - 1.
740
   */
741
0
  A[0] = p[0];
742
0
  A[1] = p[1];
743
0
  A[2] = p[2];
744
0
  A[3] = p[3];
745
746
0
  A /= seq->max_band_vec;
747
748
0
  aA = A[3];
749
0
  aB = B[3];
750
751
  /* We may need to premultiply A.
752
   */
753
0
  if (!composite->premultiplied)
754
0
    A *= aA;
755
756
  /* See https://www.cairographics.org/operators for a nice summary of
757
   * the operators and their meaning.
758
   *
759
   * Some operators need the unpremultiplied values (eg. dest-in), so
760
   * we have to do an extra unpremultiply/premultiply.
761
   */
762
763
0
  switch (mode) {
764
0
  case VIPS_BLEND_MODE_CLEAR:
765
0
    aR = 0;
766
0
    B[0] = 0;
767
0
    B[1] = 0;
768
0
    B[2] = 0;
769
0
    break;
770
771
0
  case VIPS_BLEND_MODE_SOURCE:
772
0
    aR = aA;
773
0
    B = A;
774
0
    break;
775
776
0
  case VIPS_BLEND_MODE_OVER:
777
0
    aR = aA + aB * (1 - aA);
778
0
    t1 = 1 - aA;
779
0
    B = A + t1 * B;
780
0
    break;
781
782
0
  case VIPS_BLEND_MODE_IN:
783
0
    aR = aA * aB;
784
    // if aA == 0, then aR == 0 and so B will already be 0
785
0
    if (aA != 0)
786
0
      B = A * aR / aA;
787
0
    break;
788
789
0
  case VIPS_BLEND_MODE_OUT:
790
0
    aR = aA * (1 - aB);
791
    // if aA == 0, then aR == 0 and so B will already be 0
792
0
    if (aA != 0)
793
0
      B = A * aR / aA;
794
0
    break;
795
796
0
  case VIPS_BLEND_MODE_ATOP:
797
0
    aR = aB;
798
0
    t1 = 1 - aA;
799
0
    B = A + t1 * B;
800
0
    break;
801
802
0
  case VIPS_BLEND_MODE_DEST:
803
0
    aR = aB;
804
    // B = B
805
0
    break;
806
807
0
  case VIPS_BLEND_MODE_DEST_OVER:
808
0
    aR = aB + aA * (1 - aB);
809
0
    t1 = 1 - aB;
810
0
    B = B + t1 * A;
811
0
    break;
812
813
0
  case VIPS_BLEND_MODE_DEST_IN:
814
0
    aR = aA * aB;
815
    // if aB is 0, then B is already 0
816
0
    if (aB != 0)
817
0
      B *= aR / aB;
818
0
    break;
819
820
0
  case VIPS_BLEND_MODE_DEST_OUT:
821
0
    aR = (1 - aA) * aB;
822
    // B = B
823
    // if aB is 0, then B is already 0
824
0
    if (aB != 0)
825
0
      B *= aR / aB;
826
0
    break;
827
828
0
  case VIPS_BLEND_MODE_DEST_ATOP:
829
0
    aR = aA;
830
0
    t1 = 1 - aB;
831
0
    B = t1 * A + B;
832
0
    break;
833
834
0
  case VIPS_BLEND_MODE_XOR:
835
0
    aR = aA + aB - 2 * aA * aB;
836
0
    t1 = 1 - aB;
837
0
    t2 = 1 - aA;
838
0
    B = t1 * A + t2 * B;
839
0
    break;
840
841
0
  case VIPS_BLEND_MODE_ADD:
842
0
    aR = VIPS_MIN(1, aA + aB);
843
0
    B = A + B;
844
0
    break;
845
846
0
  case VIPS_BLEND_MODE_SATURATE:
847
0
    aR = VIPS_MIN(1, aA + aB);
848
0
    t1 = VIPS_MIN(aA, 1 - aB);
849
0
    B = t1 * A + B;
850
0
    break;
851
852
0
  default:
853
    /* The PDF modes are a bit different.
854
     */
855
0
    aR = aA + aB * (1 - aA);
856
857
0
    switch (mode) {
858
0
    case VIPS_BLEND_MODE_MULTIPLY:
859
0
      f = A * B;
860
0
      break;
861
862
0
    case VIPS_BLEND_MODE_SCREEN:
863
0
      f = A + B - A * B;
864
0
      break;
865
866
0
    case VIPS_BLEND_MODE_OVERLAY:
867
0
      f = B <= 0.5f
868
0
        ? 2 * A * B
869
0
        : 1 - 2 * (1 - A) * (1 - B);
870
0
      break;
871
872
0
    case VIPS_BLEND_MODE_DARKEN:
873
0
      f = VIPS_MIN(A, B);
874
0
      break;
875
876
0
    case VIPS_BLEND_MODE_LIGHTEN:
877
0
      f = VIPS_MAX(A, B);
878
0
      break;
879
880
0
    case VIPS_BLEND_MODE_COLOUR_DODGE:
881
0
      f = A < 1
882
0
        ? VIPS_MIN(1, B / (1 - A))
883
0
        : 1;
884
0
      break;
885
886
0
    case VIPS_BLEND_MODE_COLOUR_BURN:
887
0
      f = A > 0
888
0
        ? 1 - VIPS_MIN(1, (1 - B) / A)
889
0
        : 0;
890
0
      break;
891
892
0
    case VIPS_BLEND_MODE_HARD_LIGHT:
893
0
      f = A <= 0.5f
894
0
        ? 2 * A * B
895
0
        : 1 - 2 * (1 - A) * (1 - B);
896
0
      break;
897
898
0
    case VIPS_BLEND_MODE_SOFT_LIGHT:
899
      /* You can't sqrt a vector, so we must loop.
900
       */
901
0
      for (int b = 0; b < 3; b++) {
902
0
        double g;
903
904
0
        if (B[b] <= 0.25)
905
0
          g = ((16 * B[b] - 12) * B[b] + 4) * B[b];
906
0
        else
907
0
          g = sqrt(B[b]);
908
909
0
        if (A[b] <= 0.5)
910
0
          f[b] = B[b] - (1 - 2 * A[b]) * B[b] * (1 - B[b]);
911
0
        else
912
0
          f[b] = B[b] + (2 * A[b] - 1) * (g - B[b]);
913
0
      }
914
0
      break;
915
916
0
    case VIPS_BLEND_MODE_DIFFERENCE:
917
0
      g = B - A;
918
0
      f = g > 0 ? g : -1 * g;
919
0
      break;
920
921
0
    case VIPS_BLEND_MODE_EXCLUSION:
922
0
      f = A + B - 2 * A * B;
923
0
      break;
924
925
0
    default:
926
0
      g_assert_not_reached();
927
928
      /* Stop compiler warnings.
929
       */
930
0
      for (int b = 0; b < 3; b++)
931
0
        B[b] = 0;
932
0
      f = A;
933
0
    }
934
935
0
    t1 = 1 - aB;
936
0
    t2 = 1 - aA;
937
0
    t3 = aA * aB;
938
0
    B = t1 * A + t2 * B + t3 * f;
939
0
    break;
940
0
  }
941
942
0
  B[3] = aR;
943
0
}
Unexecuted instantiation: composite.cpp:void vips_composite_base_blend3<unsigned char>(VipsCompositeSequence*, VipsBlendMode, float __vector(4)&, unsigned char*)
Unexecuted instantiation: composite.cpp:void vips_composite_base_blend3<unsigned short>(VipsCompositeSequence*, VipsBlendMode, float __vector(4)&, unsigned short*)
Unexecuted instantiation: composite.cpp:void vips_composite_base_blend3<float>(VipsCompositeSequence*, VipsBlendMode, float __vector(4)&, float*)
944
#endif /*HAVE_VECTOR_ARITH*/
945
946
/* min_T and max_T are the numeric range for this type. 0, 0 means no limit,
947
 * for example float.
948
 */
949
template <typename T, gint64 min_T, gint64 max_T>
950
static void
951
vips_combine_pixels(VipsCompositeSequence *seq, VipsPel *q)
952
0
{
953
0
  VipsCompositeBase *composite = seq->composite;
954
0
  VipsBlendMode *mode = (VipsBlendMode *) composite->mode->area.data;
955
0
  int n_mode = composite->mode->area.n;
956
0
  int n = seq->n;
957
0
  int bands = composite->bands;
958
0
  T *restrict tq = (T *restrict) q;
959
0
  T **restrict tp = (T * *restrict) seq->p;
960
961
0
  double B[MAX_BANDS + 1];
962
0
  double aB;
963
964
  /* Load and scale the base pixel to 0 - 1.
965
   */
966
0
  for (int b = 0; b <= bands; b++)
967
0
    B[b] = tp[0][b] / composite->max_band[b];
968
969
0
  aB = B[bands];
970
0
  if (!composite->premultiplied)
971
0
    for (int b = 0; b < bands; b++)
972
0
      B[b] *= aB;
973
974
0
  for (int i = 1; i < n; i++) {
975
0
    int j = seq->enabled[i];
976
0
    VipsBlendMode m = n_mode == 1 ? mode[0] : mode[j - 1];
977
978
0
    vips_composite_base_blend<T>(composite, m, B, tp[i]);
979
0
  }
980
981
  /* Unpremultiply, if necessary.
982
   */
983
0
  if (!composite->premultiplied) {
984
0
    double aR = B[bands];
985
986
0
    if (aR == 0)
987
0
      for (int b = 0; b < bands; b++)
988
0
        B[b] = 0;
989
0
    else
990
0
      for (int b = 0; b < bands; b++)
991
0
        B[b] = B[b] / aR;
992
0
  }
993
994
  /* Write back as a full range pixel, clipping to range.
995
   */
996
0
  for (int b = 0; b <= bands; b++) {
997
0
    double v;
998
999
0
    v = B[b] * composite->max_band[b];
1000
0
    if (min_T != 0 ||
1001
0
      max_T != 0) {
1002
0
      v = VIPS_CLIP(min_T, v, max_T);
1003
0
    }
1004
1005
0
    tq[b] = v;
1006
0
  }
1007
0
}
Unexecuted instantiation: composite.cpp:void vips_combine_pixels<unsigned char, 0l, 255l>(VipsCompositeSequence*, unsigned char*)
Unexecuted instantiation: composite.cpp:void vips_combine_pixels<signed char, -128l, 127l>(VipsCompositeSequence*, unsigned char*)
Unexecuted instantiation: composite.cpp:void vips_combine_pixels<unsigned short, 0l, 65535l>(VipsCompositeSequence*, unsigned char*)
Unexecuted instantiation: composite.cpp:void vips_combine_pixels<short, -32768l, 32767l>(VipsCompositeSequence*, unsigned char*)
Unexecuted instantiation: composite.cpp:void vips_combine_pixels<unsigned int, 0l, 4294967295l>(VipsCompositeSequence*, unsigned char*)
Unexecuted instantiation: composite.cpp:void vips_combine_pixels<int, -2147483648l, 2147483647l>(VipsCompositeSequence*, unsigned char*)
Unexecuted instantiation: composite.cpp:void vips_combine_pixels<float, 0l, 0l>(VipsCompositeSequence*, unsigned char*)
Unexecuted instantiation: composite.cpp:void vips_combine_pixels<double, 0l, 0l>(VipsCompositeSequence*, unsigned char*)
1008
1009
#ifdef HAVE_VECTOR_ARITH
1010
/* Three band (four with alpha) vector case. Non-double output. min_T and
1011
 * max_T are the numeric range for this type. 0, 0 means no limit,
1012
 * for example float.
1013
 */
1014
template <typename T, gint64 min_T, gint64 max_T>
1015
static void
1016
vips_combine_pixels3(VipsCompositeSequence *seq, VipsPel *q)
1017
0
{
1018
0
  VipsCompositeBase *composite = seq->composite;
1019
0
  VipsBlendMode *mode = (VipsBlendMode *) composite->mode->area.data;
1020
0
  int n_mode = composite->mode->area.n;
1021
0
  int n = seq->n;
1022
0
  T *restrict tq = (T *restrict) q;
1023
0
  T **restrict tp = (T * *restrict) seq->p;
1024
1025
0
  v4f B;
1026
0
  float aB;
1027
1028
0
  B[0] = tp[0][0];
1029
0
  B[1] = tp[0][1];
1030
0
  B[2] = tp[0][2];
1031
0
  B[3] = tp[0][3];
1032
1033
  /* Scale the base pixel to 0 - 1.
1034
   */
1035
0
  B /= seq->max_band_vec;
1036
0
  aB = B[3];
1037
1038
0
  if (!composite->premultiplied) {
1039
0
    B *= aB;
1040
0
    B[3] = aB;
1041
0
  }
1042
1043
0
  for (int i = 1; i < n; i++) {
1044
0
    int j = seq->enabled[i];
1045
0
    VipsBlendMode m = n_mode == 1 ? mode[0] : mode[j - 1];
1046
1047
0
    vips_composite_base_blend3<T>(seq, m, B, tp[i]);
1048
0
  }
1049
1050
  /* Unpremultiply, if necessary.
1051
   */
1052
0
  if (!composite->premultiplied) {
1053
0
    float aR = B[3];
1054
1055
0
    if (aR == 0)
1056
0
      for (int b = 0; b < 3; b++)
1057
0
        B[b] = 0;
1058
0
    else {
1059
0
      B /= aR;
1060
0
      B[3] = aR;
1061
0
    }
1062
0
  }
1063
1064
  /* Write back as a full range pixel, clipping to range.
1065
   */
1066
0
  B *= seq->max_band_vec;
1067
0
  if (min_T != 0 ||
1068
0
    max_T != 0) {
1069
0
    float low = min_T;
1070
0
    float high = max_T;
1071
1072
0
    B = VIPS_CLIP(low, B, high);
1073
0
  }
1074
1075
0
  tq[0] = B[0];
1076
0
  tq[1] = B[1];
1077
0
  tq[2] = B[2];
1078
0
  tq[3] = B[3];
1079
0
}
Unexecuted instantiation: composite.cpp:void vips_combine_pixels3<unsigned char, 0l, 255l>(VipsCompositeSequence*, unsigned char*)
Unexecuted instantiation: composite.cpp:void vips_combine_pixels3<unsigned short, 0l, 65535l>(VipsCompositeSequence*, unsigned char*)
Unexecuted instantiation: composite.cpp:void vips_combine_pixels3<float, 0l, 65535l>(VipsCompositeSequence*, unsigned char*)
1080
#endif /*HAVE_VECTOR_ARITH*/
1081
1082
static int
1083
vips_composite_base_gen(VipsRegion *output_region,
1084
  void *vseq, void *a, void *b, gboolean *stop)
1085
0
{
1086
0
  VipsCompositeSequence *seq = (VipsCompositeSequence *) vseq;
1087
0
  VipsCompositeBase *composite = (VipsCompositeBase *) b;
1088
0
  VipsRect *r = &output_region->valid;
1089
0
  int ps = VIPS_IMAGE_SIZEOF_PEL(output_region->im);
1090
1091
0
  VIPS_DEBUG_MSG("vips_composite_base_gen: at %d x %d, size %d x %d\n",
1092
0
    r->left, r->top, r->width, r->height);
1093
1094
  /* Find the subset of our input images which intersect this region.
1095
   */
1096
0
  vips_composite_base_select(seq, r);
1097
1098
0
  VIPS_DEBUG_MSG("  selected %d images\n", seq->n);
1099
1100
  /* Is there just one? We can prepare directly to output and return.
1101
   */
1102
0
  if (seq->n == 1) {
1103
    /* This can only be the background image, since it's the only
1104
     * image which exactly fills the whole output.
1105
     */
1106
0
    g_assert(seq->enabled[0] == 0);
1107
1108
0
    if (vips_region_prepare(seq->input_regions[0], r))
1109
0
      return -1;
1110
0
    if (vips_region_region(output_region, seq->input_regions[0],
1111
0
        r, r->left, r->top))
1112
0
      return -1;
1113
1114
0
    return 0;
1115
0
  }
1116
1117
  /* Prepare the appropriate parts into our set of composite
1118
   * regions.
1119
   */
1120
0
  for (int i = 0; i < seq->n; i++) {
1121
0
    int j = seq->enabled[i];
1122
1123
0
    VipsRect hit;
1124
0
    VipsRect request;
1125
1126
    /* Set the composite region up to be a bit of memory at the
1127
     * right position.
1128
     */
1129
0
    if (vips_region_buffer(seq->composite_regions[j], r))
1130
0
      return -1;
1131
1132
    /* Clip against this subimage position and size.
1133
     */
1134
0
    hit = *r;
1135
0
    vips_rect_intersectrect(&hit, &composite->subimages[j], &hit);
1136
1137
    /* Translate request to subimage coordinates.
1138
     */
1139
0
    request = hit;
1140
0
    request.left -= composite->subimages[j].left;
1141
0
    request.top -= composite->subimages[j].top;
1142
1143
    /* If the request is smaller than the target region, there
1144
     * will be some gaps. We must make sure these are zero.
1145
     */
1146
0
    if (request.width < r->width ||
1147
0
      request.height < r->height)
1148
0
      vips_region_black(seq->composite_regions[j]);
1149
1150
    /* And render the right part of the input image to the
1151
     * composite region.
1152
     *
1153
     * If we are not in skippable mode, we can be completely
1154
     * outside the subimage area.
1155
     */
1156
0
    if (!vips_rect_isempty(&request)) {
1157
0
      VIPS_DEBUG_MSG("  fetching pixels for input %d\n", j);
1158
0
      if (vips_region_prepare_to(seq->input_regions[j],
1159
0
          seq->composite_regions[j], &request,
1160
0
          hit.left, hit.top))
1161
0
        return -1;
1162
0
    }
1163
0
  }
1164
1165
0
  VIPS_GATE_START("vips_composite_base_gen: work");
1166
1167
0
  for (int y = 0; y < r->height; y++) {
1168
0
    VipsPel *q;
1169
1170
0
    for (int i = 0; i < seq->n; i++) {
1171
0
      int j = seq->enabled[i];
1172
1173
0
      seq->p[i] = VIPS_REGION_ADDR(seq->composite_regions[j],
1174
0
        r->left, r->top + y);
1175
0
    }
1176
0
    q = VIPS_REGION_ADDR(output_region, r->left, r->top + y);
1177
1178
0
    for (int x = 0; x < r->width; x++) {
1179
0
      switch (seq->input_regions[0]->im->BandFmt) {
1180
0
      case VIPS_FORMAT_UCHAR:
1181
0
#ifdef HAVE_VECTOR_ARITH
1182
0
        if (composite->bands == 3)
1183
0
          vips_combine_pixels3<unsigned char,
1184
0
            0, UCHAR_MAX>(seq, q);
1185
0
        else
1186
0
#endif
1187
0
          vips_combine_pixels<unsigned char,
1188
0
            0, UCHAR_MAX>(seq, q);
1189
0
        break;
1190
1191
0
      case VIPS_FORMAT_CHAR:
1192
0
        vips_combine_pixels<signed char,
1193
0
          SCHAR_MIN, SCHAR_MAX>(seq, q);
1194
0
        break;
1195
1196
0
      case VIPS_FORMAT_USHORT:
1197
0
#ifdef HAVE_VECTOR_ARITH
1198
0
        if (composite->bands == 3)
1199
0
          vips_combine_pixels3<unsigned short,
1200
0
            0, USHRT_MAX>(seq, q);
1201
0
        else
1202
0
#endif
1203
0
          vips_combine_pixels<unsigned short,
1204
0
            0, USHRT_MAX>(seq, q);
1205
0
        break;
1206
1207
0
      case VIPS_FORMAT_SHORT:
1208
0
        vips_combine_pixels<signed short,
1209
0
          SHRT_MIN, SHRT_MAX>(seq, q);
1210
0
        break;
1211
1212
0
      case VIPS_FORMAT_UINT:
1213
0
        vips_combine_pixels<unsigned int,
1214
0
          0, UINT_MAX>(seq, q);
1215
0
        break;
1216
1217
0
      case VIPS_FORMAT_INT:
1218
0
        vips_combine_pixels<signed int,
1219
0
          INT_MIN, INT_MAX>(seq, q);
1220
0
        break;
1221
1222
0
      case VIPS_FORMAT_FLOAT:
1223
0
#ifdef HAVE_VECTOR_ARITH
1224
0
        if (composite->bands == 3)
1225
0
          vips_combine_pixels3<float,
1226
0
            0, USHRT_MAX>(seq, q);
1227
0
        else
1228
0
#endif
1229
0
          vips_combine_pixels<float,
1230
0
            0, 0>(seq, q);
1231
0
        break;
1232
1233
0
      case VIPS_FORMAT_DOUBLE:
1234
0
        vips_combine_pixels<double,
1235
0
          0, 0>(seq, q);
1236
0
        break;
1237
1238
0
      default:
1239
0
        g_assert_not_reached();
1240
0
        return -1;
1241
0
      }
1242
1243
0
      for (int i = 0; i < seq->n; i++)
1244
0
        seq->p[i] += ps;
1245
0
      q += ps;
1246
0
    }
1247
0
  }
1248
1249
0
  VIPS_GATE_STOP("vips_composite_base_gen: work");
1250
1251
0
  return 0;
1252
0
}
1253
1254
/* Is a mode "skippable"?
1255
 *
1256
 * Skippable modes are ones where a black (0, 0, 0, 0) layer placed over the
1257
 * base image and composited has no effect.
1258
 *
1259
 * If all the modes in our stack are skippable, we can avoid compositing the
1260
 * whole stack for every request.
1261
 */
1262
static gboolean
1263
vips_composite_mode_skippable(VipsBlendMode mode)
1264
0
{
1265
0
  switch (mode) {
1266
0
  case VIPS_BLEND_MODE_CLEAR:
1267
0
  case VIPS_BLEND_MODE_SOURCE:
1268
0
  case VIPS_BLEND_MODE_IN:
1269
0
  case VIPS_BLEND_MODE_OUT:
1270
0
  case VIPS_BLEND_MODE_DEST_IN:
1271
0
  case VIPS_BLEND_MODE_DEST_ATOP:
1272
0
    return FALSE;
1273
1274
0
  default:
1275
0
    return TRUE;
1276
0
  }
1277
0
}
1278
1279
static int
1280
vips_composite_base_build(VipsObject *object)
1281
0
{
1282
0
  VipsObjectClass *klass = VIPS_OBJECT_GET_CLASS(object);
1283
0
  VipsConversion *conversion = VIPS_CONVERSION(object);
1284
0
  VipsCompositeBase *composite = (VipsCompositeBase *) object;
1285
1286
0
  int n;
1287
0
  VipsBlendMode *mode;
1288
0
  VipsImage **in;
1289
0
  VipsImage **decode;
1290
0
  VipsImage **compositing;
1291
0
  VipsImage **format;
1292
1293
0
  if (VIPS_OBJECT_CLASS(vips_composite_base_parent_class)->build(object))
1294
0
    return -1;
1295
1296
0
  n = composite->in->area.n;
1297
1298
0
  if (n <= 0) {
1299
0
    vips_error(klass->nickname, "%s", _("no input images"));
1300
0
    return -1;
1301
0
  }
1302
0
  if (composite->mode->area.n != n - 1 &&
1303
0
    composite->mode->area.n != 1) {
1304
0
    vips_error(klass->nickname, _("must be 1 or %d blend modes"),
1305
0
      n - 1);
1306
0
    return -1;
1307
0
  }
1308
0
  mode = (VipsBlendMode *) composite->mode->area.data;
1309
0
  composite->skippable = TRUE;
1310
0
  for (int i = 0; i < composite->mode->area.n; i++) {
1311
0
    if (mode[i] < 0 ||
1312
0
      mode[i] >= VIPS_BLEND_MODE_LAST) {
1313
0
      vips_error(klass->nickname,
1314
0
        _("blend mode index %d (%d) invalid"),
1315
0
        i, mode[i]);
1316
0
      return -1;
1317
0
    }
1318
1319
0
    if (!vips_composite_mode_skippable(mode[i]))
1320
0
      composite->skippable = FALSE;
1321
0
  }
1322
1323
0
  in = (VipsImage **) composite->in->area.data;
1324
1325
  /* Make a set of rects for the positions of the input images. Image 0
1326
   * (the background) is always at (0, 0).
1327
   */
1328
0
  if (!(composite->subimages =
1329
0
        VIPS_ARRAY(NULL, n, VipsRect)))
1330
0
    return -1;
1331
0
  for (int i = 0; i < n; i++) {
1332
0
    composite->subimages[i].left = 0;
1333
0
    composite->subimages[i].top = 0;
1334
0
    composite->subimages[i].width = in[i]->Xsize;
1335
0
    composite->subimages[i].height = in[i]->Ysize;
1336
0
  }
1337
1338
  /* Position all images, if x/y is set. Image 0
1339
   * (the background) is always at (0, 0).
1340
   */
1341
0
  if (composite->x_offset &&
1342
0
    composite->y_offset)
1343
0
    for (int i = 1; i < n; i++) {
1344
0
      composite->subimages[i].left =
1345
0
        composite->x_offset[i - 1];
1346
0
      composite->subimages[i].top =
1347
0
        composite->y_offset[i - 1];
1348
0
    }
1349
1350
0
  decode = (VipsImage **) vips_object_local_array(object, n);
1351
0
  for (int i = 0; i < n; i++)
1352
0
    if (vips_image_decode(in[i], &decode[i]))
1353
0
      return -1;
1354
0
  in = decode;
1355
1356
  /* Add a solid alpha to any images missing one.
1357
   */
1358
0
  for (int i = n - 1; i >= 0; i--)
1359
0
    if (!vips_image_hasalpha(in[i])) {
1360
0
      VipsImage *x;
1361
1362
0
      if (vips_addalpha(in[i], &x, nullptr))
1363
0
        return -1;
1364
0
      g_object_unref(in[i]);
1365
0
      in[i] = x;
1366
0
    }
1367
1368
  /* Transform to compositing space. It defaults to sRGB or B_W, usually
1369
   * 8 bit, but 16 bit if any inputs are 16 bit.
1370
   */
1371
0
  if (!vips_object_argument_isset(object, "compositing_space")) {
1372
0
    gboolean all_grey;
1373
0
    gboolean any_16;
1374
1375
0
    all_grey = TRUE;
1376
0
    for (int i = 0; i < n; i++)
1377
0
      if (in[i]->Bands > 2) {
1378
0
        all_grey = FALSE;
1379
0
        break;
1380
0
      }
1381
1382
0
    any_16 = FALSE;
1383
0
    for (int i = 0; i < n; i++)
1384
0
      if (in[i]->Type == VIPS_INTERPRETATION_GREY16 ||
1385
0
        in[i]->Type == VIPS_INTERPRETATION_RGB16) {
1386
0
        any_16 = TRUE;
1387
0
        break;
1388
0
      }
1389
1390
0
    composite->compositing_space = any_16 // FIXME: Invalidates operation cache
1391
0
      ? (all_grey
1392
0
            ? VIPS_INTERPRETATION_GREY16
1393
0
            : VIPS_INTERPRETATION_RGB16)
1394
0
      : (all_grey
1395
0
            ? VIPS_INTERPRETATION_B_W
1396
0
            : VIPS_INTERPRETATION_sRGB);
1397
0
  }
1398
1399
0
  compositing = (VipsImage **)
1400
0
    vips_object_local_array(object, n);
1401
0
  for (int i = 0; i < n; i++)
1402
0
    if (vips_colourspace(in[i], &compositing[i],
1403
0
        composite->compositing_space, nullptr))
1404
0
      return -1;
1405
0
  in = compositing;
1406
1407
  /* Check that they all now match in bands. This can fail for some
1408
   * input combinations.
1409
   */
1410
0
  for (int i = 1; i < n; i++)
1411
0
    if (in[i]->Bands != in[0]->Bands) {
1412
0
      vips_error(klass->nickname,
1413
0
        "%s", _("images do not have same "
1414
0
            "numbers of bands"));
1415
0
      return -1;
1416
0
    }
1417
1418
0
  if (in[0]->Bands > MAX_BANDS) {
1419
0
    vips_error(klass->nickname,
1420
0
      "%s", _("too many input bands"));
1421
0
    return -1;
1422
0
  }
1423
1424
0
  composite->bands = in[0]->Bands - 1;
1425
1426
  /* Set the max for each band now we know bands and compositing space.
1427
   */
1428
0
  if (vips_composite_base_max_band(composite, composite->max_band)) {
1429
0
    vips_error(klass->nickname,
1430
0
      "%s", _("unsupported compositing space"));
1431
0
    return -1;
1432
0
  }
1433
1434
  /* Transform the input images to match in format. We may have
1435
   * mixed float and double, for example.
1436
   */
1437
0
  format = (VipsImage **) vips_object_local_array(object, n);
1438
0
  if (vips__formatalike_vec(in, format, n))
1439
0
    return -1;
1440
0
  in = format;
1441
1442
  /* We want locality, so that we only prepare a few subimages each
1443
   * time.
1444
   */
1445
0
  if (vips_image_pipeline_array(conversion->out,
1446
0
      VIPS_DEMAND_STYLE_SMALLTILE, in))
1447
0
    return -1;
1448
1449
  /* The output image is always the size of the base image.
1450
   */
1451
0
  conversion->out->Xsize = in[0]->Xsize;
1452
0
  conversion->out->Ysize = in[0]->Ysize;
1453
1454
0
  if (vips_image_generate(conversion->out,
1455
0
      vips_composite_start,
1456
0
      vips_composite_base_gen,
1457
0
      vips_composite_stop,
1458
0
      in, composite))
1459
0
    return -1;
1460
1461
0
  return 0;
1462
0
}
1463
1464
static void
1465
vips_composite_base_class_init(VipsCompositeBaseClass *klass)
1466
1
{
1467
1
  GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
1468
1
  VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS(klass);
1469
1
  VipsOperationClass *operation_class = VIPS_OPERATION_CLASS(klass);
1470
1471
1
  VIPS_DEBUG_MSG("vips_composite_base_class_init\n");
1472
1473
1
  gobject_class->dispose = vips_composite_base_dispose;
1474
1
  gobject_class->set_property = vips_object_set_property;
1475
1
  gobject_class->get_property = vips_object_get_property;
1476
1477
1
  vobject_class->nickname = "composite_base";
1478
1
  vobject_class->description = _("blend images together");
1479
1
  vobject_class->build = vips_composite_base_build;
1480
1481
1
  operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
1482
1483
1
  VIPS_ARG_ENUM(klass, "compositing_space", 10,
1484
1
    _("Compositing space"),
1485
1
    _("Composite images in this colour space"),
1486
1
    VIPS_ARGUMENT_OPTIONAL_INPUT,
1487
1
    G_STRUCT_OFFSET(VipsCompositeBase, compositing_space),
1488
1
    VIPS_TYPE_INTERPRETATION, VIPS_INTERPRETATION_sRGB);
1489
1490
1
  VIPS_ARG_BOOL(klass, "premultiplied", 11,
1491
1
    _("Premultiplied"),
1492
1
    _("Images have premultiplied alpha"),
1493
1
    VIPS_ARGUMENT_OPTIONAL_INPUT,
1494
1
    G_STRUCT_OFFSET(VipsCompositeBase, premultiplied),
1495
1
    FALSE);
1496
1
}
1497
1498
static void
1499
vips_composite_base_init(VipsCompositeBase *composite)
1500
0
{
1501
0
  composite->compositing_space = VIPS_INTERPRETATION_sRGB;
1502
0
}
1503
1504
typedef struct _VipsComposite {
1505
  VipsCompositeBase parent_instance;
1506
1507
  /* For N input images, N - 1 x coordinates.
1508
   */
1509
  VipsArrayInt *x;
1510
1511
  /* For N input images, N - 1 y coordinates.
1512
   */
1513
  VipsArrayInt *y;
1514
1515
} VipsComposite;
1516
1517
typedef VipsCompositeBaseClass VipsCompositeClass;
1518
1519
/* We need C linkage for this.
1520
 */
1521
extern "C" {
1522
G_DEFINE_TYPE(VipsComposite, vips_composite, vips_composite_base_get_type());
1523
}
1524
1525
static int
1526
vips_composite_build(VipsObject *object)
1527
0
{
1528
0
  VipsObjectClass *klass = VIPS_OBJECT_GET_CLASS(object);
1529
0
  VipsCompositeBase *base = (VipsCompositeBase *) object;
1530
0
  VipsComposite *composite = (VipsComposite *) object;
1531
1532
0
  int n;
1533
1534
0
  n = 0;
1535
0
  if (vips_object_argument_isset(object, "in"))
1536
0
    n = base->in->area.n;
1537
1538
0
  if (vips_object_argument_isset(object, "x")) {
1539
0
    if (composite->x->area.n != n - 1) {
1540
0
      vips_error(klass->nickname, _("must be %d x coordinates"), n - 1);
1541
0
      return -1;
1542
0
    }
1543
0
    base->x_offset = (int *) composite->x->area.data;
1544
0
  }
1545
1546
0
  if (vips_object_argument_isset(object, "y")) {
1547
0
    if (composite->y->area.n != n - 1) {
1548
0
      vips_error(klass->nickname, _("must be %d y coordinates"), n - 1);
1549
0
      return -1;
1550
0
    }
1551
0
    base->y_offset = (int *) composite->y->area.data;
1552
0
  }
1553
1554
0
  if (VIPS_OBJECT_CLASS(vips_composite_parent_class)->build(object))
1555
0
    return -1;
1556
1557
0
  return 0;
1558
0
}
1559
1560
static void
1561
vips_composite_class_init(VipsCompositeClass *klass)
1562
1
{
1563
1
  GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
1564
1
  VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS(klass);
1565
1
  VipsOperationClass *operation_class = VIPS_OPERATION_CLASS(klass);
1566
1567
1
  VIPS_DEBUG_MSG("vips_composite_class_init\n");
1568
1569
1
  gobject_class->set_property = vips_object_set_property;
1570
1
  gobject_class->get_property = vips_object_get_property;
1571
1572
1
  vobject_class->nickname = "composite";
1573
1
  vobject_class->description =
1574
1
    _("blend an array of images with an array of blend modes");
1575
1
  vobject_class->build = vips_composite_build;
1576
1577
1
  operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
1578
1579
1
  VIPS_ARG_BOXED(klass, "in", 0,
1580
1
    _("Inputs"),
1581
1
    _("Array of input images"),
1582
1
    VIPS_ARGUMENT_REQUIRED_INPUT,
1583
1
    G_STRUCT_OFFSET(VipsCompositeBase, in),
1584
1
    VIPS_TYPE_ARRAY_IMAGE);
1585
1586
1
  VIPS_ARG_BOXED(klass, "mode", 3,
1587
1
    _("Blend modes"),
1588
1
    _("Array of VipsBlendMode to join with"),
1589
1
    VIPS_ARGUMENT_REQUIRED_INPUT,
1590
1
    G_STRUCT_OFFSET(VipsCompositeBase, mode),
1591
1
    VIPS_TYPE_ARRAY_INT);
1592
1593
1
  VIPS_ARG_BOXED(klass, "x", 4,
1594
1
    _("x coordinates"),
1595
1
    _("Array of x coordinates to join at"),
1596
1
    VIPS_ARGUMENT_OPTIONAL_INPUT,
1597
1
    G_STRUCT_OFFSET(VipsComposite, x),
1598
1
    VIPS_TYPE_ARRAY_INT);
1599
1600
1
  VIPS_ARG_BOXED(klass, "y", 5,
1601
1
    _("y coordinates"),
1602
1
    _("Array of y coordinates to join at"),
1603
1
    VIPS_ARGUMENT_OPTIONAL_INPUT,
1604
1
    G_STRUCT_OFFSET(VipsComposite, y),
1605
1
    VIPS_TYPE_ARRAY_INT);
1606
1
}
1607
1608
static void
1609
vips_composite_init(VipsComposite *composite)
1610
0
{
1611
0
}
1612
1613
static int
1614
vips_compositev(VipsImage **in, VipsImage **out, int n, int *mode, va_list ap)
1615
0
{
1616
0
  VipsArrayImage *image_array;
1617
0
  VipsArrayInt *mode_array;
1618
0
  int result;
1619
1620
0
  image_array = vips_array_image_new(in, n);
1621
0
  mode_array = vips_array_int_new(mode, n - 1);
1622
0
  result = vips_call_split("composite", ap,
1623
0
    image_array, out, mode_array);
1624
0
  vips_area_unref(VIPS_AREA(image_array));
1625
0
  vips_area_unref(VIPS_AREA(mode_array));
1626
1627
0
  return result;
1628
0
}
1629
1630
/* See conversion.c for the doc comment.
1631
 */
1632
1633
int
1634
vips_composite(VipsImage **in, VipsImage **out, int n, int *mode, ...)
1635
0
{
1636
0
  va_list ap;
1637
0
  int result;
1638
1639
0
  va_start(ap, mode);
1640
0
  result = vips_compositev(in, out, n, mode, ap);
1641
0
  va_end(ap);
1642
1643
0
  return result;
1644
0
}
1645
1646
typedef struct _VipsComposite2 {
1647
  VipsCompositeBase parent_instance;
1648
1649
  VipsImage *base;
1650
  VipsImage *overlay;
1651
  VipsBlendMode mode;
1652
  int x;
1653
  int y;
1654
1655
} VipsComposite2;
1656
1657
typedef VipsCompositeBaseClass VipsComposite2Class;
1658
1659
/* We need C linkage for this.
1660
 */
1661
extern "C" {
1662
G_DEFINE_TYPE(VipsComposite2, vips_composite2, vips_composite_base_get_type());
1663
}
1664
1665
static int
1666
vips_composite2_build(VipsObject *object)
1667
0
{
1668
0
  VipsCompositeBase *base = (VipsCompositeBase *) object;
1669
0
  VipsComposite2 *composite2 = (VipsComposite2 *) object;
1670
1671
0
  if (composite2->overlay &&
1672
0
    composite2->base) {
1673
0
    VipsImage *in[3];
1674
0
    int mode[1];
1675
1676
0
    in[0] = composite2->base;
1677
0
    in[1] = composite2->overlay;
1678
0
    in[2] = NULL;
1679
0
    base->in = vips_array_image_new(in, 2);
1680
1681
0
    mode[0] = (int) composite2->mode;
1682
0
    base->mode = vips_array_int_new(mode, 1);
1683
0
  }
1684
1685
0
  base->x_offset = &composite2->x;
1686
0
  base->y_offset = &composite2->y;
1687
1688
0
  if (VIPS_OBJECT_CLASS(vips_composite2_parent_class)->build(object))
1689
0
    return -1;
1690
1691
0
  return 0;
1692
0
}
1693
1694
static void
1695
vips_composite2_class_init(VipsCompositeClass *klass)
1696
1
{
1697
1
  GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
1698
1
  VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS(klass);
1699
1
  VipsOperationClass *operation_class = VIPS_OPERATION_CLASS(klass);
1700
1701
1
  VIPS_DEBUG_MSG("vips_composite_class_init\n");
1702
1703
1
  gobject_class->set_property = vips_object_set_property;
1704
1
  gobject_class->get_property = vips_object_get_property;
1705
1706
1
  vobject_class->nickname = "composite2";
1707
1
  vobject_class->description =
1708
1
    _("blend a pair of images with a blend mode");
1709
1
  vobject_class->build = vips_composite2_build;
1710
1711
1
  operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
1712
1713
1
  VIPS_ARG_IMAGE(klass, "base", 0,
1714
1
    _("Base"),
1715
1
    _("Base image"),
1716
1
    VIPS_ARGUMENT_REQUIRED_INPUT,
1717
1
    G_STRUCT_OFFSET(VipsComposite2, base));
1718
1719
1
  VIPS_ARG_IMAGE(klass, "overlay", 1,
1720
1
    _("Overlay"),
1721
1
    _("Overlay image"),
1722
1
    VIPS_ARGUMENT_REQUIRED_INPUT,
1723
1
    G_STRUCT_OFFSET(VipsComposite2, overlay));
1724
1725
1
  VIPS_ARG_ENUM(klass, "mode", 3,
1726
1
    _("Blend mode"),
1727
1
    _("VipsBlendMode to join with"),
1728
1
    VIPS_ARGUMENT_REQUIRED_INPUT,
1729
1
    G_STRUCT_OFFSET(VipsComposite2, mode),
1730
1
    VIPS_TYPE_BLEND_MODE, VIPS_BLEND_MODE_OVER);
1731
1732
1
  VIPS_ARG_INT(klass, "x", 4,
1733
1
    _("x"),
1734
1
    _("x position of overlay"),
1735
1
    VIPS_ARGUMENT_OPTIONAL_INPUT,
1736
1
    G_STRUCT_OFFSET(VipsComposite2, x),
1737
1
    -VIPS_MAX_COORD, VIPS_MAX_COORD, 0);
1738
1739
1
  VIPS_ARG_INT(klass, "y", 5,
1740
1
    _("y"),
1741
1
    _("y position of overlay"),
1742
1
    VIPS_ARGUMENT_OPTIONAL_INPUT,
1743
1
    G_STRUCT_OFFSET(VipsComposite2, y),
1744
1
    -VIPS_MAX_COORD, VIPS_MAX_COORD, 0);
1745
1
}
1746
1747
static void
1748
vips_composite2_init(VipsComposite2 *composite2)
1749
0
{
1750
0
}
1751
1752
/* See conversion.c for the doc comment.
1753
 */
1754
1755
int
1756
vips_composite2(VipsImage *base, VipsImage *overlay, VipsImage **out,
1757
  VipsBlendMode mode, ...)
1758
0
{
1759
0
  va_list ap;
1760
0
  int result;
1761
1762
  /* Works for gcc and clang.
1763
   */
1764
0
#pragma GCC diagnostic push
1765
0
#pragma GCC diagnostic ignored "-Wvarargs"
1766
1767
  /* Triggers a clang compiler warning because mode might not be an int.
1768
   * I think the warning is harmless for all platforms we care about.
1769
   */
1770
0
  va_start(ap, mode);
1771
1772
0
  g_assert(sizeof(mode) == sizeof(int));
1773
1774
0
#pragma GCC diagnostic pop
1775
1776
0
  result = vips_call_split("composite2", ap, base, overlay, out, mode);
1777
0
  va_end(ap);
1778
1779
0
  return result;
1780
0
}