BRL-CAD
size.c
Go to the documentation of this file.
1 /* D E C I M A T E . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2013-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @file size.c
21  *
22  * This file contains routines to scale down an image to a lower
23  * resolution.
24  *
25  */
26 
27 #include "icv.h"
28 #include "vmath.h"
29 #include "bu/log.h"
30 #include "bu/malloc.h"
31 
32 HIDDEN int
33 shrink_image(icv_image_t* bif, unsigned int factor)
34 {
35  double *data_p, *res_p; /**< input and output pointers */
36  double *p;
37  unsigned int facsq, py, px;
38  int x, y, c;
39  size_t widthstep = bif->width*bif->channels;
40  if (UNLIKELY(factor < 1)) {
41  bu_log("Cannot shrink image to 0 factor, factor should be a positive value.");
42  return -1;
43  }
44 
45  facsq = factor*factor;
46  res_p = bif->data;
47  p = (double *)bu_malloc(bif->channels*sizeof(double), "shrink_image : Pixel Values Temp Buffer");
48 
49  for (y = 0; y < bif->height; y += factor)
50  for (x = 0; x < bif->width; x += factor) {
51 
52  for (c = 0; c < bif->channels; c++) {
53  p[c]= 0;
54  }
55 
56  for (py = 0; py < factor; py++) {
57  data_p = bif->data + (y+py)*widthstep;
58  for (px = 0; px < factor; px++) {
59  for (c = 0; c < bif->channels; c++) {
60  p[c] += *data_p++;
61  }
62  }
63  }
64 
65  for (c = 0; c < bif->channels; c++)
66  *res_p++ = p[c]/facsq;
67  }
68 
69  bif->width = (int)bif->width/factor;
70  bif->height = (int)bif->height/factor;
71  bif->data = (double *)bu_realloc(bif->data, (size_t)(bif->width*bif->height*bif->channels)*sizeof(double), "shrink_image : Reallocation");
72 
73  return 0;
74 
75 }
76 
77 
78 HIDDEN int
79 under_sample(icv_image_t* bif, unsigned int factor)
80 {
81  double *data_p, *res_p;
82  int x, y, widthstep;
83 
84  if (UNLIKELY(factor < 1)) {
85  bu_log("Cannot shrink image to 0 factor, factor should be a positive value.");
86  return -1;
87  }
88 
89  widthstep = bif->width*bif->channels;
90  res_p = data_p = bif->data;
91 
92  for (y = 0; y < bif->height; y += factor) {
93  data_p = bif->data + widthstep*y;
94  for (x = 0; x < bif->width;
95  x += factor, res_p += bif->channels, data_p += factor * bif->channels)
96  VMOVEN(res_p, data_p, bif->channels);
97  }
98 
99  bif->width = (int)bif->width/factor;
100  bif->height = (int)bif->height/factor;
101  bif->data = (double *)bu_realloc(bif->data, (size_t)(bif->width*bif->height*bif->channels)*sizeof(double), "under_sample : Reallocation");
102 
103  return 0;
104 }
105 
106 
107 HIDDEN int
108 ninterp(icv_image_t* bif, unsigned int out_width, unsigned int out_height)
109 {
110  double xstep, ystep;
111  unsigned int i, j;
112  int x, y;
113  int widthstep;
114  double *in_r, *in_c; /*<< Pointer to row and col of input buffers*/
115  double *out_data, *out_p;
116  xstep = (double)(bif->width-1) / (double)(out_width) - 1.0e-06;
117  ystep = (double)(bif->height-1) / (double)(out_height) - 1.0e-06;
118 
119  if ((xstep < 1.0 && ystep > 1.0) || (xstep > 1.0 && ystep < 1.0)) {
120  bu_log("Operation unsupported. Cannot stretch one dimension while compressing the other.\n");
121  return -1;
122  }
123 
124  out_p = out_data = (double *)bu_malloc(out_width*out_height*bif->channels*sizeof(double), "ninterp : out_data");
125 
126  widthstep= bif->width*bif->channels;
127 
128  for (j = 0; j < out_height; j++) {
129  y = (int)(j*ystep);
130  in_r = bif->data + y*widthstep;
131 
132  for (i = 0; i < out_width; i++) {
133  x = (int)(i*xstep);
134 
135  in_c = in_r + x*bif->channels;
136 
137  VMOVEN(out_p, in_c, bif->channels);
138  out_p += bif->channels;
139  }
140  }
141 
142  bu_free(bif->data, "ninterp : in_data");
143 
144  bif->data = out_data;
145 
146  bif->width = out_width;
147  bif->height = out_height;
148 
149  return 0;
150 
151 }
152 
153 
154 HIDDEN int
155 binterp(icv_image_t *bif, unsigned int out_width, unsigned int out_height)
156 {
157  unsigned int i, j;
158  int c;
159  double x, y, dx, dy, mid1, mid2;
160  double xstep, ystep;
161  double *out_data, *out_p;
162  double *upp_r, *low_r; /*<< upper and lower row */
163  double *upp_c, *low_c;
164  int widthstep;
165 
166  xstep = (double)(bif->width - 1) / (double)out_width - 1.0e-6;
167  ystep = (double)(bif->height -1) / (double)out_height - 1.0e-6;
168 
169  if ((xstep < 1.0 && ystep > 1.0) || (xstep > 1.0 && ystep < 1.0)) {
170  bu_log("Operation unsupported. Cannot stretch one dimension while compressing the other.\n");
171  return -1;
172  }
173 
174  out_p = out_data = (double *)bu_malloc(out_width*out_height*bif->channels*sizeof(double), "binterp : out data");
175 
176  widthstep = bif->width*bif->channels;
177 
178  for (j = 0; j < out_height; j++) {
179  y = j*ystep;
180  dy = y - (int)y;
181 
182  low_r = bif->data + widthstep* (int)y;
183  upp_r = bif->data + widthstep* (int)(y+1);
184 
185  for (i = 0; i < out_width; i++) {
186  x = i*xstep;
187  dx = x - (int)x;
188 
189  upp_c = upp_r + (int)x*bif->channels;
190  low_c = low_r + (int)x*bif->channels;
191 
192  for (c = 0; c < bif->channels; c++) {
193  mid1 = low_c[0] + dx * ((double)low_c[bif->channels] - (double)low_c[0]);
194  mid2 = upp_c[0] + dx * ((double)upp_c[bif->channels] - (double)upp_c[0]);
195  *out_p = mid1 + dy * (mid2 - mid1);
196 
197  out_p++;
198  upp_c++;
199  low_c++;
200  }
201  }
202  }
203  bu_free(bif->data, "binterp : Input Data");
204  bif->data = out_data;
205  bif->width = out_width;
206  bif->height = out_height;
207  return 0;
208 
209 }
210 
211 
212 int
213 icv_resize(icv_image_t *bif, ICV_RESIZE_METHOD method, unsigned int out_width, unsigned int out_height, unsigned int factor)
214 {
215  ICV_IMAGE_VAL_INT(bif);
216 
217  switch (method) {
219  return under_sample(bif, factor);
220  case ICV_RESIZE_SHRINK :
221  return shrink_image(bif, factor);
222  case ICV_RESIZE_NINTERP :
223  return ninterp(bif, out_width, out_height);
224  case ICV_RESIZE_BINTERP :
225  return binterp(bif, out_width, out_height);
226  default :
227  bu_log("icv_resize : Invalid Option to resize");
228  return -1;
229  }
230 
231 }
232 
233 
234 /*
235  * Local Variables:
236  * tab-width: 8
237  * mode: C
238  * indent-tabs-mode: t
239  * c-file-style: "stroustrup"
240  * End:
241  * ex: shiftwidth=4 tabstop=8
242  */
double * data
Definition: icv.h:89
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
int width
Definition: icv.h:91
HIDDEN int ninterp(icv_image_t *bif, unsigned int out_width, unsigned int out_height)
Definition: size.c:108
int channels
Definition: icv.h:91
Definition: icv.h:86
int height
Definition: icv.h:91
#define HIDDEN
Definition: common.h:86
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
HIDDEN int under_sample(icv_image_t *bif, unsigned int factor)
Definition: size.c:79
HIDDEN int binterp(icv_image_t *bif, unsigned int out_width, unsigned int out_height)
Definition: size.c:155
void * bu_realloc(void *ptr, size_t siz, const char *str)
HIDDEN int shrink_image(icv_image_t *bif, unsigned int factor)
Definition: size.c:33
int icv_resize(icv_image_t *bif, ICV_RESIZE_METHOD method, unsigned int out_width, unsigned int out_height, unsigned int factor)
Definition: size.c:213
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
ICV_RESIZE_METHOD
Definition: icv.h:675
#define ICV_IMAGE_VAL_INT(_i)
Definition: icv.h:123
#define UNLIKELY(expression)
Definition: common.h:282