| 1 |
|
|---|
| 2 | /****************************************************************************
|
|---|
| 3 | *
|
|---|
| 4 | * MODULE: r.external
|
|---|
| 5 | *
|
|---|
| 6 | * AUTHOR(S): Glynn Clements, based on r.in.gdal
|
|---|
| 7 | * List GDAL layers by Martin Landa <landa.martin gmail.com> 8/2011
|
|---|
| 8 | *
|
|---|
| 9 | * PURPOSE: Link raster map into GRASS utilizing the GDAL library.
|
|---|
| 10 | *
|
|---|
| 11 | * COPYRIGHT: (C) 2008-2015 by Glynn Clements and the GRASS Development Team
|
|---|
| 12 | *
|
|---|
| 13 | * This program is free software under the GNU General Public
|
|---|
| 14 | * License (>=v2). Read the file COPYING that comes with GRASS
|
|---|
| 15 | * for details.
|
|---|
| 16 | *
|
|---|
| 17 | *****************************************************************************/
|
|---|
| 18 |
|
|---|
| 19 | #include <stdlib.h>
|
|---|
| 20 | #include <unistd.h>
|
|---|
| 21 | #include <math.h>
|
|---|
| 22 | #include <string.h>
|
|---|
| 23 |
|
|---|
| 24 | #include <grass/gis.h>
|
|---|
| 25 | #include <grass/raster.h>
|
|---|
| 26 | #include <grass/imagery.h>
|
|---|
| 27 | #include <grass/glocale.h>
|
|---|
| 28 |
|
|---|
| 29 | #include <gdal.h>
|
|---|
| 30 | #include <ogr_srs_api.h>
|
|---|
| 31 | #include <cpl_conv.h>
|
|---|
| 32 |
|
|---|
| 33 | #include "proto.h"
|
|---|
| 34 |
|
|---|
| 35 | int main(int argc, char *argv[])
|
|---|
| 36 | {
|
|---|
| 37 | const char *input, *source, *output;
|
|---|
| 38 | char *title;
|
|---|
| 39 | struct Cell_head cellhd;
|
|---|
| 40 | GDALDatasetH hDS;
|
|---|
| 41 | GDALRasterBandH hBand;
|
|---|
| 42 | struct GModule *module;
|
|---|
| 43 | struct {
|
|---|
| 44 | struct Option *input, *source, *output, *band, *title;
|
|---|
| 45 | } parm;
|
|---|
| 46 | struct {
|
|---|
| 47 | struct Flag *o, *j, *f, *e, *h, *v, *t, *a;
|
|---|
| 48 | } flag;
|
|---|
| 49 | int min_band, max_band, band;
|
|---|
| 50 | struct band_info info;
|
|---|
| 51 | int flip;
|
|---|
| 52 | struct Ref reference;
|
|---|
| 53 |
|
|---|
| 54 | G_gisinit(argv[0]);
|
|---|
| 55 |
|
|---|
| 56 | module = G_define_module();
|
|---|
| 57 | G_add_keyword(_("raster"));
|
|---|
| 58 | G_add_keyword(_("import"));
|
|---|
| 59 | G_add_keyword(_("external"));
|
|---|
| 60 | module->description =
|
|---|
| 61 | _("Links GDAL supported raster data as a pseudo GRASS raster map.");
|
|---|
| 62 |
|
|---|
| 63 | parm.input = G_define_standard_option(G_OPT_F_INPUT);
|
|---|
| 64 | parm.input->description = _("Name of raster file to be linked");
|
|---|
| 65 | parm.input->required = NO;
|
|---|
| 66 | parm.input->guisection = _("Input");
|
|---|
| 67 |
|
|---|
| 68 | parm.source = G_define_option();
|
|---|
| 69 | parm.source->key = "source";
|
|---|
| 70 | parm.source->description = _("Name of non-file GDAL data source");
|
|---|
| 71 | parm.source->required = NO;
|
|---|
| 72 | parm.source->type = TYPE_STRING;
|
|---|
| 73 | parm.source->key_desc = "name";
|
|---|
| 74 | parm.source->guisection = _("Input");
|
|---|
| 75 |
|
|---|
| 76 | parm.output = G_define_standard_option(G_OPT_R_OUTPUT);
|
|---|
| 77 |
|
|---|
| 78 | parm.band = G_define_option();
|
|---|
| 79 | parm.band->key = "band";
|
|---|
| 80 | parm.band->type = TYPE_INTEGER;
|
|---|
| 81 | parm.band->required = NO;
|
|---|
| 82 | parm.band->description = _("Band to select (default is all bands)");
|
|---|
| 83 | parm.band->guisection = _("Input");
|
|---|
| 84 |
|
|---|
| 85 | parm.title = G_define_option();
|
|---|
| 86 | parm.title->key = "title";
|
|---|
| 87 | parm.title->key_desc = "phrase";
|
|---|
| 88 | parm.title->type = TYPE_STRING;
|
|---|
| 89 | parm.title->required = NO;
|
|---|
| 90 | parm.title->description = _("Title for resultant raster map");
|
|---|
| 91 | parm.title->guisection = _("Metadata");
|
|---|
| 92 |
|
|---|
| 93 | flag.f = G_define_flag();
|
|---|
| 94 | flag.f->key = 'f';
|
|---|
| 95 | flag.f->description = _("List supported formats and exit");
|
|---|
| 96 | flag.f->guisection = _("Print");
|
|---|
| 97 | flag.f->suppress_required = YES;
|
|---|
| 98 |
|
|---|
| 99 | flag.o = G_define_flag();
|
|---|
| 100 | flag.o->key = 'o';
|
|---|
| 101 | flag.o->label =
|
|---|
| 102 | _("Override projection check (use current location's projection)");
|
|---|
| 103 | flag.o->description =
|
|---|
| 104 | _("Assume that the dataset has same projection as the current location");
|
|---|
| 105 |
|
|---|
| 106 | flag.j = G_define_flag();
|
|---|
| 107 | flag.j->key = 'j';
|
|---|
| 108 | flag.j->description =
|
|---|
| 109 | _("Perform projection check only and exit");
|
|---|
| 110 | flag.j->suppress_required = YES;
|
|---|
| 111 |
|
|---|
| 112 | flag.e = G_define_flag();
|
|---|
| 113 | flag.e->key = 'e';
|
|---|
| 114 | flag.e->label = _("Extend region extents based on new dataset");
|
|---|
| 115 | flag.e->description = _("Also updates the default region if in the PERMANENT mapset");
|
|---|
| 116 |
|
|---|
| 117 | flag.a = G_define_flag();
|
|---|
| 118 | flag.a->key = 'a';
|
|---|
| 119 | flag.a->label = _("Auto-adjustment for lat/lon");
|
|---|
| 120 | flag.a->description = _("Attempt to fix small precision errors in resolution and extents");
|
|---|
| 121 |
|
|---|
| 122 | flag.h = G_define_flag();
|
|---|
| 123 | flag.h->key = 'h';
|
|---|
| 124 | flag.h->description = _("Flip horizontally");
|
|---|
| 125 |
|
|---|
| 126 | flag.v = G_define_flag();
|
|---|
| 127 | flag.v->key = 'v';
|
|---|
| 128 | flag.v->description = _("Flip vertically");
|
|---|
| 129 |
|
|---|
| 130 | flag.t = G_define_flag();
|
|---|
| 131 | flag.t->key = 't';
|
|---|
| 132 | flag.t->label =
|
|---|
| 133 | _("List available bands including band type in dataset and exit");
|
|---|
| 134 | flag.t->description = _("Format: band number,type,projection check");
|
|---|
| 135 | flag.t->guisection = _("Print");
|
|---|
| 136 | flag.t->suppress_required = YES;
|
|---|
| 137 |
|
|---|
| 138 | if (G_parser(argc, argv))
|
|---|
| 139 | exit(EXIT_FAILURE);
|
|---|
| 140 |
|
|---|
| 141 | GDALAllRegister();
|
|---|
| 142 |
|
|---|
| 143 | if (flag.f->answer) {
|
|---|
| 144 | list_formats();
|
|---|
| 145 | exit(EXIT_SUCCESS);
|
|---|
| 146 | }
|
|---|
| 147 |
|
|---|
| 148 | input = parm.input->answer;
|
|---|
| 149 | source = parm.source->answer;
|
|---|
| 150 | output = parm.output->answer;
|
|---|
| 151 |
|
|---|
| 152 | flip = 0;
|
|---|
| 153 | if (flag.h->answer)
|
|---|
| 154 | flip |= FLIP_H;
|
|---|
| 155 | if (flag.v->answer)
|
|---|
| 156 | flip |= FLIP_V;
|
|---|
| 157 |
|
|---|
| 158 | if (parm.title->answer) {
|
|---|
| 159 | title = G_store(parm.title->answer);
|
|---|
| 160 | G_strip(title);
|
|---|
| 161 | }
|
|---|
| 162 | else
|
|---|
| 163 | title = NULL;
|
|---|
| 164 |
|
|---|
| 165 | if (!input && !source)
|
|---|
| 166 | G_fatal_error(_("%s= or %s= must be given"),
|
|---|
| 167 | parm.input->key, parm.source->key);
|
|---|
| 168 |
|
|---|
| 169 | if (input && source)
|
|---|
| 170 | G_fatal_error(_("%s= and %s= are mutually exclusive"),
|
|---|
| 171 | parm.input->key, parm.source->key);
|
|---|
| 172 |
|
|---|
| 173 | if (input && !G_is_absolute_path(input)) {
|
|---|
| 174 | char path[GPATH_MAX], *cwd;
|
|---|
| 175 | cwd = CPLGetCurrentDir();
|
|---|
| 176 | if (!cwd)
|
|---|
| 177 | G_fatal_error(_("Unable to get current working directory"));
|
|---|
| 178 |
|
|---|
| 179 | G_snprintf(path, GPATH_MAX, "%s%c%s", cwd, HOST_DIRSEP, input);
|
|---|
| 180 | input = G_store(path);
|
|---|
| 181 | CPLFree(cwd);
|
|---|
| 182 | }
|
|---|
| 183 |
|
|---|
| 184 | if (!input)
|
|---|
| 185 | input = source;
|
|---|
| 186 |
|
|---|
| 187 | hDS = GDALOpen(input, GA_ReadOnly);
|
|---|
| 188 | if (hDS == NULL)
|
|---|
| 189 | return 1;
|
|---|
| 190 |
|
|---|
| 191 | setup_window(&cellhd, hDS, &flip);
|
|---|
| 192 |
|
|---|
| 193 | if (flag.t->answer) {
|
|---|
| 194 | list_bands(&cellhd, hDS);
|
|---|
| 195 | /* close the GDALDataset to avoid segfault in libgdal */
|
|---|
| 196 | GDALClose(hDS);
|
|---|
| 197 | exit(EXIT_SUCCESS);
|
|---|
| 198 | }
|
|---|
| 199 |
|
|---|
| 200 | check_projection(&cellhd, hDS, NULL, 0, flag.o->answer, flag.j->answer);
|
|---|
| 201 |
|
|---|
| 202 | if (flag.a->answer && cellhd.proj == PROJECTION_LL) {
|
|---|
| 203 | G_adjust_Cell_head(&cellhd, 1, 1);
|
|---|
| 204 | G_adjust_window_ll(&cellhd);
|
|---|
| 205 | }
|
|---|
| 206 |
|
|---|
| 207 | Rast_set_window(&cellhd);
|
|---|
| 208 |
|
|---|
| 209 | if (parm.band->answer)
|
|---|
| 210 | min_band = max_band = atoi(parm.band->answer);
|
|---|
| 211 | else
|
|---|
| 212 | min_band = 1, max_band = GDALGetRasterCount(hDS);
|
|---|
| 213 |
|
|---|
| 214 | G_verbose_message(_("Proceeding with import..."));
|
|---|
| 215 |
|
|---|
| 216 | if (max_band > min_band) {
|
|---|
| 217 | if (I_find_group(output) == 1)
|
|---|
| 218 | G_warning(_("Imagery group <%s> already exists and will be overwritten."), output);
|
|---|
| 219 | I_init_group_ref(&reference);
|
|---|
| 220 | }
|
|---|
| 221 |
|
|---|
| 222 | for (band = min_band; band <= max_band; band++) {
|
|---|
| 223 | char *output2, *title2 = NULL;
|
|---|
| 224 |
|
|---|
| 225 | G_message(_("Reading band %d of %d..."),
|
|---|
| 226 | band, GDALGetRasterCount( hDS ));
|
|---|
| 227 |
|
|---|
| 228 | hBand = GDALGetRasterBand(hDS, band);
|
|---|
| 229 | if (!hBand)
|
|---|
| 230 | G_fatal_error(_("Selected band (%d) does not exist"), band);
|
|---|
| 231 |
|
|---|
| 232 | if (max_band > min_band) {
|
|---|
| 233 | G_asprintf(&output2, "%s.%d", output, band);
|
|---|
| 234 | if (title)
|
|---|
| 235 | G_asprintf(&title2, "%s (band %d)", title, band);
|
|---|
| 236 | G_debug(1, "Adding raster map <%s> to group <%s>", output2, output);
|
|---|
| 237 | I_add_file_to_group_ref(output2, G_mapset(), &reference);
|
|---|
| 238 | }
|
|---|
| 239 | else {
|
|---|
| 240 | output2 = G_store(output);
|
|---|
| 241 | if (title)
|
|---|
| 242 | title2 = G_store(title);
|
|---|
| 243 | }
|
|---|
| 244 |
|
|---|
| 245 | query_band(hBand, output2, &cellhd, &info);
|
|---|
| 246 | create_map(input, band, output2, &cellhd, &info, title, flip);
|
|---|
| 247 |
|
|---|
| 248 | G_free(output2);
|
|---|
| 249 | G_free(title2);
|
|---|
| 250 | }
|
|---|
| 251 |
|
|---|
| 252 | /* close the GDALDataset to avoid segfault in libgdal */
|
|---|
| 253 | GDALClose(hDS);
|
|---|
| 254 |
|
|---|
| 255 | if (flag.e->answer)
|
|---|
| 256 | update_default_window(&cellhd);
|
|---|
| 257 |
|
|---|
| 258 | /* Create the imagery group if multiple bands are imported */
|
|---|
| 259 | if (max_band > min_band) {
|
|---|
| 260 | I_put_group_ref(output, &reference);
|
|---|
| 261 | I_put_group(output);
|
|---|
| 262 | G_message(_("Imagery group <%s> created"), output);
|
|---|
| 263 | }
|
|---|
| 264 |
|
|---|
| 265 | exit(EXIT_SUCCESS);
|
|---|
| 266 | }
|
|---|