[GRASS-SVN] r43938 - grass/branches/releasebranch_6_4/raster/r.out.png

svn_grass at osgeo.org svn_grass at osgeo.org
Sun Oct 17 02:36:06 EDT 2010


Author: hamish
Date: 2010-10-16 23:36:06 -0700 (Sat, 16 Oct 2010)
New Revision: 43938

Modified:
   grass/branches/releasebranch_6_4/raster/r.out.png/description.html
   grass/branches/releasebranch_6_4/raster/r.out.png/pngfunc.h
   grass/branches/releasebranch_6_4/raster/r.out.png/r.out.png.c
Log:
backport worldfile and transparency flags from devbr6, useful for Google Earth/KML and gdal2tiles.py/web tile services

Modified: grass/branches/releasebranch_6_4/raster/r.out.png/description.html
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.out.png/description.html	2010-10-17 06:22:00 UTC (rev 43937)
+++ grass/branches/releasebranch_6_4/raster/r.out.png/description.html	2010-10-17 06:36:06 UTC (rev 43938)
@@ -1,16 +1,31 @@
 <h2>DESCRIPTION</h2>
 
 
-<em>r.out.png</em> exports a GRASS raster map as non-georeferenced PNG image
-format
+<em>r.out.png</em> exports a GRASS raster map in non-georeferenced PNG image
+format, respecting the current region resolution and bounds.
 
+<p>
+Optionally the user can choose to export a World File to provide basic
+georeferencing support. When used with the transparency flag this can
+create images useful for KML, TMS, or WMS overlays. (e.g. for use in
+Google Earth or as OpenLayers tiles) If output is to stdout, the world 
+file will be called <tt>png_map.wld</tt>. 
+
+
 <h2>SEE ALSO</h2>
 
-<em><a href="r.out.tiff.html">r.out.tiff</a>,</em>
-<em><a href="r.out.ascii.html">r.out.ascii</a></em>
+<em>
+<a href="r.out.gdal.html">r.out.gdal</a>,
+<a href="r.out.ppm.html">r.out.ppm</a>,
+<a href="r.out.tiff.html">r.out.tiff</a>,
+<a href="r.out.ascii.html">r.out.ascii</a>
+</em>
 
-<h2>AUTHOR</h2>
 
-Alex Shevlakov
+<h2>AUTHORS</h2>
 
-<p><i>Last changed: $Date$</i>
+Alex Shevlakov<BR>
+Hamish Bowman
+
+<p>
+<i>Last changed: $Date$</i>

Modified: grass/branches/releasebranch_6_4/raster/r.out.png/pngfunc.h
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.out.png/pngfunc.h	2010-10-17 06:22:00 UTC (rev 43937)
+++ grass/branches/releasebranch_6_4/raster/r.out.png/pngfunc.h	2010-10-17 06:36:06 UTC (rev 43938)
@@ -25,7 +25,6 @@
 #if 0
 /* unused */
 static int filter = -1;
-static int compression = Z_DEFAULT_COMPRESSION;
 #endif
 static jmpbuf_wrapper pnmtopng_jmpbuf_struct;
 

Modified: grass/branches/releasebranch_6_4/raster/r.out.png/r.out.png.c
===================================================================
--- grass/branches/releasebranch_6_4/raster/r.out.png/r.out.png.c	2010-10-17 06:22:00 UTC (rev 43937)
+++ grass/branches/releasebranch_6_4/raster/r.out.png/r.out.png.c	2010-10-17 06:36:06 UTC (rev 43938)
@@ -4,8 +4,9 @@
  * MODULE:       r.out.png
  * AUTHOR(S):    Bill Brown - USA-CERL
  *               Alex Shevlakov - sixote at yahoo.com
+ *		 Hamish Bowman
  * PURPOSE:      Export GRASS raster as non-georeferenced PNG image.
- * COPYRIGHT:    (C) 2000 by the GRASS Development Team
+ * COPYRIGHT:    (C) 2000-2010 by the GRASS Development Team
  *
  *               This program is free software under the GNU General Public
  *               License (>=v2). Read the file COPYING that comes with GRASS
@@ -14,20 +15,18 @@
  *****************************************************************************/
 
 /* 
+ * Alex Shevlakov, sixote at yahoo.com, 03/2000 
  * based on r.out.ppm by
  * Written by Bill Brown, USA-CERL March 21, 1994
  * 
- */
-
-/* Use to convert grass raster map to PNG
+ * Use to convert grass raster map to PNG
  * uses currently selected region
+ *
  */
 
-/*              Alex Shevlakov, sixote at yahoo.com, 03/2000 
- */
-
 #include <string.h>
 #include <stdlib.h>
+#include <float.h>
 
 #ifndef _MYINCLUDE_H
 #define _MYINCLUDE_H
@@ -39,49 +38,51 @@
 #include <grass/gis.h>
 #include <grass/glocale.h>
 
-#define DEF_RED 255
-#define DEF_GRN 255
-#define DEF_BLU 255
 
 typedef int FILEDESC;
 
+/* global functions */
+static int write_wld(const char *, const struct Cell_head *);
+
+
 int main(int argc, char *argv[])
 {
     struct GModule *module;
-    struct Option *rast, *png_file;
-
-    /* please, remove before GRASS 7 released */
-    struct Flag *bequiet;
-    char *cellmap, *map, *p, *basename = NULL, *ofile;
+    struct Option *rast, *png_file, *compr; /* , *bgcolor; */
+    struct Flag *bequiet, *alpha, *wld_flag;
+    char *cellmap, *map, *p, *basename = NULL, *outfile = NULL;
     char rastermap[1024];
     unsigned char *set, *ored, *ogrn, *oblu;
+    int def_red, def_grn, def_blu;
     CELL *cell_buf;
     FCELL *fcell_buf;
     DCELL *dcell_buf;
     void *voidc;
     int rtype, row, col, do_stdout = 0;
-    struct Cell_head w;
+    size_t rsize;
+    int png_compr, ret, do_alpha;
+    struct Cell_head win;
     FILEDESC cellfile = 0;
     FILE *fp;
 
     /* now goes from pnmtopng.c* -A.Sh */
     /*
-     * ** pnmtopng.c -
-     * ** read a portable anymap and produce a Portable Network Graphics file
-     * **
-     * ** derived from pnmtorast.c (c) 1990,1991 by Jef Poskanzer and some
-     * ** parts derived from ppmtogif.c by Marcel Wijkstra <wijkstra at fwi.uva.nl>
-     * ** thanks to Greg Roelofs <newt at pobox.com> for contributions and bug-fixes
-     * **
-     * ** Copyright (C) 1995-1998 by Alexander Lehmann <alex at hal.rhein-main.de>
-     * **                        and Willem van Schaik <willem at schaik.com>
-     * **
-     * ** Permission to use, copy, modify, and distribute this software and its
-     * ** documentation for any purpose and without fee is hereby granted, provided
-     * ** that the above copyright notice appear in all copies and that both that
-     * ** copyright notice and this permission notice appear in supporting
-     * ** documentation.  This software is provided "as is" without express or
-     * ** implied warranty.
+     * pnmtopng.c -
+     * read a portable anymap and produce a Portable Network Graphics file
+     *
+     * derived from pnmtorast.c (c) 1990,1991 by Jef Poskanzer and some
+     * parts derived from ppmtogif.c by Marcel Wijkstra <wijkstra at fwi.uva.nl>
+     * thanks to Greg Roelofs <newt at pobox.com> for contributions and bug-fixes
+     *
+     * Copyright (C) 1995-1998 by Alexander Lehmann <alex at hal.rhein-main.de>
+     *  		      and Willem van Schaik <willem at schaik.com>
+     *
+     * Permission to use, copy, modify, and distribute this software and its
+     * documentation for any purpose and without fee is hereby granted, provided
+     * that the above copyright notice appear in all copies and that both that
+     * copyright notice and this permission notice appear in supporting
+     * documentation.  This software is provided "as is" without express or
+     * implied warranty.
      */
 
     png_struct *png_ptr;
@@ -105,41 +106,53 @@
 
     G_gisinit(argv[0]);
 
-    rast = G_define_option();
-    rast->key = "input";
-    rast->type = TYPE_STRING;
-    rast->required = YES;
-    rast->multiple = NO;
-    rast->gisprompt = "old,cell,Raster";
-    rast->description = "Raster file to be converted.";
+    module = G_define_module();
+    module->keywords = _("raster, png");
+    module->description =
+	_("Export GRASS raster as non-georeferenced PNG image.");
 
-    png_file = G_define_option();
-    png_file->key = "output";
-    png_file->type = TYPE_STRING;
+    rast = G_define_standard_option(G_OPT_R_INPUT);
+
+    png_file = G_define_standard_option(G_OPT_F_OUTPUT);
     png_file->required = NO;
-    png_file->multiple = NO;
     png_file->answer = "<rasterfilename>.png";
-    png_file->description = "Name for new PNG file. (use out=- for stdout)";
+    png_file->description = _("Name for new PNG file (use out=- for stdout)");
 
+    compr = G_define_option();
+    compr->key = "compression";
+    compr->type = TYPE_INTEGER;
+    compr->required = NO;
+    compr->multiple = NO;
+    compr->options = "0-9";
+    compr->label = _("Compression level of PNG file");
+    compr->description = _("(0 = none, 1 = fastest, 9 = best)");
+    compr->answer = "6";
+
+/*    bgcolor = G_define_standard_option(G_OPT_C_BG); */
+
     /* please, remove before GRASS 7 released */
     bequiet = G_define_flag();
     bequiet->key = 'q';
-    bequiet->description = "Run quietly";
+    bequiet->description = _("Run quietly");
 
+    alpha = G_define_flag();
+    alpha->key = 't';
+    alpha->description = _("Make NULL cells transparent");
+
+    wld_flag = G_define_flag();
+    wld_flag->key = 'w';
+    wld_flag->description = _("Output world file");
+
     /* see what can be done to convert'em -A.Sh.
      * gscale = G_define_flag ();
      * gscale->key = 'G';
      * gscale->description = "Output greyscale instead of color";
      */
 
-    module = G_define_module();
-    module->keywords = _("raster");
-    module->description =
-	"Export GRASS raster as non-georeferenced PNG image format.";
-
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
 
+
     /* please, remove before GRASS 7 released */
     if (bequiet->answer) {
 	putenv("GRASS_VERBOSE=0");
@@ -147,14 +160,16 @@
 		    "in future. Please use '--quiet' instead."));
     }
 
+    do_alpha = alpha->answer ? TRUE : FALSE;
 
+
     strncpy(rastermap, rast->answer, 1024 * sizeof(char));
 
     if (strcmp(png_file->answer, "<rasterfilename>.png")) {
 	if (strcmp(png_file->answer, "-"))
 	    basename = G_store(png_file->answer);
 	else
-	    do_stdout = 1;
+	    do_stdout = TRUE;
     }
     else {
 	map = p = rast->answer;
@@ -168,45 +183,56 @@
 
     if (basename) {
 	G_basename(basename, "png");
-	ofile = G_malloc(strlen(basename) + 5);
-	sprintf(ofile, "%s.png", basename);
-	G_free(basename);
+	outfile = G_malloc(strlen(basename) + 5);
+	sprintf(outfile, "%s.png", basename);
     }
 
-    /*G_get_set_window (&w); *//* 10/99 MN: check for current region */
-    G_get_window(&w);
+    png_compr = atoi(compr->answer);
 
-    G_message(_("rows = %d, cols = %d"), w.rows, w.cols);
+#ifdef MAYBE_LATER
+    /* ... if at all */
+    ret = G_str_to_color(bgcolor->answer, &def_red, &def_grn, &def_blu);
+    if (ret == 0)
+    	G_fatal_error(_("[%s]: No such color"), bgcolor->answer);
+    else if (ret == 2) {  /* (ret==2) is "none" */
+    	if(!do_alpha)
+	    do_alpha = TRUE;
+    }
+#else
+    ret = G_str_to_color(DEFAULT_BG_COLOR, &def_red, &def_grn, &def_blu);
+#endif
 
+    /*G_get_set_window (&win); *//* 10/99 MN: check for current region */
+    G_get_window(&win);
+
+    G_debug(1, "rows = %d, cols = %d", win.rows, win.cols);
+
     /* open raster map for reading */
     {
 	cellmap = G_find_file2("cell", rastermap, "");
 	if (!cellmap)
-	    G_fatal_error("Couldn't find raster map %s", rastermap);
+	    G_fatal_error(_("Raster map <%s> not found"), rastermap);
 
 	if ((cellfile = G_open_cell_old(rast->answer, cellmap)) == -1)
-	    G_fatal_error("Not able to open cellfile for [%s]", rastermap);
+	    G_fatal_error(_("Unable to open raster map <%s>"), rastermap);
     }
 
     cell_buf = G_allocate_c_raster_buf();
     fcell_buf = G_allocate_f_raster_buf();
     dcell_buf = G_allocate_d_raster_buf();
 
-    ored = (unsigned char *)G_malloc(w.cols * sizeof(unsigned char));
-    ogrn = (unsigned char *)G_malloc(w.cols * sizeof(unsigned char));
-    oblu = (unsigned char *)G_malloc(w.cols * sizeof(unsigned char));
-    set = (unsigned char *)G_malloc(w.cols * sizeof(unsigned char));
+    ored = (unsigned char *)G_malloc(win.cols * sizeof(unsigned char));
+    ogrn = (unsigned char *)G_malloc(win.cols * sizeof(unsigned char));
+    oblu = (unsigned char *)G_malloc(win.cols * sizeof(unsigned char));
+    set = (unsigned char *)G_malloc(win.cols * sizeof(unsigned char));
 
     /* open png file for writing */
-    {
-	if (do_stdout)
-	    fp = stdout;
-	else if (NULL == (fp = fopen(ofile, "w")))
-	    G_fatal_error("Not able to open file for [%s]", ofile);
-	else
-	    G_free(ofile);
-    }
+    if (do_stdout)
+    	fp = stdout;
+    else if (NULL == (fp = fopen(outfile, "w")))
+    	G_fatal_error(_("Unable to open output file <%s>"), outfile);
 
+
     png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
 				      &pnmtopng_jmpbuf_struct,
 				      pnmtopng_error_handler, NULL);
@@ -235,8 +261,8 @@
     png_info_init(info_ptr);
 #endif
     png_init_io(png_ptr, fp);
-    info_ptr->width = w.cols;
-    info_ptr->height = w.rows;
+    info_ptr->width = win.cols;
+    info_ptr->height = win.rows;
     info_ptr->bit_depth = depth;
 
     /* explicit filter-type (or none) required */
@@ -244,14 +270,18 @@
 	png_set_filter(png_ptr, 0, filter);
     }
 
-    /* zlib compression-level (or none) required */
-    /* ((compression >= -1) && (compression <= 9)) */
-    /* { */
-    png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
-    /* } */
+    png_set_compression_level(png_ptr, png_compr);
 
-    G_message(_("Converting %s..."), rast->answer);
+    if(do_alpha) {
+	png_color_16 background_color;
+	background_color.red = (png_uint_16)def_red;
+	background_color.green = (png_uint_16)def_grn;
+	background_color.blue = (png_uint_16)def_blu;
+	png_set_bKGD(png_ptr, info_ptr, &background_color);
+    }
 
+    G_verbose_message(_("Converting <%s>..."), rast->answer);
+
     {
 	struct Colors colors;
 
@@ -265,14 +295,18 @@
 	else if (rtype == DCELL_TYPE)
 	    voidc = (DCELL *) dcell_buf;
 	else
-	    exit(EXIT_FAILURE);
+	    G_fatal_error(_("Raster <%s> type mismatch"), rast->answer);
 
+	rsize = G_raster_size(rtype);
+
 	/*if(!gscale->answer){ *//* 24BIT COLOR IMAGE */
 
-	if (1) {
+	if (TRUE) {
+	    if (do_alpha)
+		info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+	    else
+		info_ptr->color_type = PNG_COLOR_TYPE_RGB;
 
-	    info_ptr->color_type = PNG_COLOR_TYPE_RGB;
-
 	    /* write the png-info struct */
 	    png_write_info(png_ptr, info_ptr);
 
@@ -280,38 +314,52 @@
 	    png_set_packing(png_ptr);
 
 	    /* max: 3 color channels, one alpha channel, 16-bit */
-	    line = (png_byte *) G_malloc(w.cols * 8 * sizeof(char));
+	    line = (png_byte *) G_malloc(win.cols * 8 * sizeof(char));
 
-	    for (row = 0; row < w.rows; row++) {
+	    for (row = 0; row < win.rows; row++) {
 
-		G_percent(row, w.rows, 5);
+		G_percent(row, win.rows, 5);
+
 		if (G_get_raster_row(cellfile, (void *)voidc, row, rtype) < 0)
-		    exit(EXIT_FAILURE);
+		    G_fatal_error(_("Unable to read raster map row %d"), row);
+
 		G_lookup_raster_colors((void *)voidc, ored, ogrn, oblu, set,
-				       w.cols, &colors, rtype);
+				       win.cols, &colors, rtype);
 
 		pp = line;
 
-		for (col = 0; col < w.cols; col++) {
+		for (col = 0; col < win.cols; col++) {
 
 		    if (set[col]) {
 			*pp++ = ored[col];
 			*pp++ = ogrn[col];
 			*pp++ = oblu[col];
+			if (do_alpha) {
+			    if (G_is_null_value(G_incr_void_ptr(voidc, col * rsize), rtype))
+				*pp++ = 0;
+			    else
+				*pp++ = 255;
+			}
 		    }
 		    else {
-			*pp++ = DEF_RED;
-			*pp++ = DEF_GRN;
-			*pp++ = DEF_BLU;
+			if (do_alpha) {
+			    *pp++ = ored[col];
+			    *pp++ = ogrn[col];
+			    *pp++ = oblu[col];
+			    *pp++ = 0;
+			}
+			else {
+			    *pp++ = (unsigned char)def_red;
+			    *pp++ = (unsigned char)def_grn;
+			    *pp++ = (unsigned char)def_blu;
+			}
 		    }
-
-
 		}
 
 		png_write_row(png_ptr, line);
 
 	    }
-
+	    G_percent(row, win.rows, 5); /* finish it off */
 	}
 	else {			/* GREYSCALE IMAGE */
 
@@ -322,12 +370,13 @@
 
 
 	    /* pm_message ("don't know yet how to write grey - yumm!!"); */
-	    G_warning("don't know how to write grey scale!\n");
+	    G_warning("don't know how to write grey scale!");
 	}
 
 	G_free_colors(&colors);
 
     }
+
     G_free(cell_buf);
     G_free(fcell_buf);
     G_free(dcell_buf);
@@ -337,23 +386,36 @@
     G_free(set);
     G_close_cell(cellfile);
 
-
-
     png_write_end(png_ptr, info_ptr);
     /* png_write_destroy (png_ptr); this is no longer supported with libpng, al 11/2000 */
     /* flush first because G_free (png_ptr) can segfault due to jmpbuf problems
      * in png_write_destroy */
+
     fflush(stdout);
     /* G_free (png_ptr); */
     /* G_free (info_ptr); */
     png_destroy_write_struct(&png_ptr, &info_ptr);	/* al 11/2000 */
 
-
     fclose(fp);
 
-    return (0);
+    if (wld_flag->answer) {
+	if(do_stdout)
+	    outfile = G_store("png_map.wld");
+	else
+	    sprintf(outfile, "%s.wld", basename);
+
+	write_wld(outfile, &win);
+    }
+
+    if(basename)
+	G_free(basename);
+    if(outfile)
+	G_free(outfile);
+
+    exit(EXIT_SUCCESS);
 }
 
+
 #ifdef __STDC__
 static void pnmtopng_error_handler(png_structp png_ptr, png_const_charp msg)
 #else
@@ -373,7 +435,7 @@
      * regardless of whether _BSD_SOURCE or anything else has (or has not)
      * been defined. */
 
-    G_warning("pnmtopng:  fatal libpng error: %s", msg);
+    G_warning("pnmtopng:  fatal libpng error: [%s]", msg);
 
     jmpbuf_ptr = png_get_error_ptr(png_ptr);
     if (jmpbuf_ptr == NULL) {	/* we are completely hosed now */
@@ -383,3 +445,29 @@
 
     longjmp(jmpbuf_ptr->jmpbuf, 1);
 }
+
+
+static int write_wld(const char *fname, const struct Cell_head *win)
+{
+    int width = DBL_DIG;
+    FILE *ofile;
+
+    G_verbose_message(_("Writing world file"));
+
+    if (fname == NULL)
+	G_fatal_error(_("Got null file name"));
+    if (win == NULL)
+	G_fatal_error(_("Got null region struct"));
+    if ((ofile = fopen(fname, "w")) == NULL)
+	G_fatal_error(_("Unable to open world file for writing"));
+
+    fprintf(ofile, "%36.*f \n", width, win->ew_res);
+    fprintf(ofile, "%36.*f \n", width, 0.0);
+    fprintf(ofile, "%36.*f \n", width, 0.0);
+    fprintf(ofile, "%36.*f \n", width, -1 * win->ns_res);
+    fprintf(ofile, "%36.*f \n", width, win->west + win->ew_res / 2.0);
+    fprintf(ofile, "%36.*f \n", width, win->north - win->ns_res / 2.0);
+
+    fclose(ofile);
+    return 0;
+}



More information about the grass-commit mailing list