Coverage Report

Created: 2025-01-28 06:33

/src/libvips/libvips/conversion/bandbool.c
Line
Count
Source (jump to first uncovered line)
1
/* bandbool.c --- bool op across image bands
2
 *
3
 * 7/12/12
4
 *  - from boolean.c
5
 */
6
7
/*
8
9
  Copyright (C) 1991-2005 The National Gallery
10
11
  This library is free software; you can redistribute it and/or
12
  modify it under the terms of the GNU Lesser General Public
13
  License as published by the Free Software Foundation; either
14
  version 2.1 of the License, or (at your option) any later version.
15
16
  This library is distributed in the hope that it will be useful,
17
  but WITHOUT ANY WARRANTY; without even the implied warranty of
18
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19
  Lesser General Public License for more details.
20
21
  You should have received a copy of the GNU Lesser General Public
22
  License along with this library; if not, write to the Free Software
23
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24
  02110-1301  USA
25
26
 */
27
28
/*
29
30
  These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
31
32
 */
33
34
/*
35
#define DEBUG
36
 */
37
38
#ifdef HAVE_CONFIG_H
39
#include <config.h>
40
#endif /*HAVE_CONFIG_H*/
41
#include <glib/gi18n-lib.h>
42
43
#include <stdio.h>
44
#include <stdlib.h>
45
46
#include <vips/vips.h>
47
48
#include "bandary.h"
49
50
typedef struct _VipsBandbool {
51
  VipsBandary parent_instance;
52
53
  VipsImage *in;
54
55
  VipsOperationBoolean operation;
56
57
} VipsBandbool;
58
59
typedef VipsBandaryClass VipsBandboolClass;
60
61
G_DEFINE_TYPE(VipsBandbool, vips_bandbool, VIPS_TYPE_BANDARY);
62
63
static int
64
vips_bandbool_build(VipsObject *object)
65
0
{
66
0
  VipsObjectClass *class = VIPS_OBJECT_GET_CLASS(object);
67
0
  VipsBandary *bandary = (VipsBandary *) object;
68
0
  VipsBandbool *bandbool = (VipsBandbool *) object;
69
70
  /* << and >> don't work over bands.
71
   */
72
0
  if (bandbool->operation == VIPS_OPERATION_BOOLEAN_LSHIFT ||
73
0
    bandbool->operation == VIPS_OPERATION_BOOLEAN_RSHIFT) {
74
0
    vips_error(class->nickname,
75
0
      _("operator %s not supported across image bands"),
76
0
      vips_enum_nick(VIPS_TYPE_OPERATION_BOOLEAN,
77
0
        bandbool->operation));
78
0
    return -1;
79
0
  }
80
81
0
  if (bandbool->in) {
82
0
    if (vips_check_noncomplex(class->nickname, bandbool->in))
83
0
      return -1;
84
85
0
    bandary->n = 1;
86
0
    bandary->in = &bandbool->in;
87
88
0
    if (bandbool->in->Bands == 1)
89
0
      return vips_bandary_copy(bandary);
90
0
  }
91
92
0
  bandary->out_bands = 1;
93
94
0
  if (VIPS_OBJECT_CLASS(vips_bandbool_parent_class)->build(object))
95
0
    return -1;
96
97
0
  return 0;
98
0
}
99
100
#define SWITCH(I, F, OP) \
101
0
  switch (vips_image_get_format(im)) { \
102
0
  case VIPS_FORMAT_UCHAR: \
103
0
    I(unsigned char, OP); \
104
0
    break; \
105
0
  case VIPS_FORMAT_CHAR: \
106
0
    I(signed char, OP); \
107
0
    break; \
108
0
  case VIPS_FORMAT_USHORT: \
109
0
    I(unsigned short, OP); \
110
0
    break; \
111
0
  case VIPS_FORMAT_SHORT: \
112
0
    I(signed short, OP); \
113
0
    break; \
114
0
  case VIPS_FORMAT_UINT: \
115
0
    I(unsigned int, OP); \
116
0
    break; \
117
0
  case VIPS_FORMAT_INT: \
118
0
    I(signed int, OP); \
119
0
    break; \
120
0
  case VIPS_FORMAT_FLOAT: \
121
0
    F(float, OP); \
122
0
    break; \
123
0
  case VIPS_FORMAT_DOUBLE: \
124
0
    F(double, OP); \
125
0
    break; \
126
0
\
127
0
  default: \
128
0
    g_assert_not_reached(); \
129
0
  }
130
131
#define LOOPB(TYPE, OP) \
132
0
  { \
133
0
    TYPE *p = (TYPE *) in[0]; \
134
0
    TYPE *q = (TYPE *) out; \
135
0
\
136
0
    for (x = 0; x < width; x++) { \
137
0
      TYPE acc; \
138
0
\
139
0
      acc = p[0]; \
140
0
      for (b = 1; b < bands; b++) \
141
0
        acc = acc OP p[b]; \
142
0
\
143
0
      q[x] = acc; \
144
0
      p += bands; \
145
0
    } \
146
0
  }
147
148
#define FLOOPB(TYPE, OP) \
149
0
  { \
150
0
    TYPE *p = (TYPE *) in[0]; \
151
0
    int *q = (int *) out; \
152
0
\
153
0
    for (x = 0; x < width; x++) { \
154
0
      int acc; \
155
0
\
156
0
      acc = (int) p[0]; \
157
0
      for (b = 1; b < bands; b++) \
158
0
        acc = acc OP((int) p[b]); \
159
0
\
160
0
      q[x] = acc; \
161
0
      p += bands; \
162
0
    } \
163
0
  }
164
165
static void
166
vips_bandbool_buffer(VipsBandarySequence *seq,
167
  VipsPel *out, VipsPel **in, int width)
168
0
{
169
0
  VipsBandary *bandary = seq->bandary;
170
0
  VipsBandbool *bandbool = (VipsBandbool *) bandary;
171
0
  VipsImage *im = bandary->ready[0];
172
0
  int bands = im->Bands;
173
174
0
  int x, b;
175
176
0
  switch (bandbool->operation) {
177
0
  case VIPS_OPERATION_BOOLEAN_AND:
178
0
    SWITCH(LOOPB, FLOOPB, &);
179
0
    break;
180
181
0
  case VIPS_OPERATION_BOOLEAN_OR:
182
0
    SWITCH(LOOPB, FLOOPB, |);
183
0
    break;
184
185
0
  case VIPS_OPERATION_BOOLEAN_EOR:
186
0
    SWITCH(LOOPB, FLOOPB, ^);
187
0
    break;
188
189
0
  default:
190
0
    g_assert_not_reached();
191
0
  }
192
0
}
193
194
/* Save a bit of typing.
195
 */
196
#define UC VIPS_FORMAT_UCHAR
197
#define C VIPS_FORMAT_CHAR
198
#define US VIPS_FORMAT_USHORT
199
#define S VIPS_FORMAT_SHORT
200
#define UI VIPS_FORMAT_UINT
201
#define I VIPS_FORMAT_INT
202
#define F VIPS_FORMAT_FLOAT
203
#define X VIPS_FORMAT_COMPLEX
204
#define D VIPS_FORMAT_DOUBLE
205
#define DX VIPS_FORMAT_DPCOMPLEX
206
207
/* Format conversions for boolean.
208
 */
209
static const VipsBandFormat vips_bandbool_format_table[10] = {
210
  /* Band format:  UC  C  US  S  UI  I  F  X  D  DX */
211
  /* Promotion: */ UC, C, US, S, UI, I, I, I, I, I
212
};
213
214
static void
215
vips_bandbool_class_init(VipsBandboolClass *class)
216
1
{
217
1
  GObjectClass *gobject_class = G_OBJECT_CLASS(class);
218
1
  VipsObjectClass *object_class = (VipsObjectClass *) class;
219
1
  VipsBandaryClass *bandary_class = VIPS_BANDARY_CLASS(class);
220
221
1
  gobject_class->set_property = vips_object_set_property;
222
1
  gobject_class->get_property = vips_object_get_property;
223
224
1
  object_class->nickname = "bandbool";
225
1
  object_class->description = _("boolean operation across image bands");
226
1
  object_class->build = vips_bandbool_build;
227
228
1
  bandary_class->process_line = vips_bandbool_buffer;
229
1
  bandary_class->format_table = vips_bandbool_format_table;
230
231
1
  VIPS_ARG_IMAGE(class, "in", 0,
232
1
    _("Input"),
233
1
    _("Input image argument"),
234
1
    VIPS_ARGUMENT_REQUIRED_INPUT,
235
1
    G_STRUCT_OFFSET(VipsBandbool, in));
236
237
1
  VIPS_ARG_ENUM(class, "boolean", 200,
238
1
    _("Operation"),
239
1
    _("Boolean to perform"),
240
1
    VIPS_ARGUMENT_REQUIRED_INPUT,
241
1
    G_STRUCT_OFFSET(VipsBandbool, operation),
242
1
    VIPS_TYPE_OPERATION_BOOLEAN,
243
1
    VIPS_OPERATION_BOOLEAN_AND);
244
1
}
245
246
static void
247
vips_bandbool_init(VipsBandbool *bandbool)
248
0
{
249
0
  bandbool->operation = VIPS_OPERATION_BOOLEAN_AND;
250
0
}
251
252
static int
253
vips_bandboolv(VipsImage *in, VipsImage **out,
254
  VipsOperationBoolean operation, va_list ap)
255
0
{
256
0
  return vips_call_split("bandbool", ap, in, out, operation);
257
0
}
258
259
/**
260
 * vips_bandbool: (method)
261
 * @in: left-hand input #VipsImage
262
 * @out: (out): output #VipsImage
263
 * @boolean: boolean operation to perform
264
 * @...: %NULL-terminated list of optional named arguments
265
 *
266
 * Perform various boolean operations across the bands of an image. For
267
 * example, a three-band uchar image operated on with
268
 * #VIPS_OPERATION_BOOLEAN_AND will produce a one-band uchar image where each
269
 * pixel is the bitwise and of the band elements of the corresponding pixel in
270
 * the input image.
271
 *
272
 * The output image is the same format as the input image for integer
273
 * types. Float types are cast to int before processing. Complex types are not
274
 * supported.
275
 *
276
 * The output image always has one band.
277
 *
278
 * This operation is useful in conjunction with vips_relational(). You can use
279
 * it to see if all image bands match exactly.
280
 *
281
 * See also: vips_boolean_const().
282
 *
283
 * Returns: 0 on success, -1 on error
284
 */
285
int
286
vips_bandbool(VipsImage *in, VipsImage **out,
287
  VipsOperationBoolean boolean, ...)
288
0
{
289
0
  va_list ap;
290
0
  int result;
291
292
0
  va_start(ap, boolean);
293
0
  result = vips_bandboolv(in, out, boolean, ap);
294
0
  va_end(ap);
295
296
0
  return result;
297
0
}
298
299
/**
300
 * vips_bandand: (method)
301
 * @in: left-hand input #VipsImage
302
 * @out: (out): output #VipsImage
303
 * @...: %NULL-terminated list of optional named arguments
304
 *
305
 * Perform #VIPS_OPERATION_BOOLEAN_AND on an image. See
306
 * vips_bandbool().
307
 *
308
 * Returns: 0 on success, -1 on error
309
 */
310
int
311
vips_bandand(VipsImage *in, VipsImage **out, ...)
312
0
{
313
0
  va_list ap;
314
0
  int result;
315
316
0
  va_start(ap, out);
317
0
  result = vips_bandboolv(in, out, VIPS_OPERATION_BOOLEAN_AND, ap);
318
0
  va_end(ap);
319
320
0
  return result;
321
0
}
322
323
/**
324
 * vips_bandor: (method)
325
 * @in: left-hand input #VipsImage
326
 * @out: (out): output #VipsImage
327
 * @...: %NULL-terminated list of optional named arguments
328
 *
329
 * Perform #VIPS_OPERATION_BOOLEAN_OR on an image. See
330
 * vips_bandbool().
331
 *
332
 * Returns: 0 on success, -1 on error
333
 */
334
int
335
vips_bandor(VipsImage *in, VipsImage **out, ...)
336
0
{
337
0
  va_list ap;
338
0
  int result;
339
340
0
  va_start(ap, out);
341
0
  result = vips_bandboolv(in, out, VIPS_OPERATION_BOOLEAN_OR, ap);
342
0
  va_end(ap);
343
344
0
  return result;
345
0
}
346
347
/**
348
 * vips_bandeor: (method)
349
 * @in: left-hand input #VipsImage
350
 * @out: (out): output #VipsImage
351
 * @...: %NULL-terminated list of optional named arguments
352
 *
353
 * Perform #VIPS_OPERATION_BOOLEAN_EOR on an image. See
354
 * vips_bandbool().
355
 *
356
 * Returns: 0 on success, -1 on error
357
 */
358
int
359
vips_bandeor(VipsImage *in, VipsImage **out, ...)
360
0
{
361
0
  va_list ap;
362
0
  int result;
363
364
0
  va_start(ap, out);
365
0
  result = vips_bandboolv(in, out, VIPS_OPERATION_BOOLEAN_EOR, ap);
366
0
  va_end(ap);
367
368
0
  return result;
369
0
}