CR2RE Pipeline Reference Manual 1.6.10
hdrl_elemop.c
1/* $Id: hdrl_elemop.c,v 1.4 2013-10-04 08:03:14 jtaylor Exp $
2 *
3 * This file is part of the HDRL
4 * Copyright (C) 2013 European Southern Observatory
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21/*
22 * $Author: jtaylor $
23 * $Date: 2013-10-04 08:03:14 $
24 * $Revision: 1.4 $
25 * $Name: not supported by cvs2svn $
26 */
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31
32/*-----------------------------------------------------------------------------
33 Includes
34 -----------------------------------------------------------------------------*/
35
36#include "hdrl_utils.h"
37#include "hdrl_types.h"
38#include "hdrl_elemop.h"
39
40#include <cpl.h>
41#include <math.h>
42
43#ifndef SQR
44#define SQR(a) ((a) * (a))
45#endif
46
47/*-----------------------------------------------------------------------------
48 Functions
49 -----------------------------------------------------------------------------*/
50
51/* ---------------------------------------------------------------------------*/
68/* ---------------------------------------------------------------------------*/
69cpl_error_code hdrl_elemop_add(hdrl_data_t * a, hdrl_error_t * ea, size_t na,
70 const hdrl_data_t * b, const hdrl_error_t * eb, size_t nb,
71 const cpl_binary * mask)
72{
73 if (a == b && ea == eb) {
74 for (size_t i = 0; i < na; i++) {
75 if (mask == NULL || mask[i] == CPL_BINARY_0) {
76 a[i] += a[i];
77 ea[i] *= 2;
78 }
79 }
80 }
81 else {
82 cpl_ensure_code(na == nb || nb == 1, CPL_ERROR_ILLEGAL_INPUT);
83
84 if (nb == 1) {
85 for (size_t i = 0; i < na; i++) {
86 if (mask == NULL || mask[i] == CPL_BINARY_0) {
87 a[i] += b[0];
88 ea[i] = hypot(ea[i], eb[0]);
89 }
90 }
91 }
92 else {
93 for (size_t i = 0; i < na; i++) {
94 if (mask == NULL || mask[i] == CPL_BINARY_0) {
95 a[i] += b[i];
96 ea[i] = hypot(ea[i], eb[i]);
97 }
98 }
99 }
100 }
101
102 return CPL_ERROR_NONE;
103}
104
105/* ---------------------------------------------------------------------------*/
122/* ---------------------------------------------------------------------------*/
123cpl_error_code hdrl_elemop_sub(hdrl_data_t * a, hdrl_error_t * ea, size_t na,
124 const hdrl_data_t * b, const hdrl_error_t * eb, size_t nb,
125 const cpl_binary * mask)
126{
127 if (a == b && ea == eb) {
128 for (size_t i = 0; i < na; i++) {
129 if (mask == NULL || mask[i] == CPL_BINARY_0) {
130 a[i] = 0.;
131 ea[i] = 0.;
132 }
133 }
134 }
135 else {
136 cpl_ensure_code(na == nb || nb == 1, CPL_ERROR_ILLEGAL_INPUT);
137
138 if (nb == 1) {
139 for (size_t i = 0; i < na; i++) {
140 if (mask == NULL || mask[i] == CPL_BINARY_0) {
141 a[i] -= b[0];
142 ea[i] = hypot(ea[i], eb[0]);
143 }
144 }
145 }
146 else {
147 for (size_t i = 0; i < na; i++) {
148 if (mask == NULL || mask[i] == CPL_BINARY_0) {
149 a[i] -= b[i];
150 ea[i] = hypot(ea[i], eb[i]);
151 }
152 }
153 }
154 }
155
156 return CPL_ERROR_NONE;
157}
158
159/* ---------------------------------------------------------------------------*/
176/* ---------------------------------------------------------------------------*/
177cpl_error_code hdrl_elemop_mul(hdrl_data_t * a, hdrl_error_t * ea, size_t na,
178 const hdrl_data_t * b, const hdrl_error_t * eb, size_t nb,
179 const cpl_binary * mask)
180{
181 if (a == b && ea == eb) {
182 for (size_t i = 0; i < na; i++) {
183 if (mask == NULL || mask[i] == CPL_BINARY_0) {
184 const hdrl_data_t a_ = a[i] * a[i];
185 ea[i] = 2 * fabs(a[i]) * ea[i];
186 a[i] = a_;
187 }
188 }
189 }
190 else {
191 cpl_ensure_code(na == nb || nb == 1, CPL_ERROR_ILLEGAL_INPUT);
192
193 if (nb == 1) {
194 const hdrl_data_t b0 = b[0];
195 const hdrl_error_t eb0 = eb[0];
196 for (size_t i = 0; i < na; i++) {
197 if (mask == NULL || mask[i] == CPL_BINARY_0) {
198 const hdrl_data_t a_ = a[i] * b0;
199 ea[i] = hypot(eb0 * a[i], ea[i] * b0);
200 a[i] = a_;
201 }
202 }
203 }
204 else {
205 for (size_t i = 0; i < na; i++) {
206 if (mask == NULL || mask[i] == CPL_BINARY_0) {
207 const hdrl_data_t a_ = a[i] * b[i];
208 ea[i] = hypot(eb[i] * a[i], ea[i] * b[i]);
209 a[i] = a_;
210 }
211 }
212 }
213 }
214
215 return CPL_ERROR_NONE;
216}
217
218/* ---------------------------------------------------------------------------*/
239/* ---------------------------------------------------------------------------*/
240cpl_error_code hdrl_elemop_div(hdrl_data_t * a, hdrl_error_t * ea, size_t na,
241 const hdrl_data_t * b, const hdrl_error_t * eb, size_t nb,
242 const cpl_binary * mask)
243{
244 if (a == b && ea == eb) {
245 for (size_t i = 0; i < na; i++) {
246 if (mask == NULL || mask[i] == CPL_BINARY_0) {
247 ea[i] = 0.;
248 a[i] = 1.;
249 }
250 }
251 }
252 else {
253 cpl_ensure_code(na == nb || nb == 1, CPL_ERROR_ILLEGAL_INPUT);
254
255 if (nb == 1) {
256 const hdrl_data_t rb0 = 1. / b[0];
257 const hdrl_error_t eb0 = eb[0];
258 for (size_t i = 0; i < na; i++) {
259 if (mask == NULL || mask[i] == CPL_BINARY_0) {
260 const hdrl_data_t a_ = a[i] * rb0;
261 if (b[0] == 0.) {
262 a[i] = NAN;
263 ea[i] = NAN;
264 }
265 else {
266 /* sqrt((ea / b)^2 + (eb * a / b^2)^2) */
267 ea[i] = sqrt(SQR(ea[i] * rb0) +
268 SQR(eb0 * a_ * rb0));
269 a[i] = a_;
270 }
271 }
272 }
273 }
274 else {
275 for (size_t i = 0; i < na; i++) {
276 if (mask == NULL || mask[i] == CPL_BINARY_0) {
277 const hdrl_data_t rb = 1. / b[i];
278 const hdrl_data_t a_ = a[i] * rb;
279 if (b[i] == 0.) {
280 a[i] = NAN;
281 ea[i] = NAN;
282 }
283 else {
284 /* sqrt((ea / b)^2 + (eb * a / b^2)^2) */
285 ea[i] = sqrt(SQR(ea[i] * rb) +
286 SQR(eb[i] * a_ * rb));
287 a[i] = a_;
288 }
289 }
290 }
291 }
292 }
293
294 return CPL_ERROR_NONE;
295}
296
297/* Utility function with error propagation logic for pow */
298static inline void pow_scalar(hdrl_data_t base, hdrl_error_t base_e,
299 hdrl_data_t exp, hdrl_error_t exp_e,
300 hdrl_data_t* out, hdrl_error_t* out_e){
301
302 *out_e = 0.0;
303
304 if(base == 0. && exp < 0.){
305 *out = NAN;
306 *out_e = NAN;
307 return;
308 }
309
310 if(exp_e == .0 && exp == 2.0){
311 *out = base * base;
312 *out_e = fabs(2.0 * base_e * base);
313 return;
314 }
315
316 *out = pow(base, exp);
317
318 /*No exponent error*/
319 if(exp_e == 0.){
320 *out_e = fabs(*out * (exp / base * base_e));
321 return;
322 }
323
324 const hdrl_data_t log_base = log(fabs(base));
325 *out_e = fabs(*out) * sqrt(SQR( exp / base * base_e)
326 + SQR(log_base * exp_e));
327}
328
329/* ---------------------------------------------------------------------------*/
350/* ---------------------------------------------------------------------------*/
351cpl_error_code hdrl_elemop_pow(hdrl_data_t * a, hdrl_error_t * ea, size_t na,
352 const hdrl_data_t * b, const hdrl_error_t * eb, size_t nb,
353 const cpl_binary * mask)
354{
355 if (a == b && ea == eb) {
356 for (size_t i = 0; i < na; i++) {
357 if (mask == NULL || mask[i] == CPL_BINARY_0) {
358 hdrl_data_t loga = log(fabs(a[i]));
359 a[i] = pow(a[i], a[i]);
360 ea[i] = fabs(a[i]) *
361 sqrt(SQR(ea[i]) * (1. + SQR(loga) + 2 * loga));
362 }
363 }
364 }
365 else {
366 cpl_ensure_code(na == nb || nb == 1, CPL_ERROR_ILLEGAL_INPUT);
367
368 if (nb == 1) {
369 for (size_t i = 0; i < na; i++) {
370 if (mask == NULL || mask[i] == CPL_BINARY_0) {
371 pow_scalar(a[i], ea[i], b[0], eb[0], &a[i], &ea[i]);
372 }
373 }
374 }
375 else {
376 for (size_t i = 0; i < na; i++) {
377 if (mask == NULL || mask[i] == CPL_BINARY_0) {
378 pow_scalar(a[i], ea[i], b[i], eb[i], &a[i], &ea[i]);
379 }
380 }
381 }
382 }
383
384 return CPL_ERROR_NONE;
385}
386
387/* ---------------------------------------------------------------------------*/
408/* ---------------------------------------------------------------------------*/
409cpl_error_code hdrl_elemop_pow_inverted(hdrl_data_t * a, hdrl_error_t * ea, size_t na,
410 const hdrl_data_t * b, const hdrl_error_t * eb, size_t nb,
411 const cpl_binary * mask)
412{
413 if (a == b && ea == eb) {
414 /* a and b are the same image, order is irrelevant*/
415 return hdrl_elemop_pow(a, ea, na, b, eb, nb, mask);
416 }
417 else {
418 cpl_ensure_code(na == nb || nb == 1, CPL_ERROR_ILLEGAL_INPUT);
419
420 if (nb == 1) {
421 for (size_t i = 0; i < na; i++) {
422 if (mask == NULL || mask[i] == CPL_BINARY_0) {
423 pow_scalar(b[0], eb[0], a[i], ea[i], &a[i], &ea[i]);
424 }
425 }
426 }
427 else {
428 for (size_t i = 0; i < na; i++) {
429 if (mask == NULL || mask[i] == CPL_BINARY_0) {
430 pow_scalar(b[i], eb[i], a[i], ea[i], &a[i], &ea[i]);
431 }
432 }
433 }
434 }
435
436 return CPL_ERROR_NONE;
437}
438
439
440typedef cpl_error_code (hdrl_math_op_f)(
441 hdrl_data_t * a, hdrl_error_t * ea, size_t na,
442 const hdrl_data_t * b, const hdrl_error_t * eb, size_t nb,
443 const cpl_binary * mask);
444
445typedef cpl_error_code (hdrl_math_op_image_f)(
446 cpl_image * a, cpl_image * ae,
447 const cpl_image * b, const cpl_image * be);
448
449typedef cpl_error_code (hdrl_math_op_image_scalar_f)(
450 cpl_image * a, cpl_image * ae,
451 const hdrl_data_t b, const hdrl_error_t be);
452
453static cpl_error_code
454check_input(cpl_image * a, cpl_image * ae,
455 const cpl_image * b, const cpl_image * be)
456{
457 cpl_ensure_code(a, CPL_ERROR_NULL_INPUT);
458 cpl_ensure_code(ae, CPL_ERROR_NULL_INPUT);
459 cpl_ensure_code(b, CPL_ERROR_NULL_INPUT);
460 cpl_ensure_code(be, CPL_ERROR_NULL_INPUT);
461
462 cpl_ensure_code(cpl_image_get_size_x(a) == cpl_image_get_size_x(ae),
463 CPL_ERROR_INCOMPATIBLE_INPUT);
464 cpl_ensure_code(cpl_image_get_size_y(a) == cpl_image_get_size_y(ae),
465 CPL_ERROR_INCOMPATIBLE_INPUT);
466 cpl_ensure_code(cpl_image_get_size_x(b) == cpl_image_get_size_x(be),
467 CPL_ERROR_INCOMPATIBLE_INPUT);
468 cpl_ensure_code(cpl_image_get_size_y(b) == cpl_image_get_size_y(be),
469 CPL_ERROR_INCOMPATIBLE_INPUT);
470 cpl_ensure_code(cpl_image_get_size_x(a) == cpl_image_get_size_x(b),
471 CPL_ERROR_INCOMPATIBLE_INPUT);
472 cpl_ensure_code(cpl_image_get_size_y(a) == cpl_image_get_size_y(b),
473 CPL_ERROR_INCOMPATIBLE_INPUT);
474 cpl_ensure_code(cpl_image_get_type(a) == HDRL_TYPE_DATA,
475 CPL_ERROR_INCOMPATIBLE_INPUT);
476 cpl_ensure_code(cpl_image_get_type(ae) == HDRL_TYPE_ERROR,
477 CPL_ERROR_INCOMPATIBLE_INPUT);
478 cpl_ensure_code(cpl_image_get_type(b) == HDRL_TYPE_DATA,
479 CPL_ERROR_INCOMPATIBLE_INPUT);
480 cpl_ensure_code(cpl_image_get_type(be) == HDRL_TYPE_ERROR,
481 CPL_ERROR_INCOMPATIBLE_INPUT);
482
483 return CPL_ERROR_NONE;
484}
485
486
487static cpl_error_code
488hdrl_elemop_image_scalar(cpl_image * a, cpl_image * ae,
489 const hdrl_data_t b, const hdrl_error_t be,
490 hdrl_math_op_f * f)
491{
492 const cpl_binary * dmask = NULL;
493 cpl_ensure_code(a, CPL_ERROR_NULL_INPUT);
494 cpl_ensure_code(ae, CPL_ERROR_NULL_INPUT);
495 cpl_ensure_code(cpl_image_get_type(a) == HDRL_TYPE_DATA,
496 CPL_ERROR_INCOMPATIBLE_INPUT);
497 cpl_ensure_code(cpl_image_get_type(ae) == HDRL_TYPE_ERROR,
498 CPL_ERROR_INCOMPATIBLE_INPUT);
499 const cpl_mask * bpm = cpl_image_get_bpm_const(a);
500
501 if (bpm != NULL) {
502 dmask = cpl_mask_get_data_const(bpm);
503 }
504
505 if (f == hdrl_elemop_div && b == 0.) {
506 cpl_msg_warning(cpl_func, "dividing image by scalar zero");
507 cpl_image_add_scalar(a, NAN);
508 cpl_image_add_scalar(ae, NAN);
509 cpl_image_reject_value(a, CPL_VALUE_NAN);
510 cpl_image_reject_value(ae, CPL_VALUE_NAN);
511 return cpl_error_get_code();
512 }
513 else {
514 cpl_error_code err = f(hdrl_get_image_data(a),
515 hdrl_get_image_error(ae),
516 hdrl_get_image_npix(a),
517 &b, &be, 1,
518 dmask);
519 if (f == hdrl_elemop_pow || f == hdrl_elemop_pow_inverted) {
520 cpl_image_reject_value(a, CPL_VALUE_NAN);
521 cpl_image_reject_from_mask(ae, cpl_image_get_bpm(a));
522 }
523 return err;
524 }
525}
526
527/* doxygen in header */
528cpl_error_code
529hdrl_elemop_image_add_scalar(cpl_image * a, cpl_image * ae,
530 const hdrl_data_t b, const hdrl_error_t be)
531{
532 return hdrl_elemop_image_scalar(a, ae, b, be, hdrl_elemop_add);
533}
534
535cpl_error_code
536hdrl_elemop_image_sub_scalar(cpl_image * a, cpl_image * ae,
537 const hdrl_data_t b, const hdrl_error_t be)
538{
539 return hdrl_elemop_image_scalar(a, ae, b, be, hdrl_elemop_sub);
540}
541
542cpl_error_code
543hdrl_elemop_image_mul_scalar(cpl_image * a, cpl_image * ae,
544 const hdrl_data_t b, const hdrl_error_t be)
545{
546 return hdrl_elemop_image_scalar(a, ae, b, be, hdrl_elemop_mul);
547}
548
549cpl_error_code
550hdrl_elemop_image_div_scalar(cpl_image * a, cpl_image * ae,
551 const hdrl_data_t b, const hdrl_error_t be)
552{
553 return hdrl_elemop_image_scalar(a, ae, b, be, hdrl_elemop_div);
554}
555
556cpl_error_code
557hdrl_elemop_image_pow_scalar(cpl_image * a, cpl_image * ae,
558 const hdrl_data_t b, const hdrl_error_t be)
559{
560 return hdrl_elemop_image_scalar(a, ae, b, be, hdrl_elemop_pow);
561}
562
563cpl_error_code
564hdrl_elemop_image_exp_scalar(cpl_image * a, cpl_image * ae,
565 const hdrl_data_t b, const hdrl_error_t be)
566{
567 return hdrl_elemop_image_scalar(a, ae, b, be, hdrl_elemop_pow_inverted);
568}
569
570static cpl_error_code
571hdrl_elemop_image(cpl_image * a, cpl_image * ae,
572 const cpl_image * b, const cpl_image * be,
573 hdrl_math_op_f * f)
574{
575 cpl_error_code r = check_input(a, ae, b, be);
576 const cpl_binary * dmask = NULL;
577 cpl_ensure_code(r == CPL_ERROR_NONE, r);
578 const cpl_mask * bbpm = cpl_image_get_bpm_const(b);
579
580 if (bbpm != NULL) {
581 if (cpl_image_get_bpm_const(a)) {
582 /* a and b have bpm, merge them */
583 cpl_mask * abpm = cpl_image_get_bpm(a);
584 cpl_mask_or(abpm, bbpm);
585 dmask = cpl_mask_get_data_const(abpm);
586 }
587 else {
588 /* a has no bpm, copy from b */
589 cpl_image_reject_from_mask(a, bbpm);
590 dmask = cpl_mask_get_data_const(bbpm);
591 }
592 }
593 else {
594 const cpl_mask * abpm = cpl_image_get_bpm_const(a);
595 if (abpm) {
596 dmask = cpl_mask_get_data_const(abpm);
597 }
598 }
599
600 r = f(hdrl_get_image_data(a),
601 hdrl_get_image_error(ae),
602 hdrl_get_image_npix(a),
603 hdrl_get_image_data_const(b),
604 hdrl_get_image_error_const(be),
605 hdrl_get_image_npix(a),
606 dmask);
607
608 if (f == hdrl_elemop_div || f == hdrl_elemop_pow) {
609 cpl_image_reject_value(a, CPL_VALUE_NAN);
610 cpl_image_reject_from_mask(ae, cpl_image_get_bpm(a));
611 }
612
613 return r;
614}
615
616cpl_error_code
617hdrl_elemop_image_add_image(cpl_image * a, cpl_image * ae,
618 const cpl_image * b, const cpl_image * be)
619{
620 return hdrl_elemop_image(a, ae, b, be, hdrl_elemop_add);
621}
622
623cpl_error_code
624hdrl_elemop_image_sub_image(cpl_image * a, cpl_image * ae,
625 const cpl_image * b, const cpl_image * be)
626{
627 return hdrl_elemop_image(a, ae, b, be, hdrl_elemop_sub);
628}
629
630cpl_error_code
631hdrl_elemop_image_mul_image(cpl_image * a, cpl_image * ae,
632 const cpl_image * b, const cpl_image * be)
633{
634 return hdrl_elemop_image(a, ae, b, be, hdrl_elemop_mul);
635}
636
637cpl_error_code
638hdrl_elemop_image_div_image(cpl_image * a, cpl_image * ae,
639 const cpl_image * b, const cpl_image * be)
640{
641 return hdrl_elemop_image(a, ae, b, be, hdrl_elemop_div);
642}
643
644cpl_error_code
645hdrl_elemop_image_pow_image(cpl_image * a, cpl_image * ae,
646 const cpl_image * b, const cpl_image * be)
647{
648 return hdrl_elemop_image(a, ae, b, be, hdrl_elemop_pow);
649}
650
651static cpl_error_code
652hdrl_elemop_imagelist_vector(cpl_imagelist * self_d,
653 cpl_imagelist * self_e,
654 const cpl_vector * other_d,
655 const cpl_vector * other_e,
656 hdrl_math_op_image_scalar_f * f)
657{
658 cpl_ensure_code(self_d, CPL_ERROR_NULL_INPUT);
659 cpl_ensure_code(self_e, CPL_ERROR_NULL_INPUT);
660 cpl_ensure_code(other_d, CPL_ERROR_NULL_INPUT);
661 cpl_ensure_code(other_e, CPL_ERROR_NULL_INPUT);
662 const size_t nz = cpl_imagelist_get_size(self_d);
663 cpl_ensure_code(nz == (size_t)cpl_imagelist_get_size(self_e),
664 CPL_ERROR_INCOMPATIBLE_INPUT);
665 cpl_ensure_code(nz == (size_t)cpl_vector_get_size(other_d),
666 CPL_ERROR_INCOMPATIBLE_INPUT);
667 cpl_ensure_code(nz == (size_t)cpl_vector_get_size(other_e),
668 CPL_ERROR_INCOMPATIBLE_INPUT);
669
670 for (size_t i = 0; i < nz; i++) {
671 cpl_image * ad = cpl_imagelist_get(self_d, i);
672 cpl_image * ae = cpl_imagelist_get(self_e, i);
673 const double bd = cpl_vector_get(other_d, i);
674 const double be = cpl_vector_get(other_e, i);
675 f(ad, ae, bd, be);
676 }
677
678 return cpl_error_get_code();
679}
680
681cpl_error_code
682hdrl_elemop_imagelist_add_vector(cpl_imagelist * a,
683 cpl_imagelist * ae,
684 const cpl_vector * b,
685 const cpl_vector * be)
686{
687 return hdrl_elemop_imagelist_vector(a, ae, b, be,
688 hdrl_elemop_image_add_scalar);
689}
690
691cpl_error_code
692hdrl_elemop_imagelist_sub_vector(cpl_imagelist * a,
693 cpl_imagelist * ae,
694 const cpl_vector * b,
695 const cpl_vector * be)
696{
697 return hdrl_elemop_imagelist_vector(a, ae, b, be,
698 hdrl_elemop_image_sub_scalar);
699}
700
701cpl_error_code
702hdrl_elemop_imagelist_mul_vector(cpl_imagelist * a,
703 cpl_imagelist * ae,
704 const cpl_vector * b,
705 const cpl_vector * be)
706{
707 return hdrl_elemop_imagelist_vector(a, ae, b, be,
708 hdrl_elemop_image_mul_scalar);
709}
710
711cpl_error_code
712hdrl_elemop_imagelist_div_vector(cpl_imagelist * a,
713 cpl_imagelist * ae,
714 const cpl_vector * b,
715 const cpl_vector * be)
716{
717 return hdrl_elemop_imagelist_vector(a, ae, b, be,
718 hdrl_elemop_image_div_scalar);
719}
720
721cpl_error_code
722hdrl_elemop_imagelist_pow_vector(cpl_imagelist * a,
723 cpl_imagelist * ae,
724 const cpl_vector * b,
725 const cpl_vector * be)
726{
727 return hdrl_elemop_imagelist_vector(a, ae, b, be,
728 hdrl_elemop_image_pow_scalar);
729}
730
731static cpl_error_code
732hdrl_elemop_imagelist_image(cpl_imagelist * self_d,
733 cpl_imagelist * self_e,
734 const cpl_image * other_d,
735 const cpl_image * other_e,
736 hdrl_math_op_image_f * f)
737{
738 cpl_ensure_code(self_d, CPL_ERROR_NULL_INPUT);
739 cpl_ensure_code(self_e, CPL_ERROR_NULL_INPUT);
740 cpl_ensure_code(other_d, CPL_ERROR_NULL_INPUT);
741 cpl_ensure_code(other_e, CPL_ERROR_NULL_INPUT);
742 const size_t nz = cpl_imagelist_get_size(self_d);
743 cpl_ensure_code(nz == (size_t)cpl_imagelist_get_size(self_e),
744 CPL_ERROR_INCOMPATIBLE_INPUT);
745
746 for (size_t i = 0; i < nz; i++) {
747 cpl_image * ad = cpl_imagelist_get(self_d, i);
748 cpl_image * ae = cpl_imagelist_get(self_e, i);
749 f(ad, ae, other_d, other_e);
750 }
751
752 return cpl_error_get_code();
753}
754
755cpl_error_code
756hdrl_elemop_imagelist_add_image(cpl_imagelist * a,
757 cpl_imagelist * ae,
758 const cpl_image * b,
759 const cpl_image * be)
760{
761 return hdrl_elemop_imagelist_image(a, ae, b, be,
762 hdrl_elemop_image_add_image);
763}
764
765cpl_error_code
766hdrl_elemop_imagelist_sub_image(cpl_imagelist * a,
767 cpl_imagelist * ae,
768 const cpl_image * b,
769 const cpl_image * be)
770{
771 return hdrl_elemop_imagelist_image(a, ae, b, be,
772 hdrl_elemop_image_sub_image);
773}
774
775cpl_error_code
776hdrl_elemop_imagelist_mul_image(cpl_imagelist * a,
777 cpl_imagelist * ae,
778 const cpl_image * b,
779 const cpl_image * be)
780{
781 return hdrl_elemop_imagelist_image(a, ae, b, be,
782 hdrl_elemop_image_mul_image);
783}
784
785cpl_error_code
786hdrl_elemop_imagelist_div_image(cpl_imagelist * a,
787 cpl_imagelist * ae,
788 const cpl_image * b,
789 const cpl_image * be)
790{
791 return hdrl_elemop_imagelist_image(a, ae, b, be,
792 hdrl_elemop_image_div_image);
793}
794
795cpl_error_code
796hdrl_elemop_imagelist_pow_image(cpl_imagelist * a,
797 cpl_imagelist * ae,
798 const cpl_image * b,
799 const cpl_image * be)
800{
801 return hdrl_elemop_imagelist_image(a, ae, b, be,
802 hdrl_elemop_image_pow_image);
803}
804
805static cpl_error_code
806hdrl_elemop_imagelist(cpl_imagelist * self_d,
807 cpl_imagelist * self_e,
808 const cpl_imagelist * other_d,
809 const cpl_imagelist * other_e,
810 hdrl_math_op_image_f * f)
811{
812 cpl_ensure_code(self_d, CPL_ERROR_NULL_INPUT);
813 cpl_ensure_code(other_d, CPL_ERROR_NULL_INPUT);
814 cpl_ensure_code(self_e, CPL_ERROR_NULL_INPUT);
815 cpl_ensure_code(other_e, CPL_ERROR_NULL_INPUT);
816 const size_t nz = cpl_imagelist_get_size(self_d);
817 cpl_ensure_code(nz == (size_t)cpl_imagelist_get_size(self_e),
818 CPL_ERROR_INCOMPATIBLE_INPUT);
819 cpl_ensure_code(nz == (size_t)cpl_imagelist_get_size(other_d),
820 CPL_ERROR_INCOMPATIBLE_INPUT);
821 cpl_ensure_code(nz == (size_t)cpl_imagelist_get_size(other_e),
822 CPL_ERROR_INCOMPATIBLE_INPUT);
823
824 for (size_t i = 0; i < nz; i++) {
825 cpl_image * ad = cpl_imagelist_get(self_d, i);
826 cpl_image * ae = cpl_imagelist_get(self_e, i);
827 const cpl_image * bd = cpl_imagelist_get_const(other_d, i);
828 const cpl_image * be = cpl_imagelist_get_const(other_e, i);
829 f(ad, ae, bd, be);
830 }
831
832 return cpl_error_get_code();
833}
834
835cpl_error_code
836hdrl_elemop_imagelist_add_imagelist(cpl_imagelist * a,
837 cpl_imagelist * ae,
838 const cpl_imagelist * b,
839 const cpl_imagelist * be)
840{
841 return hdrl_elemop_imagelist(a, ae, b, be,
842 hdrl_elemop_image_add_image);
843}
844
845cpl_error_code
846hdrl_elemop_imagelist_sub_imagelist(cpl_imagelist * a,
847 cpl_imagelist * ae,
848 const cpl_imagelist * b,
849 const cpl_imagelist * be)
850{
851 return hdrl_elemop_imagelist(a, ae, b, be,
852 hdrl_elemop_image_sub_image);
853}
854
855cpl_error_code
856hdrl_elemop_imagelist_mul_imagelist(cpl_imagelist * a,
857 cpl_imagelist * ae,
858 const cpl_imagelist * b,
859 const cpl_imagelist * be)
860{
861 return hdrl_elemop_imagelist(a, ae, b, be,
862 hdrl_elemop_image_mul_image);
863}
864
865cpl_error_code
866hdrl_elemop_imagelist_div_imagelist(cpl_imagelist * a,
867 cpl_imagelist * ae,
868 const cpl_imagelist * b,
869 const cpl_imagelist * be)
870{
871 return hdrl_elemop_imagelist(a, ae, b, be,
872 hdrl_elemop_image_div_image);
873}
874
875cpl_error_code
876hdrl_elemop_imagelist_pow_imagelist(cpl_imagelist * a,
877 cpl_imagelist * ae,
878 const cpl_imagelist * b,
879 const cpl_imagelist * be)
880{
881 return hdrl_elemop_imagelist(a, ae, b, be,
882 hdrl_elemop_image_pow_image);
883}