26 #include <cxmessages.h>
31 #include <cpl_recipe.h>
32 #include <cpl_plugininfo.h>
33 #include <cpl_parameterlist.h>
34 #include <cpl_frameset.h>
35 #include <cpl_propertylist.h>
44 #include "gistacking.h"
50 #define GIMASTERBIAS_BIAS_EXTENSION_IMG 0
51 #define GIMASTERBIAS_BIAS_EXTENSION_PL 0
52 #define GIMASTERBIAS_BAD_PIXEL_EXTENSION 0
55 static cxint giframestack(cpl_parameterlist*, cpl_frameset*);
64 giframestack_create(cpl_plugin* plugin)
67 cpl_recipe* recipe = (cpl_recipe*)plugin;
78 recipe->parameters = cpl_parameterlist_new();
79 cx_assert(recipe->parameters != NULL);
97 giframestack_exec(cpl_plugin* plugin)
100 cpl_recipe* recipe = (cpl_recipe*)plugin;
105 if (recipe->parameters == NULL || recipe->frames == NULL) {
109 status = giframestack(recipe->parameters, recipe->frames);
121 giframestack_destroy(cpl_plugin* plugin)
124 cpl_recipe* recipe = (cpl_recipe*)plugin;
133 cpl_parameterlist_delete(recipe->parameters);
135 giraffe_error_clear();
146 giframestack(cpl_parameterlist* config, cpl_frameset* set)
149 const cxchar*
const _id =
"giframestack";
155 cxdouble exptime = 0.;
157 cx_string *tag = NULL;
159 cx_list *frames = NULL;
160 cx_list *images = NULL;
162 cx_list_iterator position;
166 cpl_propertylist *properties = NULL;
168 cpl_frame* frame = NULL;
170 cpl_frameset_iterator *it = NULL;
172 GiImage *image = NULL;
173 GiImage *result = NULL;
174 GiImage **stack = NULL;
176 GiStackingConfig *setup = NULL;
178 GiRecipeInfo info = {(cxchar*)_id, 1, NULL, config};
185 cpl_msg_error(_id,
"Invalid parameter list! Aborting ...");
199 cpl_msg_info(_id,
"Searching for frames to combine ...");
201 it = cpl_frameset_iterator_new(set);
203 frame = cpl_frameset_iterator_get(it);
206 cpl_msg_error(_id,
"Empty input frameset encountered!");
208 cpl_frameset_iterator_delete(it);
222 while (status != 0 && count < cpl_frameset_get_size(set)) {
224 cpl_frameset_iterator_advance(it, 1);
226 frame = cpl_frameset_iterator_get(it);
233 cpl_frameset_iterator_delete(it);
236 if (count == cpl_frameset_get_size(set)) {
237 cpl_msg_error(_id,
"The input frameset does not contain any "
249 tag = cx_string_create(cpl_frame_get_tag(frame));
258 cpl_msg_info(_id,
"Selecting '%s' frames for combination.",
261 frames = cx_list_new();
262 cx_list_push_back(frames, frame);
264 images = cx_list_new();
265 cx_list_push_back(images, image);
268 frame = cpl_frameset_find(set, cx_string_get(tag));
270 if (frame == cx_list_front(frames)) {
271 frame = cpl_frameset_find(set, NULL);
274 while (frame != NULL) {
276 if (frame != cx_list_front(frames)) {
282 cpl_frame_get_filename(frame), 0);
292 cx_list_push_back(frames, frame);
293 cx_list_push_back(images, _image);
298 cpl_msg_warning(_id,
"Ignoring frame '%s' because of "
300 cpl_frame_get_filename(frame));
315 frame = cpl_frameset_find(set, NULL);
325 count = cx_list_size(images);
327 if (count < setup->min_nr_frames) {
329 cpl_msg_error(_id,
"Not enough frames (%" CPL_SIZE_FORMAT
330 "). Stacking method '%d' requires at least %d frames! "
331 "Aborting...", count, setup->stackmethod,
332 setup->min_nr_frames);
337 cx_list_delete(frames);
340 cx_string_delete(tag);
355 cpl_msg_info(_id,
"Combining %" CPL_SIZE_FORMAT
" frames (%s) ...", count,
358 stack = cx_calloc(count + 1,
sizeof(GiImage*));
361 position = cx_list_begin(images);
363 while (position != cx_list_end(images)) {
364 stack[i] = cx_list_get(images, position);
365 position = cx_list_next(images, position);
371 if (result == NULL) {
373 cpl_msg_error(_id,
"Frame combination failed! Aborting ...");
381 cx_list_delete(frames);
384 cx_string_delete(tag);
405 cpl_msg_info(_id,
"Updating combined frame properties ...");
408 cx_assert(properties != NULL);
413 if (properties == NULL) {
415 cpl_msg_error(_id,
"Updating combined frame properties failed!");
423 cx_list_delete(frames);
426 cx_string_delete(tag);
433 giraffe_error_push();
435 cpl_propertylist_update_double(properties, GIALIAS_BZERO, 0.);
436 cpl_propertylist_update_double(properties, GIALIAS_CRPIX1, 1.);
439 position = cx_list_begin(images);
441 while (position != cx_list_end(images)) {
443 cpl_propertylist* p =
446 exptime += cpl_propertylist_get_double(p, GIALIAS_EXPTIME);
447 position = cx_list_next(images, position);
451 cpl_propertylist_update_double(properties, GIALIAS_EXPTTOT, exptime);
453 cpl_propertylist_update_int(properties, GIALIAS_DATANCOM, count);
455 cpl_propertylist_erase(properties, GIALIAS_EXPTIME);
456 cpl_propertylist_erase(properties, GIALIAS_TPLEXPNO);
459 if (cpl_error_get_code() != CPL_ERROR_NONE) {
461 cpl_msg_error(_id,
"Updating combined frame properties failed!");
469 cx_list_delete(frames);
472 cx_string_delete(tag);
486 cpl_msg_info(_id,
"Writing combined frame ...");
490 cx_string_append(tag,
"_COMBINED");
493 CPL_FRAME_LEVEL_FINAL, TRUE, TRUE);
497 cpl_msg_error(_id,
"Cannot create local file! Aborting ...");
505 cx_list_delete(frames);
508 cx_string_delete(tag);
515 cpl_frameset_insert(set, frame);
528 cx_list_delete(frames);
531 cx_string_delete(tag);
545 cpl_plugin_get_info(cpl_pluginlist* list)
548 cpl_recipe* recipe = cx_calloc(1,
sizeof *recipe);
549 cpl_plugin* plugin = &recipe->interface;
552 cpl_plugin_init(plugin,
554 GIRAFFE_BINARY_VERSION,
555 CPL_PLUGIN_TYPE_RECIPE,
557 "Creates a stacked image from a set of raw images.",
564 giframestack_destroy);
566 cpl_pluginlist_append(list, plugin);
cpl_frame * giraffe_frame_create_image(GiImage *image, const cxchar *tag, cpl_frame_level level, cxbool save, cxbool update)
Create an image product frame.
void giraffe_image_delete(GiImage *self)
Destroys an image.
cpl_propertylist * giraffe_image_get_properties(const GiImage *self)
Get the properties of an image.
cxint giraffe_image_add_info(GiImage *image, const GiRecipeInfo *info, const cpl_frameset *set)
Add additional frame information to an image.
cpl_image * giraffe_image_get(const GiImage *self)
Gets the image data.
GiImage * giraffe_image_new(cpl_type type)
Creates an empty image container.
cxint giraffe_image_set_properties(GiImage *self, cpl_propertylist *properties)
Attaches a property list to an image.
cxint giraffe_image_load(GiImage *self, const cxchar *filename, cxint position)
Gets image data and properties from a file.
void giraffe_stacking_config_add(cpl_parameterlist *list)
Adds parameters for the stacking of images.
void giraffe_stacking_config_destroy(GiStackingConfig *config)
Destroys a setup structure for the stacking of images.
GiStackingConfig * giraffe_stacking_config_create(cpl_parameterlist *list)
Creates a setup structure for the stacking of images.
GiImage * giraffe_stacking_stack_images(GiImage **img_array, const GiStackingConfig *config)
Stack a list of images using one of four different kinds of stacking and return the resulting image.
const cxchar * giraffe_get_license(void)
Get the pipeline copyright and license.