efros_freeman  0.1
quilting_main.c
Go to the documentation of this file.
1 /*
2  Copyright (c) 2016 Lara Raad <lara.raad@cmla.ens-cachan.fr>,
3  Bruno Galerne <bruno.galerne@parisdescartes.fr>
4 
5  Quilting is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Affero General Public License as
7  published by the Free Software Foundation, either version 3 of the
8  License, or (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 Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <math.h>
22 #include <time.h>
23 #include <string.h>
24 #include <getopt.h>
25 #include <assert.h>
26 #include <unistd.h>
27 
28 #include "quilting.h"
29 #include "random_number.h"
30 #include "io_png.h"
31 
32 //* print a message and abort the execution *//
33 #define FATAL(MSG) \
34 do { \
35  fprintf(stderr, MSG "\n"); \
36  abort(); \
37  } while (0);
38 
39 static int display_usage()
40 {
41  printf("\nquilting_main -p wp -r ratio -t tol -o overlap -s seed "
42  "src_im.png out_im.png pos_map.png synthesis_map.png\n\n");
43  printf("Required parameters:\n");
44  printf(" src_im.png : name of the input PNG image\n");
45  printf(" out_im.png : name of the output PNG image\n");
46  printf(" pos_map.png : name of the position map PNG image\n");
47  printf(" synthesis_map.png : name of the synthesis map PNG image\n\n");
48  printf("Optionnal parameters:\n");
49  printf(" wp : int > size(src_im.png) that "
50  "specifies the size of the patch used to synthesize "
51  "out_im.png\n");
52  printf(" ratio : float >= 1 that specifies the increase "
53  "of size of out_im.png relatively to the size "
54  "of src_im.png\n");
55  printf(" tol : float > 0 to specify the distance "
56  "tolerance when comparing patches in src_im.png\n");
57  printf(" overlap : float 0 < o < 1 to specify the patch "
58  "overlap ratio\n");
59  printf(" seed : unsigned int to specify the seed "
60  "for the random number generator "
61  "(seed = time(NULL) by default)\n");
62 
63  return (1);
64 }
65 
66 int main(int argc, char *argv[])
67 {
68  //*
69  //* Getting parameters: patch size, overlap size, number
70  //* of blocks per row, number of blocks per column, tolerance
71  //* for distance
72  //*
73 
74  char *fname_in; //* input file name *//
75  char *fname_out; //* output file name *//
76  char *fname_positionMap; //* position map file name *//
77  char *fname_synthesisMap; //* synthesis map file name *//
78 
79  Image src_im; //* input data *//
80  Image out_im; //* output data *//
81  int wp; //* patch size *//
82  float ratio; //* ratio for the
83  //* output size (must be >1) *//
84  float tol; //* distance tolerance *//
85  float overlap; //* patch overlap ratio *//
86  int wo; //* overlap size between blocks *//
87  int p_row; //* number of patches per row *//
88  int p_col; //* number of patches per column *//
89 
90  long seed = 0; /* seed for the random number
91  * generator */
92  int p_flag = 0;
93  int s_flag = 0;
94  int c; /* getopt flag */
95 
96  //* "default" value initialization *//
97  wp = 40;
98  ratio = 1.;
99  tol = .1;
100  overlap = .25;
101 
102  //* process the options and parameters *//
103 
104  while ((c = getopt(argc, argv, "p:r:t:o:s:h")) != -1) {
105  switch (c) {
106  case 'p':
107  //* patch size specified *//
108  p_flag = 1;
109  wp = atof(optarg);
110  break;
111  case 'r':
112  //* ratio specified *//
113  ratio = atof(optarg);
114  if (ratio < 1)
115  FATAL("Option usage: The ratio "
116  "specified by -r must be greater than 1.");
117  break;
118  case 't':
119  //* distance tolerance specified *//
120  tol = atof(optarg);
121  if (tol <= 0.)
122  FATAL("Option usage: The tolerance error "
123  "specified by -t must be greater than 0.");
124  break;
125  case 'o':
126  //* overlap ratio specified *//
127  overlap = atof(optarg);
128  if (overlap <= 0. || overlap >= 1.)
129  FATAL("Option usage: The overlap ratio "
130  "specified by -o must be between 0. and 1.");
131  break;
132  case 's':
133  //* seed specified *//
134  s_flag = 1;
135  seed = atol(optarg);
136  break;
137  case 'h':
138  //* display usage *//
139  display_usage();
140  return (-1);
141  default:
142  abort();
143  }
144  }
145 
146  //* process the non-option parameters *//
147  if (4 > (argc - optind)) {
148  printf("The input and output image file names are missing\n\n");
149  display_usage();
150  return (-1);
151  }
152  fname_in = argv[optind++];
153  fname_out = argv[optind++];
154  fname_positionMap = argv[optind++];
155  fname_synthesisMap = argv[optind++];
156 
157  //* Reading input image *//
158  src_im.img = io_png_read_f32(fname_in, &src_im.w, &src_im.h, &src_im.c);
159 
160  //* Initilization of the random number generator *//
161  if (s_flag == 0) {
162  long s = time(NULL);
163  random_number(&s);
164  }
165  else {
166  random_number(&seed);
167  }
168 
169  //* deal with patch size,*//
170  //*if higher than the min lentgh of the input abort*//
171  if((p_flag==1) && ((wp > (int) src_im.h) || (wp > (int) src_im.w)))
172  {
173  printf("Conflict: the patch size should be smaller "
174  "than the minimal length of the input image\n\n");
175  display_usage();
176  return (-1);
177  }
178 
179  //* deal with patch size, if equal to zero abort*//
180  if((p_flag==1) && (wp==0))
181  {
182  printf("Conflict: the patch size should be greater than zero\n\n");
183  display_usage();
184  return (-1);
185  }
186 
187  //* compute overlap size *//
188  if ((wo = (int) round(wp*overlap))<=0 || wo>=wp)
189  FATAL("Conflict: The patch overlap size should be at least one pixel "
190  "and less than the patch size");
191 
192  //* compute number of patches per row and per column needed*//
193  //* to synthesize a (factor*M) x (factor*N) modulo (wp) image *//
194  int M = roundf(ratio*src_im.h);
195  int N = roundf(ratio*src_im.w);
196  int C = src_im.c;
197  float a;
198  if (src_im.w < src_im.h)
199  a = M - wo;
200  else
201  a = N - wo;
202  float b;
203  if (src_im.h < src_im.w)
204  b = N - wo;
205  else
206  b = M - wo;
207  float d = wp - wo;
208  p_row = (int) ceil(b/d);
209  p_col = (int) ceil(a/d);
210 
211  Image pos_map;// each pixel in the source image is associated to
212  // a different color from a continuous colormap
213  Image synth_map;// shows for each synthesized patch its position
214  // in the source image
215 
216  //* Create position map*//
217  initialize_image(&pos_map, src_im.h, src_im.w, 3);
218  create_position_map(pos_map);
219 
220  //* Image synthesis *//
221  if (s_flag == 0)
222  out_im = quilting_synthesis(src_im, wp, wo, p_row, p_col,
223  tol, &pos_map, &synth_map, NULL);
224  else
225  out_im = quilting_synthesis(src_im, wp, wo, p_row, p_col,
226  tol, &pos_map, &synth_map, &seed);
227 
228  //* Crop synthesis map *//
229  Image synth_map_crop;
230  if (crop_image(&synth_map_crop, &synth_map, M, N, 3))
231  {
232  FATAL("The size of the cropped image is bigger "
233  "than the image to crop");
234  }
235 
236  //* Crop output image *//
237  Image out_im_crop;
238  if (crop_image(&out_im_crop, &out_im, M, N, C))
239  {
240  FATAL("The size of the cropped image is bigger "
241  "than the image to crop");
242  }
243 
244  //* Writing position map in png file *//
245  io_png_write_f32(fname_positionMap, pos_map.img,
246  pos_map.w, pos_map.h, pos_map.c);
247 
248  //* Writing synthesis map in png file *//
249  io_png_write_f32(fname_synthesisMap, synth_map_crop.img,
250  synth_map_crop.w, synth_map_crop.h, synth_map_crop.c);
251 
252  //* Writing output image in png file *//
253  io_png_write_f32(fname_out, out_im_crop.img,
254  out_im_crop.w, out_im_crop.h, out_im_crop.c);
255 
256  //* Release memory *//
257  free(pos_map.img);
258  free(synth_map.img);
259  free(synth_map_crop.img);
260  free(src_im.img);
261  free(out_im.img);
262  free(out_im_crop.img);
263 
264  return 0;
265 }