source: grass/branches/develbranch_6/lib/gis/closecell.c

Last change on this file was 59649, checked in by mmetz, 10 years ago

sync devbr6 to relbr6

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id
  • Property svn:mime-type set to text/x-csrc
File size: 11.4 KB
Line 
1/***********************************************************************
2 *
3 * G_close_cell(fd)
4 * Closes and does housekeeping on an opened cell file
5 *
6 * G_unopen_cell(fd)
7 * Closes and does housekeeping on an opened cell file
8 * without creating the cell file
9 *
10 * parms:
11 * int fd open cell file
12 *
13 * returns:
14 * -1 on fail
15 * 0 on success
16 *
17 * note:
18 * On closing of a cell file that was open for writing, dummy cats
19 * and history files are created. Histogram and range info are written.
20 *
21 **********************************************************************/
22
23#ifdef __MINGW32__
24# include <windows.h>
25#endif
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <unistd.h>
31#include <fcntl.h>
32#include <signal.h>
33#include <grass/gis.h>
34#include <grass/glocale.h>
35#include "G.h"
36
37#define FORMAT_FILE "f_format"
38#define QUANT_FILE "f_quant"
39#define NULL_FILE "null"
40
41static int close_old(int);
42static int close_new(int, int);
43static char CELL_DIR[100];
44
45
46/*!
47 * \brief close a raster map
48 *
49 * The raster map
50 * opened on file descriptor <b>fd</b> is closed. Memory allocated for raster
51 * processing is freed. If open for writing, skeletal support files for the new
52 * raster map are created as well.
53 * <b>Note.</b> If a module wants to explicitly write support files (e.g., a
54 * specific color table) for a raster map it creates, it must do so after the
55 * raster map is closed. Otherwise the close will overwrite the support files.
56 * See Raster_Map_Layer_Support_Routines for routines which write
57 * raster support files.
58 *
59 * If the map is a new floating point, move the
60 * <tt>.tmp</tt> file into the <tt>fcell</tt> element, create an empty file in the
61 * <tt>cell</tt> directory; write the floating-point range file; write a default
62 * quantization file quantization file is set here to round fp numbers (this is
63 * a default for now). create an empty category file, with max cat = max value
64 * (for backwards compatibility). Move the <tt>.tmp</tt> NULL-value bitmap file to
65 * the <tt>cell_misc</tt> directory.
66 *
67 * \param fd
68 * \return int
69 */
70
71int G_close_cell(int fd)
72{
73 struct fileinfo *fcb = &G__.fileinfo[fd];
74
75 if (fd < 0 || fd >= G__.fileinfo_count || fcb->open_mode <= 0)
76 return -1;
77 if (fcb->open_mode == OPEN_OLD)
78 return close_old(fd);
79
80 return close_new(fd, 1);
81}
82
83
84/*!
85 * \brief unopen a raster map
86 *
87 * The raster map
88 * opened on file descriptor <b>fd</b> is closed. Memory allocated for raster
89 * processing is freed. If open for writing, the raster map is not created and
90 * the temporary file created when the raster map was opened is removed (see
91 * Creating_and_Opening_New_Raster_Files).
92 * This routine is useful when errors are detected and it is desired to not
93 * create the new raster map. While it is true that the raster map will not be
94 * created if the module exits without closing the file, the temporary file will
95 * not be removed at module exit. GRASS database management will eventually
96 * remove the temporary file, but the file can be quite large and will take up
97 * disk space until GRASS does remove it. Use this routine as a courtesy to the
98 * user.
99 *
100 * \param fd
101 * \return int
102 */
103
104int G_unopen_cell(int fd)
105{
106 struct fileinfo *fcb = &G__.fileinfo[fd];
107
108 if (fd < 0 || fd >= G__.fileinfo_count || fcb->open_mode <= 0)
109 return -1;
110 if (fcb->open_mode == OPEN_OLD)
111 return close_old(fd);
112 else
113 return close_new(fd, 0);
114}
115
116static int close_old(int fd)
117{
118 struct fileinfo *fcb = &G__.fileinfo[fd];
119 int i;
120
121 /* if G__.auto_mask was only allocated for reading map rows to create
122 non-existant null rows, and not for actuall mask, free G__.mask_row
123 if(G__.auto_mask <=0)
124 G_free (G__.mask_buf);
125 This is obsolete since now the mask_bus is always allocated
126 */
127
128 if (fcb->gdal)
129 G_close_gdal_link(fcb->gdal);
130
131 for (i = 0; i < NULL_ROWS_INMEM; i++)
132 G_free(fcb->NULL_ROWS[i]);
133 G_free(fcb->null_work_buf);
134
135 if (fcb->cellhd.compressed)
136 G_free(fcb->row_ptr);
137 G_free(fcb->col_map);
138 G_free(fcb->mapset);
139 G_free(fcb->data);
140 G_free(fcb->name);
141 if (fcb->reclass_flag)
142 G_free_reclass(&fcb->reclass);
143 fcb->open_mode = -1;
144
145 if (fcb->map_type != CELL_TYPE) {
146 G_quant_free(&fcb->quant);
147 xdr_destroy(&fcb->xdrstream);
148 }
149 close(fd);
150
151 return 1;
152}
153
154static int close_new(int fd, int ok)
155{
156 struct fileinfo *fcb = &G__.fileinfo[fd];
157 int stat;
158 struct Categories cats;
159 struct History hist;
160 char path[GPATH_MAX];
161 CELL cell_min, cell_max;
162 int row, i, open_mode;
163
164 if (ok) {
165 switch (fcb->open_mode) {
166 case OPEN_NEW_COMPRESSED:
167 G_debug(1, "close %s compressed", fcb->name);
168 break;
169 case OPEN_NEW_UNCOMPRESSED:
170 G_debug(1, "close %s uncompressed", fcb->name);
171 break;
172 case OPEN_NEW_RANDOM:
173 G_debug(1, "close %s random", fcb->name);
174 break;
175 }
176
177 if (fcb->open_mode != OPEN_NEW_RANDOM &&
178 fcb->cur_row < fcb->cellhd.rows) {
179 G_zero_raster_buf(fcb->data, fcb->map_type);
180 for (row = fcb->cur_row; row < fcb->cellhd.rows; row++)
181 G_put_raster_row(fd, fcb->data, fcb->map_type);
182 G_free(fcb->data);
183 fcb->data = NULL;
184 }
185
186 /* create path : full null file name */
187 G__make_mapset_element_misc("cell_misc", fcb->name);
188 G__file_name_misc(path, "cell_misc", NULL_FILE, fcb->name,
189 G_mapset());
190 remove(path);
191
192 if (fcb->null_cur_row > 0) {
193 /* if temporary NULL file exists, write it into cell_misc/name/null */
194 int null_fd;
195
196 null_fd = G__open_null_write(fd);
197 if (null_fd <= 0)
198 return -1;
199 if (null_fd < 1)
200 return -1;
201
202 /* first finish writing null file */
203 /* write out the rows stored in memory */
204 for (row = fcb->min_null_row; row < fcb->null_cur_row; row++)
205 G__write_null_bits(null_fd,
206 fcb->NULL_ROWS[row - fcb->min_null_row],
207 row, fcb->cellhd.cols, fd);
208
209 /* write missing rows */
210 if (fcb->open_mode != OPEN_NEW_RANDOM
211 && fcb->null_cur_row < fcb->cellhd.rows) {
212 G__init_null_bits(fcb->null_work_buf, fcb->cellhd.cols);
213 for (row = fcb->null_cur_row; row < fcb->cellhd.rows; row++)
214 G__write_null_bits(null_fd, fcb->null_work_buf, row,
215 fcb->cellhd.cols, fd);
216 }
217 close(null_fd);
218
219 if (rename(fcb->null_temp_name, path)) {
220 G_warning(_("closecell: can't move [%s] to null-cells file [%s]"),
221 fcb->null_temp_name, path);
222 stat = -1;
223 }
224 else {
225 remove(fcb->null_temp_name);
226 }
227 }
228 else {
229 remove(fcb->null_temp_name);
230 remove(path);
231 } /* null_cur_row > 0 */
232
233 if (fcb->open_mode == OPEN_NEW_COMPRESSED) { /* auto compression */
234 fcb->row_ptr[fcb->cellhd.rows] = lseek(fd, 0L, SEEK_CUR);
235 G__write_row_ptrs(fd);
236 }
237
238 if (fcb->map_type != CELL_TYPE) { /* floating point map */
239 int cell_fd;
240
241 if (G__write_fp_format(fd) != 0) {
242 G_warning(_("Error writing floating point format file for map %s"),
243 fcb->name);
244 stat = -1;
245 }
246
247 /* now write 0-length cell file */
248 G__make_mapset_element("cell");
249 cell_fd =
250 creat(G__file_name(path, "cell", fcb->name, fcb->mapset),
251 0666);
252 close(cell_fd);
253 strcpy(CELL_DIR, "fcell");
254 }
255 else {
256 /* remove fcell/name file */
257 G__file_name(path, "fcell", fcb->name, fcb->mapset);
258 remove(path);
259 /* remove cell_misc/name/f_format */
260 G__file_name_misc(path, "cell_misc", FORMAT_FILE, fcb->name,
261 fcb->mapset);
262 remove(path);
263 strcpy(CELL_DIR, "cell");
264 }
265 } /* ok */
266 /* NOW CLOSE THE FILE DESCRIPTOR */
267
268 close(fd);
269 /* remember open_mode */
270 open_mode = fcb->open_mode;
271 fcb->open_mode = -1;
272
273 if (fcb->data != NULL)
274 G_free(fcb->data);
275
276 if (fcb->null_temp_name != NULL) {
277 G_free(fcb->null_temp_name);
278 fcb->null_temp_name = NULL;
279 }
280
281 /* if the cell file was written to a temporary file
282 * move this temporary file into the cell file
283 * if the move fails, tell the user, but go ahead and create
284 * the support files
285 */
286 stat = 1;
287 if (ok && (fcb->temp_name != NULL)) {
288 G__file_name(path, CELL_DIR, fcb->name, fcb->mapset);
289 remove(path);
290 if (rename(fcb->temp_name, path)) {
291 G_warning(_("closecell: can't move [%s] to cell file [%s]"),
292 fcb->temp_name, path);
293 stat = -1;
294 }
295 else {
296 remove(fcb->temp_name);
297 }
298 }
299
300 if (fcb->temp_name != NULL) {
301 G_free(fcb->temp_name);
302 }
303
304 if (ok) {
305 /* remove color table */
306 G_remove_colors(fcb->name, "");
307
308 /* create a history file */
309 G_short_history(fcb->name, "raster", &hist);
310 G_write_history(fcb->name, &hist);
311
312 /* write the range */
313 if (fcb->map_type == CELL_TYPE) {
314 G_write_range(fcb->name, &fcb->range);
315 G__remove_fp_range(fcb->name);
316 }
317 /*NOTE: int range for floating point maps is not written out */
318 else { /* if(fcb->map_type != CELL_TYPE) */
319
320 G_write_fp_range(fcb->name, &fcb->fp_range);
321 G_construct_default_range(&fcb->range);
322 /* this range will be used to add default rule to quant structure */
323 }
324
325 if (fcb->map_type != CELL_TYPE)
326 fcb->cellhd.format = -1;
327 else /* CELL map */
328 fcb->cellhd.format = fcb->nbytes - 1;
329
330 /* write header file */
331 G_put_cellhd(fcb->name, &fcb->cellhd);
332
333 /* if map is floating point write the quant rules, otherwise remove f_quant */
334 if (fcb->map_type != CELL_TYPE) {
335 /* DEFAULT RANGE QUANT
336 G_get_fp_range_min_max(&fcb->fp_range, &dcell_min, &dcell_max);
337 if(!G_is_d_null_value(&dcell_min) && !G_is_d_null_value(&dcell_max))
338 {
339 G_get_range_min_max(&fcb->range, &cell_min, &cell_max);
340 G_quant_add_rule(&fcb->quant, dcell_min, dcell_max,
341 cell_min, cell_max);
342 }
343 */
344 G_quant_round(&fcb->quant);
345 if (G_write_quant(fcb->name, fcb->mapset, &fcb->quant) < 0)
346 G_warning(_("Unable to write quant file!"));
347 }
348 else {
349 /* remove cell_misc/name/f_quant */
350 G__file_name_misc(path, "cell_misc", QUANT_FILE, fcb->name,
351 fcb->mapset);
352 remove(path);
353 }
354
355 /* create empty cats file */
356 G_get_range_min_max(&fcb->range, &cell_min, &cell_max);
357 if (G_is_c_null_value(&cell_max))
358 cell_max = 0;
359 G_init_cats(cell_max, (char *)NULL, &cats);
360 G_write_cats(fcb->name, &cats);
361 G_free_cats(&cats);
362
363 /* write the histogram */
364 /* only works for integer maps */
365 if ((fcb->map_type == CELL_TYPE)
366 && (fcb->want_histogram)) {
367 G_write_histogram_cs(fcb->name, &fcb->statf);
368 G_free_cell_stats(&fcb->statf);
369 }
370 else {
371 G_remove_histogram(fcb->name);
372 }
373 } /* OK */
374
375 G_free(fcb->name);
376 G_free(fcb->mapset);
377
378 for (i = 0; i < NULL_ROWS_INMEM; i++)
379 G_free(fcb->NULL_ROWS[i]);
380 G_free(fcb->null_work_buf);
381
382 if (fcb->map_type != CELL_TYPE)
383 G_quant_free(&fcb->quant);
384
385 return stat;
386}
387
388/* returns 0 on success, 1 on failure */
389int G__write_fp_format(int fd)
390{
391 struct fileinfo *fcb = &G__.fileinfo[fd];
392 struct Key_Value *format_kv;
393 char path[GPATH_MAX];
394 int stat;
395
396 if (fcb->map_type == CELL_TYPE) {
397 G_warning(_("Unable to write f_format file for CELL maps"));
398 return 0;
399 }
400 format_kv = G_create_key_value();
401 if (fcb->map_type == FCELL_TYPE)
402 G_set_key_value("type", "float", format_kv);
403 else
404 G_set_key_value("type", "double", format_kv);
405
406 G_set_key_value("byte_order", "xdr", format_kv);
407
408 if (fcb->open_mode == OPEN_NEW_COMPRESSED)
409 G_set_key_value("lzw_compression_bits", "-1", format_kv);
410
411 G__make_mapset_element_misc("cell_misc", fcb->name);
412 G__file_name_misc(path, "cell_misc", FORMAT_FILE, fcb->name, fcb->mapset);
413 G_write_key_value_file(path, format_kv, &stat);
414
415 G_free_key_value(format_kv);
416
417 return stat;
418}
Note: See TracBrowser for help on using the repository browser.