main.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. /****************************************************************************
  2. *
  3. * MODULE: r.resamp.filter
  4. * AUTHOR(S): Glynn Clements <glynn gclements.plus.com>
  5. * PURPOSE:
  6. * COPYRIGHT: (C) 2010 by Glynn Clements and the GRASS Development Team
  7. *
  8. * This program is free software under the GNU General Public
  9. * License (>=v2). Read the file COPYING that comes with GRASS
  10. * for details.
  11. *
  12. *****************************************************************************/
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <limits.h>
  16. #include <math.h>
  17. #include <grass/gis.h>
  18. #include <grass/raster.h>
  19. #include <grass/glocale.h>
  20. static double f_box(double x)
  21. {
  22. return (x > 1) ? 0
  23. : 1;
  24. }
  25. static double f_bartlett(double x)
  26. {
  27. return (x > 1) ? 0
  28. : 1 - x;
  29. }
  30. static double f_hermite(double x)
  31. {
  32. return (x > 1) ? 0
  33. : (2 * x - 3) * x * x + 1;
  34. }
  35. static double f_gauss(double x)
  36. {
  37. return exp(-2 * x * x) * sqrt(2 / M_PI);
  38. }
  39. static double f_normal(double x)
  40. {
  41. return f_gauss(x/2) / 2;
  42. }
  43. static double f_sinc(double x)
  44. {
  45. return (x == 0) ? 1 : sin(M_PI * x) / (M_PI * x);
  46. }
  47. static double lanczos(double x, int a)
  48. {
  49. return (x > a) ? 0
  50. : f_sinc(x) * f_sinc(x / a);
  51. }
  52. static double f_lanczos1(double x)
  53. {
  54. return lanczos(x, 1);
  55. }
  56. static double f_lanczos2(double x)
  57. {
  58. return lanczos(x, 2);
  59. }
  60. static double f_lanczos3(double x)
  61. {
  62. return lanczos(x, 3);
  63. }
  64. static double f_hann(double x)
  65. {
  66. return cos(M_PI * x) / 2 + 0.5;
  67. }
  68. static double f_hamming(double x)
  69. {
  70. return 0.46 * cos(M_PI * x) + 0.54;
  71. }
  72. static double f_blackman(double x)
  73. {
  74. return cos(M_PI * x) / 2 + 0.08 * cos(2 * M_PI * x) + 0.42;
  75. }
  76. struct filter_type {
  77. const char *name;
  78. double (*func)(double);
  79. int radius;
  80. };
  81. static const struct filter_type menu[] = {
  82. {"box", f_box, 1},
  83. {"bartlett", f_bartlett, 1},
  84. {"gauss", f_gauss, 0},
  85. {"normal", f_normal, 0},
  86. {"hermite", f_hermite, 1},
  87. {"sinc", f_sinc, 0},
  88. {"lanczos1", f_lanczos1, 1},
  89. {"lanczos2", f_lanczos2, 2},
  90. {"lanczos3", f_lanczos3, 3},
  91. {"hann", f_hann, 0},
  92. {"hamming", f_hamming, 0},
  93. {"blackman", f_blackman, 0},
  94. {NULL},
  95. };
  96. static char *build_filter_list(void)
  97. {
  98. char *buf = G_malloc(1024);
  99. char *p = buf;
  100. int i;
  101. for (i = 0; menu[i].name; i++) {
  102. const char *q;
  103. if (i)
  104. *p++ = ',';
  105. for (q = menu[i].name; *q; p++, q++)
  106. *p = *q;
  107. }
  108. *p = '\0';
  109. return buf;
  110. }
  111. static const struct filter_type *find_method(const char *name)
  112. {
  113. int i;
  114. for (i = 0; menu[i].name; i++)
  115. if (strcmp(menu[i].name, name) == 0)
  116. return &menu[i];
  117. G_fatal_error(_("Filter <%s> not found"), name);
  118. return NULL;
  119. }
  120. struct filter {
  121. double (*func)(double);
  122. double x_radius;
  123. double y_radius;
  124. };
  125. #define MAX_FILTERS 8
  126. static int infile, outfile;
  127. static struct filter filters[MAX_FILTERS];
  128. static int num_filters;
  129. static int nulls;
  130. static struct Cell_head dst_w, src_w;
  131. static double f_x_radius, f_y_radius;
  132. static int row_scale, col_scale;
  133. static DCELL *inbuf;
  134. static DCELL *outbuf;
  135. static DCELL **bufs;
  136. static double *h_weights;
  137. static double *v_weights;
  138. static int *mapcol0, *mapcol1;
  139. static int *maprow0, *maprow1;
  140. static void make_h_weights(void)
  141. {
  142. int col;
  143. h_weights = G_malloc(dst_w.cols * col_scale * sizeof(double));
  144. mapcol0 = G_malloc(dst_w.cols * sizeof(int));
  145. mapcol1 = G_malloc(dst_w.cols * sizeof(int));
  146. for (col = 0; col < dst_w.cols; col++) {
  147. double dx = Rast_col_to_easting(col + 0.5, &dst_w);
  148. double x0 = Rast_easting_to_col(dx - f_x_radius, &src_w);
  149. double x1 = Rast_easting_to_col(dx + f_x_radius, &src_w);
  150. int col0 = (int)floor(x0);
  151. int col1 = (int)floor(x1) + 1;
  152. int cols = col1 - col0;
  153. int j;
  154. mapcol0[col] = col0;
  155. mapcol1[col] = col1;
  156. for (j = 0; j < cols; j++) {
  157. double sx = Rast_col_to_easting(col0 + j + 0.5, &src_w);
  158. double r = fabs(sx - dx);
  159. double w = 1.0;
  160. int k;
  161. for (k = 0; k < num_filters; k++)
  162. w *= (*filters[k].func)(r / filters[k].x_radius);
  163. h_weights[col * col_scale + j] = w;
  164. }
  165. for (j = cols; j < col_scale; j++)
  166. h_weights[col * col_scale + j] = 0;
  167. }
  168. }
  169. static void make_v_weights(void)
  170. {
  171. int row;
  172. v_weights = G_malloc(dst_w.rows * row_scale * sizeof(double));
  173. maprow0 = G_malloc(dst_w.rows * sizeof(int));
  174. maprow1 = G_malloc(dst_w.rows * sizeof(int));
  175. for (row = 0; row < dst_w.rows; row++) {
  176. double dy = Rast_row_to_northing(row + 0.5, &dst_w);
  177. double y0 = Rast_northing_to_row(dy + f_y_radius, &src_w);
  178. double y1 = Rast_northing_to_row(dy - f_y_radius, &src_w);
  179. int row0 = (int)floor(y0);
  180. int row1 = (int)floor(y1) + 1;
  181. int rows = row1 - row0;
  182. int i;
  183. maprow0[row] = row0;
  184. maprow1[row] = row1;
  185. for (i = 0; i < rows; i++) {
  186. double sy = Rast_row_to_northing(row0 + i + 0.5, &src_w);
  187. double r = fabs(sy - dy);
  188. double w = 1.0;
  189. int k;
  190. for (k = 0; k < num_filters; k++)
  191. w *= (*filters[k].func)(r / filters[k].y_radius);
  192. v_weights[row * row_scale + i] = w;
  193. }
  194. for (i = rows; i < row_scale; i++)
  195. v_weights[row * row_scale + i] = 0;
  196. }
  197. }
  198. static void h_filter(DCELL *dst, const DCELL *src)
  199. {
  200. int col;
  201. for (col = 0; col < dst_w.cols; col++) {
  202. int col0 = mapcol0[col];
  203. int col1 = mapcol1[col];
  204. int cols = col1 - col0;
  205. double numer = 0.0;
  206. double denom = 0.0;
  207. int null = 0;
  208. int j;
  209. for (j = 0; j < cols; j++) {
  210. double w = h_weights[col * col_scale + j];
  211. const DCELL *c = &src[col0 + j];
  212. if (Rast_is_d_null_value(c)) {
  213. if (nulls) {
  214. null = 1;
  215. break;
  216. }
  217. }
  218. else {
  219. numer += w * (*c);
  220. denom += w;
  221. }
  222. }
  223. if (null || denom == 0)
  224. Rast_set_d_null_value(&dst[col], 1);
  225. else
  226. dst[col] = numer / denom;
  227. }
  228. }
  229. static void v_filter(DCELL *dst, DCELL **src, int row, int rows)
  230. {
  231. int col;
  232. for (col = 0; col < dst_w.cols; col++) {
  233. double numer = 0.0;
  234. double denom = 0.0;
  235. int null = 0;
  236. int i;
  237. for (i = 0; i < rows; i++) {
  238. double w = v_weights[row * row_scale + i];
  239. const DCELL *c = &src[i][col];
  240. if (Rast_is_d_null_value(c)) {
  241. if (nulls) {
  242. null = 1;
  243. break;
  244. }
  245. }
  246. else {
  247. numer += w * (*c);
  248. denom += w;
  249. }
  250. }
  251. if (null || denom == 0)
  252. Rast_set_d_null_value(&dst[col], 1);
  253. else
  254. dst[col] = numer / denom;
  255. }
  256. }
  257. static void filter(void)
  258. {
  259. int cur_row;
  260. int num_rows = 0;
  261. int row;
  262. make_h_weights();
  263. make_v_weights();
  264. for (row = 0; row < dst_w.rows; row++) {
  265. int row0 = maprow0[row];
  266. int row1 = maprow1[row];
  267. int rows = row1 - row0;
  268. int i;
  269. G_percent(row, dst_w.rows, 2);
  270. if (row0 >= cur_row && row0 < cur_row + num_rows) {
  271. int m = row0 - cur_row;
  272. int n = cur_row + num_rows - row0;
  273. int i;
  274. for (i = 0; i < n; i++) {
  275. DCELL *tmp = bufs[i];
  276. bufs[i] = bufs[m + i];
  277. bufs[m + i] = tmp;
  278. }
  279. cur_row = row0;
  280. num_rows = n;
  281. }
  282. else {
  283. cur_row = row0;
  284. num_rows = 0;
  285. }
  286. for (i = num_rows; i < rows; i++) {
  287. G_debug(5, "read: %p = %d", bufs[i], row0 + i);
  288. Rast_get_d_row(infile, inbuf, row0 + i);
  289. h_filter(bufs[i], inbuf);
  290. }
  291. num_rows = rows;
  292. v_filter(outbuf, bufs, row, rows);
  293. Rast_put_d_row(outfile, outbuf);
  294. G_debug(5, "write: %d", row);
  295. }
  296. G_percent(dst_w.rows, dst_w.rows, 2);
  297. }
  298. int main(int argc, char *argv[])
  299. {
  300. struct GModule *module;
  301. struct
  302. {
  303. struct Option *rastin, *rastout, *method,
  304. *radius, *x_radius, *y_radius;
  305. } parm;
  306. struct
  307. {
  308. struct Flag *nulls;
  309. } flag;
  310. char title[64];
  311. int i;
  312. G_gisinit(argv[0]);
  313. module = G_define_module();
  314. G_add_keyword(_("raster"));
  315. G_add_keyword(_("resample"));
  316. module->description =
  317. _("Resamples raster map layers using an analytic kernel.");
  318. parm.rastin = G_define_standard_option(G_OPT_R_INPUT);
  319. parm.rastout = G_define_standard_option(G_OPT_R_OUTPUT);
  320. parm.method = G_define_option();
  321. parm.method->key = "filter";
  322. parm.method->type = TYPE_STRING;
  323. parm.method->required = YES;
  324. parm.method->multiple = YES;
  325. parm.method->description = _("Filter kernel(s)");
  326. parm.method->options = build_filter_list();
  327. parm.radius = G_define_option();
  328. parm.radius->key = "radius";
  329. parm.radius->type = TYPE_DOUBLE;
  330. parm.radius->required = NO;
  331. parm.radius->multiple = YES;
  332. parm.radius->description = _("Filter radius");
  333. parm.x_radius = G_define_option();
  334. parm.x_radius->key = "x_radius";
  335. parm.x_radius->type = TYPE_DOUBLE;
  336. parm.x_radius->required = NO;
  337. parm.x_radius->multiple = YES;
  338. parm.x_radius->description = _("Filter radius (horizontal)");
  339. parm.y_radius = G_define_option();
  340. parm.y_radius->key = "y_radius";
  341. parm.y_radius->type = TYPE_DOUBLE;
  342. parm.y_radius->required = NO;
  343. parm.y_radius->multiple = YES;
  344. parm.y_radius->description = _("Filter radius (vertical)");
  345. flag.nulls = G_define_flag();
  346. flag.nulls->key = 'n';
  347. flag.nulls->description = _("Propagate NULLs");
  348. if (G_parser(argc, argv))
  349. exit(EXIT_FAILURE);
  350. if (parm.radius->answer) {
  351. if (parm.x_radius->answer || parm.y_radius->answer)
  352. G_fatal_error(_("radius= and x_radius=/y_radius= are mutually exclusive"));
  353. }
  354. else {
  355. if (!parm.x_radius->answer && !parm.y_radius->answer)
  356. G_fatal_error(_("Either radius= or x_radius=/y_radius= required"));
  357. if (!parm.x_radius->answer || !parm.y_radius->answer)
  358. G_fatal_error(_("Both x_radius= and y_radius= required"));
  359. }
  360. nulls = flag.nulls->answer;
  361. f_x_radius = f_y_radius = 1e100;
  362. for (i = 0; ; i++) {
  363. const char *filter_arg = parm.method->answers[i];
  364. const char *x_radius_arg = parm.radius->answer
  365. ? parm.radius->answers[i]
  366. : parm.x_radius->answers[i];
  367. const char *y_radius_arg = parm.radius->answer
  368. ? parm.radius->answers[i]
  369. : parm.y_radius->answers[i];
  370. const struct filter_type *type;
  371. struct filter *filter;
  372. if (!filter_arg && !x_radius_arg && !y_radius_arg)
  373. break;
  374. if (!filter_arg || !x_radius_arg || !y_radius_arg)
  375. G_fatal_error(_("Differing number of values for filter= and [xy_]radius="));
  376. if (num_filters >= MAX_FILTERS)
  377. G_fatal_error(_("Too many filters (max: %d)"), MAX_FILTERS);
  378. filter = &filters[num_filters++];
  379. type = find_method(filter_arg);
  380. filter->func = type->func;
  381. filter->x_radius = fabs(atof(x_radius_arg));
  382. filter->y_radius = fabs(atof(y_radius_arg));
  383. if (type->radius) {
  384. double rx = type->radius * filter->x_radius;
  385. double ry = type->radius * filter->y_radius;
  386. if (rx < f_x_radius)
  387. f_x_radius = rx;
  388. if (ry < f_y_radius)
  389. f_y_radius = ry;
  390. }
  391. }
  392. if (f_x_radius > 1e99 || f_y_radius > 1e99)
  393. G_fatal_error(_("At least one filter must be finite"));
  394. G_get_set_window(&dst_w);
  395. /* set window to old map */
  396. Rast_get_cellhd(parm.rastin->answer, "", &src_w);
  397. /* enlarge source window */
  398. {
  399. double y0 = Rast_row_to_northing(0.5, &dst_w);
  400. double y1 = Rast_row_to_northing(dst_w.rows - 0.5, &dst_w);
  401. double x0 = Rast_col_to_easting(0.5, &dst_w);
  402. double x1 = Rast_col_to_easting(dst_w.cols - 0.5, &dst_w);
  403. int r0 = (int)floor(Rast_northing_to_row(y0 + f_y_radius, &src_w) - 0.1);
  404. int r1 = (int)ceil(Rast_northing_to_row(y1 - f_y_radius, &src_w) + 0.1);
  405. int c0 = (int)floor(Rast_easting_to_col(x0 - f_x_radius, &src_w) - 0.1);
  406. int c1 = (int)ceil(Rast_easting_to_col(x1 + f_x_radius, &src_w) + 0.1);
  407. src_w.south -= src_w.ns_res * (r1 - src_w.rows);
  408. src_w.north += src_w.ns_res * (-r0);
  409. src_w.west -= src_w.ew_res * (-c0);
  410. src_w.east += src_w.ew_res * (c1 - src_w.cols);
  411. src_w.rows = r1 - r0;
  412. src_w.cols = c1 - c0;
  413. }
  414. row_scale = 2 + 2 * ceil(f_y_radius / src_w.ns_res);
  415. col_scale = 2 + 2 * ceil(f_x_radius / src_w.ew_res);
  416. /* allocate buffers for intermediate rows */
  417. bufs = G_malloc(row_scale * sizeof(DCELL *));
  418. for (i = 0; i < row_scale; i++)
  419. bufs[i] = Rast_allocate_d_buf();
  420. Rast_set_input_window(&src_w);
  421. Rast_set_output_window(&dst_w);
  422. inbuf = Rast_allocate_d_input_buf();
  423. outbuf = Rast_allocate_d_output_buf();
  424. infile = Rast_open_old(parm.rastin->answer, "");
  425. outfile = Rast_open_new(parm.rastout->answer, DCELL_TYPE);
  426. filter();
  427. Rast_close(infile);
  428. Rast_close(outfile);
  429. /* record map metadata/history info */
  430. sprintf(title, "Filter resample by %s", parm.method->answer);
  431. Rast_put_cell_title(parm.rastout->answer, title);
  432. {
  433. struct History history;
  434. char buf_nsres[100], buf_ewres[100];
  435. Rast_short_history(parm.rastout->answer, "raster", &history);
  436. Rast_set_history(&history, HIST_DATSRC_1, parm.rastin->answer);
  437. G_format_resolution(src_w.ns_res, buf_nsres, src_w.proj);
  438. G_format_resolution(src_w.ew_res, buf_ewres, src_w.proj);
  439. Rast_format_history(&history, HIST_DATSRC_2,
  440. "Source map NS res: %s EW res: %s",
  441. buf_nsres, buf_ewres);
  442. Rast_command_history(&history);
  443. Rast_write_history(parm.rastout->answer, &history);
  444. }
  445. /* copy color table from source map */
  446. {
  447. struct Colors colors;
  448. if (Rast_read_colors(parm.rastin->answer, "", &colors) < 0)
  449. G_fatal_error(_("Unable to read color table for %s"),
  450. parm.rastin->answer);
  451. Rast_mark_colors_as_fp(&colors);
  452. Rast_write_colors(parm.rastout->answer, G_mapset(), &colors);
  453. }
  454. return EXIT_SUCCESS;
  455. }