[gdal-dev] gdal_translate: a preliminary `-gcp_file' patch

Ivan Shmakov ivan at theory.asu.ru
Thu Dec 13 04:09:10 EST 2007


	Since the current version of GDAL doesn't support reading GCPs
	from some of the data sets I use [1], I have to use
	`gdal_translate' to specify all the GCPs, like:

$ file=/where/is/AIRS-L2-RetStd.hdf
$ gdal_translate \
      $(paste <(hdfdump --text "$file" {Long,Lat}itude) \
            | gawk '$1 != -9999 && $2 != -9999 { print "-gcp", (NR - 1) % 30 + .5, int ((NR - 1) / 30) + .5, $1, $2; }') \
      "HDF4_EOS:EOS_SWATH:\"$file\":L2_Standard_atmospheric&surface_product:TSurfStd" \
      AIRS-L2-RetStd.TSurfStd.gcp.tiff
$ 

	There, the dimensions of the data set are 30x45.

	However, would I try to use the above on a larger data set (say,
	MODIS 1 km, which is 1354x2030 for a standard NASA granule),
	I'll quickly run into the command line size limit (on most of
	the operating systems I know.)

	Therefore, I suggest the new `-gcp_from FILE' option for
	`gdal_translate'.

	The patch is roughly as follows.  Beware that the getline ()
	function is a GNU extension, available either from GNU Libc [2],
	or Gnulib [3].

--- gdal_translate.cpp.~4~	2007-12-13 11:32:31.000000000 +0600
+++ gdal_translate.cpp	2007-12-13 13:57:30.000000000 +0600
@@ -57,6 +57,7 @@
             "       [-srcwin xoff yoff xsize ysize] [-projwin ulx uly lrx lry]\n"
             "       [-a_srs srs_def] [-a_ullr ulx uly lrx lry] [-a_nodata value]\n"
             "       [-gcp pixel line easting northing [elevation]]*\n" 
+            "       [-gcp_from gcp_file]*\n" 
             "       [-mo \"META-TAG=VALUE\"]* [-quiet] [-sds]\n"
             "       [-co \"NAME=VALUE\"]*\n"
             "       src_dataset dst_dataset\n\n" );
@@ -79,6 +80,79 @@
 }
 
 /************************************************************************/
+/*                           handleGCPfrom ()                           */
+/************************************************************************/
+static int
+handleGCPfrom (const char *filename, GDAL_GCP **gcpp, int *ngcpp)
+{
+    /* NB: `ngcpp' should be of type `size_t *' rather than `int *' */
+    FILE *fp;
+    int lineno;
+    char *linebuf = 0;
+    size_t linesz = 0;
+    size_t new_points;
+
+    /* open the file, return -1 on failure */
+    fp = fopen (filename, "r");
+    if (fp == 0) {
+        /* use strerror () here? */
+        /* follow generic Unix ``program: message'' convention? */
+        fprintf (stderr, "WARNING: handleGCPfrom (): %s: %s\n",
+                 filename, "fopen () failed");
+        return -1;
+    }
+
+    /* parse the file */
+    /* NB: for better performance, CPLRealloc () the array in bigger
+     *     steps */
+    for (lineno = 0, new_points = 0; ! feof (fp); lineno++) {
+        int rv;
+        float pix, lin, x, y, elev;
+
+        /* NB: fscanf () is hardly a good idea */
+        {
+            ssize_t read;
+            if ((read = getline (&linebuf, &linesz, fp)) < 0) {
+                /* NB: a warning if not EOF here? */
+                break;
+            }
+        }
+
+        rv = sscanf (linebuf, " %f %f %f %f %f",
+                     &pix, &lin, &x, &y, &elev);
+        if (rv < 4) {
+            fprintf (stderr,
+                     ("WARNING: handleGCPfrom (): %s:%d"
+                      ": cannot parse line\n"),
+                     filename, lineno);
+            continue;
+        }
+
+        /* append the GCP just read to the array */
+
+        new_points++;
+        *gcpp = (GDAL_GCP *)
+            CPLRealloc (*gcpp, sizeof (**gcpp) * (++(*ngcpp)));
+        GDAL_GCP *tailp = *gcpp + *ngcpp - 1;
+        GDALInitGCPs (1, tailp);
+
+        tailp->dfGCPPixel = pix;
+        tailp->dfGCPLine = lin;
+        tailp->dfGCPX = x;
+        tailp->dfGCPY = y;
+    }
+
+    /* deallocate the line buffer */
+    CPLFree (linebuf);
+
+    /* close the file */
+    fclose (fp);
+
+    /* . */
+    return new_points;
+}
+
+/************************************************************************/
 /*                             ProxyMain()                              */
 /************************************************************************/
 
@@ -221,6 +295,11 @@
             /* should set id and info? */
         }   
 
+        else if (EQUAL (argv[i], "-gcp_from") && i < argc - 1) {
+            handleGCPfrom (argv[++i], &pasGCPs, &nGCPCount);
+            ++i;
+        }
+
         else if( EQUAL(argv[i],"-a_nodata") && i < argc - 1 )
         {
             bSetNoData = TRUE;

[1] http://trac.osgeo.org/gdal/ticket/2079
[2] http://www.gnu.org/software/libc/
[3] http://www.gnu.org/software/gnulib/



More information about the gdal-dev mailing list