CR2RE Pipeline Reference Manual 1.6.2
cr2res_util_trace.c
1/*
2 * This file is part of the CR2RES Pipeline
3 * Copyright (C) 2002,2003 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 <cpl.h>
29#include "hdrl.h"
30
31#include "cr2res_utils.h"
32#include "cr2res_pfits.h"
33#include "cr2res_dfs.h"
34#include "cr2res_io.h"
35#include "cr2res_trace.h"
36#include "cr2res_wave.h"
37
38/*-----------------------------------------------------------------------------
39 Define
40 -----------------------------------------------------------------------------*/
41
42#define RECIPE_STRING "cr2res_util_trace"
43
44/*-----------------------------------------------------------------------------
45 Plugin registration
46 -----------------------------------------------------------------------------*/
47
48int cpl_plugin_get_info(cpl_pluginlist * list);
49
50/*-----------------------------------------------------------------------------
51 Private function prototypes
52 -----------------------------------------------------------------------------*/
53
54static cpl_frameset * cr2res_util_trace_find_RAW(const cpl_frameset * in) ;
55static int cr2res_util_trace_create(cpl_plugin *);
56static int cr2res_util_trace_exec(cpl_plugin *);
57static int cr2res_util_trace_destroy(cpl_plugin *);
58static int cr2res_util_trace(cpl_frameset *, const cpl_parameterlist *);
59
60/*-----------------------------------------------------------------------------
61 Static variables
62 -----------------------------------------------------------------------------*/
63
64static char cr2res_util_trace_description[] = "\
65Traces detection \n\
66 This utility detects the traces, fits polynomials on their edges \n\
67 (Upper and Lower) and in their centers (All), and stores these \n\
68 informations in the TRACE_WAVE file. \n\
69 Each trace is uniquely identified by its Order/TraceNb values. \n\
70 The Order values refer to the keywords indices (e.g. HIERARCH ESO INS \n\
71 WLEN CENY4) in the product headers. \n\
72 The TraceNb starts with 1, identifies traces within the same order. \n\
73 The additional columns : \n\
74 "CR2RES_COL_WAVELENGTH" \n\
75 "CR2RES_COL_WAVELENGTH_ERROR" \n\
76 "CR2RES_COL_SLIT_CURV_A" \n\
77 "CR2RES_COL_SLIT_CURV_B" \n\
78 "CR2RES_COL_SLIT_CURV_C" \n\
79 "CR2RES_COL_SLIT_FRACTION" \n\
80 are filled with default values. \n\
81 \n\
82 Inputs \n\
83 raw.fits " CR2RES_FLAT_RAW " [1 to n] \n\
84 or " CR2RES_UTIL_CALIB_PROCATG " \n\
85 \n\
86 Outputs \n\
87 <input_name>_tw.fits " CR2RES_UTIL_TRACE_TW_PROCATG" \n\
88 \n\
89 Algorithm \n\
90 loop on input raw frames f: \n\
91 loop on detectors d: \n\
92 Use cr2res_trace(--degree, --min_cluster, --smooth, --opening) \n\
93 to measure the traces \n\
94 if --split_traces, call cr2res_trace_split_traces() to split \n\
95 the traces \n\
96 Use cr2res_trace_add_extra_columns() to add the additional \n\
97 columns (slit fraction, wl, slit curvature) \n\
98 Save the trace wave table \n\
99 \n\
100 Library functions used \n\
101 cr2res_io_load_image() \n\
102 cr2res_trace() \n\
103 cr2res_trace_add_extra_columns() \n\
104 cr2res_trace_split_traces() \n\
105 cr2res_io_save_TRACE_WAVE() \n\
106" ;
107
108/*-----------------------------------------------------------------------------
109 Function code
110 -----------------------------------------------------------------------------*/
111
112/*----------------------------------------------------------------------------*/
122/*----------------------------------------------------------------------------*/
123int cpl_plugin_get_info(cpl_pluginlist * list)
124{
125 cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe );
126 cpl_plugin * plugin = &recipe->interface;
127
128 if (cpl_plugin_init(plugin,
129 CPL_PLUGIN_API,
130 CR2RES_BINARY_VERSION,
131 CPL_PLUGIN_TYPE_RECIPE,
132 RECIPE_STRING,
133 "Trace utility",
134 cr2res_util_trace_description,
135 CR2RES_PIPELINE_AUTHORS,
136 PACKAGE_BUGREPORT,
138 cr2res_util_trace_create,
139 cr2res_util_trace_exec,
140 cr2res_util_trace_destroy)) {
141 cpl_msg_error(cpl_func, "Plugin initialization failed");
142 (void)cpl_error_set_where(cpl_func);
143 return 1;
144 }
145
146 if (cpl_pluginlist_append(list, plugin)) {
147 cpl_msg_error(cpl_func, "Error adding plugin to list");
148 (void)cpl_error_set_where(cpl_func);
149 return 1;
150 }
151 return 0;
152}
153
154/*----------------------------------------------------------------------------*/
162/*----------------------------------------------------------------------------*/
163static int cr2res_util_trace_create(cpl_plugin * plugin)
164{
165 cpl_recipe * recipe;
166 cpl_parameter * p;
167
168 /* Check that the plugin is part of a valid recipe */
169 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
170 recipe = (cpl_recipe *)plugin;
171 else
172 return -1;
173
174 /* Create the parameters list in the cpl_recipe object */
175 recipe->parameters = cpl_parameterlist_new();
176
177 /* Fill the parameters list */
178 p = cpl_parameter_new_value("cr2res.cr2res_util_trace.degree",
179 CPL_TYPE_INT, "polynomial degree for the fit to the orders",
180 "cr2res.cr2res_util_trace", 2);
181 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "degree");
182 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
183 cpl_parameterlist_append(recipe->parameters, p);
184
185 p = cpl_parameter_new_value("cr2res.cr2res_util_trace.min_cluster",
186 CPL_TYPE_INT, "size in pixels of the smallest allowed cluster",
187 "cr2res.cr2res_util_trace", 200000);
188 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "min_cluster");
189 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
190 cpl_parameterlist_append(recipe->parameters, p);
191
192 p = cpl_parameter_new_value("cr2res.cr2res_util_trace.smooth_x",
193 CPL_TYPE_INT, "Length of the smoothing kernel in x",
194 "cr2res.cr2res_util_trace", 111);
195 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "smooth_x");
196 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
197 cpl_parameterlist_append(recipe->parameters, p);
198
199 p = cpl_parameter_new_value("cr2res.cr2res_util_trace.smooth_y",
200 CPL_TYPE_INT, "Length of the smoothing kernel in y",
201 "cr2res.cr2res_util_trace", 401);
202 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "smooth_y");
203 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
204 cpl_parameterlist_append(recipe->parameters, p);
205
206 p = cpl_parameter_new_value("cr2res.cr2res_util_trace.threshold",
207 CPL_TYPE_DOUBLE, "Detection Threshold",
208 "cr2res.cr2res_util_trace", 3.0);
209 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "threshold");
210 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
211 cpl_parameterlist_append(recipe->parameters, p);
212
213 /*
214 p = cpl_parameter_new_value("cr2res.cr2res_util_trace.trace_filter",
215 CPL_TYPE_BOOL, "Only keep the predefined order traces",
216 "cr2res.cr2res_util_trace", TRUE);
217 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "trace_filter");
218 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
219 cpl_parameterlist_append(recipe->parameters, p) ;
220 */
221
222 p = cpl_parameter_new_value("cr2res.cr2res_util_trace.opening",
223 CPL_TYPE_BOOL, "Use a morphological opening to rejoin clusters",
224 "cr2res.cr2res_util_trace", TRUE);
225 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "opening");
226 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
227 cpl_parameterlist_append(recipe->parameters, p);
228
229 p = cpl_parameter_new_value("cr2res.cr2res_util_trace.split_traces",
230 CPL_TYPE_INT, "Split the full slit traces",
231 "cr2res.cr2res_util_trace", 0);
232 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "split_traces");
233 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
234 cpl_parameterlist_append(recipe->parameters, p);
235
236 p = cpl_parameter_new_value("cr2res.cr2res_util_trace.detector",
237 CPL_TYPE_INT, "Only reduce the specified detector",
238 "cr2res.cr2res_util_trace", 0);
239 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "detector");
240 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
241 cpl_parameterlist_append(recipe->parameters, p);
242
243 return 0;
244}
245
246/*----------------------------------------------------------------------------*/
252/*----------------------------------------------------------------------------*/
253static int cr2res_util_trace_exec(cpl_plugin * plugin)
254{
255 cpl_recipe *recipe;
256
257 /* Get the recipe out of the plugin */
258 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
259 recipe = (cpl_recipe *)plugin;
260 else return -1;
261
262 return cr2res_util_trace(recipe->frames, recipe->parameters);
263}
264
265/*----------------------------------------------------------------------------*/
271/*----------------------------------------------------------------------------*/
272static int cr2res_util_trace_destroy(cpl_plugin * plugin)
273{
274 cpl_recipe *recipe;
275
276 /* Get the recipe out of the plugin */
277 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
278 recipe = (cpl_recipe *)plugin;
279 else return -1 ;
280
281 cpl_parameterlist_delete(recipe->parameters);
282 return 0 ;
283}
284
285/*----------------------------------------------------------------------------*/
292/*----------------------------------------------------------------------------*/
293static int cr2res_util_trace(
294 cpl_frameset * frameset,
295 const cpl_parameterlist * parlist)
296{
297 const cpl_parameter * param;
298 int min_cluster, degree, opening, reduce_det,
299 split_traces, smooth_x, smooth_y, trace_filter ;
300 double threshold ;
301 cpl_frameset * rawframes ;
302 cpl_frameset * cur_fset ;
303 char * out_file;
304 hdrl_image * flat_ima ;
305 cpl_image * debug_ima ;
306 int det_nr, zp_order ;
307 cpl_propertylist * plist ;
308 cpl_table * filtered_traces ;
309 char * setting_id ;
310 cpl_table * traces_tmp ;
311 cpl_table * traces[CR2RES_NB_DETECTORS] ;
312 cpl_propertylist * ext_plist[CR2RES_NB_DETECTORS] ;
313 int i ;
314
315 /* RETRIEVE INPUT PARAMETERS */
316 param = cpl_parameterlist_find_const(parlist,
317 "cr2res.cr2res_util_trace.min_cluster");
318 min_cluster = cpl_parameter_get_int(param);
319 param = cpl_parameterlist_find_const(parlist,
320 "cr2res.cr2res_util_trace.degree");
321 degree = cpl_parameter_get_int(param);
322 param = cpl_parameterlist_find_const(parlist,
323 "cr2res.cr2res_util_trace.smooth_x");
324 smooth_x = cpl_parameter_get_int(param);
325 param = cpl_parameterlist_find_const(parlist,
326 "cr2res.cr2res_util_trace.smooth_y");
327 smooth_y = cpl_parameter_get_int(param);
328 param = cpl_parameterlist_find_const(parlist,
329 "cr2res.cr2res_util_trace.threshold");
330 threshold = cpl_parameter_get_double(param);
331 param = cpl_parameterlist_find_const(parlist,
332 "cr2res.cr2res_util_trace.opening");
333 opening = cpl_parameter_get_bool(param);
334 /*
335 param = cpl_parameterlist_find_const(parlist,
336 "cr2res.cr2res_util_trace.trace_filter");
337 trace_filter = cpl_parameter_get_bool(param);
338 */
339 trace_filter = 0 ;
340 param = cpl_parameterlist_find_const(parlist,
341 "cr2res.cr2res_util_trace.split_traces");
342 split_traces = cpl_parameter_get_int(param);
343 param = cpl_parameterlist_find_const(parlist,
344 "cr2res.cr2res_util_trace.detector");
345 reduce_det = cpl_parameter_get_int(param);
346
347 /* Check Parameters */
348
349 /* Identify the RAW and CALIB frames in the input frameset */
350 if (cr2res_dfs_set_groups(frameset) != CPL_ERROR_NONE) {
351 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
352 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
353 return -1 ;
354 }
355
356 /* Get Calibration frames */
357
358 /* Get the rawframes */
359 rawframes = cr2res_util_trace_find_RAW(frameset) ;
360 if (rawframes==NULL || cpl_frameset_get_size(rawframes) <= 0) {
361 cpl_msg_error(__func__, "Cannot find any RAW file") ;
362 cpl_error_set(__func__, CPL_ERROR_DATA_NOT_FOUND) ;
363 return -1 ;
364 }
365
366 /* Loop on the RAW frames */
367 for (i = 0; i < cpl_frameset_get_size(rawframes); i++) {
368 const cpl_frame *cur_frame;
369 const char *cur_fname;
370 /* Get the Current Frame */
371 cur_frame = cpl_frameset_get_position(rawframes, i) ;
372 cur_fname = cpl_frame_get_filename(cur_frame) ;
373 cpl_msg_info(__func__, "Reduce Frame %s", cur_fname) ;
374 cpl_msg_indent_more() ;
375
376 /* Loop over the detectors */
377 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
378
379 /* Initialise */
380 traces[det_nr-1] = NULL ;
381
382 /* Store the extension header for product saving */
383 ext_plist[det_nr-1] = cpl_propertylist_load(cur_fname,
384 cr2res_io_get_ext_idx(cur_fname, det_nr, 1)) ;
385
386 /* Compute only one detector */
387 if (reduce_det != 0 && det_nr != reduce_det) continue ;
388
389 cpl_msg_info(__func__, "Process detector number %d", det_nr) ;
390 cpl_msg_indent_more() ;
391
392 /* Load the image in which the orders are to extract*/
393 cpl_msg_info(__func__, "Load the Image") ;
394 if ((flat_ima = cr2res_io_load_image(cur_fname, det_nr)) == NULL) {
395 cpl_msg_warning(__func__,
396 "Cannot load the image - skip detector");
397 cpl_error_reset() ;
398 cpl_msg_indent_less() ;
399 continue ;
400 }
401
402 /* Get the traces */
403 cpl_msg_info(__func__, "Compute the traces") ;
404 cpl_msg_indent_more() ;
405 if ((traces[det_nr-1] = cr2res_trace(hdrl_image_get_image(flat_ima),
406 smooth_x, smooth_y, threshold, opening, degree,
407 min_cluster)) == NULL) {
408 cpl_msg_warning(__func__,
409 "Cannot compute trace - skip detector");
410 cpl_error_reset() ;
411 hdrl_image_delete(flat_ima) ;
412 cpl_msg_indent_less() ;
413 cpl_msg_indent_less() ;
414 continue ;
415 }
416 cpl_msg_indent_less() ;
417
418 /* Add The remaining Columns to the trace table */
419 if (cr2res_trace_add_extra_columns(traces[det_nr-1],
420 cur_fname, det_nr) != 0) {
421 cpl_msg_warning(__func__,
422 "Cannot complete the trace table - skip detector");
423 cpl_error_reset() ;
424 hdrl_image_delete(flat_ima) ;
425 cpl_table_delete(traces[det_nr-1]) ;
426 traces[det_nr-1] = NULL ;
427 cpl_msg_indent_less() ;
428 continue ;
429 }
430
431 /* Filter out traces */
432 if (trace_filter) {
433 cpl_msg_info(__func__, "Filter out the traces") ;
434 cpl_msg_indent_more() ;
435
436 /* Get the setting and the zp_order */
437 plist = cpl_propertylist_load(cur_fname, 0) ;
438 setting_id = cpl_strdup(cr2res_pfits_get_wlen_id(plist)) ;
439 zp_order = cr2res_pfits_get_order_zp(plist) ;
440 cpl_propertylist_delete(plist) ;
441 filtered_traces = cr2res_trace_filter(traces[det_nr-1],
442 setting_id, zp_order) ;
443 cpl_free(setting_id) ;
444 cpl_table_delete(traces[det_nr-1]) ;
445 traces[det_nr-1] = filtered_traces ;
446 cpl_msg_indent_less() ;
447 if (cpl_table_get_nrow(traces[det_nr-1]) == 0) {
448 cpl_msg_error(__func__, "All traces are filtered out") ;
449 hdrl_image_delete(flat_ima) ;
450 cpl_table_delete(traces[det_nr-1]) ;
451 traces[det_nr-1] = NULL ;
452 cpl_msg_indent_less() ;
453 continue ;
454 }
455 }
456
457 /* Split the traces when required */
458 if (split_traces) {
459 cpl_msg_info(__func__,
460 "Split the full slit traces in %d traces",
461 split_traces);
462 /* Split the full slit traces */
463 if ((traces_tmp = cr2res_trace_split(traces[det_nr-1], -100,
464 split_traces)) == NULL) {
465 cpl_msg_warning(__func__,
466 "Failed splitting the traces - skip detector") ;
467 cpl_error_reset() ;
468 hdrl_image_delete(flat_ima) ;
469 cpl_table_delete(traces[det_nr-1]) ;
470 traces[det_nr-1] = NULL ;
471 cpl_msg_indent_less() ;
472 continue ;
473 } else {
474 cpl_table_delete(traces[det_nr-1]) ;
475 traces[det_nr-1] = traces_tmp ;
476 traces_tmp = NULL ;
477 }
478 }
479
480 /* Debug Image */
481 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
482 debug_ima = cr2res_trace_gen_image(traces[det_nr-1],
483 hdrl_image_get_size_x(flat_ima),
484 hdrl_image_get_size_y(flat_ima)) ;
485 out_file = cpl_sprintf("debug_%s_trace_map_%d.fits",
487 det_nr);
488 cpl_image_save(debug_ima, out_file, CPL_BPP_IEEE_DOUBLE, NULL,
489 CPL_IO_CREATE) ;
490 cpl_free(out_file);
491 cpl_image_delete(debug_ima) ;
492 }
493 hdrl_image_delete(flat_ima) ;
494 cpl_msg_indent_less() ;
495 }
496 cpl_msg_indent_less() ;
497
498 /* Save the Products */
499 out_file = cpl_sprintf("%s_tw.fits",
501 cur_fset = cpl_frameset_new() ;
502 cpl_frameset_insert(cur_fset, cpl_frame_duplicate(cur_frame)) ;
503 cr2res_io_save_TRACE_WAVE(out_file, frameset, cur_fset, parlist, traces,
504 NULL, ext_plist, CR2RES_UTIL_TRACE_TW_PROCATG, RECIPE_STRING);
505 cpl_frameset_delete(cur_fset) ;
506 cpl_free(out_file);
507
508 /* Free and return */
509 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
510 if (ext_plist[det_nr-1] != NULL)
511 cpl_propertylist_delete(ext_plist[det_nr-1]) ;
512 if (traces[det_nr-1] != NULL)
513 cpl_table_delete(traces[det_nr-1]) ;
514 }
515 }
516 cpl_frameset_delete(rawframes) ;
517 return (int)cpl_error_get_code();
518}
519
520/*----------------------------------------------------------------------------*/
528/*----------------------------------------------------------------------------*/
529static cpl_frameset * cr2res_util_trace_find_RAW(const cpl_frameset * in)
530{
531 cpl_frameset * out ;
532
533 /* Check entries */
534 if (in == NULL) return NULL ;
535
536 out = cr2res_extract_frameset(in, CR2RES_FLAT_RAW) ;
537 if (out == NULL)
538 out = cr2res_extract_frameset(in, CR2RES_UTIL_CALIB_PROCATG) ;
539 return out ;
540}
541
542
543
cpl_error_code cr2res_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: cr2res_dfs.c:53
int cr2res_io_save_TRACE_WAVE(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, cpl_table **tables, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a TRACE_WAVE.
Definition: cr2res_io.c:1670
int cr2res_io_get_ext_idx(const char *filename, int detector, int data)
Get the wished extension number for a detector.
Definition: cr2res_io.c:644
hdrl_image * cr2res_io_load_image(const char *in, int detector)
Load an hdrl image from a image file.
Definition: cr2res_io.c:704
const char * cr2res_pfits_get_wlen_id(const cpl_propertylist *plist)
find out the Setting
Definition: cr2res_pfits.c:137
cpl_table * cr2res_trace_filter(const cpl_table *tw, const char *setting, int zp_order)
Only keep the predefined orders of the setting.
cpl_image * cr2res_trace_gen_image(cpl_table *trace, int nx, int ny)
Make an image out of the trace solution.
Definition: cr2res_trace.c:362
cpl_table * cr2res_trace_split(cpl_table *trace_wave, int order_idx, int nb_subtraces)
Splits full slit traces into several sub traces.
cpl_table * cr2res_trace(cpl_image *ima, int smooth_x, int smooth_y, double threshold, int opening, int degree, int min_cluster)
Main function for running all parts of the trace algorithm.
Definition: cr2res_trace.c:163
int cr2res_trace_add_extra_columns(cpl_table *traces, const char *infile, int det_nr)
Add extra columns to the plain trace table.
Definition: cr2res_trace.c:972
char * cr2res_get_root_name(const char *filename)
Find out the root part of a basename (name without extension).
cpl_frameset * cr2res_extract_frameset(const cpl_frameset *in, const char *tag)
Extract the frames with the given tag from a frameset.
char * cr2res_get_base_name(const char *filename)
Find out the base name of a file (i.e. without prefix path)
const char * cr2res_get_license(void)
Get the pipeline copyright and license.
cpl_size hdrl_image_get_size_y(const hdrl_image *self)
return size of Y dimension of image
Definition: hdrl_image.c:540
cpl_size hdrl_image_get_size_x(const hdrl_image *self)
return size of X dimension of image
Definition: hdrl_image.c:525
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
Definition: hdrl_image.c:105
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
Definition: hdrl_image.c:379