1 /*
2 / gaiagraphics_grids.c
3 /
4 / GRIDS auxiliary helpers
5 /
6 / version 1.0, 2010 July 20
7 /
8 / Author: Sandro Furieri a.furieri@lqt.it
9 /
10 / Copyright (C) 2010 Alessandro Furieri
11 /
12 / This program is free software: you can redistribute it and/or modify
13 / it under the terms of the GNU Lesser General Public License as published by
14 / the Free Software Foundation, either version 3 of the License, or
15 / (at your option) any later version.
16 /
17 / This program is distributed in the hope that it will be useful,
18 / but WITHOUT ANY WARRANTY; without even the implied warranty of
19 / MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 / GNU Lesser General Public License for more details.
21 /
22 / You should have received a copy of the GNU Lesser General Public License
23 / along with this program. If not, see <http://www.gnu.org/licenses/>.
24 /
25 */
26
27 #include <stdio.h>
28 #include <math.h>
29 #include <float.h>
30 #include <limits.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <sys/types.h>
34
35 #include "gaiagraphics.h"
36 #include "gaiagraphics_internals.h"
37
38 #define GRID_HGT_3 1
39 #define GRID_HGT_1 2
40 #define GRID_BIN_HDR 3
41 #define GRID_FLT_HDR 4
42 #define GRID_DEM_HDR 5
43 #define GRID_ASCII 6
44
45 struct grid_codec_data
46 {
47 /* a struct used by GRID codec */
48 int grid_type;
49 int is_writer;
50 int little_endian;
51 void *grid_buffer;
52 long *row_offsets;
53 };
54
55 GGRAPH_PRIVATE int
gg_image_strip_prepare_from_hgt(FILE * in,int lon,int lat,gGraphStripImagePtr * image_handle)56 gg_image_strip_prepare_from_hgt (FILE * in, int lon, int lat,
57 gGraphStripImagePtr * image_handle)
58 {
59 /* preparing to decode an HGT-GRID [by strips] */
60 gGraphStripImagePtr img = NULL;
61 struct grid_codec_data *grid_codec = NULL;
62 long file_length;
63 int type;
64 int width;
65 int height;
66 double pixel_size;
67 double half_pixel;
68 int buf_size;
69 void *grid_buffer = NULL;
70 int ret = GGRAPH_HGT_CODEC_ERROR;
71 *image_handle = NULL;
72
73 /* retrieving the HGT dimensions */
74 if (fseek (in, 0, SEEK_END) != 0)
75 return GGRAPH_HGT_CODEC_ERROR;
76 file_length = ftell (in);
77 if (file_length == (1201 * 1201 * sizeof (short)))
78 {
79 type = GRID_HGT_3;
80 width = 1201;
81 height = 1201;
82 pixel_size = 1.0 / 1200.0;
83 }
84 else if (file_length == (3601 * 3601 * sizeof (short)))
85 {
86 type = GRID_HGT_1;
87 width = 3601;
88 height = 3601;
89 pixel_size = 1.0 / 3600.0;
90 }
91 else
92 return GGRAPH_HGT_CODEC_ERROR;
93
94 img =
95 gg_strip_image_create (in, GGRAPH_IMAGE_HGT, GG_PIXEL_GRID, width,
96 height, 16, 1, GGRAPH_SAMPLE_INT, "WGS 84",
97 "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs");
98 if (!img)
99 {
100 ret = GGRAPH_INSUFFICIENT_MEMORY;
101 goto error;
102 }
103 /* setting up georeferencing infos */
104 half_pixel = pixel_size / 2.0;
105 img->is_georeferenced = 1;
106 img->srid = 4326;
107 img->upper_left_x = (double) lon - half_pixel;
108 img->upper_left_y = (double) lat + 1.0 + half_pixel;
109 img->pixel_x_size = pixel_size;
110 img->pixel_y_size = pixel_size;
111 img->no_data_value = SHRT_MIN;
112
113 /* setting up the GRID codec struct */
114 grid_codec = malloc (sizeof (struct grid_codec_data));
115 if (!grid_codec)
116 goto error;
117 grid_codec->grid_type = type;
118 grid_codec->is_writer = 0;
119 grid_codec->grid_buffer = NULL;
120 grid_codec->row_offsets = NULL;
121 img->codec_data = grid_codec;
122
123 /* allocating the GRID read buffer */
124 buf_size = sizeof (short) * width;
125 grid_buffer = malloc (buf_size);
126 if (!grid_buffer)
127 goto error;
128 grid_codec->grid_buffer = grid_buffer;
129
130 *image_handle = img;
131 return GGRAPH_OK;
132
133 error:
134 if (img)
135 gGraphDestroyImage (img);
136 return ret;
137 }
138
139 GGRAPH_PRIVATE void
gg_grid_codec_destroy(void * p)140 gg_grid_codec_destroy (void *p)
141 {
142 /* destroyng the GRID codec data */
143 struct grid_codec_data *codec = (struct grid_codec_data *) p;
144 if (!codec)
145 return;
146 if (codec->grid_buffer)
147 free (codec->grid_buffer);
148 if (codec->row_offsets)
149 free (codec->row_offsets);
150 free (codec);
151 }
152
153 static int
read_from_hgt(FILE * in,gGraphStripImagePtr img,void * scanline)154 read_from_hgt (FILE * in, gGraphStripImagePtr img, void *scanline)
155 {
156 /* decoding an HGT-GRID [by strip] */
157 int width = img->width;
158 int height = img->height;
159 size_t scan_size = width * 2;
160 int row;
161 int incr = 0;
162 int x;
163 int endian_arch = gg_endian_arch ();
164 off_t pos = img->next_row * scan_size;
165 unsigned char *p_in;
166 short *p_out;
167 short cell_value;
168
169 /* positioning on the start scanline */
170 if (fseek (in, pos, SEEK_SET) != 0)
171 return GGRAPH_HGT_CODEC_ERROR;
172 for (row = 0; row < img->rows_per_block; row++)
173 {
174 /* reading the required number of scanlines */
175 if ((row + img->next_row) >= height)
176 break;
177 if (fread (scanline, 1, scan_size, in) != scan_size)
178 return GGRAPH_HGT_CODEC_ERROR;
179 p_in = scanline;
180 p_out = (short *) (img->pixels);
181 p_out += (row * width);
182 for (x = 0; x < width; x++)
183 {
184 cell_value = gg_import_int16 (p_in, 0, endian_arch);
185 *p_out++ = cell_value;
186 p_in += sizeof (short);
187 }
188 incr++;
189 }
190 img->next_row += incr;
191 img->current_available_rows = incr;
192 return GGRAPH_OK;
193 }
194
195 GGRAPH_PRIVATE int
gg_image_strip_read_from_hgt(gGraphStripImagePtr img,int * progress)196 gg_image_strip_read_from_hgt (gGraphStripImagePtr img, int *progress)
197 {
198 /* decoding an HGT-GRID [by strip] */
199 struct grid_codec_data *grid_codec =
200 (struct grid_codec_data *) (img->codec_data);
201 FILE *in = img->file_handle;
202
203 if (grid_codec->grid_type == GRID_HGT_1
204 || grid_codec->grid_type == GRID_HGT_3)
205 {
206 int ret = read_from_hgt (in, img, grid_codec->grid_buffer);
207 if (ret == GGRAPH_OK && progress != NULL)
208 *progress =
209 (int) (((double) (img->next_row + 1) * 100.0) /
210 (double) (img->height));
211 return ret;
212 }
213 return GGRAPH_ERROR;
214 }
215
216 GGRAPH_DECLARE int
gGraphCheckHgtPath(const char * path,int * lat,int * lon)217 gGraphCheckHgtPath (const char *path, int *lat, int *lon)
218 {
219 /* checking for HGT format - retrieving coord from path */
220 char file_name[1024];
221 char coord_lat[8];
222 char coord_lon[8];
223 int lat_sign = 1;
224 int lon_sign = 1;
225 int i;
226 int start = 0;
227
228 for (i = strlen (path) - 1; i >= 0; i--)
229 {
230 /* attempting to extract the file name */
231 if (path[i] == '/' || path[i] == '\\')
232 {
233 start = i + 1;
234 break;
235 }
236 }
237 strcpy (file_name, path + start);
238
239 if (strlen (file_name) != 11)
240 return GGRAPH_ERROR;
241 if (file_name[0] == 'N')
242 ;
243 else if (file_name[0] == 'S')
244 lat_sign = -1;
245 else
246 return GGRAPH_ERROR;
247 if (file_name[1] >= '0' && file_name[1] <= '9')
248 coord_lat[0] = file_name[1];
249 else
250 return GGRAPH_ERROR;
251 if (file_name[2] >= '0' && file_name[2] <= '9')
252 {
253 coord_lat[1] = file_name[2];
254 coord_lat[2] = '\0';
255 }
256 else
257 return GGRAPH_ERROR;
258 if (file_name[3] == 'E')
259 ;
260 else if (file_name[3] == 'W')
261 lon_sign = -1;
262 else
263 return GGRAPH_ERROR;
264 if (file_name[4] >= '0' && file_name[4] <= '9')
265 coord_lon[0] = file_name[4];
266 else
267 return GGRAPH_ERROR;
268 if (file_name[5] >= '0' && file_name[5] <= '9')
269 coord_lon[1] = file_name[5];
270 if (file_name[6] >= '0' && file_name[6] <= '9')
271 {
272 coord_lon[2] = file_name[6];
273 coord_lon[3] = '\0';
274 }
275 else
276 return GGRAPH_ERROR;
277 if (file_name[7] != '.')
278 return GGRAPH_ERROR;
279 if (file_name[8] != 'h')
280 return GGRAPH_ERROR;
281 if (file_name[9] != 'g')
282 return GGRAPH_ERROR;
283 if (file_name[10] != 't')
284 return GGRAPH_ERROR;
285 /* ok, it's an HGT file */
286 *lat = atoi (coord_lat) * lat_sign;
287 *lon = atoi (coord_lon) * lon_sign;
288 return GGRAPH_OK;
289 }
290
291 GGRAPH_DECLARE int
gGraphImageInfosFromHgtFile(const char * path,int lat,int lon,const void ** infos_handle)292 gGraphImageInfosFromHgtFile (const char *path, int lat, int lon,
293 const void **infos_handle)
294 {
295 /* retrieving Image infos from HGT file */
296 FILE *in = NULL;
297 gGraphImageInfosPtr infos = NULL;
298 long file_length;
299 int width;
300 int height;
301 double pixel_size;
302 double half_pixel;
303
304 *infos_handle = NULL;
305
306 /* attempting to open the image file */
307 in = fopen (path, "rb");
308 if (in == NULL)
309 return GGRAPH_FILE_OPEN_ERROR;
310
311 /* retrieving the HGT dimensions */
312 if (fseek (in, 0, SEEK_END) != 0)
313 return GGRAPH_HGT_CODEC_ERROR;
314 file_length = ftell (in);
315 if (file_length == (1201 * 1201 * sizeof (short)))
316 {
317 width = 1201;
318 height = 1201;
319 pixel_size = 1.0 / 1200.0;
320 }
321 else if (file_length == (3601 * 3601 * sizeof (short)))
322 {
323 width = 3601;
324 height = 3601;
325 pixel_size = 1.0 / 3600.0;
326 }
327 else
328 {
329 fclose (in);
330 return GGRAPH_HGT_CODEC_ERROR;
331 }
332 fclose (in);
333
334 infos =
335 gg_image_infos_create (GG_PIXEL_GRID, width, height, 16, 1,
336 GGRAPH_SAMPLE_INT, "WGS 84",
337 "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs");
338 if (!infos)
339 return GGRAPH_INSUFFICIENT_MEMORY;
340
341 /* setting up georeferencing infos */
342 half_pixel = pixel_size / 2.0;
343 infos->is_georeferenced = 1;
344 infos->srid = 4326;
345 infos->upper_left_x = (double) lon - half_pixel;
346 infos->upper_left_y = (double) lat + 1.0 + half_pixel;
347 infos->pixel_x_size = pixel_size;
348 infos->pixel_y_size = pixel_size;
349 infos->no_data_value = SHRT_MIN;
350
351 *infos_handle = infos;
352 return GGRAPH_OK;
353 }
354
355 GGRAPH_DECLARE int
gGraphCheckBinPath(const char * path,char * hdr_path,int dont_test)356 gGraphCheckBinPath (const char *path, char *hdr_path, int dont_test)
357 {
358 /* checking for BIN+HDR format */
359 char naked_path[1024];
360 int i;
361 int start = 0;
362 FILE *in;
363
364 *hdr_path = '\0';
365 for (i = strlen (path) - 1; i >= 0; i--)
366 {
367 /* attempting to extract the file name */
368 if (path[i] == '.')
369 {
370 start = i;
371 break;
372 }
373 }
374 strcpy (naked_path, path);
375 if (strcasecmp (path + start, ".bin") != 0)
376 return GGRAPH_ERROR;
377 naked_path[start] = '\0';
378 strcat (naked_path, ".hdr");
379 if (dont_test)
380 {
381 strcpy (hdr_path, naked_path);
382 return GGRAPH_OK;
383 }
384
385 in = fopen (naked_path, "rb");
386 if (in != NULL)
387 {
388 fclose (in);
389 strcpy (hdr_path, naked_path);
390 return GGRAPH_OK;
391 }
392 naked_path[start] = '\0';
393 strcat (naked_path, ".HDR");
394 in = fopen (naked_path, "rb");
395 if (in != NULL)
396 {
397 fclose (in);
398 strcpy (hdr_path, naked_path);
399 return GGRAPH_OK;
400 }
401
402 return GGRAPH_ERROR;
403 }
404
405 GGRAPH_DECLARE int
gGraphCheckFltPath(const char * path,char * hdr_path,int dont_test)406 gGraphCheckFltPath (const char *path, char *hdr_path, int dont_test)
407 {
408 /* checking for FLT+HDR format */
409 char naked_path[1024];
410 int i;
411 int start = 0;
412 FILE *in;
413
414 *hdr_path = '\0';
415 for (i = strlen (path) - 1; i >= 0; i--)
416 {
417 /* attempting to extract the file name */
418 if (path[i] == '.')
419 {
420 start = i;
421 break;
422 }
423 }
424 strcpy (naked_path, path);
425 if (strcasecmp (path + start, ".flt") != 0)
426 return GGRAPH_ERROR;
427 naked_path[start] = '\0';
428 strcat (naked_path, ".hdr");
429 if (dont_test)
430 {
431 strcpy (hdr_path, naked_path);
432 return GGRAPH_OK;
433 }
434
435 in = fopen (naked_path, "rb");
436 if (in != NULL)
437 {
438 fclose (in);
439 strcpy (hdr_path, naked_path);
440 return GGRAPH_OK;
441 }
442 naked_path[start] = '\0';
443 strcat (naked_path, ".HDR");
444 in = fopen (naked_path, "rb");
445 if (in != NULL)
446 {
447 fclose (in);
448 strcpy (hdr_path, naked_path);
449 return GGRAPH_OK;
450 }
451
452 return GGRAPH_ERROR;
453 }
454
455 GGRAPH_DECLARE int
gGraphCheckDemPath(const char * path,char * hdr_path,int dont_test)456 gGraphCheckDemPath (const char *path, char *hdr_path, int dont_test)
457 {
458 /* checking for DEM+HDR format */
459 char naked_path[1024];
460 int i;
461 int start = 0;
462 FILE *in;
463
464 *hdr_path = '\0';
465 for (i = strlen (path) - 1; i >= 0; i--)
466 {
467 /* attempting to extract the file name */
468 if (path[i] == '.')
469 {
470 start = i;
471 break;
472 }
473 }
474 strcpy (naked_path, path);
475 if (strcasecmp (path + start, ".dem") != 0)
476 return GGRAPH_ERROR;
477 naked_path[start] = '\0';
478 strcat (naked_path, ".hdr");
479 if (dont_test)
480 {
481 strcpy (hdr_path, naked_path);
482 return GGRAPH_OK;
483 }
484
485 in = fopen (naked_path, "rb");
486 if (in != NULL)
487 {
488 fclose (in);
489 strcpy (hdr_path, naked_path);
490 return GGRAPH_OK;
491 }
492 naked_path[start] = '\0';
493 strcat (naked_path, ".HDR");
494 in = fopen (naked_path, "rb");
495 if (in != NULL)
496 {
497 fclose (in);
498 strcpy (hdr_path, naked_path);
499 return GGRAPH_OK;
500 }
501
502 return GGRAPH_ERROR;
503 }
504
505 GGRAPH_DECLARE int
gGraphCheckAscPath(const char * path)506 gGraphCheckAscPath (const char *path)
507 {
508 /* checking for ASC format */
509 int i;
510 int start = 0;
511
512 for (i = strlen (path) - 1; i >= 0; i--)
513 {
514 /* attempting to extract the file name */
515 if (path[i] == '.')
516 {
517 start = i;
518 break;
519 }
520 }
521 if (strcasecmp (path + start, ".asc") != 0)
522 return GGRAPH_ERROR;
523 return GGRAPH_OK;
524 }
525
526 static char *
string_tokenizer(char * string,char * delimiters,char ** ptr)527 string_tokenizer (char *string, char *delimiters, char **ptr)
528 {
529 /* breaking a string into distinct tokens */
530 char *start = NULL;
531 char *p;
532 if (*ptr != NULL)
533 p = *ptr;
534 else
535 p = string;
536
537 if (p == NULL)
538 return NULL;
539
540 while (1)
541 {
542 int sep = 0;
543 char *pd = delimiters;
544
545 if (*p == '\0')
546 {
547 /* last token end */
548 *ptr = p;
549 break;
550 }
551
552 while (*pd != '\0')
553 {
554 if (*p == *pd)
555 {
556 /* found a separator char */
557 sep = 1;
558 break;
559 }
560 pd++;
561 }
562 if (sep)
563 {
564 if (start)
565 {
566 /* token end */
567 *p = '\0';
568 *ptr = p + 1;
569 break;
570 }
571 }
572 else
573 {
574 if (!start)
575 {
576 /* token start */
577 start = p;
578 }
579 }
580 p++;
581 }
582
583 return start;
584 }
585
586 static int
cvtToInt(const char * str,int * value)587 cvtToInt (const char *str, int *value)
588 {
589 /* attempting to convert from string to int */
590 const char *p = str;
591 int error = 0;
592 int digits = 0;
593 int sign = 0;
594 while (*p != '\0')
595 {
596 if (*p >= '0' && *p <= '9')
597 digits++;
598 else if (*p == '-' || *p == '+')
599 {
600 if (digits == 0)
601 sign++;
602 else
603 error = 1;
604 }
605 else
606 error = 1;
607 p++;
608 }
609 if (digits > 0 && sign < 2 && error == 0)
610 {
611 *value = atoi (str);
612 return 1;
613 }
614 return 0;
615 }
616
617 static int
cvtToDouble(const char * str,double * value)618 cvtToDouble (const char *str, double *value)
619 {
620 /* attempting to convert from string to double */
621 const char *p = str;
622 int error = 0;
623 int digits = 0;
624 int comma = 0;
625 int sign = 0;
626 while (*p != '\0')
627 {
628 if (*p >= '0' && *p <= '9')
629 digits++;
630 else if (*p == '.')
631 comma++;
632 else if (*p == '-' || *p == '+')
633 {
634 if (digits == 0)
635 sign++;
636 else
637 error = 1;
638 }
639 else
640 error = 1;
641 p++;
642 }
643 if (digits > 0 && sign < 2 && comma < 2 && error == 0)
644 {
645 *value = atof (str);
646 return 1;
647 }
648 return 0;
649 }
650
651 static int
parse_binflt_hdr(const char * hdr_path,int * width,int * height,int * bits_per_sample,int * sample,int * endian,double * no_data,double * min,double * max,double * ulx,double * uly,double * pixel_x_size,double * pixel_y_size,int * expected_length)652 parse_binflt_hdr (const char *hdr_path, int *width, int *height,
653 int *bits_per_sample, int *sample, int *endian,
654 double *no_data, double *min, double *max, double *ulx,
655 double *uly, double *pixel_x_size, double *pixel_y_size,
656 int *expected_length)
657 {
658 /* parsing an HDR file [BIN or FLT format] */
659 FILE *hdr = NULL;
660 int s_width = INT_MIN;
661 int s_height = INT_MIN;
662 int sample_format = GGRAPH_SAMPLE_UNKNOWN;
663 int sample_bits = INT_MIN;
664 double no_data_value = DBL_MAX;
665 double x_pixel_size = DBL_MAX;
666 double y_pixel_size = DBL_MAX;
667 double lower_left_x = DBL_MAX;
668 double lower_left_y = DBL_MAX;
669 double min_value = DBL_MAX;
670 double max_value = DBL_MIN;
671 int little_endian = 0;
672 int c;
673 int i_tk;
674 char *saveptr;
675 char hdr_buf[1024];
676 char *token;
677 char keyword[1024];
678 char value[1024];
679 char *p_hdr;
680 int cvt_int;
681 double cvt_dbl;
682 int x_centered;
683 int y_centered;
684 double half_pixel;
685
686 /* opening the HDR header file */
687 hdr = fopen (hdr_path, "rb");
688 if (hdr == NULL)
689 return 0;
690
691 p_hdr = hdr_buf;
692 while ((c = getc (hdr)) != EOF)
693 {
694 /* parsing the Header file */
695 if (c == '\r')
696 continue;
697 if (c == '\n')
698 {
699 *p_hdr = '\0';
700 if (*hdr_buf == '\0')
701 {
702 /* skipping empty lines */
703 p_hdr = hdr_buf;
704 continue;
705 }
706 /* breaking the string into separate tokens */
707 i_tk = 0;
708 saveptr = NULL;
709 while (1)
710 {
711 token = string_tokenizer (hdr_buf, " \t", &saveptr);
712 if (token == NULL)
713 break;
714 if (*token == '\0')
715 continue;
716 if (i_tk == 0)
717 {
718 strcpy (keyword, token);
719 i_tk++;
720 continue;
721 }
722
723 strcpy (value, token);
724 i_tk++;
725 }
726
727 if (i_tk != 2)
728 goto stop;
729 if (strcasecmp (keyword, "BYTEORDER") == 0)
730 {
731 if (strcasecmp (value, "LSBFIRST") == 0)
732 little_endian = 1;
733 else
734 little_endian = 0;
735 }
736 else if (strcasecmp (keyword, "NROWS") == 0)
737 {
738 if (!cvtToInt (value, &cvt_int))
739 goto stop;
740 s_height = cvt_int;
741 }
742 else if (strcasecmp (keyword, "NCOLS") == 0)
743 {
744 if (!cvtToInt (value, &cvt_int))
745 goto stop;
746 s_width = cvt_int;
747 }
748 else if (strcasecmp (keyword, "NUMBERTYPE") == 0)
749 {
750 if (strcasecmp (value, "2_BYTE_INTEGER") == 0)
751 {
752 sample_format = GGRAPH_SAMPLE_INT;
753 sample_bits = 16;
754 }
755 else if (strcasecmp (value, "4_BYTE_INTEGER") == 0)
756 {
757 sample_format = GGRAPH_SAMPLE_INT;
758 sample_bits = 32;
759 }
760 else if (strcasecmp (value, "4_BYTE_FLOAT") == 0)
761 {
762 sample_format = GGRAPH_SAMPLE_FLOAT;
763 sample_bits = 32;
764 }
765 else if (strcasecmp (value, "8_BYTE_FLOAT") == 0)
766 {
767 sample_format = GGRAPH_SAMPLE_FLOAT;
768 sample_bits = 64;
769 }
770 else
771 goto stop;
772 }
773 else if (strcasecmp (keyword, "NODATA_VALUE") == 0)
774 {
775 if (!cvtToDouble (value, &cvt_dbl))
776 goto stop;
777 no_data_value = cvt_dbl;
778 }
779 else if (strcasecmp (keyword, "XLLCENTER") == 0)
780 {
781 if (!cvtToDouble (value, &cvt_dbl))
782 goto stop;
783 lower_left_x = cvt_dbl;
784 x_centered = 1;
785 }
786 else if (strcasecmp (keyword, "XLLCORNER") == 0)
787 {
788 if (!cvtToDouble (value, &cvt_dbl))
789 goto stop;
790 lower_left_x = cvt_dbl;
791 x_centered = 0;
792 }
793 else if (strcasecmp (keyword, "YLLCENTER") == 0)
794 {
795 if (!cvtToDouble (value, &cvt_dbl))
796 goto stop;
797 lower_left_y = cvt_dbl;
798 y_centered = 1;
799 }
800 else if (strcasecmp (keyword, "YLLCORNER") == 0)
801 {
802 if (!cvtToDouble (value, &cvt_dbl))
803 goto stop;
804 lower_left_y = cvt_dbl;
805 y_centered = 0;
806 }
807 else if (strcasecmp (keyword, "CELLSIZE") == 0)
808 {
809 if (!cvtToDouble (value, &cvt_dbl))
810 goto stop;
811 x_pixel_size = cvt_dbl;
812 y_pixel_size = cvt_dbl;
813 }
814 else if (strcasecmp (keyword, "ZUNITS") == 0)
815 {
816 /* ignoring */
817 }
818 else if (strcasecmp (keyword, "MIN_VALUE") == 0)
819 {
820 if (!cvtToDouble (value, &cvt_dbl))
821 goto stop;
822 min_value = cvt_dbl;
823 }
824 else if (strcasecmp (keyword, "MAX_VALUE") == 0)
825 {
826 if (!cvtToDouble (value, &cvt_dbl))
827 goto stop;
828 max_value = cvt_dbl;
829 }
830 else
831 {
832 /* unrecognized tag */
833 goto stop;
834 }
835 p_hdr = hdr_buf;
836 continue;
837 }
838 *p_hdr++ = c;
839 if (p_hdr - hdr_buf > 1024)
840 goto stop;
841 }
842 fclose (hdr);
843 hdr = NULL;
844
845 if (s_width <= 0 || s_height <= 0 || sample_bits <= 0)
846 goto stop;
847 if (sample_format == GGRAPH_SAMPLE_UNKNOWN)
848 goto stop;
849 if (no_data_value == INT_MAX)
850 goto stop;
851 if (x_pixel_size == DBL_MAX || y_pixel_size == DBL_MAX)
852 goto stop;
853 if (lower_left_x == DBL_MAX || lower_left_y == DBL_MAX)
854 goto stop;
855 if (min_value == DBL_MAX || max_value == DBL_MIN)
856 goto stop;
857
858 *width = s_width;
859 *height = s_height;
860 *sample = sample_format;
861 *bits_per_sample = sample_bits;
862 *endian = little_endian;
863 *no_data = no_data_value;
864 *ulx = lower_left_x;
865 half_pixel = x_pixel_size / 2.0;
866 if (x_centered)
867 *ulx -= half_pixel;
868 *uly = lower_left_y + ((double) s_height * y_pixel_size);
869 half_pixel = y_pixel_size / 2.0;
870 if (y_centered)
871 *uly += half_pixel;
872 *pixel_x_size = x_pixel_size;
873 *pixel_y_size = y_pixel_size;
874 *min = min_value;
875 *max = max_value;
876 if (sample_bits == 16)
877 *expected_length = s_width * s_height * 2;
878 else if (sample_bits == 32)
879 *expected_length = s_width * s_height * 4;
880 else if (sample_bits == 64)
881 *expected_length = s_width * s_height * 8;
882 else
883 *expected_length = -1;
884 return 1;
885
886 stop:
887 if (hdr)
888 fclose (hdr);
889 return 0;
890 }
891
892 GGRAPH_DECLARE int
gGraphImageInfosFromBinFile(const char * path,const char * hdr_path,const void ** infos_handle)893 gGraphImageInfosFromBinFile (const char *path, const char *hdr_path,
894 const void **infos_handle)
895 {
896 /* retrieving Image infos from BIN+HDR file */
897 FILE *in = NULL;
898 gGraphImageInfosPtr infos = NULL;
899 long file_length;
900 int expected_length;
901 int width;
902 int height;
903 double ulx;
904 double uly;
905 double pixel_x_size;
906 double pixel_y_size;
907 int sample;
908 int bits_per_sample;
909 int endian;
910 double no_data;
911 double min;
912 double max;
913
914 *infos_handle = NULL;
915
916 if (!parse_binflt_hdr
917 (hdr_path, &width, &height, &bits_per_sample, &sample, &endian,
918 &no_data, &min, &max, &ulx, &uly, &pixel_x_size, &pixel_y_size,
919 &expected_length))
920 return GGRAPH_BIN_CODEC_ERROR;
921
922 /* attempting to open the image file */
923 in = fopen (path, "rb");
924 if (in == NULL)
925 return GGRAPH_FILE_OPEN_ERROR;
926
927 /* retrieving the BIN dimensions */
928 if (fseek (in, 0, SEEK_END) != 0)
929 return GGRAPH_BIN_CODEC_ERROR;
930 file_length = ftell (in);
931 if (file_length != expected_length)
932 {
933 fclose (in);
934 return GGRAPH_BIN_CODEC_ERROR;
935 }
936 fclose (in);
937
938 infos =
939 gg_image_infos_create (GG_PIXEL_GRID, width, height, bits_per_sample, 1,
940 sample, NULL, NULL);
941 if (!infos)
942 return GGRAPH_INSUFFICIENT_MEMORY;
943
944 /* setting up georeferencing infos */
945 infos->is_georeferenced = 1;
946 infos->upper_left_x = ulx;
947 infos->upper_left_y = uly;
948 infos->pixel_x_size = pixel_x_size;
949 infos->pixel_y_size = pixel_y_size;
950 infos->no_data_value = no_data;
951 infos->min_value = min;
952 infos->max_value = max;
953
954 *infos_handle = infos;
955 return GGRAPH_OK;
956 }
957
958 GGRAPH_DECLARE int
gGraphImageInfosFromFltFile(const char * path,const char * hdr_path,const void ** infos_handle)959 gGraphImageInfosFromFltFile (const char *path, const char *hdr_path,
960 const void **infos_handle)
961 {
962 /* retrieving Image infos from FLT+HDR file */
963 FILE *in = NULL;
964 gGraphImageInfosPtr infos = NULL;
965 long file_length;
966 int expected_length;
967 int width;
968 int height;
969 double ulx;
970 double uly;
971 double pixel_x_size;
972 double pixel_y_size;
973 int sample;
974 int bits_per_sample;
975 int endian;
976 double no_data;
977 double min;
978 double max;
979
980 *infos_handle = NULL;
981
982 if (!parse_binflt_hdr
983 (hdr_path, &width, &height, &bits_per_sample, &sample, &endian,
984 &no_data, &min, &max, &ulx, &uly, &pixel_x_size, &pixel_y_size,
985 &expected_length))
986 return GGRAPH_FLT_CODEC_ERROR;
987
988 /* attempting to open the image file */
989 in = fopen (path, "rb");
990 if (in == NULL)
991 return GGRAPH_FILE_OPEN_ERROR;
992
993 /* retrieving the FLT dimensions */
994 if (fseek (in, 0, SEEK_END) != 0)
995 return GGRAPH_FLT_CODEC_ERROR;
996 file_length = ftell (in);
997 if (file_length != expected_length)
998 {
999 fclose (in);
1000 return GGRAPH_FLT_CODEC_ERROR;
1001 }
1002 fclose (in);
1003
1004 infos =
1005 gg_image_infos_create (GG_PIXEL_GRID, width, height, bits_per_sample, 1,
1006 sample, NULL, NULL);
1007 if (!infos)
1008 return GGRAPH_INSUFFICIENT_MEMORY;
1009
1010 /* setting up georeferencing infos */
1011 infos->is_georeferenced = 1;
1012 infos->upper_left_x = ulx;
1013 infos->upper_left_y = uly;
1014 infos->pixel_x_size = pixel_x_size;
1015 infos->pixel_y_size = pixel_y_size;
1016 infos->no_data_value = no_data;
1017 infos->min_value = min;
1018 infos->max_value = max;
1019
1020 *infos_handle = infos;
1021 return GGRAPH_OK;
1022 }
1023
1024 static int
parse_dem_hdr(const char * hdr_path,int * width,int * height,int * bits_per_sample,int * sample,int * endian,double * no_data,double * ulx,double * uly,double * pixel_x_size,double * pixel_y_size,int * expected_length)1025 parse_dem_hdr (const char *hdr_path, int *width, int *height,
1026 int *bits_per_sample, int *sample, int *endian, double *no_data,
1027 double *ulx, double *uly, double *pixel_x_size,
1028 double *pixel_y_size, int *expected_length)
1029 {
1030 /* parsing an HDR file [DEM format] */
1031 FILE *hdr = NULL;
1032 int s_width = INT_MIN;
1033 int s_height = INT_MIN;
1034 int sample_format = GGRAPH_SAMPLE_UNKNOWN;
1035 int sample_bits = INT_MIN;
1036 double no_data_value = DBL_MAX;
1037 double x_pixel_size = DBL_MAX;
1038 double y_pixel_size = DBL_MAX;
1039 double upper_left_x = DBL_MAX;
1040 double upper_left_y = DBL_MAX;
1041 int band_row_bytes = INT_MIN;
1042 int total_row_bytes = INT_MIN;
1043 int little_endian = 0;
1044 int c;
1045 int i_tk;
1046 char *saveptr;
1047 char hdr_buf[1024];
1048 char *token;
1049 char keyword[1024];
1050 char value[1024];
1051 char *p_hdr;
1052 int cvt_int;
1053 double cvt_dbl;
1054
1055 /* opening the HDR header file */
1056 hdr = fopen (hdr_path, "rb");
1057 if (hdr == NULL)
1058 return 0;
1059
1060 p_hdr = hdr_buf;
1061 while ((c = getc (hdr)) != EOF)
1062 {
1063 /* parsing the Header file */
1064 if (c == '\r' || c == '\n')
1065 {
1066 *p_hdr = '\0';
1067 if (*hdr_buf == '\0')
1068 {
1069 /* skipping empty lines */
1070 p_hdr = hdr_buf;
1071 continue;
1072 }
1073 /* breaking the string into separate tokens */
1074 i_tk = 0;
1075 saveptr = NULL;
1076 while (1)
1077 {
1078 token = string_tokenizer (hdr_buf, " \t", &saveptr);
1079 if (token == NULL)
1080 break;
1081 if (*token == '\0')
1082 continue;
1083 if (i_tk == 0)
1084 {
1085 strcpy (keyword, token);
1086 i_tk++;
1087 continue;
1088 }
1089
1090 strcpy (value, token);
1091 i_tk++;
1092 }
1093
1094 if (i_tk != 2)
1095 goto stop;
1096 if (strcasecmp (keyword, "BYTEORDER") == 0)
1097 {
1098 if (strcasecmp (value, "M") == 0)
1099 little_endian = 0;
1100 else
1101 little_endian = 1;
1102 }
1103 else if (strcasecmp (keyword, "LAYOUT") == 0)
1104 {
1105 /* Bands organization: only Band Interleave by Line is supported */
1106 if (strcasecmp (value, "BIL") != 0)
1107 goto stop;
1108 }
1109 else if (strcasecmp (keyword, "NROWS") == 0)
1110 {
1111 if (!cvtToInt (value, &cvt_int))
1112 goto stop;
1113 s_height = cvt_int;
1114 }
1115 else if (strcasecmp (keyword, "NCOLS") == 0)
1116 {
1117 if (!cvtToInt (value, &cvt_int))
1118 goto stop;
1119 s_width = cvt_int;
1120 }
1121 else if (strcasecmp (keyword, "NBANDS") == 0)
1122 {
1123 /* expected: 1 band */
1124 if (!cvtToInt (value, &cvt_int))
1125 goto stop;
1126 if (cvt_int != 1)
1127 goto stop;
1128 }
1129 else if (strcasecmp (keyword, "NBITS") == 0)
1130 {
1131 /* expected: 16 or 32 bit ints */
1132 if (!cvtToInt (value, &cvt_int))
1133 goto stop;
1134 if (cvt_int == 16)
1135 {
1136 sample_format = GGRAPH_SAMPLE_INT;
1137 sample_bits = 16;
1138 }
1139 else if (cvt_int == 32)
1140 {
1141 sample_format = GGRAPH_SAMPLE_INT;
1142 sample_bits = 32;
1143 }
1144 else
1145 goto stop;
1146 }
1147 else if (strcasecmp (keyword, "BANDROWBYTES") == 0)
1148 {
1149 if (!cvtToInt (value, &cvt_int))
1150 goto stop;
1151 band_row_bytes = cvt_int;
1152 }
1153 else if (strcasecmp (keyword, "TOTALROWBYTES") == 0)
1154 {
1155 if (!cvtToInt (value, &cvt_int))
1156 goto stop;
1157 total_row_bytes = cvt_int;
1158 }
1159 else if (strcasecmp (keyword, "BANDGAPBYTES") == 0)
1160 {
1161 /* expected: 0 bytes between bands */
1162 if (!cvtToInt (value, &cvt_int))
1163 goto stop;
1164 if (cvt_int != 0)
1165 goto stop;
1166 }
1167 else if (strcasecmp (keyword, "NODATA") == 0)
1168 {
1169 if (!cvtToInt (value, &cvt_int))
1170 goto stop;
1171 no_data_value = cvt_int;
1172 }
1173 else if (strcasecmp (keyword, "ULXMAP") == 0)
1174 {
1175 if (!cvtToDouble (value, &cvt_dbl))
1176 goto stop;
1177 upper_left_x = cvt_dbl;
1178 }
1179 else if (strcasecmp (keyword, "ULYMAP") == 0)
1180 {
1181 if (!cvtToDouble (value, &cvt_dbl))
1182 goto stop;
1183 upper_left_y = cvt_dbl;
1184 }
1185 else if (strcasecmp (keyword, "XDIM") == 0)
1186 {
1187 if (!cvtToDouble (value, &cvt_dbl))
1188 goto stop;
1189 x_pixel_size = cvt_dbl;
1190 }
1191 else if (strcasecmp (keyword, "YDIM") == 0)
1192 {
1193 if (!cvtToDouble (value, &cvt_dbl))
1194 goto stop;
1195 y_pixel_size = cvt_dbl;
1196 }
1197 else
1198 {
1199 /* unrecognized tag */
1200 goto stop;
1201 }
1202 p_hdr = hdr_buf;
1203 continue;
1204 }
1205 *p_hdr++ = c;
1206 if (p_hdr - hdr_buf > 1024)
1207 goto stop;
1208 }
1209 fclose (hdr);
1210 hdr = NULL;
1211
1212 if (s_width <= 0 || s_height <= 0 || sample_bits <= 0)
1213 goto stop;
1214 if (sample_format == GGRAPH_SAMPLE_UNKNOWN)
1215 goto stop;
1216 if (no_data_value == INT_MAX)
1217 goto stop;
1218 if (x_pixel_size == DBL_MAX || y_pixel_size == DBL_MAX)
1219 goto stop;
1220 if (upper_left_x == DBL_MAX || upper_left_y == DBL_MAX)
1221 goto stop;
1222 if (sample_bits == 16)
1223 {
1224 if (2 * s_width != band_row_bytes)
1225 goto stop;
1226 if (2 * s_width != total_row_bytes)
1227 goto stop;
1228 }
1229 if (sample_bits == 32)
1230 {
1231 if (4 * s_width != band_row_bytes)
1232 goto stop;
1233 if (4 * s_width != total_row_bytes)
1234 goto stop;
1235 }
1236 *width = s_width;
1237 *height = s_height;
1238 *sample = sample_format;
1239 *bits_per_sample = sample_bits;
1240 *endian = little_endian;
1241 *no_data = no_data_value;
1242 *ulx = upper_left_x;
1243 *uly = upper_left_y;
1244 *pixel_x_size = x_pixel_size;
1245 *pixel_y_size = y_pixel_size;
1246 if (sample_bits == 16)
1247 *expected_length = s_width * s_height * 2;
1248 else if (sample_bits == 32)
1249 *expected_length = s_width * s_height * 4;
1250 else
1251 *expected_length = -1;
1252 return 1;
1253
1254 stop:
1255 if (hdr)
1256 fclose (hdr);
1257 return 0;
1258 }
1259
1260 GGRAPH_DECLARE int
gGraphImageInfosFromDemFile(const char * path,const char * hdr_path,const void ** infos_handle)1261 gGraphImageInfosFromDemFile (const char *path, const char *hdr_path,
1262 const void **infos_handle)
1263 {
1264 /* retrieving Image infos from DEM+HDR file */
1265 FILE *in = NULL;
1266 gGraphImageInfosPtr infos = NULL;
1267 long file_length;
1268 int expected_length;
1269 int width;
1270 int height;
1271 double ulx;
1272 double uly;
1273 double pixel_x_size;
1274 double pixel_y_size;
1275 int sample;
1276 int bits_per_sample;
1277 int endian;
1278 double no_data;
1279
1280 *infos_handle = NULL;
1281
1282 if (!parse_dem_hdr
1283 (hdr_path, &width, &height, &bits_per_sample, &sample, &endian,
1284 &no_data, &ulx, &uly, &pixel_x_size, &pixel_y_size, &expected_length))
1285 return GGRAPH_FLT_CODEC_ERROR;
1286
1287 /* attempting to open the image file */
1288 in = fopen (path, "rb");
1289 if (in == NULL)
1290 return GGRAPH_FILE_OPEN_ERROR;
1291
1292 /* retrieving the FLT dimensions */
1293 if (fseek (in, 0, SEEK_END) != 0)
1294 return GGRAPH_FLT_CODEC_ERROR;
1295 file_length = ftell (in);
1296 if (file_length != expected_length)
1297 {
1298 fclose (in);
1299 return GGRAPH_FLT_CODEC_ERROR;
1300 }
1301 fclose (in);
1302
1303 infos =
1304 gg_image_infos_create (GG_PIXEL_GRID, width, height, bits_per_sample, 1,
1305 sample, NULL, NULL);
1306 if (!infos)
1307 return GGRAPH_INSUFFICIENT_MEMORY;
1308
1309 /* setting up georeferencing infos */
1310 infos->is_georeferenced = 1;
1311 infos->upper_left_x = ulx;
1312 infos->upper_left_y = uly;
1313 infos->pixel_x_size = pixel_x_size;
1314 infos->pixel_y_size = pixel_y_size;
1315 infos->no_data_value = no_data;
1316
1317 *infos_handle = infos;
1318 return GGRAPH_OK;
1319 }
1320
1321 static int
parse_asc_hdr(const char * path,FILE * file,int * width,int * height,double * ulx,double * uly,double * pixel_x_size,double * pixel_y_size,double * no_data)1322 parse_asc_hdr (const char *path, FILE * file, int *width, int *height,
1323 double *ulx, double *uly, double *pixel_x_size,
1324 double *pixel_y_size, double *no_data)
1325 {
1326 /* parsing an ASC file [ASCII GRID format] */
1327 FILE *hdr = NULL;
1328 int s_width = INT_MIN;
1329 int s_height = INT_MIN;
1330 double x_pixel_size = DBL_MAX;
1331 double y_pixel_size = DBL_MAX;
1332 double lower_left_x = DBL_MAX;
1333 double lower_left_y = DBL_MAX;
1334 double no_data_value = DBL_MAX;
1335 int c;
1336 int i_tk;
1337 char *saveptr;
1338 char hdr_buf[1024];
1339 char *token;
1340 char keyword[1024];
1341 char value[1024];
1342 char *p_hdr;
1343 int cvt_int;
1344 double cvt_dbl;
1345 int x_centered;
1346 int y_centered;
1347 double half_pixel;
1348 int row;
1349
1350 if (path != NULL)
1351 {
1352 /* opening the ASC header file */
1353 hdr = fopen (path, "rb");
1354 }
1355 else
1356 hdr = file;
1357 if (hdr == NULL)
1358 return 0;
1359 row = 0;
1360 p_hdr = hdr_buf;
1361 while ((c = getc (hdr)) != EOF)
1362 {
1363 /* parsing the Header file */
1364 if (c == '\r')
1365 continue;
1366 if (c == '\n')
1367 {
1368 row++;
1369 *p_hdr = '\0';
1370 if (*hdr_buf == '\0')
1371 {
1372 /* skipping empty lines */
1373 p_hdr = hdr_buf;
1374 continue;
1375 }
1376 /* breaking the string into separate tokens */
1377 i_tk = 0;
1378 saveptr = NULL;
1379 while (1)
1380 {
1381 token = string_tokenizer (hdr_buf, " \t", &saveptr);
1382 if (token == NULL)
1383 break;
1384 if (*token == '\0')
1385 continue;
1386 if (i_tk == 0)
1387 {
1388 strcpy (keyword, token);
1389 i_tk++;
1390 continue;
1391 }
1392
1393 strcpy (value, token);
1394 i_tk++;
1395 }
1396
1397 if (i_tk != 2)
1398 goto stop;
1399 if (strcasecmp (keyword, "NROWS") == 0)
1400 {
1401 if (!cvtToInt (value, &cvt_int))
1402 goto stop;
1403 s_height = cvt_int;
1404 }
1405 else if (strcasecmp (keyword, "NCOLS") == 0)
1406 {
1407 if (!cvtToInt (value, &cvt_int))
1408 goto stop;
1409 s_width = cvt_int;
1410 }
1411 else if (strcasecmp (keyword, "NODATA_VALUE") == 0)
1412 {
1413 if (!cvtToDouble (value, &cvt_dbl))
1414 goto stop;
1415 no_data_value = cvt_dbl;
1416 }
1417 else if (strcasecmp (keyword, "XLLCENTER") == 0)
1418 {
1419 if (!cvtToDouble (value, &cvt_dbl))
1420 goto stop;
1421 lower_left_x = cvt_dbl;
1422 x_centered = 1;
1423 }
1424 else if (strcasecmp (keyword, "XLLCORNER") == 0)
1425 {
1426 if (!cvtToDouble (value, &cvt_dbl))
1427 goto stop;
1428 lower_left_x = cvt_dbl;
1429 x_centered = 0;
1430 }
1431 else if (strcasecmp (keyword, "YLLCENTER") == 0)
1432 {
1433 if (!cvtToDouble (value, &cvt_dbl))
1434 goto stop;
1435 lower_left_y = cvt_dbl;
1436 y_centered = 1;
1437 }
1438 else if (strcasecmp (keyword, "YLLCORNER") == 0)
1439 {
1440 if (!cvtToDouble (value, &cvt_dbl))
1441 goto stop;
1442 lower_left_y = cvt_dbl;
1443 y_centered = 0;
1444 }
1445 else if (strcasecmp (keyword, "CELLSIZE") == 0)
1446 {
1447 if (!cvtToDouble (value, &cvt_dbl))
1448 goto stop;
1449 x_pixel_size = cvt_dbl;
1450 y_pixel_size = x_pixel_size;
1451 }
1452 else
1453 {
1454 /* unrecognized tag */
1455 goto stop;
1456 }
1457 p_hdr = hdr_buf;
1458 if (row == 6)
1459 break;
1460 continue;
1461 }
1462 *p_hdr++ = c;
1463 if (p_hdr - hdr_buf > 1024)
1464 goto stop;
1465 }
1466 if (path != NULL)
1467 fclose (hdr);
1468 hdr = NULL;
1469
1470 if (s_width <= 0 || s_height <= 0)
1471 goto stop;
1472 if (no_data_value == INT_MAX)
1473 goto stop;
1474 if (x_pixel_size == DBL_MAX || y_pixel_size == DBL_MAX)
1475 goto stop;
1476 if (lower_left_x == DBL_MAX || lower_left_y == DBL_MAX)
1477 goto stop;
1478 *width = s_width;
1479 *height = s_height;
1480 *no_data = no_data_value;
1481 *ulx = lower_left_x;
1482 half_pixel = x_pixel_size / 2.0;
1483 if (x_centered)
1484 *ulx -= half_pixel;
1485 *uly = lower_left_y + ((double) s_height * y_pixel_size);
1486 half_pixel = y_pixel_size / 2.0;
1487 if (y_centered)
1488 *uly += half_pixel;
1489 *pixel_x_size = x_pixel_size;
1490 *pixel_y_size = y_pixel_size;
1491 return 1;
1492
1493 stop:
1494 if (path != NULL)
1495 {
1496 if (hdr)
1497 fclose (hdr);
1498 }
1499 return 0;
1500 }
1501
1502 GGRAPH_DECLARE int
gGraphImageInfosFromAscFile(const char * path,const void ** infos_handle)1503 gGraphImageInfosFromAscFile (const char *path, const void **infos_handle)
1504 {
1505 /* retrieving Image infos from ASC file */
1506 gGraphImageInfosPtr infos = NULL;
1507 int width;
1508 int height;
1509 double ulx;
1510 double uly;
1511 double pixel_x_size;
1512 double pixel_y_size;
1513 double no_data;
1514
1515 *infos_handle = NULL;
1516
1517 if (!parse_asc_hdr
1518 (path, NULL, &width, &height, &ulx, &uly, &pixel_x_size, &pixel_y_size,
1519 &no_data))
1520 return GGRAPH_ASCII_CODEC_ERROR;
1521
1522 infos =
1523 gg_image_infos_create (GG_PIXEL_GRID, width, height, 32, 1,
1524 GGRAPH_SAMPLE_FLOAT, NULL, NULL);
1525 if (!infos)
1526 return GGRAPH_INSUFFICIENT_MEMORY;
1527
1528 /* setting up georeferencing infos */
1529 infos->is_georeferenced = 1;
1530 infos->upper_left_x = ulx;
1531 infos->upper_left_y = uly;
1532 infos->pixel_x_size = pixel_x_size;
1533 infos->pixel_y_size = pixel_y_size;
1534 infos->no_data_value = no_data;
1535
1536 *infos_handle = infos;
1537 return GGRAPH_OK;
1538 }
1539
1540 GGRAPH_PRIVATE int
gg_image_strip_prepare_from_bin_hdr(FILE * in,const char * hdr_path,gGraphStripImagePtr * image_handle)1541 gg_image_strip_prepare_from_bin_hdr (FILE * in, const char *hdr_path,
1542 gGraphStripImagePtr * image_handle)
1543 {
1544 /* preparing to decode an BIN-GRID [by strips] */
1545 gGraphStripImagePtr img = NULL;
1546 struct grid_codec_data *grid_codec = NULL;
1547 long file_length;
1548 int expected_length;
1549 int width;
1550 int height;
1551 double ulx;
1552 double uly;
1553 double pixel_x_size;
1554 double pixel_y_size;
1555 int sample;
1556 int bits_per_sample;
1557 int endian;
1558 double no_data;
1559 double min;
1560 double max;
1561 int buf_size;
1562 void *grid_buffer = NULL;
1563 int ret = GGRAPH_BIN_CODEC_ERROR;
1564 *image_handle = NULL;
1565
1566 if (!parse_binflt_hdr
1567 (hdr_path, &width, &height, &bits_per_sample, &sample, &endian,
1568 &no_data, &min, &max, &ulx, &uly, &pixel_x_size, &pixel_y_size,
1569 &expected_length))
1570 return GGRAPH_BIN_CODEC_ERROR;
1571
1572 /* retrieving the BIN dimensions */
1573 if (fseek (in, 0, SEEK_END) != 0)
1574 return GGRAPH_BIN_CODEC_ERROR;
1575 file_length = ftell (in);
1576 if (file_length != expected_length)
1577 return GGRAPH_BIN_CODEC_ERROR;
1578
1579 img =
1580 gg_strip_image_create (in, GGRAPH_IMAGE_BIN_HDR, GG_PIXEL_GRID, width,
1581 height, bits_per_sample, 1, sample, NULL, NULL);
1582 if (!img)
1583 {
1584 ret = GGRAPH_INSUFFICIENT_MEMORY;
1585 goto error;
1586 }
1587
1588 /* setting up georeferencing infos */
1589 img->is_georeferenced = 1;
1590 img->upper_left_x = ulx;
1591 img->upper_left_y = uly;
1592 img->pixel_x_size = pixel_x_size;
1593 img->pixel_y_size = pixel_y_size;
1594 img->no_data_value = no_data;
1595 img->min_value = min;
1596 img->max_value = max;
1597
1598 /* setting up the GRID codec struct */
1599 grid_codec = malloc (sizeof (struct grid_codec_data));
1600 if (!grid_codec)
1601 goto error;
1602 grid_codec->grid_type = GRID_BIN_HDR;
1603 grid_codec->is_writer = 0;
1604 grid_codec->grid_buffer = NULL;
1605 grid_codec->row_offsets = NULL;
1606 grid_codec->little_endian = endian;
1607 img->codec_data = grid_codec;
1608
1609 /* allocating the GRID read buffer */
1610 if (sample == GGRAPH_SAMPLE_INT)
1611 {
1612 if (bits_per_sample == 16)
1613 buf_size = sizeof (short) * width;
1614 if (bits_per_sample == 32)
1615 buf_size = sizeof (int) * width;
1616 }
1617 if (sample == GGRAPH_SAMPLE_FLOAT)
1618 {
1619 if (bits_per_sample == 32)
1620 buf_size = sizeof (float) * width;
1621 if (bits_per_sample == 64)
1622 buf_size = sizeof (double) * width;
1623 }
1624 grid_buffer = malloc (buf_size);
1625 if (!grid_buffer)
1626 goto error;
1627 grid_codec->grid_buffer = grid_buffer;
1628
1629 *image_handle = img;
1630 return GGRAPH_OK;
1631
1632 error:
1633 if (img)
1634 gGraphDestroyImage (img);
1635 return ret;
1636 }
1637
1638 GGRAPH_PRIVATE int
gg_image_strip_prepare_from_flt_hdr(FILE * in,const char * hdr_path,gGraphStripImagePtr * image_handle)1639 gg_image_strip_prepare_from_flt_hdr (FILE * in, const char *hdr_path,
1640 gGraphStripImagePtr * image_handle)
1641 {
1642 /* preparing to decode an FLT-GRID [by strips] */
1643 gGraphStripImagePtr img = NULL;
1644 struct grid_codec_data *grid_codec = NULL;
1645 long file_length;
1646 int expected_length;
1647 int width;
1648 int height;
1649 double ulx;
1650 double uly;
1651 double pixel_x_size;
1652 double pixel_y_size;
1653 int sample;
1654 int bits_per_sample;
1655 int endian;
1656 double no_data;
1657 double min;
1658 double max;
1659 int buf_size;
1660 void *grid_buffer = NULL;
1661 int ret = GGRAPH_FLT_CODEC_ERROR;
1662 *image_handle = NULL;
1663
1664 if (!parse_binflt_hdr
1665 (hdr_path, &width, &height, &bits_per_sample, &sample, &endian,
1666 &no_data, &min, &max, &ulx, &uly, &pixel_x_size, &pixel_y_size,
1667 &expected_length))
1668 return GGRAPH_FLT_CODEC_ERROR;
1669
1670 /* retrieving the FLT dimensions */
1671 if (fseek (in, 0, SEEK_END) != 0)
1672 return GGRAPH_FLT_CODEC_ERROR;
1673 file_length = ftell (in);
1674 if (file_length != expected_length)
1675 return GGRAPH_FLT_CODEC_ERROR;
1676
1677 img =
1678 gg_strip_image_create (in, GGRAPH_IMAGE_FLT_HDR, GG_PIXEL_GRID, width,
1679 height, bits_per_sample, 1, sample, NULL, NULL);
1680 if (!img)
1681 {
1682 ret = GGRAPH_INSUFFICIENT_MEMORY;
1683 goto error;
1684 }
1685
1686 /* setting up georeferencing infos */
1687 img->is_georeferenced = 1;
1688 img->upper_left_x = ulx;
1689 img->upper_left_y = uly;
1690 img->pixel_x_size = pixel_x_size;
1691 img->pixel_y_size = pixel_y_size;
1692 img->no_data_value = no_data;
1693 img->min_value = min;
1694 img->max_value = max;
1695
1696 /* setting up the GRID codec struct */
1697 grid_codec = malloc (sizeof (struct grid_codec_data));
1698 if (!grid_codec)
1699 goto error;
1700 grid_codec->grid_type = GRID_FLT_HDR;
1701 grid_codec->is_writer = 0;
1702 grid_codec->grid_buffer = NULL;
1703 grid_codec->row_offsets = NULL;
1704 grid_codec->little_endian = endian;
1705 img->codec_data = grid_codec;
1706
1707 /* allocating the GRID read buffer */
1708 if (sample == GGRAPH_SAMPLE_INT)
1709 {
1710 if (bits_per_sample == 16)
1711 buf_size = sizeof (short) * width;
1712 if (bits_per_sample == 32)
1713 buf_size = sizeof (int) * width;
1714 }
1715 if (sample == GGRAPH_SAMPLE_FLOAT)
1716 {
1717 if (bits_per_sample == 32)
1718 buf_size = sizeof (float) * width;
1719 if (bits_per_sample == 64)
1720 buf_size = sizeof (double) * width;
1721 }
1722 grid_buffer = malloc (buf_size);
1723 if (!grid_buffer)
1724 goto error;
1725 grid_codec->grid_buffer = grid_buffer;
1726
1727 *image_handle = img;
1728 return GGRAPH_OK;
1729
1730 error:
1731 if (img)
1732 gGraphDestroyImage (img);
1733 return ret;
1734 }
1735
1736 GGRAPH_PRIVATE int
gg_image_strip_prepare_from_dem_hdr(FILE * in,const char * hdr_path,gGraphStripImagePtr * image_handle)1737 gg_image_strip_prepare_from_dem_hdr (FILE * in, const char *hdr_path,
1738 gGraphStripImagePtr * image_handle)
1739 {
1740 /* preparing to decode an DEM-GRID [by strips] */
1741 gGraphStripImagePtr img = NULL;
1742 struct grid_codec_data *grid_codec = NULL;
1743 long file_length;
1744 int expected_length;
1745 int width;
1746 int height;
1747 double ulx;
1748 double uly;
1749 double pixel_x_size;
1750 double pixel_y_size;
1751 int sample;
1752 int bits_per_sample;
1753 int endian;
1754 double no_data;
1755 int buf_size;
1756 void *grid_buffer = NULL;
1757 int ret = GGRAPH_DEM_CODEC_ERROR;
1758 *image_handle = NULL;
1759
1760 if (!parse_dem_hdr
1761 (hdr_path, &width, &height, &bits_per_sample, &sample, &endian,
1762 &no_data, &ulx, &uly, &pixel_x_size, &pixel_y_size, &expected_length))
1763 return GGRAPH_DEM_CODEC_ERROR;
1764
1765 /* retrieving the DEM dimensions */
1766 if (fseek (in, 0, SEEK_END) != 0)
1767 return GGRAPH_DEM_CODEC_ERROR;
1768 file_length = ftell (in);
1769 if (file_length != expected_length)
1770 return GGRAPH_DEM_CODEC_ERROR;
1771
1772 img =
1773 gg_strip_image_create (in, GGRAPH_IMAGE_DEM_HDR, GG_PIXEL_GRID, width,
1774 height, bits_per_sample, 1, sample, NULL, NULL);
1775 if (!img)
1776 {
1777 ret = GGRAPH_INSUFFICIENT_MEMORY;
1778 goto error;
1779 }
1780
1781 /* setting up georeferencing infos */
1782 img->is_georeferenced = 1;
1783 img->upper_left_x = ulx;
1784 img->upper_left_y = uly;
1785 img->pixel_x_size = pixel_x_size;
1786 img->pixel_y_size = pixel_y_size;
1787 img->no_data_value = no_data;
1788
1789 /* setting up the GRID codec struct */
1790 grid_codec = malloc (sizeof (struct grid_codec_data));
1791 if (!grid_codec)
1792 goto error;
1793 grid_codec->grid_type = GRID_DEM_HDR;
1794 grid_codec->is_writer = 0;
1795 grid_codec->grid_buffer = NULL;
1796 grid_codec->row_offsets = NULL;
1797 grid_codec->little_endian = endian;
1798 img->codec_data = grid_codec;
1799
1800 /* allocating the GRID read buffer */
1801 if (bits_per_sample == 16)
1802 buf_size = sizeof (short) * width;
1803 if (bits_per_sample == 32)
1804 buf_size = sizeof (int) * width;
1805 grid_buffer = malloc (buf_size);
1806 if (!grid_buffer)
1807 goto error;
1808 grid_codec->grid_buffer = grid_buffer;
1809
1810 *image_handle = img;
1811 return GGRAPH_OK;
1812
1813 error:
1814 if (img)
1815 gGraphDestroyImage (img);
1816 return ret;
1817 }
1818
1819 static int
parse_asc_offsets(FILE * in,int height,long ** row_offsets)1820 parse_asc_offsets (FILE * in, int height, long **row_offsets)
1821 {
1822 /* retrieving row-offsets from an ASC file [ASCII GRID format] */
1823 int c;
1824 int row = 0;
1825 int ind = 0;
1826 long *offsets = *row_offsets;
1827 long current = 0;
1828
1829 rewind (in);
1830 while ((c = getc (in)) != EOF)
1831 {
1832 /* parsing the Header file */
1833 if (c == '\n')
1834 {
1835 row++;
1836 if (row >= 6)
1837 {
1838 if (ind < height)
1839 *(offsets + ind) = current;
1840 ind++;
1841 }
1842 }
1843 current++;
1844 }
1845 if (ind != height + 1)
1846 return 0;
1847 return 1;
1848 }
1849
1850 GGRAPH_PRIVATE int
gg_image_strip_prepare_from_ascii_grid(FILE * in,gGraphStripImagePtr * image_handle)1851 gg_image_strip_prepare_from_ascii_grid (FILE * in,
1852 gGraphStripImagePtr * image_handle)
1853 {
1854 /* preparing to decode an ASCII-GRID [by strips] */
1855 gGraphStripImagePtr img = NULL;
1856 struct grid_codec_data *grid_codec = NULL;
1857 int width;
1858 int height;
1859 double ulx;
1860 double uly;
1861 double pixel_x_size;
1862 double pixel_y_size;
1863 double no_data;
1864 long *row_offsets = NULL;
1865 int ret = GGRAPH_ASCII_CODEC_ERROR;
1866 *image_handle = NULL;
1867
1868 if (!parse_asc_hdr
1869 (NULL, in, &width, &height, &ulx, &uly, &pixel_x_size, &pixel_y_size,
1870 &no_data))
1871 return GGRAPH_ASCII_CODEC_ERROR;
1872
1873 /* preparing the row-offset array */
1874 row_offsets = malloc (sizeof (long) * height);
1875 if (!row_offsets)
1876 return GGRAPH_ASCII_CODEC_ERROR;
1877 if (!parse_asc_offsets (in, height, &row_offsets))
1878 {
1879 free (row_offsets);
1880 return GGRAPH_ASCII_CODEC_ERROR;
1881 }
1882
1883 img =
1884 gg_strip_image_create (in, GGRAPH_IMAGE_ASCII_GRID, GG_PIXEL_GRID,
1885 width, height, 32, 1, GGRAPH_SAMPLE_FLOAT, NULL,
1886 NULL);
1887 if (!img)
1888 {
1889 ret = GGRAPH_INSUFFICIENT_MEMORY;
1890 goto error;
1891 }
1892
1893 /* setting up georeferencing infos */
1894 img->is_georeferenced = 1;
1895 img->upper_left_x = ulx;
1896 img->upper_left_y = uly;
1897 img->pixel_x_size = pixel_x_size;
1898 img->pixel_y_size = pixel_y_size;
1899 img->no_data_value = no_data;
1900
1901 /* setting up the GRID codec struct */
1902 grid_codec = malloc (sizeof (struct grid_codec_data));
1903 if (!grid_codec)
1904 goto error;
1905 grid_codec->grid_type = GRID_ASCII;
1906 grid_codec->is_writer = 0;
1907 grid_codec->grid_buffer = NULL;
1908 grid_codec->row_offsets = row_offsets;
1909 img->codec_data = grid_codec;
1910
1911 *image_handle = img;
1912 return GGRAPH_OK;
1913
1914 error:
1915 if (img)
1916 gGraphDestroyImage (img);
1917 return ret;
1918 }
1919
1920 static int
read_from_bin_grid(FILE * in,gGraphStripImagePtr img,int sample,int bits_per_pixel,int type,void * scanline,int endian)1921 read_from_bin_grid (FILE * in, gGraphStripImagePtr img, int sample,
1922 int bits_per_pixel, int type, void *scanline, int endian)
1923 {
1924 /* decoding a BIN-GRID or a FLT-GRID [by strip] */
1925 int width = img->width;
1926 int height = img->height;
1927 size_t scan_size;
1928 int row;
1929 int incr = 0;
1930 int x;
1931 int endian_arch = gg_endian_arch ();
1932 off_t pos;
1933 unsigned char *p_in;
1934 short *p_out_short;
1935 short cell_value_short;
1936 int *p_out_int;
1937 int cell_value_int;
1938 float *p_out_float;
1939 float cell_value_float;
1940 double *p_out_double;
1941 double cell_value_double;
1942
1943 if (bits_per_pixel == 16)
1944 scan_size = width * 2;
1945 if (bits_per_pixel == 32)
1946 scan_size = width * 4;
1947 if (bits_per_pixel == 64)
1948 scan_size = width * 8;
1949 pos = img->next_row * scan_size;
1950 /* positioning on the start scanline */
1951 if (fseek (in, pos, SEEK_SET) != 0)
1952 {
1953 if (type == GRID_BIN_HDR)
1954 return GGRAPH_BIN_CODEC_ERROR;
1955 if (type == GRID_FLT_HDR)
1956 return GGRAPH_FLT_CODEC_ERROR;
1957 if (type == GRID_DEM_HDR)
1958 return GGRAPH_DEM_CODEC_ERROR;
1959 }
1960 for (row = 0; row < img->rows_per_block; row++)
1961 {
1962 /* reading the required number of scanlines */
1963 if ((row + img->next_row) >= height)
1964 break;
1965 if (fread (scanline, 1, scan_size, in) != scan_size)
1966 return GGRAPH_HGT_CODEC_ERROR;
1967 p_in = scanline;
1968 if (sample == GGRAPH_SAMPLE_INT)
1969 {
1970 if (bits_per_pixel == 16)
1971 {
1972 p_out_short = (short *) (img->pixels);
1973 p_out_short += (row * width);
1974 }
1975
1976 if (bits_per_pixel == 32)
1977 {
1978 p_out_int = (int *) (img->pixels);
1979 p_out_int += (row * width);
1980 }
1981 }
1982 if (sample == GGRAPH_SAMPLE_FLOAT)
1983 {
1984 if (bits_per_pixel == 32)
1985 {
1986 p_out_float = (float *) (img->pixels);
1987 p_out_float += (row * width);
1988 }
1989
1990 if (bits_per_pixel == 64)
1991 {
1992 p_out_double = (double *) (img->pixels);
1993 p_out_double += (row * width);
1994 }
1995 }
1996 for (x = 0; x < width; x++)
1997 {
1998 if (sample == GGRAPH_SAMPLE_INT)
1999 {
2000 if (bits_per_pixel == 16)
2001 {
2002 cell_value_short =
2003 gg_import_int16 (p_in, endian, endian_arch);
2004 *p_out_short++ = cell_value_short;
2005 p_in += sizeof (short);
2006 }
2007 if (bits_per_pixel == 32)
2008 {
2009 cell_value_int =
2010 gg_import_int32 (p_in, endian, endian_arch);
2011 *p_out_int++ = cell_value_int;
2012 p_in += sizeof (int);
2013 }
2014 }
2015 if (sample == GGRAPH_SAMPLE_FLOAT)
2016 {
2017 if (bits_per_pixel == 32)
2018 {
2019 cell_value_float =
2020 gg_import_float (p_in, endian, endian_arch);
2021 *p_out_float++ = cell_value_float;
2022 p_in += sizeof (float);
2023 }
2024 if (bits_per_pixel == 64)
2025 {
2026 cell_value_double =
2027 gg_import_double (p_in, endian, endian_arch);
2028 *p_out_double++ = cell_value_double;
2029 p_in += sizeof (double);
2030 }
2031 }
2032 }
2033 incr++;
2034 }
2035 img->next_row += incr;
2036 img->current_available_rows = incr;
2037 return GGRAPH_OK;
2038 }
2039
2040 GGRAPH_PRIVATE int
gg_image_strip_read_from_bin_grid(gGraphStripImagePtr img,int * progress)2041 gg_image_strip_read_from_bin_grid (gGraphStripImagePtr img, int *progress)
2042 {
2043 /* decoding a BIN-GRID or a FLT-GRID [by strip] */
2044 struct grid_codec_data *grid_codec =
2045 (struct grid_codec_data *) (img->codec_data);
2046 FILE *in = img->file_handle;
2047
2048 if (grid_codec->grid_type == GRID_BIN_HDR
2049 || grid_codec->grid_type == GRID_FLT_HDR)
2050 {
2051 int ret = read_from_bin_grid (in, img, img->sample_format,
2052 img->bits_per_sample,
2053 grid_codec->grid_type,
2054 grid_codec->grid_buffer,
2055 grid_codec->little_endian);
2056 if (ret == GGRAPH_OK && progress != NULL)
2057 *progress =
2058 (int) (((double) (img->next_row + 1) * 100.0) /
2059 (double) (img->height));
2060 return ret;
2061 }
2062 return GGRAPH_ERROR;
2063 }
2064
2065 GGRAPH_PRIVATE int
gg_image_strip_read_from_dem_grid(gGraphStripImagePtr img,int * progress)2066 gg_image_strip_read_from_dem_grid (gGraphStripImagePtr img, int *progress)
2067 {
2068 /* decoding a DEM-GRID [by strip] */
2069 struct grid_codec_data *grid_codec =
2070 (struct grid_codec_data *) (img->codec_data);
2071 FILE *in = img->file_handle;
2072
2073 if (grid_codec->grid_type == GRID_DEM_HDR)
2074 {
2075 int ret = read_from_bin_grid (in, img, img->sample_format,
2076 img->bits_per_sample,
2077 grid_codec->grid_type,
2078 grid_codec->grid_buffer,
2079 grid_codec->little_endian);
2080 if (ret == GGRAPH_OK && progress != NULL)
2081 *progress =
2082 (int) (((double) (img->next_row + 1) * 100.0) /
2083 (double) (img->height));
2084 return ret;
2085 }
2086 return GGRAPH_ERROR;
2087 }
2088
2089 static int
read_from_ascii_grid(FILE * in,gGraphStripImagePtr img,long * row_offsets)2090 read_from_ascii_grid (FILE * in, gGraphStripImagePtr img, long *row_offsets)
2091 {
2092 /* decoding an ASCII-GRID [by strip] */
2093 int width = img->width;
2094 int height = img->height;
2095 int row;
2096 int incr = 0;
2097 int col;
2098 int c;
2099 float *p_out;
2100 float cell_value;
2101 char buf[256];
2102 char *p;
2103
2104 /* positioning on the start scanline */
2105 if (fseek (in, row_offsets[img->next_row], SEEK_SET) != 0)
2106 return GGRAPH_ASCII_CODEC_ERROR;
2107 if (getc (in) != '\n')
2108 return GGRAPH_ASCII_CODEC_ERROR;
2109
2110 for (row = 0; row < img->rows_per_block; row++)
2111 {
2112 /* reading the required number of scanlines */
2113 if ((row + img->next_row) >= height)
2114 break;
2115 p_out = (float *) (img->pixels);
2116 p_out += row * width;
2117 p = buf;
2118 col = 0;
2119 while ((c = getc (in)) != EOF)
2120 {
2121 /* parsing cell values */
2122 if (c == '\r')
2123 continue;
2124 if (c == '\n')
2125 break;
2126 if (c == ' ')
2127 {
2128 /* cell end */
2129 *p = '\0';
2130 cell_value = atof (buf);
2131 if (col >= width)
2132 return GGRAPH_ASCII_CODEC_ERROR;
2133 *p_out++ = cell_value;
2134 col++;
2135 p = buf;
2136 continue;
2137 }
2138 if ((p - buf) >= 256)
2139 return GGRAPH_ASCII_CODEC_ERROR;
2140 *p++ = c;
2141 }
2142 if (col != width)
2143 return GGRAPH_ASCII_CODEC_ERROR;
2144 incr++;
2145 }
2146 img->next_row += incr;
2147 img->current_available_rows = incr;
2148 return GGRAPH_OK;
2149 }
2150
2151 GGRAPH_PRIVATE int
gg_image_strip_read_from_ascii_grid(gGraphStripImagePtr img,int * progress)2152 gg_image_strip_read_from_ascii_grid (gGraphStripImagePtr img, int *progress)
2153 {
2154 /* decoding an ASCII-GRID [by strip] */
2155 struct grid_codec_data *grid_codec =
2156 (struct grid_codec_data *) (img->codec_data);
2157 FILE *in = img->file_handle;
2158
2159 if (grid_codec->grid_type == GRID_ASCII)
2160 {
2161 int ret = read_from_ascii_grid (in, img, grid_codec->row_offsets);
2162 if (ret == GGRAPH_OK && progress != NULL)
2163 *progress =
2164 (int) (((double) (img->next_row + 1) * 100.0) /
2165 (double) (img->height));
2166 return ret;
2167 }
2168 return GGRAPH_ERROR;
2169 }
2170
2171 GGRAPH_PRIVATE int
gg_image_prepare_to_ascii_grid_by_strip(const gGraphStripImagePtr img,FILE * out)2172 gg_image_prepare_to_ascii_grid_by_strip (const gGraphStripImagePtr img,
2173 FILE * out)
2174 {
2175 /* preparing to export an ASCII GRID [by strips] */
2176 char dummy[256];
2177
2178 fprintf (out, "ncols %d\r\n", img->width);
2179 fprintf (out, "nrows %d\r\n", img->height);
2180 gGraphSmartPrintf (img->upper_left_x, dummy);
2181 fprintf (out, "xllcorner %s\r\n", dummy);
2182 gGraphSmartPrintf (img->upper_left_y -
2183 ((double) (img->height) * img->pixel_y_size), dummy);
2184 fprintf (out, "yllcorner %s\r\n", dummy);
2185 gGraphSmartPrintf (img->pixel_y_size, dummy);
2186 fprintf (out, "cellsize %s\r\n", dummy);
2187 gGraphSmartPrintf (img->no_data_value, dummy);
2188 fprintf (out, "NODATA_value %s\r\n", dummy);
2189
2190 return GGRAPH_OK;
2191 }
2192
2193 GGRAPH_PRIVATE int
gg_image_write_to_ascii_grid_by_strip(const gGraphStripImagePtr img,int * progress)2194 gg_image_write_to_ascii_grid_by_strip (const gGraphStripImagePtr img,
2195 int *progress)
2196 {
2197 /* scanline(s) ASCII GRID export [by strip] */
2198 FILE *out = img->file_handle;
2199 int row;
2200 int col;
2201 char *p_in_int8;
2202 unsigned char *p_in_uint8;
2203 short *p_in_int16;
2204 unsigned short *p_in_uint16;
2205 int *p_in_int32;
2206 unsigned int *p_in_uint32;
2207 float *p_in_flt;
2208 double *p_in_dbl;
2209 char dummy[256];
2210
2211 for (row = 0; row < img->current_available_rows; row++)
2212 {
2213 switch (img->sample_format)
2214 {
2215 case GGRAPH_SAMPLE_UINT:
2216 switch (img->bits_per_sample)
2217 {
2218 case 8:
2219 p_in_uint8 = (unsigned char *) (img->pixels);
2220 p_in_uint8 += row * img->width;
2221 break;
2222 case 16:
2223 p_in_uint16 = (unsigned short *) (img->pixels);
2224 p_in_uint16 += row * img->width;
2225 break;
2226 case 32:
2227 p_in_uint32 = (unsigned int *) (img->pixels);
2228 p_in_uint32 += row * img->width;
2229 break;
2230 };
2231 break;
2232 case GGRAPH_SAMPLE_INT:
2233 switch (img->bits_per_sample)
2234 {
2235 case 8:
2236 p_in_int8 = (char *) (img->pixels);
2237 p_in_int8 += row * img->width;
2238 break;
2239 case 16:
2240 p_in_int16 = (short *) (img->pixels);
2241 p_in_int16 += row * img->width;
2242 break;
2243 case 32:
2244 p_in_int32 = (int *) (img->pixels);
2245 p_in_int32 += row * img->width;
2246 break;
2247 };
2248 break;
2249 case GGRAPH_SAMPLE_FLOAT:
2250 switch (img->bits_per_sample)
2251 {
2252 case 32:
2253 p_in_flt = (float *) (img->pixels);
2254 p_in_flt += row * img->width;
2255 break;
2256 case 64:
2257 p_in_dbl = (double *) (img->pixels);
2258 p_in_dbl += row * img->width;
2259 break;
2260 };
2261 break;
2262 };
2263 for (col = 0; col < img->width; col++)
2264 {
2265 switch (img->sample_format)
2266 {
2267 case GGRAPH_SAMPLE_UINT:
2268 switch (img->bits_per_sample)
2269 {
2270 case 8:
2271 sprintf (dummy, "%u", *p_in_uint8++);
2272 break;
2273 case 16:
2274 sprintf (dummy, "%u", *p_in_uint16++);
2275 break;
2276 case 32:
2277 sprintf (dummy, "%u", *p_in_uint32++);
2278 break;
2279 };
2280 break;
2281 case GGRAPH_SAMPLE_INT:
2282 switch (img->bits_per_sample)
2283 {
2284 case 8:
2285 sprintf (dummy, "%d", *p_in_int8++);
2286 break;
2287 case 16:
2288 sprintf (dummy, "%d", *p_in_int16++);
2289 break;
2290 case 32:
2291 sprintf (dummy, "%d", *p_in_int32++);
2292 break;
2293 };
2294 break;
2295 case GGRAPH_SAMPLE_FLOAT:
2296 switch (img->bits_per_sample)
2297 {
2298 case 32:
2299 gGraphSmartPrintf (*p_in_flt++, dummy);
2300 break;
2301 case 64:
2302 gGraphSmartPrintf (*p_in_dbl++, dummy);
2303 break;
2304 };
2305 break;
2306 };
2307 fprintf (out, "%s ", dummy);
2308 }
2309 /* terminating a full scanline */
2310 fprintf (out, "\r\n");
2311 }
2312 img->next_row += img->current_available_rows;
2313
2314 if (progress != NULL)
2315 *progress =
2316 (int) (((double) (img->next_row + 1) * 100.0) /
2317 (double) (img->height));
2318 return GGRAPH_OK;
2319 }
2320
2321 GGRAPH_PRIVATE int
gg_image_prepare_to_bin_hdr_by_strip(const gGraphStripImagePtr img)2322 gg_image_prepare_to_bin_hdr_by_strip (const gGraphStripImagePtr img)
2323 {
2324 /* preparing to export a BIN+HDR GRID [by strips] */
2325 struct grid_codec_data *grid_codec = NULL;
2326 int buf_size;
2327 void *grid_buffer = NULL;
2328
2329 if (img->sample_format != GGRAPH_SAMPLE_INT)
2330 return GGRAPH_BIN_CODEC_ERROR;
2331 if (img->bits_per_sample == 16 || img->bits_per_sample == 32)
2332 ;
2333 else
2334 return GGRAPH_BIN_CODEC_ERROR;
2335
2336 /* setting up the GRID codec struct */
2337 grid_codec = malloc (sizeof (struct grid_codec_data));
2338 if (!grid_codec)
2339 return GGRAPH_BIN_CODEC_ERROR;
2340 grid_codec->grid_type = GRID_BIN_HDR;
2341 grid_codec->is_writer = 1;
2342 grid_codec->grid_buffer = NULL;
2343 grid_codec->row_offsets = NULL;
2344
2345 /* allocating the GRID read buffer */
2346 if (img->bits_per_sample == 16)
2347 buf_size = sizeof (short) * img->width;
2348 else
2349 buf_size = sizeof (int) * img->width;
2350 grid_buffer = malloc (buf_size);
2351 if (!grid_buffer)
2352 {
2353 free (grid_codec);
2354 return GGRAPH_BIN_CODEC_ERROR;
2355 }
2356 grid_codec->grid_buffer = grid_buffer;
2357 img->codec_data = grid_codec;
2358
2359 return GGRAPH_OK;
2360 }
2361
2362 GGRAPH_PRIVATE int
gg_image_prepare_to_flt_hdr_by_strip(const gGraphStripImagePtr img)2363 gg_image_prepare_to_flt_hdr_by_strip (const gGraphStripImagePtr img)
2364 {
2365 /* preparing to export a FLT+HDR GRID [by strips] */
2366 struct grid_codec_data *grid_codec = NULL;
2367 int buf_size;
2368 void *grid_buffer = NULL;
2369
2370 if (img->sample_format != GGRAPH_SAMPLE_FLOAT)
2371 return GGRAPH_FLT_CODEC_ERROR;
2372 if (img->bits_per_sample == 32 || img->bits_per_sample == 64)
2373 ;
2374 else
2375 return GGRAPH_FLT_CODEC_ERROR;
2376
2377 /* setting up the GRID codec struct */
2378 grid_codec = malloc (sizeof (struct grid_codec_data));
2379 if (!grid_codec)
2380 return GGRAPH_FLT_CODEC_ERROR;
2381 grid_codec->grid_type = GRID_FLT_HDR;
2382 grid_codec->is_writer = 1;
2383 grid_codec->grid_buffer = NULL;
2384 grid_codec->row_offsets = NULL;
2385
2386 /* allocating the GRID read buffer */
2387 if (img->bits_per_sample == 32)
2388 buf_size = sizeof (float) * img->width;
2389 else
2390 buf_size = sizeof (double) * img->width;
2391 grid_buffer = malloc (buf_size);
2392 if (!grid_buffer)
2393 {
2394 free (grid_codec);
2395 return GGRAPH_FLT_CODEC_ERROR;
2396 }
2397 grid_codec->grid_buffer = grid_buffer;
2398 img->codec_data = grid_codec;
2399
2400 return GGRAPH_OK;
2401 }
2402
2403 GGRAPH_PRIVATE int
gg_image_write_to_bin_hdr_by_strip(const gGraphStripImagePtr img,int * progress)2404 gg_image_write_to_bin_hdr_by_strip (const gGraphStripImagePtr img,
2405 int *progress)
2406 {
2407 /* scanline(s) BIN+HDR GRID export [by strip] */
2408 FILE *out = img->file_handle;
2409 struct grid_codec_data *grid_codec =
2410 (struct grid_codec_data *) (img->codec_data);
2411 int row;
2412 int col;
2413 short *p_in_int16;
2414 int *p_in_int32;
2415 unsigned char *p_out;
2416 size_t sz;
2417 int endian_arch = gg_endian_arch ();
2418
2419 for (row = 0; row < img->current_available_rows; row++)
2420 {
2421 switch (img->bits_per_sample)
2422 {
2423 case 16:
2424 p_in_int16 = (short *) (img->pixels);
2425 p_in_int16 += row * img->width;
2426 sz = img->width * sizeof (short);
2427 break;
2428 case 32:
2429 p_in_int32 = (int *) (img->pixels);
2430 p_in_int32 += row * img->width;
2431 sz = img->width * sizeof (int);
2432 break;
2433 };
2434 p_out = grid_codec->grid_buffer;
2435
2436 for (col = 0; col < img->width; col++)
2437 {
2438 switch (img->bits_per_sample)
2439 {
2440 case 16:
2441 if (*p_in_int16 < img->min_value)
2442 img->min_value = *p_in_int16;
2443 if (*p_in_int16 > img->max_value)
2444 img->max_value = *p_in_int16;
2445 gg_export_int16 (*p_in_int16++, p_out, 1, endian_arch);
2446 p_out += sizeof (short);
2447 break;
2448 case 32:
2449 if (*p_in_int32 < img->min_value)
2450 img->min_value = *p_in_int32;
2451 if (*p_in_int32 > img->max_value)
2452 img->max_value = *p_in_int32;
2453 gg_export_int32 (*p_in_int32++, p_out, 1, endian_arch);
2454 p_out += sizeof (int);
2455 break;
2456 };
2457 }
2458 /* terminating a full scanline */
2459 if (fwrite (grid_codec->grid_buffer, 1, sz, out) != sz)
2460 return GGRAPH_BIN_CODEC_ERROR;
2461 }
2462 img->next_row += img->current_available_rows;
2463
2464 if (progress != NULL)
2465 *progress =
2466 (int) (((double) (img->next_row + 1) * 100.0) /
2467 (double) (img->height));
2468 return GGRAPH_OK;
2469 }
2470
2471 GGRAPH_PRIVATE int
gg_image_write_to_flt_hdr_by_strip(const gGraphStripImagePtr img,int * progress)2472 gg_image_write_to_flt_hdr_by_strip (const gGraphStripImagePtr img,
2473 int *progress)
2474 {
2475 /* scanline(s) FLT+HDR GRID export [by strip] */
2476 FILE *out = img->file_handle;
2477 struct grid_codec_data *grid_codec =
2478 (struct grid_codec_data *) (img->codec_data);
2479 int row;
2480 int col;
2481 float *p_in_float;
2482 double *p_in_double;
2483 unsigned char *p_out;
2484 size_t sz;
2485 int endian_arch = gg_endian_arch ();
2486
2487 for (row = 0; row < img->current_available_rows; row++)
2488 {
2489 switch (img->bits_per_sample)
2490 {
2491 case 32:
2492 p_in_float = (float *) (img->pixels);
2493 p_in_float += row * img->width;
2494 sz = img->width * sizeof (float);
2495 break;
2496 case 64:
2497 p_in_double = (double *) (img->pixels);
2498 p_in_double += row * img->width;
2499 sz = img->width * sizeof (double);
2500 break;
2501 };
2502 p_out = grid_codec->grid_buffer;
2503
2504 for (col = 0; col < img->width; col++)
2505 {
2506 switch (img->bits_per_sample)
2507 {
2508 case 32:
2509 if (*p_in_float < img->min_value)
2510 img->min_value = *p_in_float;
2511 if (*p_in_float > img->max_value)
2512 img->max_value = *p_in_float;
2513 gg_export_float (*p_in_float++, p_out, 1, endian_arch);
2514 p_out += sizeof (float);
2515 break;
2516 case 64:
2517 if (*p_in_double < img->min_value)
2518 img->min_value = *p_in_double;
2519 if (*p_in_double > img->max_value)
2520 img->max_value = *p_in_double;
2521 gg_export_double (*p_in_double++, p_out, 1, endian_arch);
2522 p_out += sizeof (float);
2523 break;
2524 };
2525 }
2526 /* terminating a full scanline */
2527 if (fwrite (grid_codec->grid_buffer, 1, sz, out) != sz)
2528 return GGRAPH_FLT_CODEC_ERROR;
2529 }
2530 img->next_row += img->current_available_rows;
2531
2532 if (progress != NULL)
2533 *progress =
2534 (int) (((double) (img->next_row + 1) * 100.0) /
2535 (double) (img->height));
2536 return GGRAPH_OK;
2537 }
2538
2539 GGRAPH_DECLARE int
gGraphWriteBinHeader(const char * hdr_path,const void * ptr)2540 gGraphWriteBinHeader (const char *hdr_path, const void *ptr)
2541 {
2542 /* exporting a BIN Header file */
2543 FILE *out = NULL;
2544 char dummy[256];
2545 gGraphStripImagePtr img = (gGraphStripImagePtr) ptr;
2546
2547 if (img == NULL)
2548 return GGRAPH_INVALID_IMAGE;
2549 if (img->signature != GG_STRIP_IMAGE_MAGIC_SIGNATURE)
2550 return GGRAPH_INVALID_IMAGE;
2551
2552 /* attempting to open/create the header file */
2553 out = fopen (hdr_path, "wb");
2554 if (out == NULL)
2555 return GGRAPH_FILE_OPEN_ERROR;
2556
2557 fprintf (out, "NCOLS %d\r\n", img->width);
2558 fprintf (out, "NROWS %d\r\n", img->height);
2559 gGraphSmartPrintf (img->upper_left_x, dummy);
2560 fprintf (out, "XLLCORNER %s\r\n", dummy);
2561 gGraphSmartPrintf (img->upper_left_y -
2562 ((double) (img->height) * img->pixel_y_size), dummy);
2563 fprintf (out, "YLLCORNER %s\r\n", dummy);
2564 gGraphSmartPrintf (img->pixel_y_size, dummy);
2565 fprintf (out, "CELLSIZE %s\r\n", dummy);
2566 gGraphSmartPrintf (img->no_data_value, dummy);
2567 fprintf (out, "NODATA_VALUE %s\r\n", dummy);
2568 fprintf (out, "BYTEORDER LSBFIRST\r\n");
2569 if (img->bits_per_sample == 16)
2570 fprintf (out, "NUMBERTYPE 2_BYTE_INTEGER\r\n");
2571 else
2572 fprintf (out, "NUMBERTYPE 4_BYTE_INTEGER\r\n");
2573 fprintf (out, "ZUNITS METERS\r\n");
2574 gGraphSmartPrintf (img->min_value, dummy);
2575 fprintf (out, "MIN_VALUE %s\r\n", dummy);
2576 gGraphSmartPrintf (img->max_value, dummy);
2577 fprintf (out, "MAX_VALUE %s\r\n", dummy);
2578
2579 fclose (out);
2580
2581 return GGRAPH_OK;
2582 }
2583
2584 GGRAPH_DECLARE int
gGraphWriteFltHeader(const char * hdr_path,const void * ptr)2585 gGraphWriteFltHeader (const char *hdr_path, const void *ptr)
2586 {
2587 /* exporting a FLT Header file */
2588 FILE *out = NULL;
2589 char dummy[256];
2590 gGraphStripImagePtr img = (gGraphStripImagePtr) ptr;
2591
2592 if (img == NULL)
2593 return GGRAPH_INVALID_IMAGE;
2594 if (img->signature != GG_STRIP_IMAGE_MAGIC_SIGNATURE)
2595 return GGRAPH_INVALID_IMAGE;
2596
2597 /* attempting to open/create the header file */
2598 out = fopen (hdr_path, "wb");
2599 if (out == NULL)
2600 return GGRAPH_FILE_OPEN_ERROR;
2601
2602 fprintf (out, "ncols %d\r\n", img->width);
2603 fprintf (out, "nrows %d\r\n", img->height);
2604 gGraphSmartPrintf (img->upper_left_x, dummy);
2605 fprintf (out, "xllcorner %s\r\n", dummy);
2606 gGraphSmartPrintf (img->upper_left_y -
2607 ((double) (img->height) * img->pixel_y_size), dummy);
2608 fprintf (out, "yllcorner %s\r\n", dummy);
2609 gGraphSmartPrintf (img->pixel_y_size, dummy);
2610 fprintf (out, "cellsize %s\r\n", dummy);
2611 gGraphSmartPrintf (img->no_data_value, dummy);
2612 fprintf (out, "NODATA_value %s\r\n", dummy);
2613 fprintf (out, "byteorder LSBFIRST\r\n");
2614 if (img->bits_per_sample == 32)
2615 fprintf (out, "NUMBERTYPE 4_BYTE_FLOAT\r\n");
2616 else
2617 fprintf (out, "NUMBERTYPE 8_BYTE_FLOAT\r\n");
2618 gGraphSmartPrintf (img->min_value, dummy);
2619 fprintf (out, "MIN_VALUE %s\r\n", dummy);
2620 gGraphSmartPrintf (img->max_value, dummy);
2621 fprintf (out, "MAX_VALUE %s\r\n", dummy);
2622
2623 fclose (out);
2624
2625 return GGRAPH_OK;
2626 }
2627