[go: up one dir, main page]

File: sum.c

package info (click to toggle)
siril 0.9.10-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 23,168 kB
  • sloc: ansic: 43,770; cpp: 6,893; sh: 2,958; makefile: 365; xml: 185
file content (174 lines) | stat: -rw-r--r-- 5,587 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
 * This file is part of Siril, an astronomy image processor.
 * Copyright (C) 2005-2011 Francois Meyer (dulle at free.fr)
 * Copyright (C) 2012-2019 team free-astro (see more in AUTHORS file)
 * Reference site is https://free-astro.org/index.php/Siril
 *
 * Siril is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Siril is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Siril. If not, see <http://www.gnu.org/licenses/>.
 */

#include "core/siril.h"
#include "core/processing.h"
#include "core/proto.h"		// FITS functions
#include "io/sequence.h"
#include "stacking.h"

struct sum_stacking_data {
	unsigned long *sum[3];	// the new image's channels
	double exposure;	// sum of the exposures
	int reglayer;		// layer used for registration data
};

static int sum_stacking_prepare_hook(struct generic_seq_args *args) {
	struct sum_stacking_data *ssdata = args->user;
	unsigned int nbdata = args->seq->ry * args->seq->rx;
	ssdata->sum[0] = calloc(nbdata, sizeof(unsigned long)*args->seq->nb_layers);
	if (ssdata->sum[0] == NULL){
		printf("Stacking: memory allocation failure\n");
		return -1;
	}
	if(args->seq->nb_layers == 3){
		ssdata->sum[1] = ssdata->sum[0] + nbdata;	// index of green layer in sum[0]
		ssdata->sum[2] = ssdata->sum[0] + nbdata*2;	// index of blue layer in sum[0]
	} else {
		ssdata->sum[1] = NULL;
		ssdata->sum[2] = NULL;
	}

	ssdata->exposure = 0.0;
	return 0;
}

static int sum_stacking_image_hook(struct generic_seq_args *args, int o, int i, fits *fit, rectangle *_) {
	struct sum_stacking_data *ssdata = args->user;
	int shiftx, shifty, nx, ny, x, y, ii, layer;
	int pixel = 0;	// index in sum[0]

#ifdef _OPENMP
#pragma omp atomic
#endif
	ssdata->exposure += fit->exposure;
	
	if (ssdata->reglayer != -1 && args->seq->regparam[ssdata->reglayer]) {
		shiftx = roundf_to_int(args->seq->regparam[ssdata->reglayer][i].shiftx * args->seq->upscale_at_stacking);
		shifty = roundf_to_int(args->seq->regparam[ssdata->reglayer][i].shifty * args->seq->upscale_at_stacking);
	} else {
		shiftx = 0;
		shifty = 0;
	}

	for (y=0; y < fit->ry; ++y){
		for (x=0; x < fit->rx; ++x){
			nx = x - shiftx;
			ny = y - shifty;
			if (nx >= 0 && nx < fit->rx && ny >= 0 && ny < fit->ry) {
				// we have data for this pixel
				ii = ny * fit->rx + nx;		// index in source image
				if (ii >= 0 && ii < fit->rx * fit->ry){
					for(layer=0; layer<args->seq->nb_layers; ++layer) {
#ifdef _OPENMP
#pragma omp atomic
#endif
						ssdata->sum[layer][pixel] += fit->pdata[layer][ii];
					}
				}
			}
			++pixel;
		}
	}
	return 0;
}

// convert the result and store it into gfit
static int sum_stacking_finalize_hook(struct generic_seq_args *args) {
	struct sum_stacking_data *ssdata = args->user;
	unsigned long max = 0L;	// max value of the image's channels
	unsigned int i, nbdata;
	int layer;

	nbdata = args->seq->ry * args->seq->rx * args->seq->nb_layers;
	// find the max first
	#pragma omp parallel for reduction(max:max)
	for (i=0; i < nbdata; ++i)
		if (ssdata->sum[0][i] > max)
			max = ssdata->sum[0][i];

	clearfits(&gfit);
	fits *fit = &gfit;
	if (new_fit_image(&fit, args->seq->rx, args->seq->ry, args->seq->nb_layers))
		return -1;

	/* We copy metadata from reference to the final fit */
	if (args->seq->type == SEQ_REGULAR) {
		int ref = 0;
		// FIXME: sum stacking does not have a reference, should we add
		// it or use another image here?
		if (args->seq->reference_image > 0)
			ref = args->seq->reference_image;
		if (!seq_open_image(args->seq, ref)) {
			import_metadata_from_fitsfile(args->seq->fptr[ref], &gfit);
			seq_close_image(args->seq, ref);
		}
	}

	gfit.hi = round_to_WORD(max);
	gfit.exposure = ssdata->exposure;
	gfit.bitpix = gfit.orig_bitpix = USHORT_IMG;

	double ratio = 1.0;
	if (max > USHRT_MAX)
		ratio = USHRT_MAX_DOUBLE / (double)max;

	nbdata = args->seq->ry * args->seq->rx;
	for (layer=0; layer<args->seq->nb_layers; ++layer){
		unsigned long* from = ssdata->sum[layer];
		WORD *to = gfit.pdata[layer];
		for (i=0; i < nbdata; ++i) {
			if (ratio == 1.0)
				*to++ = round_to_WORD(*from++);
			else	*to++ = round_to_WORD((double)(*from++) * ratio);
		}
	}

	free(ssdata->sum[0]);
	return 0;
}

int stack_summing_generic(struct stacking_args *stackargs) {
	struct generic_seq_args *args = malloc(sizeof(struct generic_seq_args));
	args->seq = stackargs->seq;
	args->partial_image = FALSE;
	args->filtering_criterion = stackargs->filtering_criterion;
	args->filtering_parameter = stackargs->filtering_parameter;
	args->nb_filtered_images = stackargs->nb_images_to_stack;
	args->prepare_hook = sum_stacking_prepare_hook;
	args->image_hook = sum_stacking_image_hook;
	args->save_hook = NULL;
	args->finalize_hook = sum_stacking_finalize_hook;
	args->idle_function = NULL;
	args->stop_on_error = TRUE;
	args->description = _("Sum stacking");
	args->has_output = FALSE;
	args->already_in_a_thread = TRUE;
	args->parallel = TRUE;

	struct sum_stacking_data *ssdata = malloc(sizeof(struct sum_stacking_data));
	ssdata->reglayer = stackargs->reglayer;
	args->user = ssdata;

	//start_in_new_thread(generic_sequence_worker, args);
	generic_sequence_worker(args);
	return args->retval;
}