CR2RE Pipeline Reference Manual 1.7.0
irplib_fft.c
1/*
2 * This file is part of the IRPLIB Pipeline
3 * Copyright (C) 2002,2003,2014 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 Includes
26 -----------------------------------------------------------------------------*/
27
28#include "irplib_fft.h"
29
30/*----------------------------------------------------------------------------*/
34/*----------------------------------------------------------------------------*/
35
37
38
39/*----------------------------------------------------------------------------*/
52/*----------------------------------------------------------------------------*/
53cpl_error_code
54irplib_image_find_shift(const cpl_image *self,
55 const cpl_image *other,
56 double *px,
57 double *py)
58{
59 const cpl_size nx = cpl_image_get_size_x(self);
60 const cpl_size ny = cpl_image_get_size_y(self);
61 const cpl_size type = cpl_image_get_type(self);
62 const size_t bufsz =
63 (size_t)(nx * ny) * cpl_type_get_sizeof(type | CPL_TYPE_COMPLEX);
64 cpl_imagelist *iml;
65 cpl_imagelist *fml;
66 cpl_image *fself;
67 cpl_image *fother;
68 void *fdata;
69 cpl_error_code code = CPL_ERROR_NONE;
70
71 cpl_ensure_code(px != NULL, CPL_ERROR_NULL_INPUT);
72 cpl_ensure_code(py != NULL, CPL_ERROR_NULL_INPUT);
73
74 iml = cpl_imagelist_new();
75 /* Input images _not_ modified */
76 CPL_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
77 cpl_imagelist_set(iml, (cpl_image *)self, 0);
78 cpl_imagelist_set(iml, (cpl_image *)other, 1);
79 CPL_DIAG_PRAGMA_POP;
80
81 fdata = cpl_calloc(2, bufsz); /* Don't need two calloc()s here */
82
83 fml = cpl_imagelist_new();
84 fself = cpl_image_wrap(nx, ny, type | CPL_TYPE_COMPLEX, fdata);
85 fother =
86 cpl_image_wrap(nx, ny, type | CPL_TYPE_COMPLEX, (char *)fdata + bufsz);
87
88 cpl_imagelist_set(fml, fself, 0);
89 cpl_imagelist_set(fml, fother, 1);
90
91 if (cpl_fft_imagelist(fml, iml, CPL_FFT_FORWARD)) {
92 code = cpl_error_set_where(cpl_func);
93 }
94 else {
95 /* Should not be able to fail now */
96 cpl_size xmax = 1, ymax = 1;
97 /* Share pixel buffer with fself which is not needed at the same time */
98 cpl_image *imgpos =
99 cpl_image_wrap(nx, ny, type, cpl_image_get_data(fself));
100
101 /* Cross-correlate */
102 cpl_image_conjugate(fother, fother);
103 cpl_image_multiply(fother, fself);
104
105 cpl_fft_image(imgpos, fother, CPL_FFT_BACKWARD | CPL_FFT_NOSCALE);
106
107 cpl_image_get_maxpos(imgpos, &xmax, &ymax);
108
109 (void)cpl_image_unwrap(imgpos);
110
111 /* The pixel position starts from 1, the offset from 0 */
112 xmax--;
113 ymax--;
114
115 /* The offset is signed, from -N/2 to N/2-1 */
116 *px = 2 * xmax >= nx ? xmax - nx : xmax;
117 *py = 2 * ymax >= ny ? ymax - ny : ymax;
118 }
119
120 cpl_imagelist_unwrap(iml);
121 cpl_image_unwrap(cpl_imagelist_unset(fml, 1));
122 cpl_imagelist_delete(fml);
123
124 return code;
125}
126