main.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /****************************************************************************
  2. *
  3. * MODULE: r.compress
  4. *
  5. * AUTHOR(S): James Westervelt - CERL
  6. * Michael Shapiro - CERL
  7. *
  8. * PURPOSE: Compress and decompress raster map files.
  9. *
  10. * COPYRIGHT: (C) 2003 by the GRASS Development Team
  11. *
  12. * This program is free software under the GNU General Public
  13. * License (>=v2). Read the file COPYING that comes with GRASS
  14. * for details.
  15. *
  16. ***************************************************************************/
  17. /****************************************************************************
  18. * compress_cell converts straight grid_cell files into compressed grid_cell
  19. * files. Compressed files have the following format:
  20. *
  21. * - Array of addresses pointing to the internal start of each row
  22. * First byte of each row is the nuber of bytes per cell for that row
  23. * Remainder of the row is a series of byte groups that describe the data:
  24. * First byte: number of cells that contain the category given by second
  25. * Next byte(s): category number. The number of bytes is determined
  26. * by the number of bytes in a cell
  27. *
  28. * The normal G_open_cell(), and Rast_put_row() do the compression
  29. * This program must only check that the file is not a reclass file and
  30. * is not already compressed.
  31. *
  32. * The only trick is to preserve the support files
  33. *
  34. *****************************************************************************/
  35. #include <stdlib.h>
  36. #include <limits.h>
  37. #include <sys/types.h>
  38. #include <unistd.h>
  39. #include <grass/gis.h>
  40. #include <grass/raster.h>
  41. #include <grass/glocale.h>
  42. static off_t newsize, oldsize;
  43. static int process(char *, int);
  44. static int doit(char *, int, RASTER_MAP_TYPE);
  45. int main(int argc, char *argv[])
  46. {
  47. int stat;
  48. int n;
  49. char *name;
  50. struct GModule *module;
  51. struct Option *map;
  52. struct Flag *uncompress;
  53. G_gisinit(argv[0]);
  54. module = G_define_module();
  55. G_add_keyword(_("raster"));
  56. G_add_keyword(_("map management"));
  57. module->description = _("Compresses and decompresses raster maps.");
  58. map = G_define_option();
  59. map->key = "map";
  60. map->type = TYPE_STRING;
  61. map->required = YES;
  62. map->gisprompt = "old,cell,raster";
  63. map->multiple = YES;
  64. map->description = _("Name of existing raster map(s)");
  65. uncompress = G_define_flag();
  66. uncompress->key = 'u';
  67. uncompress->description = _("Uncompress the map");
  68. if (G_parser(argc, argv))
  69. exit(EXIT_FAILURE);
  70. stat = 0;
  71. for (n = 0; (name = map->answers[n]); n++)
  72. if (process(name, uncompress->answer))
  73. stat = 1;
  74. exit(stat);
  75. }
  76. static int process(char *name, int uncompress)
  77. {
  78. struct Colors colr;
  79. struct History hist;
  80. struct Categories cats;
  81. struct Quant quant;
  82. int colr_ok;
  83. int hist_ok;
  84. int cats_ok;
  85. int quant_ok;
  86. off_t diff;
  87. RASTER_MAP_TYPE map_type;
  88. char rname[GNAME_MAX], rmapset[GMAPSET_MAX];
  89. if (G_find_raster(name, G_mapset()) == NULL) {
  90. G_warning(_("[%s] not found"), name);
  91. return 1;
  92. }
  93. if (Rast_is_reclass(name, G_mapset(), rname, rmapset) > 0) {
  94. G_warning(uncompress
  95. ?
  96. _("[%s] is a reclass file of map <%s> in mapset <%s> - can't uncompress")
  97. :
  98. _("[%s] is a reclass file of map <%s> in mapset <%s> - can't compress"),
  99. name, rname, rmapset);
  100. return 1;
  101. }
  102. if (G_find_file2_misc("cell_misc", "gdal", name, G_mapset())) {
  103. G_warning(_("[%s] is a GDAL-linked map - can't (un)compress"), name);
  104. return 1;
  105. }
  106. map_type = Rast_map_type(name, G_mapset());
  107. G_suppress_warnings(1);
  108. colr_ok = Rast_read_colors(name, G_mapset(), &colr) > 0;
  109. hist_ok = Rast_read_history(name, G_mapset(), &hist) >= 0;
  110. cats_ok = Rast_read_cats(name, G_mapset(), &cats) >= 0;
  111. if (map_type != CELL_TYPE) {
  112. Rast_quant_init(&quant);
  113. quant_ok = Rast_read_quant(name, G_mapset(), &quant);
  114. G_suppress_warnings(0);
  115. }
  116. if (doit(name, uncompress, map_type))
  117. return 1;
  118. if (colr_ok) {
  119. Rast_write_colors(name, G_mapset(), &colr);
  120. Rast_free_colors(&colr);
  121. }
  122. if (hist_ok)
  123. Rast_write_history(name, &hist);
  124. if (cats_ok) {
  125. cats.num = Rast_get_max_c_cat(name, G_mapset());
  126. Rast_write_cats(name, &cats);
  127. Rast_free_cats(&cats);
  128. }
  129. if (map_type != CELL_TYPE && quant_ok)
  130. Rast_write_quant(name, G_mapset(), &quant);
  131. diff = newsize - oldsize;
  132. if (diff < 0)
  133. diff = -diff;
  134. if (sizeof(off_t) > sizeof(long) && diff > ULONG_MAX)
  135. diff = ULONG_MAX;
  136. if (newsize < oldsize)
  137. G_message(uncompress
  138. ? _("DONE: uncompressed file is %lu bytes smaller")
  139. : _("DONE: compressed file is %lu bytes smaller"),
  140. (unsigned long)diff);
  141. else if (newsize > oldsize)
  142. G_message(uncompress
  143. ? _("DONE: uncompressed file is %lu bytes bigger")
  144. : _("DONE: compressed file is %lu bytes bigger"),
  145. (unsigned long)diff);
  146. else
  147. G_message("same size");
  148. return 0;
  149. }
  150. static int doit(char *name, int uncompress, RASTER_MAP_TYPE map_type)
  151. {
  152. struct Cell_head cellhd;
  153. int new, old, nrows, row;
  154. void *rast;
  155. Rast_get_cellhd(name, G_mapset(), &cellhd);
  156. /* check if already compressed/decompressed */
  157. if (uncompress && cellhd.compressed == 0) {
  158. G_warning(_("[%s] already uncompressed"), name);
  159. return 1;
  160. }
  161. else if (!uncompress && cellhd.compressed > 0) {
  162. G_warning(_("[%s] already compressed"), name);
  163. return 1;
  164. }
  165. G_message(_("\n%sCOMPRESS [%s]"), uncompress ? "UN" : "", name);
  166. Rast_set_window(&cellhd);
  167. old = Rast_open_old(name, G_mapset());
  168. if (uncompress) {
  169. if (map_type == CELL_TYPE) {
  170. Rast_set_cell_format(cellhd.format);
  171. new = Rast_open_c_new_uncompressed(name);
  172. }
  173. else {
  174. Rast_set_fp_type(map_type);
  175. new = Rast_open_fp_new_uncompressed(name);
  176. }
  177. }
  178. else
  179. new = Rast_open_new(name, map_type);
  180. nrows = Rast_window_rows();
  181. rast = Rast_allocate_buf(map_type);
  182. oldsize = lseek(old, (off_t) 0, SEEK_END);
  183. /* the null file is written automatically */
  184. for (row = 0; row < nrows; row++) {
  185. G_percent(row, nrows, 2);
  186. Rast_get_row_nomask(old, rast, row, map_type);
  187. Rast_put_row(new, rast, map_type);
  188. }
  189. G_free(rast);
  190. Rast_close(old);
  191. if (row < nrows) {
  192. Rast_unopen(new);
  193. return 1;
  194. }
  195. Rast_close(new);
  196. newsize = 0;
  197. old = Rast_open_old(name, G_mapset());
  198. newsize = lseek(old, (off_t) 0, SEEK_END);
  199. Rast_close(old);
  200. return 0;
  201. }