1 /***************************************************************************
2 qgis.d.rast.c
3 ---------------------
4 begin : February 2010
5 copyright : (C) 2010 by Radim Blazek
6 email : radim dot blazek at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15 /****************************************************************************
16 *
17 * MODULE: qgis.d.rast
18 * AUTHOR(S): Radim Blazek <radim.blazek gmail.com>
19 * using d.rast from GRASS
20 * PURPOSE: display raster maps in active graphics display
21 * COPYRIGHT: (C) 2010 by Radim Blazek
22 *
23 * This program is free software under the GNU General Public
24 * License (>=v2).
25 *
26 *****************************************************************************/
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <math.h>
31 #include <assert.h>
32 #include <limits.h>
33 #ifdef WIN32
34 #include <fcntl.h>
35 #include <io.h>
36 #endif
37 #include <grass/version.h>
38 #include <grass/gis.h>
39 #include <grass/raster.h>
40 #include <grass/display.h>
41
42 #if defined(_MSC_VER) && _MSC_VER < 1900
43 #include <float.h>
44 #define INFINITY (DBL_MAX+DBL_MAX)
45 #define NAN (INFINITY-INFINITY)
46 #endif
47
48 int display( char *name, char *mapset, RASTER_MAP_TYPE data_type, char *format );
49
main(int argc,char ** argv)50 int main( int argc, char **argv )
51 {
52 char *mapset = 0;
53 char *name = 0;
54 struct GModule *module;
55 struct Option *map;
56 struct Option *win;
57 struct Option *format;
58 struct Cell_head window;
59 RASTER_MAP_TYPE raster_type;
60
61 /* Initialize the GIS calls */
62 G_gisinit( argv[0] );
63
64 module = G_define_module();
65 module->description = ( "Output raster map layers in a format suitable for display in QGIS" );
66
67 map = G_define_standard_option( G_OPT_R_MAP );
68 map->description = ( "Raster map to be displayed" );
69
70 format = G_define_option();
71 format->key = "format";
72 format->type = TYPE_STRING;
73 format->description = "format";
74 format->options = "color,value";
75
76 win = G_define_option();
77 win->key = "window";
78 win->type = TYPE_DOUBLE;
79 win->multiple = YES;
80 win->description = "xmin,ymin,xmax,ymax,ncols,nrows";
81
82 if ( G_parser( argc, argv ) )
83 exit( EXIT_FAILURE );
84
85 name = map->answer;
86 mapset = "";
87
88 /* It can happen that GRASS data set is 'corrupted' and zone differs in WIND and
89 * cellhd, and Rast_open_old fails, so it is better to read window from map */
90 /* G_get_window( &window ); */
91 Rast_get_cellhd( name, mapset, &window );
92 window.west = atof( win->answers[0] );
93 window.south = atof( win->answers[1] );
94 window.east = atof( win->answers[2] );
95 window.north = atof( win->answers[3] );
96 window.cols = atoi( win->answers[4] );
97 window.rows = atoi( win->answers[5] );
98 G_adjust_Cell_head( &window, 1, 1 );
99 G_set_window( &window );
100
101 Rast_suppress_masking(); // must be after G_set_window()
102
103 raster_type = Rast_map_type( name, "" );
104
105 display( name, mapset, raster_type, format->answer );
106
107 exit( EXIT_SUCCESS );
108 }
109
110 static int cell_draw( char *, char *, struct Colors *, RASTER_MAP_TYPE, char *format );
111
display(char * name,char * mapset,RASTER_MAP_TYPE data_type,char * format)112 int display( char *name,
113 char *mapset,
114 RASTER_MAP_TYPE data_type,
115 char *format )
116 {
117 struct Colors colors;
118
119 if ( Rast_read_colors( name, mapset, &colors ) == -1 )
120 G_fatal_error( ( "Color file for <%s> not available" ), name );
121
122 //G_set_null_value_color(r, g, b, &colors);
123
124 /* Go draw the raster map */
125 cell_draw( name, mapset, &colors, data_type, format );
126
127 /* release the colors now */
128 Rast_free_colors( &colors );
129
130 return 0;
131 }
132
cell_draw(char * name,char * mapset,struct Colors * colors,RASTER_MAP_TYPE data_type,char * format)133 static int cell_draw( char *name,
134 char *mapset,
135 struct Colors *colors,
136 RASTER_MAP_TYPE data_type,
137 char *format )
138 {
139 int cellfile;
140 void *xarray = 0;
141 int row;
142 int ncols, nrows;
143 static unsigned char *red, *grn, *blu, *set;
144 int i;
145 void *ptr = 0;
146 int big_endian;
147 long one = 1;
148 FILE *fo = 0;
149 size_t raster_size;
150 #ifdef NAN
151 double dnul = NAN;
152 float fnul = ( float )( NAN );
153 #else
154 double dnul = strtod( "NAN", 0 );
155 float fnul = strtof( "NAN", 0 );
156 // another possibility would be nan()/nanf() - C99
157 // and 0./0. if all fails
158 #endif
159
160 assert( dnul != dnul );
161 assert( fnul != fnul );
162
163 big_endian = !( *( ( char * )( &one ) ) );
164
165 ncols = Rast_window_cols();
166 nrows = Rast_window_rows();
167
168 /* Make sure map is available */
169 if ( ( cellfile = Rast_open_old( name, mapset ) ) == -1 )
170 G_fatal_error( ( "Unable to open raster map <%s>" ), name );
171
172 /* Allocate space for cell buffer */
173 xarray = Rast_allocate_buf( data_type );
174 red = G_malloc( ncols );
175 grn = G_malloc( ncols );
176 blu = G_malloc( ncols );
177 set = G_malloc( ncols );
178
179 /* some buggy C libraries require BOTH setmode() and fdopen(bin) */
180 // Do not use Q_OS_WIN, we are in C file, no Qt headers
181 #ifdef WIN32
182 if ( _setmode( _fileno( stdout ), _O_BINARY ) == -1 )
183 G_fatal_error( "Cannot set stdout mode" );
184 #endif
185 // Unfortunately this is not sufficient on Windows to switch stdout to binary mode
186 fo = fdopen( fileno( stdout ), "wb" );
187
188 raster_size = Rast_cell_size( data_type );
189 //fprintf( fo, "%d %d", data_type, raster_size );
190 //exit(0);
191 /* loop for array rows */
192 for ( row = 0; row < nrows; row++ )
193 {
194 Rast_get_row( cellfile, xarray, row, data_type );
195 ptr = xarray;
196
197 Rast_lookup_colors( xarray, red, grn, blu, set, ncols, colors,
198 data_type );
199
200 for ( i = 0; i < ncols; i++ )
201 {
202 unsigned char alpha = 255;
203 //G_debug ( 0, "row = %d col = %d", row, i );
204 if ( Rast_is_null_value( ptr, data_type ) )
205 {
206 alpha = 0;
207 }
208
209 if ( strcmp( format, "color" ) == 0 )
210 {
211 // We need data suitable for QImage 32-bpp
212 // the data are stored in QImage as QRgb which is unsigned int.
213 // Because it depends on byte order of the platform we have to
214 // consider byte order (well, middle endian ignored)
215 if ( big_endian )
216 {
217 // I have never tested this
218 fprintf( fo, "%c%c%c%c", alpha, red[i], grn[i], blu[i] );
219 }
220 else
221 {
222 fprintf( fo, "%c%c%c%c", blu[i], grn[i], red[i], alpha );
223 }
224 }
225 else
226 {
227 if ( data_type == CELL_TYPE )
228 {
229 //G_debug ( 0, "valx = %d", *((CELL *) ptr));
230 }
231 if ( Rast_is_null_value( ptr, data_type ) )
232 {
233 // see comments in QgsGrassRasterProvider::noDataValue()
234 if ( data_type == CELL_TYPE )
235 {
236 //int nul = -2000000000;
237 int nul = INT_MIN;
238 fwrite( &nul, 4, 1, fo );
239 }
240 else if ( data_type == DCELL_TYPE )
241 {
242 //double nul = -1e+300;
243 fwrite( &dnul, 8, 1, fo );
244 }
245 else if ( data_type == FCELL_TYPE )
246 {
247 //double nul = -1e+30;
248 fwrite( &fnul, 4, 1, fo );
249 }
250 }
251 else
252 {
253 fwrite( ptr, raster_size, 1, fo );
254 }
255 }
256 ptr = G_incr_void_ptr( ptr, raster_size );
257 }
258 }
259
260 Rast_close( cellfile );
261 fclose( fo );
262
263 return ( 0 );
264 }
265