1 /*
2
3 rl2ascii -- ASCII Grids related functions
4
5 version 0.1, 2013 December 26
6
7 Author: Sandro Furieri a.furieri@lqt.it
8
9 -----------------------------------------------------------------------------
10
11 Version: MPL 1.1/GPL 2.0/LGPL 2.1
12
13 The contents of this file are subject to the Mozilla Public License Version
14 1.1 (the "License"); you may not use this file except in compliance with
15 the License. You may obtain a copy of the License at
16 http://www.mozilla.org/MPL/
17
18 Software distributed under the License is distributed on an "AS IS" basis,
19 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
20 for the specific language governing rights and limitations under the
21 License.
22
23 The Original Code is the SpatiaLite library
24
25 The Initial Developer of the Original Code is Alessandro Furieri
26
27 Portions created by the Initial Developer are Copyright (C) 2008-2013
28 the Initial Developer. All Rights Reserved.
29
30 Alternatively, the contents of this file may be used under the terms of
31 either the GNU General Public License Version 2 or later (the "GPL"), or
32 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 in which case the provisions of the GPL or the LGPL are applicable instead
34 of those above. If you wish to allow use of your version of this file only
35 under the terms of either the GPL or the LGPL, and not to allow others to
36 use your version of this file under the terms of the MPL, indicate your
37 decision by deleting the provisions above and replace them with the notice
38 and other provisions required by the GPL or the LGPL. If you do not delete
39 the provisions above, a recipient may use your version of this file under
40 the terms of any one of the MPL, the GPL or the LGPL.
41
42 */
43
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <float.h>
48
49 #include "rasterlite2/sqlite.h"
50
51 #include "config.h"
52
53 #include "rasterlite2/rasterlite2.h"
54 #include "rasterlite2/rl2tiff.h"
55 #include "rasterlite2_private.h"
56
57 static int
parse_ncols(const char * str,unsigned int * width)58 parse_ncols (const char *str, unsigned int *width)
59 {
60 /* attempting to parse the NCOLS item */
61 if (strncasecmp (str, "ncols ", 6) == 0)
62 {
63 *width = atoi (str + 6);
64 return 1;
65 }
66 return 0;
67 }
68
69 static int
parse_nrows(const char * str,unsigned int * height)70 parse_nrows (const char *str, unsigned int *height)
71 {
72 /* attempting to parse the NROWS item */
73 if (strncasecmp (str, "nrows ", 6) == 0)
74 {
75 *height = atoi (str + 6);
76 return 1;
77 }
78 return 0;
79 }
80
81 static int
parse_xllcorner(const char * str,double * minx)82 parse_xllcorner (const char *str, double *minx)
83 {
84 /* attempting to parse the XLLCORNER item */
85 if (strncasecmp (str, "xllcorner ", 10) == 0)
86 {
87 *minx = atof (str + 10);
88 return 1;
89 }
90 return 0;
91 }
92
93 static int
parse_yllcorner(const char * str,double * miny)94 parse_yllcorner (const char *str, double *miny)
95 {
96 /* attempting to parse the YLLCORNER item */
97 if (strncasecmp (str, "yllcorner ", 10) == 0)
98 {
99 *miny = atof (str + 10);
100 return 1;
101 }
102 return 0;
103 }
104
105 static int
parse_xllcenter(const char * str,double * minx)106 parse_xllcenter (const char *str, double *minx)
107 {
108 /* attempting to parse the XLLCENTER item */
109 if (strncasecmp (str, "xllcenter ", 10) == 0)
110 {
111 *minx = atof (str + 10);
112 return 1;
113 }
114 return 0;
115 }
116
117 static int
parse_yllcenter(const char * str,double * miny)118 parse_yllcenter (const char *str, double *miny)
119 {
120 /* attempting to parse the YLLCENTER item */
121 if (strncasecmp (str, "yllcenter ", 10) == 0)
122 {
123 *miny = atof (str + 10);
124 return 1;
125 }
126 return 0;
127 }
128
129 static int
parse_cellsize(const char * str,double * xres)130 parse_cellsize (const char *str, double *xres)
131 {
132 /* attempting to parse the CELLSIZE item */
133 if (strncasecmp (str, "cellsize ", 9) == 0)
134 {
135 *xres = atof (str + 9);
136 return 1;
137 }
138 return 0;
139 }
140
141 static int
parse_nodata(const char * str,double * no_data)142 parse_nodata (const char *str, double *no_data)
143 {
144 /* attempting to parse the NODATA_value item */
145 if (strncasecmp (str, "NODATA_value ", 13) == 0)
146 {
147 *no_data = atof (str + 13);
148 return 1;
149 }
150 return 0;
151 }
152
153 static int
get_ascii_header(FILE * in,unsigned int * width,unsigned int * height,double * minx,double * miny,double * maxx,double * maxy,double * xres,double * yres,double * no_data)154 get_ascii_header (FILE * in, unsigned int *width, unsigned int *height,
155 double *minx, double *miny, double *maxx, double *maxy,
156 double *xres, double *yres, double *no_data)
157 {
158 /* attempting to parse the ASCII Header */
159 char buf[1024];
160 char *p_out = buf;
161 int line_no = 0;
162 int c;
163 int ok_ncols = 0;
164 int ok_nrows = 0;
165 int ok_xll = 0;
166 int ok_yll = 0;
167 int ok_cellsize = 0;
168 int ok_nodata = 0;
169
170 while ((c = getc (in)) != EOF)
171 {
172 if (c == '\r')
173 continue;
174 if (c == '\n')
175 {
176 *p_out = '\0';
177 if (parse_ncols (buf, width))
178 ok_ncols++;
179 if (parse_nrows (buf, height))
180 ok_nrows++;
181 if (parse_xllcorner (buf, minx))
182 ok_xll++;
183 if (parse_xllcenter (buf, minx))
184 ok_xll++;
185 if (parse_yllcorner (buf, miny))
186 ok_yll++;
187 if (parse_yllcenter (buf, miny))
188 ok_yll++;
189 if (parse_cellsize (buf, xres))
190 ok_cellsize++;
191 if (parse_nodata (buf, no_data))
192 ok_nodata++;
193 line_no++;
194 if (line_no == 6)
195 break;
196 p_out = buf;
197 continue;
198 }
199 if ((p_out - buf) >= 1024)
200 goto error;
201 *p_out++ = c;
202 }
203 if (ok_ncols == 1 && ok_nrows == 1 && ok_xll == 1 && ok_yll == 1
204 && ok_cellsize == 1 && ok_nodata == 1)
205 ;
206 else
207 goto error;
208
209 *maxx = *minx + ((double) (*width) * *xres);
210 *yres = *xres;
211 *maxy = *miny + ((double) (*height) * *yres);
212 return 1;
213
214 error:
215 *width = 0;
216 *height = 0;
217 *minx = DBL_MAX;
218 *miny = DBL_MAX;
219 *maxx = 0.0 - DBL_MAX;
220 *maxy = 0.0 - DBL_MAX;
221 *xres = 0.0;
222 *yres = 0.0;
223 *no_data = DBL_MAX;
224 return 0;
225 }
226
227 static rl2PrivAsciiOriginPtr
alloc_ascii_origin(const char * path,int srid,unsigned char sample_type,unsigned short width,unsigned short height,double minx,double miny,double maxx,double maxy,double xres,double yres,double no_data)228 alloc_ascii_origin (const char *path, int srid, unsigned char sample_type,
229 unsigned short width, unsigned short height, double minx,
230 double miny, double maxx, double maxy, double xres,
231 double yres, double no_data)
232 {
233 /* allocating and initializing an ASCII Grid origin */
234 int len;
235 rl2PrivAsciiOriginPtr ascii = malloc (sizeof (rl2PrivAsciiOrigin));
236 if (ascii == NULL)
237 return NULL;
238 len = strlen (path);
239 ascii->path = malloc (len + 1);
240 strcpy (ascii->path, path);
241 ascii->tmp = NULL;
242 ascii->width = width;
243 ascii->height = height;
244 ascii->Srid = srid;
245 ascii->hResolution = xres;
246 ascii->vResolution = yres;
247 ascii->minX = minx;
248 ascii->minY = miny;
249 ascii->maxX = maxx;
250 ascii->maxY = maxy;
251 ascii->sample_type = sample_type;
252 ascii->noData = no_data;
253 return ascii;
254 }
255
256 RL2_DECLARE rl2AsciiGridOriginPtr
rl2_create_ascii_grid_origin(const char * path,int srid,unsigned char sample_type)257 rl2_create_ascii_grid_origin (const char *path, int srid,
258 unsigned char sample_type)
259 {
260 /* creating an ASCII Grid Origin */
261 FILE *in;
262 unsigned int width;
263 unsigned int height;
264 double minx;
265 double miny;
266 double maxx;
267 double maxy;
268 double xres;
269 double yres;
270 double no_data;
271 char buf[1024];
272 char *p_out = buf;
273 unsigned int line_no = 0;
274 unsigned int col_no = 0;
275 int new_line = 1;
276 int c;
277 rl2PrivAsciiOriginPtr ascii = NULL;
278 void *scanline = NULL;
279 char *p_int8;
280 unsigned char *p_uint8;
281 short *p_int16;
282 unsigned short *p_uint16;
283 int *p_int32;
284 unsigned int *p_uint32;
285 float *p_float;
286 double *p_double;
287 int sz;
288
289 if (path == NULL)
290 return NULL;
291 if (srid <= 0)
292 return NULL;
293 switch (sample_type)
294 {
295 case RL2_SAMPLE_INT8:
296 case RL2_SAMPLE_UINT8:
297 case RL2_SAMPLE_INT16:
298 case RL2_SAMPLE_UINT16:
299 case RL2_SAMPLE_INT32:
300 case RL2_SAMPLE_UINT32:
301 case RL2_SAMPLE_FLOAT:
302 case RL2_SAMPLE_DOUBLE:
303 break;
304 default:
305 return NULL;
306 };
307
308 in = fopen (path, "r");
309 if (in == NULL)
310 {
311 fprintf (stderr, "ASCII Origin: Unable to open %s\n", path);
312 return NULL;
313 }
314 if (!get_ascii_header
315 (in, &width, &height, &minx, &miny, &maxx, &maxy, &xres, &yres,
316 &no_data))
317 {
318 fprintf (stderr, "ASCII Origin: invalid Header found on %s\n", path);
319 goto error;
320 }
321
322 ascii =
323 alloc_ascii_origin (path, srid, sample_type, width, height, minx, miny,
324 maxx, maxy, xres, yres, no_data);
325 if (ascii == NULL)
326 goto error;
327
328 *buf = '\0';
329 col_no = width;
330 /* creating the helper Temporary File */
331 ascii->tmp = tmpfile ();
332 if (ascii->tmp == NULL)
333 goto error;
334 switch (sample_type)
335 {
336 case RL2_SAMPLE_INT8:
337 case RL2_SAMPLE_UINT8:
338 sz = ascii->width;
339 break;
340 case RL2_SAMPLE_INT16:
341 case RL2_SAMPLE_UINT16:
342 sz = ascii->width * 2;
343 break;
344 case RL2_SAMPLE_INT32:
345 case RL2_SAMPLE_UINT32:
346 case RL2_SAMPLE_FLOAT:
347 sz = ascii->width * 4;
348 break;
349 case RL2_SAMPLE_DOUBLE:
350 sz = ascii->width * 8;
351 break;
352 };
353 scanline = malloc (sz);
354 if (scanline == NULL)
355 goto error;
356
357 while ((c = getc (in)) != EOF)
358 {
359 if (c == '\r')
360 continue;
361 if (c == ' ' || c == '\n')
362 {
363 *p_out = '\0';
364 if (*buf != '\0')
365 {
366 char int8_value;
367 unsigned char uint8_value;
368 short int16_value;
369 unsigned short uint16_value;
370 int int32_value;
371 unsigned int uint32_value;
372 float flt_value;
373 double dbl_value = atof (buf);
374 if (new_line)
375 {
376 if (col_no != width)
377 goto error;
378 line_no++;
379 new_line = 0;
380 col_no = 0;
381 switch (sample_type)
382 {
383 case RL2_SAMPLE_INT8:
384 p_int8 = scanline;
385 break;
386 case RL2_SAMPLE_UINT8:
387 p_uint8 = scanline;
388 break;
389 case RL2_SAMPLE_INT16:
390 p_int16 = scanline;
391 break;
392 case RL2_SAMPLE_UINT16:
393 p_uint16 = scanline;
394 break;
395 case RL2_SAMPLE_INT32:
396 p_int32 = scanline;
397 break;
398 case RL2_SAMPLE_UINT32:
399 p_uint32 = scanline;
400 break;
401 case RL2_SAMPLE_FLOAT:
402 p_float = scanline;
403 break;
404 case RL2_SAMPLE_DOUBLE:
405 p_double = scanline;
406 break;
407 };
408 }
409 switch (sample_type)
410 {
411 case RL2_SAMPLE_INT8:
412 int8_value = truncate_8 (dbl_value);
413 *p_int8++ = int8_value;
414 break;
415 case RL2_SAMPLE_UINT8:
416 uint8_value = truncate_u8 (dbl_value);
417 *p_uint8++ = uint8_value;
418 break;
419 case RL2_SAMPLE_INT16:
420 int16_value = truncate_16 (dbl_value);
421 *p_int16++ = int16_value;
422 break;
423 case RL2_SAMPLE_UINT16:
424 uint16_value = truncate_u16 (dbl_value);
425 *p_uint16++ = uint16_value;
426 break;
427 case RL2_SAMPLE_INT32:
428 int32_value = truncate_32 (dbl_value);
429 *p_int32++ = int32_value;
430 break;
431 case RL2_SAMPLE_UINT32:
432 uint32_value = truncate_u32 (dbl_value);
433 *p_uint32++ = uint32_value;
434 break;
435 case RL2_SAMPLE_FLOAT:
436 flt_value = (float) dbl_value;
437 *p_float++ = flt_value;
438 break;
439 case RL2_SAMPLE_DOUBLE:
440 *p_double++ = dbl_value;
441 break;
442 };
443 col_no++;
444 if (col_no == ascii->width)
445 fwrite (scanline, sz, 1, ascii->tmp);
446 }
447 p_out = buf;
448 if (c == '\n')
449 new_line = 1;
450 continue;
451 }
452
453 if ((p_out - buf) >= 1024)
454 goto error;
455 *p_out++ = c;
456 }
457 if (line_no != height)
458 goto error;
459
460 fclose (in);
461 free (scanline);
462 return (rl2AsciiGridOriginPtr) ascii;
463
464 error:
465 if (scanline != NULL)
466 free (scanline);
467 if (ascii != NULL)
468 rl2_destroy_ascii_grid_origin ((rl2AsciiGridOriginPtr) ascii);
469 if (in != NULL)
470 fclose (in);
471 return NULL;
472 }
473
474 RL2_DECLARE void
rl2_destroy_ascii_grid_origin(rl2AsciiGridOriginPtr ascii)475 rl2_destroy_ascii_grid_origin (rl2AsciiGridOriginPtr ascii)
476 {
477 /* memory cleanup - destroying an ASCII Grid Origin object */
478 rl2PrivAsciiOriginPtr org = (rl2PrivAsciiOriginPtr) ascii;
479 if (org == NULL)
480 return;
481 if (org->path != NULL)
482 free (org->path);
483 if (org->tmp != NULL)
484 fclose (org->tmp);
485 free (org);
486 }
487
488 RL2_DECLARE const char *
rl2_get_ascii_grid_origin_path(rl2AsciiGridOriginPtr ascii)489 rl2_get_ascii_grid_origin_path (rl2AsciiGridOriginPtr ascii)
490 {
491 /* retrieving the input path from an ASCII Grid origin */
492 rl2PrivAsciiOriginPtr origin = (rl2PrivAsciiOriginPtr) ascii;
493 if (origin == NULL)
494 return NULL;
495
496 return origin->path;
497 }
498
499 RL2_DECLARE int
rl2_get_ascii_grid_origin_size(rl2AsciiGridOriginPtr ascii,unsigned int * width,unsigned int * height)500 rl2_get_ascii_grid_origin_size (rl2AsciiGridOriginPtr ascii,
501 unsigned int *width, unsigned int *height)
502 {
503 /* retrieving Width and Height from an ASCII Grid origin */
504 rl2PrivAsciiOriginPtr origin = (rl2PrivAsciiOriginPtr) ascii;
505 if (origin == NULL)
506 return RL2_ERROR;
507
508 *width = origin->width;
509 *height = origin->height;
510 return RL2_OK;
511 }
512
513 RL2_DECLARE int
rl2_get_ascii_grid_origin_srid(rl2AsciiGridOriginPtr ascii,int * srid)514 rl2_get_ascii_grid_origin_srid (rl2AsciiGridOriginPtr ascii, int *srid)
515 {
516 /* retrieving the SRID from an ASCII Grid origin */
517 rl2PrivAsciiOriginPtr origin = (rl2PrivAsciiOriginPtr) ascii;
518 if (origin == NULL)
519 return RL2_ERROR;
520
521 *srid = origin->Srid;
522 return RL2_OK;
523 }
524
525 RL2_DECLARE int
rl2_get_ascii_grid_origin_extent(rl2AsciiGridOriginPtr ascii,double * minX,double * minY,double * maxX,double * maxY)526 rl2_get_ascii_grid_origin_extent (rl2AsciiGridOriginPtr ascii, double *minX,
527 double *minY, double *maxX, double *maxY)
528 {
529 /* retrieving the Extent from an ASCII Grid origin */
530 rl2PrivAsciiOriginPtr origin = (rl2PrivAsciiOriginPtr) ascii;
531 if (origin == NULL)
532 return RL2_ERROR;
533
534 *minX = origin->minX;
535 *minY = origin->minY;
536 *maxX = origin->maxX;
537 *maxY = origin->maxY;
538 return RL2_OK;
539 }
540
541 RL2_DECLARE int
rl2_get_ascii_grid_origin_resolution(rl2AsciiGridOriginPtr ascii,double * hResolution,double * vResolution)542 rl2_get_ascii_grid_origin_resolution (rl2AsciiGridOriginPtr ascii,
543 double *hResolution, double *vResolution)
544 {
545 /* retrieving the Pixel Resolution from an ASCII Grid origin */
546 rl2PrivAsciiOriginPtr origin = (rl2PrivAsciiOriginPtr) ascii;
547 if (origin == NULL)
548 return RL2_ERROR;
549
550 *hResolution = origin->hResolution;
551 *vResolution = origin->vResolution;
552 return RL2_OK;
553 }
554
555 RL2_DECLARE int
rl2_get_ascii_grid_origin_type(rl2AsciiGridOriginPtr ascii,unsigned char * sample_type,unsigned char * pixel_type,unsigned char * num_bands)556 rl2_get_ascii_grid_origin_type (rl2AsciiGridOriginPtr ascii,
557 unsigned char *sample_type,
558 unsigned char *pixel_type,
559 unsigned char *num_bands)
560 {
561 /* retrieving the sample/pixel type from an ASCII Grid origin */
562 rl2PrivAsciiOriginPtr origin = (rl2PrivAsciiOriginPtr) ascii;
563 if (origin == NULL)
564 return RL2_ERROR;
565
566 *sample_type = origin->sample_type;
567 *pixel_type = RL2_PIXEL_DATAGRID;
568 *num_bands = 1;
569 return RL2_OK;
570 }
571
572 RL2_DECLARE int
rl2_eval_ascii_grid_origin_compatibility(rl2CoveragePtr cvg,rl2AsciiGridOriginPtr ascii)573 rl2_eval_ascii_grid_origin_compatibility (rl2CoveragePtr cvg,
574 rl2AsciiGridOriginPtr ascii)
575 {
576 /* testing if a Coverage and an ASCII Grid origin are mutually compatible */
577 unsigned char sample_type;
578 unsigned char pixel_type;
579 unsigned char num_bands;
580 int srid;
581 double hResolution;
582 double vResolution;
583 double confidence;
584 rl2PrivCoveragePtr coverage = (rl2PrivCoveragePtr) cvg;
585
586 if (coverage == NULL || ascii == NULL)
587 return RL2_ERROR;
588 if (rl2_get_ascii_grid_origin_type
589 (ascii, &sample_type, &pixel_type, &num_bands) != RL2_OK)
590 return RL2_ERROR;
591
592 if (coverage->sampleType != sample_type)
593 return RL2_FALSE;
594 if (coverage->pixelType != pixel_type)
595 return RL2_FALSE;
596 if (coverage->nBands != num_bands)
597 return RL2_FALSE;
598
599 /* checking for resolution compatibility */
600 if (rl2_get_ascii_grid_origin_srid (ascii, &srid) != RL2_OK)
601 return RL2_FALSE;
602 if (coverage->Srid != srid)
603 return RL2_FALSE;
604 if (rl2_get_ascii_grid_origin_resolution (ascii, &hResolution, &vResolution)
605 != RL2_OK)
606 return RL2_FALSE;
607 confidence = coverage->hResolution / 100.0;
608 if (hResolution < (coverage->hResolution - confidence)
609 || hResolution > (coverage->hResolution + confidence))
610 return RL2_FALSE;
611 confidence = coverage->vResolution / 100.0;
612 if (vResolution < (coverage->vResolution - confidence)
613 || vResolution > (coverage->vResolution + confidence))
614 return RL2_FALSE;
615 return RL2_TRUE;
616 }
617
618 static int
read_ascii_int8(rl2PrivAsciiOriginPtr origin,unsigned int width,unsigned int height,unsigned int startRow,unsigned int startCol,char * pixels)619 read_ascii_int8 (rl2PrivAsciiOriginPtr origin, unsigned int width,
620 unsigned int height, unsigned int startRow,
621 unsigned int startCol, char *pixels)
622 {
623 /* reading from the Temporary helper file - INT8 */
624 unsigned int x;
625 unsigned int y;
626 unsigned int row;
627 unsigned int col;
628 for (y = 0, row = startRow; y < height && row < origin->height; y++, row++)
629 {
630 /* looping on rows */
631 long offset = (row * origin->width) + startCol;
632 char *p_out = pixels + (y * width);
633 if (fseek (origin->tmp, offset, SEEK_SET) != 0)
634 return 0;
635 for (x = 0, col = startCol; x < width && col < origin->width;
636 x++, col++)
637 {
638 char int8;
639 if (fread (&int8, sizeof (char), 1, origin->tmp) <= 0)
640 return 0;
641 *p_out++ = int8;
642 }
643 }
644 return 1;
645 }
646
647 static int
read_ascii_uint8(rl2PrivAsciiOriginPtr origin,unsigned int width,unsigned int height,unsigned int startRow,unsigned int startCol,unsigned char * pixels)648 read_ascii_uint8 (rl2PrivAsciiOriginPtr origin, unsigned int width,
649 unsigned int height, unsigned int startRow,
650 unsigned int startCol, unsigned char *pixels)
651 {
652 /* reading from the Temporary helper file - UINT8 */
653 unsigned int x;
654 unsigned int y;
655 unsigned int row;
656 unsigned int col;
657 for (y = 0, row = startRow; y < height && row < origin->height; y++, row++)
658 {
659 /* looping on rows */
660 long offset = (row * origin->width) + startCol;
661 unsigned char *p_out = pixels + (y * width);
662 if (fseek (origin->tmp, offset, SEEK_SET) != 0)
663 return 0;
664 for (x = 0, col = startCol; x < width && col < origin->width;
665 x++, col++)
666 {
667 unsigned char uint8;
668 if (fread (&uint8, sizeof (unsigned char), 1, origin->tmp) <= 0)
669 return 0;
670 *p_out++ = uint8;
671 }
672 }
673 return 1;
674 }
675
676 static int
read_ascii_int16(rl2PrivAsciiOriginPtr origin,unsigned int width,unsigned int height,unsigned int startRow,unsigned int startCol,short * pixels)677 read_ascii_int16 (rl2PrivAsciiOriginPtr origin, unsigned int width,
678 unsigned int height, unsigned int startRow,
679 unsigned int startCol, short *pixels)
680 {
681 /* reading from the Temporary helper file - INT16 */
682 unsigned int x;
683 unsigned int y;
684 unsigned int row;
685 unsigned int col;
686 for (y = 0, row = startRow; y < height && row < origin->height; y++, row++)
687 {
688 /* looping on rows */
689 long offset =
690 (row * origin->width * sizeof (short)) +
691 (startCol * sizeof (short));
692 short *p_out = pixels + (y * width);
693 if (fseek (origin->tmp, offset, SEEK_SET) < 0)
694 return 0;
695 for (x = 0, col = startCol; x < width && col < origin->width;
696 x++, col++)
697 {
698 short int16;
699 if (fread (&int16, sizeof (short), 1, origin->tmp) <= 0)
700 return 0;
701 *p_out++ = int16;
702 }
703 }
704 return 1;
705 }
706
707 static int
read_ascii_uint16(rl2PrivAsciiOriginPtr origin,unsigned int width,unsigned int height,unsigned int startRow,unsigned int startCol,unsigned short * pixels)708 read_ascii_uint16 (rl2PrivAsciiOriginPtr origin, unsigned int width,
709 unsigned int height, unsigned int startRow,
710 unsigned int startCol, unsigned short *pixels)
711 {
712 /* reading from the Temporary helper file - UINT16 */
713 unsigned int x;
714 unsigned int y;
715 unsigned int row;
716 unsigned int col;
717 for (y = 0, row = startRow; y < height && row < origin->height; y++, row++)
718 {
719 /* looping on rows */
720 long offset =
721 (row * origin->width * sizeof (unsigned short)) +
722 (startCol * sizeof (unsigned short));
723 unsigned short *p_out = pixels + (y * width);
724 if (fseek (origin->tmp, offset, SEEK_SET) != 0)
725 return 0;
726 for (x = 0, col = startCol; x < width && col < origin->width;
727 x++, col++)
728 {
729 unsigned short uint16;
730 if (fread (&uint16, sizeof (unsigned short), 1, origin->tmp) <=
731 0)
732 return 0;
733 *p_out++ = uint16;
734 }
735 }
736 return 1;
737 }
738
739 static int
read_ascii_int32(rl2PrivAsciiOriginPtr origin,unsigned int width,unsigned int height,unsigned int startRow,unsigned int startCol,int * pixels)740 read_ascii_int32 (rl2PrivAsciiOriginPtr origin, unsigned int width,
741 unsigned int height, unsigned int startRow,
742 unsigned int startCol, int *pixels)
743 {
744 /* reading from the Temporary helper file - INT32 */
745 unsigned int x;
746 unsigned int y;
747 unsigned int row;
748 unsigned int col;
749 for (y = 0, row = startRow; y < height && row < origin->height; y++, row++)
750 {
751 /* looping on rows */
752 long offset =
753 (row * origin->width * sizeof (int)) + (startCol * sizeof (int));
754 int *p_out = pixels + (y * width);
755 if (fseek (origin->tmp, offset, SEEK_SET) != 0)
756 return 0;
757 for (x = 0, col = startCol; x < width && col < origin->width;
758 x++, col++)
759 {
760 int int32;
761 if (fread (&int32, sizeof (int), 1, origin->tmp) <= 0)
762 return 0;
763 *p_out++ = int32;
764 }
765 }
766 return 1;
767 }
768
769 static int
read_ascii_uint32(rl2PrivAsciiOriginPtr origin,unsigned int width,unsigned int height,unsigned int startRow,unsigned int startCol,unsigned int * pixels)770 read_ascii_uint32 (rl2PrivAsciiOriginPtr origin, unsigned int width,
771 unsigned int height, unsigned int startRow,
772 unsigned int startCol, unsigned int *pixels)
773 {
774 /* reading from the Temporary helper file - UINT32 */
775 unsigned int x;
776 unsigned int y;
777 unsigned int row;
778 unsigned int col;
779 for (y = 0, row = startRow; y < height && row < origin->height; y++, row++)
780 {
781 /* looping on rows */
782 long offset =
783 (row * origin->width * sizeof (unsigned int)) +
784 (startCol * sizeof (unsigned int));
785 unsigned int *p_out = pixels + (y * width);
786 if (fseek (origin->tmp, offset, SEEK_SET) != 0)
787 return 0;
788 for (x = 0, col = startCol; x < width && col < origin->width;
789 x++, col++)
790 {
791 unsigned int uint32;
792 if (fread (&uint32, sizeof (unsigned int), 1, origin->tmp) <= 0)
793 return 0;
794 *p_out++ = uint32;
795 }
796 }
797 return 1;
798 }
799
800 static int
read_ascii_float(rl2PrivAsciiOriginPtr origin,unsigned int width,unsigned int height,unsigned int startRow,unsigned int startCol,float * pixels)801 read_ascii_float (rl2PrivAsciiOriginPtr origin, unsigned int width,
802 unsigned int height, unsigned int startRow,
803 unsigned int startCol, float *pixels)
804 {
805 /* reading from the Temporary helper file - FLOAT */
806 unsigned int x;
807 unsigned int y;
808 unsigned int row;
809 unsigned int col;
810 for (y = 0, row = startRow; y < height && row < origin->height; y++, row++)
811 {
812 /* looping on rows */
813 long offset =
814 (row * origin->width * sizeof (float)) +
815 (startCol * sizeof (float));
816 float *p_out = pixels + (y * width);
817 if (fseek (origin->tmp, offset, SEEK_SET) != 0)
818 return 0;
819 for (x = 0, col = startCol; x < width && col < origin->width;
820 x++, col++)
821 {
822 float flt;
823 if (fread (&flt, sizeof (float), 1, origin->tmp) <= 0)
824 return 0;
825 *p_out++ = flt;
826 }
827 }
828 return 1;
829 }
830
831 static int
read_ascii_double(rl2PrivAsciiOriginPtr origin,unsigned int width,unsigned int height,unsigned int startRow,unsigned int startCol,double * pixels)832 read_ascii_double (rl2PrivAsciiOriginPtr origin, unsigned int width,
833 unsigned int height, unsigned int startRow,
834 unsigned int startCol, double *pixels)
835 {
836 /* reading from the Temporary helper file - DOUBLE */
837 unsigned int x;
838 unsigned int y;
839 unsigned int row;
840 unsigned int col;
841 for (y = 0, row = startRow; y < height && row < origin->height; y++, row++)
842 {
843 /* looping on rows */
844 long offset =
845 (row * origin->width * sizeof (double)) +
846 (startCol * sizeof (double));
847 double *p_out = pixels + (y * width);
848 if (fseek (origin->tmp, offset, SEEK_SET) != 0)
849 return 0;
850 for (x = 0, col = startCol; x < width && col < origin->width;
851 x++, col++)
852 {
853 double dbl;
854 if (fread (&dbl, sizeof (double), 1, origin->tmp) <= 0)
855 return 0;
856 *p_out++ = dbl;
857 }
858 }
859 return 1;
860 }
861
862 static int
read_ascii_pixels(rl2PrivAsciiOriginPtr origin,unsigned short width,unsigned short height,unsigned char sample_type,unsigned int startRow,unsigned int startCol,void * pixels)863 read_ascii_pixels (rl2PrivAsciiOriginPtr origin, unsigned short width,
864 unsigned short height, unsigned char sample_type,
865 unsigned int startRow, unsigned int startCol, void *pixels)
866 {
867 /* reading from the Temporary helper file */
868 switch (sample_type)
869 {
870 case RL2_SAMPLE_INT8:
871 return read_ascii_int8 (origin, width, height, startRow, startCol,
872 (char *) pixels);
873 case RL2_SAMPLE_UINT8:
874 return read_ascii_uint8 (origin, width, height, startRow, startCol,
875 (unsigned char *) pixels);
876 case RL2_SAMPLE_INT16:
877 return read_ascii_int16 (origin, width, height, startRow, startCol,
878 (short *) pixels);
879 case RL2_SAMPLE_UINT16:
880 return read_ascii_uint16 (origin, width, height, startRow, startCol,
881 (unsigned short *) pixels);
882 case RL2_SAMPLE_INT32:
883 return read_ascii_int32 (origin, width, height, startRow, startCol,
884 (int *) pixels);
885 case RL2_SAMPLE_UINT32:
886 return read_ascii_uint32 (origin, width, height, startRow, startCol,
887 (unsigned int *) pixels);
888 case RL2_SAMPLE_FLOAT:
889 return read_ascii_float (origin, width, height, startRow, startCol,
890 (float *) pixels);
891 case RL2_SAMPLE_DOUBLE:
892 return read_ascii_double (origin, width, height, startRow, startCol,
893 (double *) pixels);
894 };
895 return 0;
896 }
897
898 static int
read_from_ascii(rl2PrivAsciiOriginPtr origin,unsigned short width,unsigned short height,unsigned char sample_type,unsigned int startRow,unsigned int startCol,unsigned char ** pixels,int * pixels_sz)899 read_from_ascii (rl2PrivAsciiOriginPtr origin, unsigned short width,
900 unsigned short height, unsigned char sample_type,
901 unsigned int startRow, unsigned int startCol,
902 unsigned char **pixels, int *pixels_sz)
903 {
904 /* creating a tile from the ASCII Grid origin */
905 unsigned char *bufPixels = NULL;
906 int bufPixelsSz = 0;
907 int pix_sz = 1;
908 rl2PixelPtr no_data = NULL;
909
910 no_data = rl2_create_pixel (sample_type, RL2_PIXEL_DATAGRID, 1);
911
912 /* allocating the pixels buffer */
913 switch (sample_type)
914 {
915 case RL2_SAMPLE_INT8:
916 pix_sz = 1;
917 rl2_set_pixel_sample_int8 (no_data, (char) (origin->noData));
918 break;
919 case RL2_SAMPLE_UINT8:
920 pix_sz = 1;
921 rl2_set_pixel_sample_uint8 (no_data, 0,
922 (unsigned char) (origin->noData));
923 break;
924 case RL2_SAMPLE_INT16:
925 rl2_set_pixel_sample_int16 (no_data, (short) (origin->noData));
926 pix_sz = 2;
927 break;
928 case RL2_SAMPLE_UINT16:
929 rl2_set_pixel_sample_uint16 (no_data, 0,
930 (unsigned short) (origin->noData));
931 pix_sz = 2;
932 break;
933 case RL2_SAMPLE_INT32:
934 pix_sz = 4;
935 rl2_set_pixel_sample_int32 (no_data, (int) (origin->noData));
936 break;
937 case RL2_SAMPLE_UINT32:
938 pix_sz = 4;
939 rl2_set_pixel_sample_uint32 (no_data,
940 (unsigned int) (origin->noData));
941 break;
942 case RL2_SAMPLE_FLOAT:
943 pix_sz = 4;
944 rl2_set_pixel_sample_float (no_data, (float) (origin->noData));
945 break;
946 case RL2_SAMPLE_DOUBLE:
947 pix_sz = 8;
948 rl2_set_pixel_sample_double (no_data, (double) (origin->noData));
949 break;
950 };
951 bufPixelsSz = width * height * pix_sz;
952 bufPixels = malloc (bufPixelsSz);
953 if (bufPixels == NULL)
954 goto error;
955 if ((startRow + height) > origin->height
956 || (startCol + width) > origin->width)
957 rl2_prime_void_tile (bufPixels, width, height, sample_type, 1, no_data);
958
959 if (!read_ascii_pixels
960 (origin, width, height, sample_type, startRow, startCol, bufPixels))
961 goto error;
962
963 rl2_destroy_pixel (no_data);
964 *pixels = bufPixels;
965 *pixels_sz = bufPixelsSz;
966 return RL2_OK;
967 error:
968 if (bufPixels != NULL)
969 free (bufPixels);
970 if (no_data != NULL)
971 rl2_destroy_pixel (no_data);
972 return RL2_ERROR;
973 }
974
975 RL2_DECLARE rl2RasterPtr
rl2_get_tile_from_ascii_grid_origin(rl2CoveragePtr cvg,rl2AsciiGridOriginPtr ascii,unsigned int startRow,unsigned int startCol)976 rl2_get_tile_from_ascii_grid_origin (rl2CoveragePtr cvg,
977 rl2AsciiGridOriginPtr ascii,
978 unsigned int startRow,
979 unsigned int startCol)
980 {
981 /* attempting to create a Coverage-tile from an ASCII Grid origin */
982 unsigned int x;
983 rl2PrivCoveragePtr coverage = (rl2PrivCoveragePtr) cvg;
984 rl2PrivAsciiOriginPtr origin = (rl2PrivAsciiOriginPtr) ascii;
985 rl2RasterPtr raster = NULL;
986 unsigned char *pixels = NULL;
987 int pixels_sz = 0;
988 unsigned char *mask = NULL;
989 int mask_size = 0;
990 unsigned int unused_width = 0;
991 unsigned int unused_height = 0;
992
993 if (coverage == NULL || origin == NULL)
994 return NULL;
995 if (rl2_eval_ascii_grid_origin_compatibility (cvg, ascii) != RL2_TRUE)
996 return NULL;
997 if (origin->tmp == NULL)
998 return NULL;
999
1000 /* testing for tile's boundary validity */
1001 if (startCol > origin->width)
1002 return NULL;
1003 if (startRow > origin->height)
1004 return NULL;
1005 x = startCol / coverage->tileWidth;
1006 if ((x * coverage->tileWidth) != startCol)
1007 return NULL;
1008 x = startRow / coverage->tileHeight;
1009 if ((x * coverage->tileHeight) != startRow)
1010 return NULL;
1011
1012 /* attempting to create the tile */
1013 if (read_from_ascii
1014 (origin, coverage->tileWidth, coverage->tileHeight,
1015 coverage->sampleType, startRow, startCol, &pixels,
1016 &pixels_sz) != RL2_OK)
1017 goto error;
1018 if (startCol + coverage->tileWidth > origin->width)
1019 unused_width = (startCol + coverage->tileWidth) - origin->width;
1020 if (startRow + coverage->tileHeight > origin->height)
1021 unused_height = (startRow + coverage->tileHeight) - origin->height;
1022 if (unused_width || unused_height)
1023 {
1024 /*
1025 * creating a Transparency Mask so to shadow any
1026 * unused portion of the current tile
1027 */
1028 unsigned int shadow_x = coverage->tileWidth - unused_width;
1029 unsigned int shadow_y = coverage->tileHeight - unused_height;
1030 unsigned int row;
1031 mask_size = coverage->tileWidth * coverage->tileHeight;
1032 mask = malloc (mask_size);
1033 if (mask == NULL)
1034 goto error;
1035 /* full Transparent mask */
1036 memset (mask, 0, coverage->tileWidth * coverage->tileHeight);
1037 for (row = 0; row < coverage->tileHeight; row++)
1038 {
1039 unsigned char *p = mask + (row * coverage->tileWidth);
1040 if (row < shadow_y)
1041 {
1042 /* setting opaque pixels */
1043 memset (p, 1, shadow_x);
1044 }
1045 }
1046 }
1047 raster =
1048 rl2_create_raster (coverage->tileWidth, coverage->tileHeight,
1049 coverage->sampleType, RL2_PIXEL_DATAGRID, 1, pixels,
1050 pixels_sz, NULL, mask, mask_size, NULL);
1051 if (raster == NULL)
1052 goto error;
1053 return raster;
1054 error:
1055 if (pixels != NULL)
1056 free (pixels);
1057 if (mask != NULL)
1058 free (mask);
1059 return NULL;
1060 }
1061
1062 static rl2PrivAsciiDestinationPtr
alloc_ascii_destination(const char * path,unsigned int width,unsigned int height,double x,double y,double res,int is_centered,double no_data,int decimal_digits)1063 alloc_ascii_destination (const char *path, unsigned int width,
1064 unsigned int height, double x, double y,
1065 double res, int is_centered, double no_data,
1066 int decimal_digits)
1067 {
1068 /* allocating and initializing an ASCII Grid detination */
1069 int len;
1070 rl2PrivAsciiDestinationPtr ascii =
1071 malloc (sizeof (rl2PrivAsciiDestination));
1072 if (ascii == NULL)
1073 return NULL;
1074 len = strlen (path);
1075 ascii->path = malloc (len + 1);
1076 strcpy (ascii->path, path);
1077 ascii->out = NULL;
1078 ascii->width = width;
1079 ascii->height = height;
1080 ascii->Resolution = res;
1081 ascii->X = x;
1082 ascii->Y = y;
1083 ascii->isCentered = is_centered;
1084 ascii->noData = no_data;
1085 if (decimal_digits < 0)
1086 ascii->decimalDigits = 0;
1087 else if (decimal_digits > 18)
1088 ascii->decimalDigits = 18;
1089 else
1090 ascii->decimalDigits = decimal_digits;
1091 ascii->headerDone = 'N';
1092 ascii->nextLineNo = 0;
1093 ascii->pixels = NULL;
1094 ascii->sampleType = RL2_SAMPLE_UNKNOWN;
1095 return ascii;
1096 }
1097
1098 RL2_DECLARE rl2AsciiGridDestinationPtr
rl2_create_ascii_grid_destination(const char * path,unsigned int width,unsigned int height,double resolution,double x,double y,int is_centered,double no_data,int decimal_digits,void * pixels,int pixels_size,unsigned char sample_type)1099 rl2_create_ascii_grid_destination (const char *path, unsigned int width,
1100 unsigned int height, double resolution,
1101 double x, double y, int is_centered,
1102 double no_data, int decimal_digits,
1103 void *pixels, int pixels_size,
1104 unsigned char sample_type)
1105 {
1106 /* creating an ASCII Grid Destination */
1107 FILE *out;
1108 rl2PrivAsciiDestinationPtr ascii = NULL;
1109 int pix_sz = 0;
1110
1111 if (path == NULL)
1112 return NULL;
1113 if (pixels == NULL)
1114 return NULL;
1115
1116 switch (sample_type)
1117 {
1118 case RL2_SAMPLE_INT8:
1119 case RL2_SAMPLE_UINT8:
1120 pix_sz = 1;
1121 break;
1122 case RL2_SAMPLE_INT16:
1123 case RL2_SAMPLE_UINT16:
1124 pix_sz = 2;
1125 break;
1126 case RL2_SAMPLE_INT32:
1127 case RL2_SAMPLE_UINT32:
1128 case RL2_SAMPLE_FLOAT:
1129 pix_sz = 4;
1130 break;
1131 case RL2_SAMPLE_DOUBLE:
1132 pix_sz = 8;
1133 break;
1134 };
1135 if (pix_sz < 1)
1136 return NULL;
1137 if (pixels_size != (int) (width * height * pix_sz))
1138 return NULL;
1139
1140 out = fopen (path, "w");
1141 if (out == NULL)
1142 {
1143 fprintf (stderr, "ASCII Destination: Unable to open %s\n", path);
1144 return NULL;
1145 }
1146
1147 ascii =
1148 alloc_ascii_destination (path, width, height, x, y, resolution,
1149 is_centered, no_data, decimal_digits);
1150 if (ascii == NULL)
1151 goto error;
1152
1153 /* creating the output File */
1154 out = fopen (path, "wb");
1155 if (out == NULL)
1156 goto error;
1157 ascii->out = out;
1158 ascii->pixels = pixels;
1159 ascii->sampleType = sample_type;
1160
1161 return (rl2AsciiGridDestinationPtr) ascii;
1162
1163 error:
1164 if (ascii != NULL)
1165 rl2_destroy_ascii_grid_destination ((rl2AsciiGridDestinationPtr) ascii);
1166 if (out != NULL)
1167 fclose (out);
1168 return NULL;
1169 }
1170
1171 RL2_DECLARE void
rl2_destroy_ascii_grid_destination(rl2AsciiGridDestinationPtr ascii)1172 rl2_destroy_ascii_grid_destination (rl2AsciiGridDestinationPtr ascii)
1173 {
1174 /* memory cleanup - destroying an ASCII Grid destination object */
1175 rl2PrivAsciiDestinationPtr dst = (rl2PrivAsciiDestinationPtr) ascii;
1176 if (dst == NULL)
1177 return;
1178 if (dst->path != NULL)
1179 free (dst->path);
1180 if (dst->out != NULL)
1181 fclose (dst->out);
1182 if (dst->pixels != NULL)
1183 free (dst->pixels);
1184 free (dst);
1185 }
1186
1187 RL2_DECLARE const char *
rl2_get_ascii_grid_destination_path(rl2AsciiGridDestinationPtr ascii)1188 rl2_get_ascii_grid_destination_path (rl2AsciiGridDestinationPtr ascii)
1189 {
1190 /* retrieving the input path from an ASCII Grid destination */
1191 rl2PrivAsciiDestinationPtr dst = (rl2PrivAsciiDestinationPtr) ascii;
1192 if (dst == NULL)
1193 return NULL;
1194
1195 return dst->path;
1196 }
1197
1198 RL2_DECLARE int
rl2_get_ascii_grid_destination_size(rl2AsciiGridDestinationPtr ascii,unsigned int * width,unsigned int * height)1199 rl2_get_ascii_grid_destination_size (rl2AsciiGridDestinationPtr ascii,
1200 unsigned int *width, unsigned int *height)
1201 {
1202 /* retrieving Width and Height from an ASCII Grid destination */
1203 rl2PrivAsciiDestinationPtr dst = (rl2PrivAsciiDestinationPtr) ascii;
1204 if (dst == NULL)
1205 return RL2_ERROR;
1206
1207 *width = dst->width;
1208 *height = dst->height;
1209 return RL2_OK;
1210 }
1211
1212 RL2_DECLARE int
rl2_get_ascii_grid_destination_tiepoint(rl2AsciiGridDestinationPtr ascii,double * X,double * Y)1213 rl2_get_ascii_grid_destination_tiepoint (rl2AsciiGridDestinationPtr ascii,
1214 double *X, double *Y)
1215 {
1216 /* retrieving the tiepoint from an ASCII Grid destination */
1217 rl2PrivAsciiDestinationPtr dst = (rl2PrivAsciiDestinationPtr) ascii;
1218 if (dst == NULL)
1219 return RL2_ERROR;
1220
1221 *X = dst->X;
1222 *Y = dst->Y;
1223 return RL2_OK;
1224 }
1225
1226 RL2_DECLARE int
rl2_get_ascii_grid_destination_resolution(rl2AsciiGridDestinationPtr ascii,double * resolution)1227 rl2_get_ascii_grid_destination_resolution (rl2AsciiGridDestinationPtr ascii,
1228 double *resolution)
1229 {
1230 /* retrieving the Pixel Resolution from an ASCII Grid destination */
1231 rl2PrivAsciiDestinationPtr dst = (rl2PrivAsciiDestinationPtr) ascii;
1232 if (dst == NULL)
1233 return RL2_ERROR;
1234
1235 *resolution = dst->Resolution;
1236 return RL2_OK;
1237 }
1238
1239 RL2_DECLARE int
rl2_write_ascii_grid_header(rl2AsciiGridDestinationPtr ascii)1240 rl2_write_ascii_grid_header (rl2AsciiGridDestinationPtr ascii)
1241 {
1242 /* attempting to write the ASCII Grid header */
1243 rl2PrivAsciiDestinationPtr dst = (rl2PrivAsciiDestinationPtr) ascii;
1244 if (dst == NULL)
1245 return RL2_ERROR;
1246 if (dst->out == NULL)
1247 return RL2_ERROR;
1248 if (dst->headerDone != 'N')
1249 return RL2_ERROR;
1250
1251 fprintf (dst->out, "ncols %u\r\n", dst->width);
1252 fprintf (dst->out, "nrows %u\r\n", dst->height);
1253 if (dst->isCentered)
1254 {
1255 fprintf (dst->out, "xllcenter %1.8f\r\n", dst->X);
1256 fprintf (dst->out, "yllcenter %1.8f\r\n", dst->Y);
1257 }
1258 else
1259 {
1260 fprintf (dst->out, "xllcorner %1.8f\r\n", dst->X);
1261 fprintf (dst->out, "yllcorner %1.8f\r\n", dst->Y);
1262 }
1263 fprintf (dst->out, "cellsize %1.8f\r\n", dst->Resolution);
1264 fprintf (dst->out, "NODATA_value %1.8f\r\n", dst->noData);
1265 dst->headerDone = 'Y';
1266 return RL2_OK;
1267 }
1268
1269 static char *
format_pixel(double cell_value,int decimal_digits)1270 format_pixel (double cell_value, int decimal_digits)
1271 {
1272 /* well formatting an ASCII pixel */
1273 char format[32];
1274 char *pixel;
1275 char *p;
1276 sprintf (format, " %%1.%df", decimal_digits);
1277 pixel = sqlite3_mprintf (format, cell_value);
1278 if (decimal_digits == 0)
1279 return pixel;
1280 p = pixel + strlen (pixel) - 1;
1281 while (1)
1282 {
1283 if (*p == '0')
1284 *p = '\0';
1285 else if (*p == '.')
1286 {
1287 *p = '\0';
1288 break;
1289 }
1290 else
1291 break;
1292 p--;
1293 }
1294 return pixel;
1295 }
1296
1297 RL2_DECLARE int
rl2_write_ascii_grid_scanline(rl2AsciiGridDestinationPtr ascii,unsigned int * line_no)1298 rl2_write_ascii_grid_scanline (rl2AsciiGridDestinationPtr ascii,
1299 unsigned int *line_no)
1300 {
1301 /* attempting to write a scanline into an ASCII Grid */
1302 char *p8;
1303 unsigned char *pu8;
1304 short *p16;
1305 unsigned short *pu16;
1306 int *p32;
1307 unsigned int *pu32;
1308 float *pflt;
1309 double *pdbl;
1310 double cell_value;
1311 char *pxl;
1312 unsigned int x;
1313 rl2PrivAsciiDestinationPtr dst = (rl2PrivAsciiDestinationPtr) ascii;
1314
1315 if (dst == NULL)
1316 return RL2_ERROR;
1317 if (dst->out == NULL)
1318 return RL2_ERROR;
1319 if (dst->headerDone != 'Y')
1320 return RL2_ERROR;
1321 if (dst->nextLineNo >= dst->height)
1322 return RL2_ERROR;
1323
1324 switch (dst->sampleType)
1325 {
1326 case RL2_SAMPLE_INT8:
1327 p8 = dst->pixels;
1328 p8 += (dst->nextLineNo * dst->width);
1329 break;
1330 case RL2_SAMPLE_UINT8:
1331 pu8 = dst->pixels;
1332 pu8 += (dst->nextLineNo * dst->width);
1333 break;
1334 case RL2_SAMPLE_INT16:
1335 p16 = dst->pixels;
1336 p16 += (dst->nextLineNo * dst->width);
1337 break;
1338 case RL2_SAMPLE_UINT16:
1339 pu16 = dst->pixels;
1340 pu16 += (dst->nextLineNo * dst->width);
1341 break;
1342 case RL2_SAMPLE_INT32:
1343 p32 = dst->pixels;
1344 p32 += (dst->nextLineNo * dst->width);
1345 break;
1346 case RL2_SAMPLE_UINT32:
1347 pu32 = dst->pixels;
1348 pu32 += (dst->nextLineNo * dst->width);
1349 break;
1350 case RL2_SAMPLE_FLOAT:
1351 pflt = dst->pixels;
1352 pflt += (dst->nextLineNo * dst->width);
1353 break;
1354 case RL2_SAMPLE_DOUBLE:
1355 pdbl = dst->pixels;
1356 pdbl += (dst->nextLineNo * dst->width);
1357 break;
1358 };
1359
1360 for (x = 0; x < dst->width; x++)
1361 {
1362 switch (dst->sampleType)
1363 {
1364 case RL2_SAMPLE_INT8:
1365 cell_value = *p8++;
1366 break;
1367 case RL2_SAMPLE_UINT8:
1368 cell_value = *pu8++;
1369 break;
1370 case RL2_SAMPLE_INT16:
1371 cell_value = *p16++;
1372 break;
1373 case RL2_SAMPLE_UINT16:
1374 cell_value = *pu16++;
1375 break;
1376 case RL2_SAMPLE_INT32:
1377 cell_value = *p32++;
1378 break;
1379 case RL2_SAMPLE_UINT32:
1380 cell_value = *pu32++;
1381 break;
1382 case RL2_SAMPLE_FLOAT:
1383 cell_value = *pflt++;
1384 break;
1385 case RL2_SAMPLE_DOUBLE:
1386 cell_value = *pdbl++;
1387 break;
1388 };
1389 pxl = format_pixel (cell_value, dst->decimalDigits);
1390 fprintf (dst->out, "%s", pxl);
1391 sqlite3_free (pxl);
1392 }
1393 fprintf (dst->out, "\r\n");
1394
1395 dst->nextLineNo += 1;
1396 *line_no = dst->nextLineNo;
1397 return RL2_OK;
1398 }
1399