efros_freeman  0.1
common.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 <stdlib.h>
20 #include <stdio.h>
21 #include <math.h>
22 #include <assert.h>
23 #include <string.h>
24 #include <fftw3.h>
25 
26 #include "common.h"
27 #include "quilting.h"
28 #include "random_number.h"
29 
30 /**
31 * This method initializes the output image taking a random patch from the
32 * input texture and placing it on the left-top corner of the output image.
33 * @author Lara Raad
34 * @param src_img The input texture sample
35 * @param wp The size of the patches
36 * @param wo The size of the overlap area betwenn patches
37 * @param p_row Number of patches per row in the output image
38 * @param p_col Number of patches per column in the output image
39 * @param patch_src Top left corner position of the patch from the source
40 * @date 24/05/2012
41 */
42 Image initialize(Image src_img, int wp, int wo, int p_row,
43  int p_col, Corner *patch_src){
44  Image img;
45  int i, j, k, rows, cols, channels, pos, pos_s, inc, inc_s;
46  rows = p_row*wp - (p_row - 1)*wo;
47  cols = p_col*wp - (p_col - 1)*wo;
48  channels = src_img.c;
49 
50  initialize_image(&img, rows, cols, channels);
51 
52  // Paste random block from input texture in left top corner
53  // of the output image.
54 
55  // Random positions in [0,h-wp)x[O,w-wp)
56  int x_rand = random_number(NULL) % (src_img.h-wp+1);
57  assert(x_rand<(int)(src_img.h-wp+1));
58  int y_rand = random_number(NULL) % (src_img.w-wp+1);
59  assert(y_rand<(int)(src_img.w-wp+1));
60 
61  patch_src->x = x_rand;
62  patch_src->y = y_rand;
63 
64  inc = img.h*img.w;
65  inc_s = src_img.h*src_img.w;
66 
67  //paste the first block into the output image
68  for(i=0; i < wp; i++)
69  {
70  for(j=0; j < wp; j++)
71  {
72  pos = i*img.w + j;
73  pos_s = (x_rand + i)*src_img.w +(y_rand +j);
74  assert(pos_s < (int) (src_img.w*src_img.h));
75  for(k=0; k<channels; k++)
76  {
77  img.img[pos + k*inc] = src_img.img[pos_s + k*inc_s];
78  }
79  }
80  }
81 
82  return img;
83 }
84 
85 /**
86 * This method initializes images of type float.
87 * It sets the numeber of rows, columns and channels
88 * and sets the pixels values to zero.
89 * @author Lara Raad
90 * @param im The image to initialize
91 * @param rows Number of rows of the image
92 * @param cols Number of columns of the image
93 * @param channels Number of channels of the image
94 * @date 24/05/2012
95 */
96 void initialize_image(Image *im, int rows, int cols, int channels)
97 {
98  int size;
99  im->h = rows;
100  im->w = cols;
101  im->c = channels;
102  size = rows*cols*channels;
103  im->img = (float *) calloc(size, sizeof(float));
104 }
105 
106 /**
107 * This method initializes images of type double. It sets the number
108 * of rows, columns and channels and sets the pixels values to zero.
109 * @author Lara Raad
110 * @param im The image to initialize
111 * @param rows Number of rows of the image
112 * @param cols Number of columns of the image
113 * @param channels Number of channels of the image
114 * @date 24/05/2012
115 */
116 void initialize_image_D(Image_D *im, int rows, int cols, int channels)
117 {
118  int size;
119  im->h = rows;
120  im->w = cols;
121  im->c = channels;
122  size = rows*cols*channels;
123  im->img = (double *) calloc(size, sizeof(double));
124 }
125 
126 /**
127 * This method initializes images of type long double. It sets the number
128 * of rows, columns and channels and sets the pixels values to zero.
129 * @author Lara Raad
130 * @param im The image to initialize
131 * @param rows Number of rows of the image
132 * @param cols Number of columns of the image
133 * @param channels Number of channels of the image
134 * @date 24/05/2012
135 */
136 void initialize_image_LD(Image_LD *im, int rows, int cols, int channels)
137 {
138  int size;
139  im->h = rows;
140  im->w = cols;
141  im->c = channels;
142  size = rows*cols*channels;
143  im->img = (long double *) calloc(size, sizeof(long double));
144 }
145 
146 /**
147 * This method initializes images of type unsigned long. It sets the number
148 * of rows, columns and channels and sets the pixels values to zero.
149 * @author Lara Raad
150 * @param im The image to initialize
151 * @param rows Number of rows of the image
152 * @param cols Number of columns of the image
153 * @param channels Number of channels of the image
154 * @date 24/05/2012
155 */
156 void initialize_image_UI(Image_UI *im, int rows, int cols, int channels)
157 {
158  int size;
159  im->h = rows;
160  im->w = cols;
161  im->c = channels;
162  size = rows*cols*channels;
163  im->img = (unsigned long *) calloc(size, sizeof(unsigned long));
164 }
165 
166 /**
167 * This method creates a position map that associates a different
168 * color from a continuous colormap to every pixel of the source
169 * image
170 * @author Lara Raad
171 * @param pos_map Position map image
172 * @date 09/05/2013
173 */
175 {
176  size_t count = 0;
177  size_t inc = pos_map.h*pos_map.w;
178  size_t i,j;
179 
180  for(i=0;i<pos_map.h;i++)
181  {
182  for(j=0;j<pos_map.w;j++)
183  {
184  pos_map.img[count] = (i*255)/pos_map.h;//Red
185  pos_map.img[count+inc] = (j*255)/pos_map.w;//Green
186  pos_map.img[count+2*inc] = (i*j*255)/(pos_map.w*pos_map.h);//Blue
187  count++;
188  }
189  }
190 }
191 
192 /**
193 * This method crops an image to be of size MxNxC
194 * @author Lara Raad
195 * @param im Image to crop
196 * @param M,N,C Size of the cropped image
197 * @param im_crop The cropped image
198 * @date 09/08/2013
199 */
200 int crop_image(Image *im_crop, Image *im, int M, int N, int C)
201 {
202  if( (M > (int) im->h) || (N > (int) im->w) )
203  {
204  return 1;
205  }
206 
207  int i,j,k;
208  initialize_image(im_crop, M, N, C);
209  for(k=0;k<C;k++)
210  {
211  for(i=0;i<M;i++)
212  {
213  for(j=0;j<N;j++)
214  {
215  im_crop->img[i*N+j + k*M*N] =
216  im->img[i*im->w+j + k*im->h*im->w];
217  }
218  }
219  }
220  return 0;
221 }
222 
223 /**
224 * This method updates the synthesis map for each patch added
225 * in the synthesized image
226 * @author Lara Raad
227 * @param synth_map Synthesis map
228 * @param pos_map Color map of the texture sample
229 * @param leftTop_src Position of the patch to add taken in the src image
230 * @param leftTop_output Position in the ouput image where we add a block
231 * @param pathc_sz Patch size
232 * @param binIm Binary image used to indicate which pixels are form
233 * the old patch and wich pixels are from the new patch
234 * @date 26/02/2014
235 */
236 int update_synth_map(Image * synth_map, Image * pos_map, Corner * leftTop_src,
237  Corner * leftTop_output, int wp, Image binIm)
238 {
239  int kk, ll, pos_posMap, pos_synthMap, x_s, y_s, x_o, y_o, inc_o, inc_s;
240  x_s = leftTop_src->x;
241  y_s = leftTop_src->y;
242  assert( (x_s < (int)((synth_map->w-wp+1)*(synth_map->h-wp+1))) &&
243  (y_s < (int)((synth_map->w-wp+1)*(synth_map->h-wp+1))) );
244  x_o = leftTop_output->x;
245  y_o = leftTop_output->y;
246  inc_s = pos_map->w*pos_map->h;
247  inc_o = synth_map->w*synth_map->h;
248 
249  for (kk=0; kk<wp; kk++)
250  {
251  for (ll=0; ll<wp; ll++)
252  {
253  pos_posMap = (x_s + kk)*pos_map->w + (y_s + ll);
254  pos_synthMap = (x_o + kk)*synth_map->w + (y_o + ll);
255  assert(pos_posMap < (int)(pos_map->h*pos_map->w));
256  assert(pos_synthMap < (int)(synth_map->h*synth_map->w));
257  synth_map->img[pos_synthMap] =
258  binIm.img[kk*binIm.w+ll]*synth_map->img[pos_synthMap]
259  + (1-binIm.img[kk*binIm.w+ll])*pos_map->img[pos_posMap];
260  synth_map->img[pos_synthMap + inc_o] =
261  binIm.img[kk*binIm.w+ll]*synth_map->img[pos_synthMap + inc_o]
262  + (1-binIm.img[kk*binIm.w+ll])*pos_map->img[pos_posMap + inc_s];
263  synth_map->img[pos_synthMap + 2*inc_o] =
264  binIm.img[kk*binIm.w+ll]*synth_map->img[pos_synthMap + 2*inc_o]
265  + (1-binIm.img[kk*binIm.w+ll])*pos_map->img[pos_posMap + 2*inc_s];
266  }
267  }
268 
269  return 0;
270 }
271 
272 /**
273 * This method removes the extension of a filename
274 * @author Lara Raad
275 * @param filename File name to which the extension is removed
276 * @date 25/08/2014
277 */
278 char* remove_ext_filename(char *filename)
279 {
280  // get the string after the last '/' (when exists) and
281  // remove extension .png
282  char *file;
283  if ((file = strrchr( filename, '/'))==NULL)
284  file = filename;
285  else
286  file = file +1;
287  int i = strlen(file);
288  while( (file[i-1] != '.') && (i>0))
289  {
290  i--;
291  }
292  int posDot = i-1;
293  char *fileNoExt = (char *) calloc(posDot, sizeof(char));
294  strncpy(fileNoExt,file,posDot);
295  return fileNoExt;
296 }
297 
298 /**
299 * This method computes the 2-D FFT of an input image
300 * @author Lara Raad
301 * @param img Input image to apply the 2-D FFT
302 * @param fft_im 2-D FFT of the input image img
303 * @param h,w Dimensions of img (height and width)
304 * @date 26/02/2014
305 */
306 int im_fft(float *img, fftwl_complex *fft_im, int h, int w)
307 {
308  fftwl_plan p_im;
309  Image_LD src_ld;// copy of src_im in a long double version
310  int pos_im;
311 
312  initialize_image_LD(&src_ld, h, w, 1);
313 
314  for(int i=0; i<(int)h; i++)
315  {
316  for(int j=0; j<(int)w; j++)
317  {
318  pos_im = i*w + j;
319  src_ld.img[pos_im] = (long double)(img[pos_im]);
320  }
321  }
322 
323  // create plan
324  #pragma omp critical (make_plan)
325  p_im = fftwl_plan_dft_r2c_2d(h,w,src_ld.img,fft_im,FFTW_ESTIMATE);
326  // execute fft
327  fftwl_execute(p_im);
328 
329  free(src_ld.img);
330  #pragma omp critical (make_plan)
331  fftwl_destroy_plan(p_im);
332 
333  return 0;
334 }