show git hash (if available) when invoking -v key
[gpivtools.git] / src / image / imgproc.c
blob6fe601cf20c5871a2e770c68db36277ae4afc11e
1 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 c-style: "K&R" -*- */
3 /*---------------------------------------------------------------------------
4 imgproc: processes image
6 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
7 Gerber van der Graaf <gerber_graaf@users.sourceforge.net
9 imgproc is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR 'PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software Foundation,
21 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 ------------------------------------------------------------------------*/
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <glib.h>
28 #include <gpiv.h>
29 #include "config.h"
30 #include "git-rev.h"
32 #define PARFILE "gpivrc" /* Parameter file name */
34 #define USAGE "\
35 Usage: imgproc | mktestimg | smooth | hilo | clip | fft | lowpass | highpass | getbit | subtr-img \n\
36 [-b int] [-h | --help] [-i | --image] [-o | --operation] \n\
37 [-p | --print] [-w int] [-f | --filter] [-t | --threshold int] \n\
38 [-v] [filename] < stdin > stdout \n\
39 \n\
40 keys: \n\
41 \n\
42 -b bit: for getbit: bit number [0, .., 7] \n\
43 -f | --filter: for imgproc: image filter to be performed: \n\
44 make test image (0), subtract image (1), smoothing (2), \n\
45 high-low filtering (3), clipping (4), fft (5), \n\
46 inverse fft (6), lowpass filter (9), highpass filter (10), \n\
47 getbit (11) \n\
48 -h | --help: this on-line help \n\
49 -i | --image: for subtract image: image filename used for subtraction \n \
50 Default: background.png. \n\
51 -p | --print: print parameters to stdout \n\
52 -o | --operation: for smoothing: set pixel equal to the mean of the \n\
53 window value (0), subtract mean from pixel (1) \n\
54 add (2), multiply (3) or divide (4)\n\
55 -t | --threshold: only for clip: threshold value to be set to zero \n\
56 -w size: window size (default: 15) \n\
57 -v | --version: version number \n\
58 filename: full image filename. Overrides stdin and stdout. \n\
59 If stdin and stdout are used, input is expected to be .png \n\
63 #define HELP "\
64 Image processing program for PIV images."
68 * Global variables
70 gboolean use_stdin_stdout = FALSE;
71 /* gboolean print_par = FALSE; */
72 gboolean fname_subtr__set = FALSE;
73 gboolean verbose = FALSE;
77 static void
78 command_args (int argc,
79 char *argv[],
80 char fname[GPIV_MAX_CHARS],
81 GpivImageProcPar *image_proc_par
83 /* ----------------------------------------------------------------------------
84 * Command line argument handling */
86 char c;
87 int argc_next;
88 while (--argc > 0 && (*++argv)[0] == '-') {
89 argc_next = 0;
91 * argc_next is set to 1 if the next cmd line argument has to be searched for;
92 * in case that the command line argument concerns more than one char or cmd
93 * line argument needs a parameter
95 while (argc_next == 0 && (c = *++argv[0])) {
96 switch (c) {
97 case 'v':
99 * Use Git version control system
101 #ifdef GIT_HASH
102 printf ("git hash: %s\n", GIT_REV);
103 #else
104 printf ("version: %s\n", GPIVTOOLS_VERSION);
105 #endif
106 exit(0);
107 break;
108 case 'h':
109 printf("\n%s", argv[0]);
110 printf("\n%s", HELP);
111 printf("\n%s", USAGE);
112 exit(0);
113 break;
115 * (average) image filename used to subtract from input image
117 case 'i':
118 strcpy(image_proc_par->fname, *++argv);
119 image_proc_par->fname__set = TRUE;
120 argc_next = 1;
121 --argc;
123 * bitnumber for getbit
125 case 'b':
126 image_proc_par->bit = atoi(*++argv);
127 image_proc_par->bit__set = TRUE;
128 argc_next = 1;
129 --argc;
130 break;
132 * file name
134 case 'f':
135 image_proc_par->filter = atoi(*++argv);
136 image_proc_par->filter__set = TRUE;
137 --argc;
138 argc_next = 1;
139 break;
143 * whar to do with the mean value of a window: operation
145 case 'o':
146 image_proc_par->smooth_operator = atoi(*++argv);
147 image_proc_par->smooth_operator__set = TRUE;
148 --argc;
149 argc_next = 1;
150 break;
153 * print pararameters
155 case 'p':
156 verbose = TRUE;
157 break;
160 * threshold
162 case 't':
163 image_proc_par->threshold = atoi(*++argv);
164 image_proc_par->threshold__set = TRUE;
165 --argc;
166 argc_next = 1;
167 break;
170 * window size
172 case 'w':
173 image_proc_par->window = atoi(*++argv);
174 image_proc_par->window__set = TRUE;
175 --argc;
176 argc_next = 1;
177 break;
180 * long option keys
182 case '-':
183 if (strcmp("-help", *argv) == 0) {
184 printf("\n%s", argv[0]);
185 printf("\n%s", HELP);
186 printf("\n%s", USAGE);
187 exit(0);
189 } else if (strcmp("-print", *argv) == 0) {
190 verbose = TRUE;
192 } else if (strcmp("-filter", *argv) == 0) {
193 image_proc_par->filter = atoi(*++argv);
194 image_proc_par->filter__set = TRUE;
195 --argc;
197 } else if (strcmp("-version", *argv) == 0) {
198 #ifdef GIT_HASH
199 printf ("git hash: %s\n", GIT_REV);
200 #else
201 printf ("version: %s\n", GPIVTOOLS_VERSION);
202 #endif
203 exit(0);
205 } else if (strcmp("-operation", *argv) == 0) {
206 image_proc_par->smooth_operator = atoi(*++argv);
207 image_proc_par->smooth_operator__set = TRUE;
208 --argc;
210 } else if (strcmp("-threshold", *argv) == 0) {
211 image_proc_par->threshold = atoi(*++argv);
212 image_proc_par->threshold__set = TRUE;
213 --argc;
214 argc_next = 1;
216 } else {
217 gpiv_error("%s: unknown option: %s", argv[0], *argv);
219 argc_next = 1;
220 break;
222 default:
223 gpiv_error("%s: unknown option: %s", argv[0], *argv);
224 break;
230 if (argc == 1) {
231 strcpy(fname, argv[argc - 1]);
232 use_stdin_stdout = FALSE;
233 } else if (argc == 0) {
234 use_stdin_stdout = TRUE;
235 verbose = FALSE;
236 } else {
237 gpiv_error("%s: unknown argument: %s", argv[0], *argv);
244 static gchar *
245 make_fname (char *fname,
246 char *fname_parameter,
247 char *fname_out
249 /*-----------------------------------------------------------------------------
250 * generates filenames for output
253 gchar *err_msg = NULL;
254 gchar *fname_base = NULL;
256 if (fname == NULL ) {
257 err_msg = "make_fname: \"fname_in == NULL\"";
258 return (err_msg);
261 fname_base = g_strdup(fname);
262 strtok(fname_base, ".");
263 gpiv_io_make_fname(fname_base, GPIV_EXT_PAR, fname_parameter);
264 if (verbose) printf("# Parameter file: %s\n", fname_parameter);
266 gpiv_io_make_fname(fname_base, GPIV_EXT_PNG_IMAGE_PROC, fname_out);
267 if (verbose) printf("# Output image file: %s\n", fname_out);
269 g_free (fname_base);
270 return (err_msg);
276 * Image processing functions
279 /* static void */
280 /* imgproc_invfft(GpivImagePar image_par, */
281 /* GpivImageProcPar image_proc_par, */
282 /* guint16 **img_in, */
283 /* guint16 **img_out); */
288 int
289 main (int argc,
290 char *argv[]
292 /* ----------------------------------------------------------------------------
293 * main routine to process images for PIV
296 FILE *fp = NULL, *fp_par = NULL;
297 gchar *err_msg = NULL;
298 gchar fname_in[GPIV_MAX_CHARS],
299 fname_out[GPIV_MAX_CHARS],
300 fname_parameter[GPIV_MAX_CHARS];
302 GpivImage *image = NULL;
304 GpivImageProcPar *image_proc_par = g_new0 (GpivImageProcPar, 1);
305 GpivImageProcPar *image_proc_par_default = g_new0 (GpivImageProcPar, 1);
307 char *c = NULL;
310 * Image process parameter initialization
312 gpiv_imgproc_parameters_set (image_proc_par, FALSE);
313 gpiv_imgproc_default_parameters (image_proc_par_default, TRUE);
316 * Image processing parameter initialization
317 * Define operation type from program name, which is a symbolic link to imgproc
319 if ((c = strstr(argv[0], "imgproc")) != NULL) {
320 image_proc_par->filter = 0;
321 image_proc_par->filter__set = FALSE;
322 } else if ((c = strstr(argv[0], "mktestimg")) != NULL) {
323 image_proc_par->filter = GPIV_IMGFI_MKTESTIMG;
324 image_proc_par->filter__set = TRUE;
325 } else if ((c = strstr(argv[0], "smooth")) != NULL) {
326 image_proc_par->filter = GPIV_IMGFI_SMOOTH;
327 image_proc_par->filter__set = TRUE;
328 } else if ((c = strstr(argv[0], "hilo")) != NULL) {
329 image_proc_par->filter = GPIV_IMGFI_HILO;
330 image_proc_par->filter__set = TRUE;
331 } else if ((c = strstr(argv[0], "clip")) != NULL) {
332 image_proc_par->filter = GPIV_IMGFI_CLIP;
333 image_proc_par->filter__set = TRUE;
334 } else if ((c = strstr(argv[0], "fft")) != NULL) {
335 image_proc_par->filter = GPIV_IMGFI_FFT;
336 image_proc_par->filter__set = TRUE;
337 /* } else if ((c = strstr(argv[0], "invfft")) != NULL) { */
338 /* image_proc_par->filter = GPIV_IMGFI_INVFFT; */
339 /* image_proc_par->filter__set = TRUE; */
340 } else if ((c = strstr(argv[0], "lowpass")) != NULL) {
341 image_proc_par->filter = GPIV_IMGFI_LOWPASS;
342 image_proc_par->filter__set = TRUE;
343 } else if ((c = strstr(argv[0], "highpass")) != NULL) {
344 image_proc_par->filter = GPIV_IMGFI_HIGHPASS;
345 image_proc_par->filter__set = TRUE;
346 } else if ((c = strstr(argv[0], "getbit")) != NULL) {
347 image_proc_par->filter = GPIV_IMGFI_GETBIT;
348 image_proc_par->filter__set = TRUE;
349 } else if ((c = strstr(argv[0], "subtr-img")) != NULL) {
350 image_proc_par->filter = GPIV_IMGFI_SUBTRACT;
351 image_proc_par->filter__set = TRUE;
352 } else {
353 gpiv_error("imgproc: unvalid program name or symlink");
358 * Reads command line arguments.
359 * Reads image header and image processing parametes from resource files
360 * if not overridden by the commandline options
362 command_args (argc, argv, fname_in, image_proc_par);
363 gpiv_scan_parameter (GPIV_IMGPROCPAR_KEY, PARFILE, image_proc_par, verbose);
364 gpiv_scan_resourcefiles (GPIV_IMGPROCPAR_KEY, image_proc_par, verbose);
366 if (use_stdin_stdout == FALSE) {
369 * Generating filenames
371 make_fname(fname_in, fname_parameter, fname_out);
372 if (verbose)
373 printf("\n# Parameters written to: %s", fname_parameter);
379 * Check if all image process parameters have been read
381 g_message ("main:: 0a");
382 if ((err_msg =
383 gpiv_imgproc_check_parameters_read (image_proc_par, image_proc_par_default))
384 != NULL) gpiv_warning ("%s: %s", argv[0], err_msg);
386 g_message ("main:: 0b");
387 if (use_stdin_stdout == FALSE) {
388 if ((fp_par = fopen (fname_parameter, "a")) == NULL) {
389 gpiv_error ("%s: failure opening %s for input",
390 argv[0], fname_parameter);
392 gpiv_imgproc_print_parameters (fp_par, image_proc_par);
393 fclose (fp_par);
396 if (verbose) gpiv_imgproc_print_parameters (stdout, image_proc_par);
399 * reads images
401 /* g_message ("main:: 2"); */
402 if (image_proc_par->filter != GPIV_IMGFI_MKTESTIMG) {
403 if (use_stdin_stdout) {
404 if ((image = gpiv_read_image (stdin)) == NULL) {
405 gpiv_error ("%s: gpiv_fread_image_ni", argv[0]);
408 } else {
409 if ((image = gpiv_fread_image (fname_in)) == NULL) {
410 gpiv_error ("%s: %s", argv[0], err_msg);
415 /* g_message ("main:: 3"); */
417 * Here the function calls for the image processing
419 if (image_proc_par->filter == GPIV_IMGFI_MKTESTIMG) {
420 GpivImagePar *image_par = g_new0 (GpivImagePar, 1);
421 GpivImagePar *image_par_default = g_new0 (GpivImagePar, 1);
423 gpiv_img_parameters_set (image_par, FALSE);
424 gpiv_img_default_parameters (image_par_default, TRUE);
425 gpiv_scan_parameter (GPIV_IMGPAR_KEY, PARFILE, image_par, verbose);
426 gpiv_scan_resourcefiles (GPIV_IMGPAR_KEY, image_par, verbose);
427 if (gpiv_img_check_header_required_read (image_par) != NULL) {
428 gpiv_img_ovwrt_parameters (image_par_default, image_par);
430 if (verbose) gpiv_img_print_header (stdout, image_par);
432 if ((image = gpiv_imgproc_mktestimg (image_par, image_proc_par)) == NULL) {
433 gpiv_error ("%s: %s", argv[0], err_msg);
437 } else if (image_proc_par->filter == GPIV_IMGFI_HILO) {
438 if ((err_msg = gpiv_imgproc_highlow (image, image_proc_par)) != NULL) {
439 gpiv_error ("%s: %s", argv[0], err_msg);
443 } else if (image_proc_par->filter == GPIV_IMGFI_SMOOTH) {
444 if ((err_msg = gpiv_imgproc_smooth (image, image_proc_par)) != NULL) {
445 gpiv_error ("%s: %s", argv[0], err_msg);
449 } else if (image_proc_par->filter == GPIV_IMGFI_CLIP) {
450 if ((err_msg = gpiv_imgproc_clip (image, image_proc_par)) != NULL) {
451 gpiv_error ("%s: %s", argv[0], err_msg);
455 } else if (image_proc_par->filter == GPIV_IMGFI_FFT) {
456 if ((err_msg = gpiv_imgproc_fft (image, image_proc_par)) != NULL) {
457 gpiv_error ("%s: %s", argv[0], err_msg);
460 /* } else if (image_proc_par->filter == GPIV_FI_INVFFT) { */
461 /* gpiv_imgproc_invfft (image_par, image_proc_par, img1_in, img1_out)) */
462 /* if (image_par->x_corr) { */
463 /* gpiv_imgproc_invfft(image_par, image_proc_par, img2_in, img2_out)) */
466 /* BUGFIX: Libgpiv TODO */
467 /* #ifndef USE_FFTW3 */
469 } else if (image_proc_par->filter == GPIV_IMGFI_CORR) {
470 if ((err_msg =
471 gpiv_imgproc_correlate (image_par, image_proc_par, img1_in, img2_in,
472 &img1_out))
473 != NULL) gpiv_error ("%s: %s", argv[0], err_msg);
476 } else if (image_proc_par->filter == GPIV_IMGFI_CONV) {
477 if ((err_msg =
478 gpiv_imgproc_convolve (image_par, image_proc_par, img1_in, img2_in,
479 &img1_out))
480 != NULL) gpiv_error ("%s: %s", argv[0], err_msg);
483 } else if (image_proc_par->filter == GPIV_IMGFI_LOWPASS) {
484 if ((err_msg =
485 gpiv_imgproc_lowpass (image_par, image_proc_par, img1_in))
486 != NULL) gpiv_error ("%s: %s", argv[0], err_msg);
487 img1_out = img1_in;
488 if (image_par->x_corr) {
489 if ((err_msg =
490 gpiv_imgproc_lowpass(image_par, image_proc_par, img2_in))
491 != NULL) gpiv_error ("%s: %s", argv[0], err_msg);
492 img2_out = img2_in;
497 /* #endif USE_FFTW3 */
498 } else if (image_proc_par->filter == GPIV_IMGFI_HIGHPASS) {
499 if ((err_msg = gpiv_imgproc_highpass (image, image_proc_par)) != NULL) {
500 gpiv_error ("%s: %s", argv[0], err_msg);
504 } else if (image_proc_par->filter == GPIV_IMGFI_GETBIT) {
505 if ((err_msg = gpiv_imgproc_getbit (image, image_proc_par)) != NULL) {
506 gpiv_error ("%s: %s", argv[0], err_msg);
510 } else if (image_proc_par->filter == GPIV_IMGFI_SUBTRACT) {
511 GpivImage *image_subtract = NULL;
513 if (image_proc_par->fname__set == FALSE) {
514 gpiv_error ("%s: no filename set for subtract image. Use -i filename", argv[0]);
517 if ((image_subtract = gpiv_fread_image (image_proc_par->fname)) == NULL) {
518 gpiv_error ("%s: failing gpiv_fread_image", argv[0]);
521 if ((err_msg = gpiv_imgproc_subtractimg(image_subtract, image)) != NULL) {
522 gpiv_error ("%s: %s", argv[0], err_msg);
526 } else {
527 gpiv_error("imgproc: non-existing filter %d", image_proc_par->filter);
532 * And writing to output
534 if (use_stdin_stdout == TRUE) {
535 fp = stdout;
536 if ((err_msg = gpiv_write_png_image (fp, image, TRUE)) != NULL) {
537 gpiv_error ("%s: %s\n", argv[0], err_msg);
541 } else {
542 if ((fp = fopen (fname_out, "wb")) == NULL) {
543 gpiv_error ("%s: unable to open %s", argv[0], fname_out);
546 if ((err_msg = gpiv_write_png_image (fp, image, TRUE)) != NULL) {
547 gpiv_error ("%s: %s\n", argv[0], err_msg);
550 fclose(fp);
554 return 0;