1 /*
2 
3  rl2pyramid -- DBMS Pyramid functions
4 
5  version 0.1, 2014 July 13
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 <sys/types.h>
50 #if defined(_WIN32) && !defined(__MINGW32__)
51 #include <io.h>
52 #include <direct.h>
53 #else
54 #include <dirent.h>
55 #endif
56 
57 #include "config.h"
58 
59 #ifdef LOADABLE_EXTENSION
60 #include "rasterlite2/sqlite.h"
61 #endif
62 
63 #include "rasterlite2/rasterlite2.h"
64 #include "rasterlite2/rl2tiff.h"
65 #include "rasterlite2/rl2graphics.h"
66 #include "rasterlite2_private.h"
67 
68 #include <spatialite/gaiaaux.h>
69 
70 /* 64 bit integer: portable format for printf() */
71 #if defined(_WIN32) && !defined(__MINGW32__)
72 #define ERR_FRMT64 "ERROR: unable to decode Tile ID=%I64d\n"
73 #else
74 #define ERR_FRMT64 "ERROR: unable to decode Tile ID=%lld\n"
75 #endif
76 
77 static int
do_insert_pyramid_levels(sqlite3 * handle,int id_level,double res_x,double res_y,sqlite3_stmt * stmt_levl)78 do_insert_pyramid_levels (sqlite3 * handle, int id_level, double res_x,
79 			  double res_y, sqlite3_stmt * stmt_levl)
80 {
81 /* INSERTing the Pyramid levels */
82     int ret;
83     sqlite3_reset (stmt_levl);
84     sqlite3_clear_bindings (stmt_levl);
85     sqlite3_bind_int (stmt_levl, 1, id_level);
86     sqlite3_bind_double (stmt_levl, 2, res_x);
87     sqlite3_bind_double (stmt_levl, 3, res_y);
88     sqlite3_bind_double (stmt_levl, 4, res_x * 2.0);
89     sqlite3_bind_double (stmt_levl, 5, res_y * 2.0);
90     sqlite3_bind_double (stmt_levl, 6, res_x * 4.0);
91     sqlite3_bind_double (stmt_levl, 7, res_y * 4.0);
92     sqlite3_bind_double (stmt_levl, 8, res_x * 8.0);
93     sqlite3_bind_double (stmt_levl, 9, res_y * 8.0);
94     ret = sqlite3_step (stmt_levl);
95     if (ret == SQLITE_DONE || ret == SQLITE_ROW)
96 	;
97     else
98       {
99 	  fprintf (stderr,
100 		   "INSERT INTO levels; sqlite3_step() error: %s\n",
101 		   sqlite3_errmsg (handle));
102 	  goto error;
103       }
104     return 1;
105   error:
106     return 0;
107 }
108 
109 static int
do_insert_pyramid_tile(sqlite3 * handle,unsigned char * blob_odd,int blob_odd_sz,unsigned char * blob_even,int blob_even_sz,int id_level,sqlite3_int64 section_id,int srid,double minx,double miny,double maxx,double maxy,sqlite3_stmt * stmt_tils,sqlite3_stmt * stmt_data)110 do_insert_pyramid_tile (sqlite3 * handle, unsigned char *blob_odd,
111 			int blob_odd_sz, unsigned char *blob_even,
112 			int blob_even_sz, int id_level,
113 			sqlite3_int64 section_id, int srid, double minx,
114 			double miny, double maxx, double maxy,
115 			sqlite3_stmt * stmt_tils, sqlite3_stmt * stmt_data)
116 {
117 /* INSERTing a Pyramid tile */
118     int ret;
119     sqlite3_int64 tile_id;
120     unsigned char *blob;
121     int blob_size;
122     gaiaGeomCollPtr geom;
123 
124     sqlite3_reset (stmt_tils);
125     sqlite3_clear_bindings (stmt_tils);
126     sqlite3_bind_int (stmt_tils, 1, id_level);
127     if (section_id < 0)
128 	sqlite3_bind_null (stmt_tils, 2);
129     else
130 	sqlite3_bind_int64 (stmt_tils, 2, section_id);
131     geom = build_extent (srid, minx, miny, maxx, maxy);
132     gaiaToSpatiaLiteBlobWkb (geom, &blob, &blob_size);
133     gaiaFreeGeomColl (geom);
134     sqlite3_bind_blob (stmt_tils, 3, blob, blob_size, free);
135     ret = sqlite3_step (stmt_tils);
136     if (ret == SQLITE_DONE || ret == SQLITE_ROW)
137 	;
138     else
139       {
140 	  fprintf (stderr,
141 		   "INSERT INTO tiles; sqlite3_step() error: %s\n",
142 		   sqlite3_errmsg (handle));
143 	  goto error;
144       }
145     tile_id = sqlite3_last_insert_rowid (handle);
146     /* INSERTing tile data */
147     sqlite3_reset (stmt_data);
148     sqlite3_clear_bindings (stmt_data);
149     sqlite3_bind_int64 (stmt_data, 1, tile_id);
150     sqlite3_bind_blob (stmt_data, 2, blob_odd, blob_odd_sz, free);
151     if (blob_even == NULL)
152 	sqlite3_bind_null (stmt_data, 3);
153     else
154 	sqlite3_bind_blob (stmt_data, 3, blob_even, blob_even_sz, free);
155     ret = sqlite3_step (stmt_data);
156     if (ret == SQLITE_DONE || ret == SQLITE_ROW)
157 	;
158     else
159       {
160 	  fprintf (stderr,
161 		   "INSERT INTO tile_data; sqlite3_step() error: %s\n",
162 		   sqlite3_errmsg (handle));
163 	  goto error;
164       }
165     return 1;
166   error:
167     return 0;
168 }
169 
170 static int
resolve_section_id(sqlite3 * handle,const char * coverage,const char * section,sqlite3_int64 * sect_id)171 resolve_section_id (sqlite3 * handle, const char *coverage, const char *section,
172 		    sqlite3_int64 * sect_id)
173 {
174 /* resolving the Section ID by name */
175     char *table;
176     char *xtable;
177     char *sql;
178     sqlite3_stmt *stmt = NULL;
179     int ret;
180     int ok = 0;
181 
182 /* Section infos */
183     table = sqlite3_mprintf ("%s_sections", coverage);
184     xtable = gaiaDoubleQuotedSql (table);
185     sqlite3_free (table);
186     sql = sqlite3_mprintf ("SELECT section_id "
187 			   "FROM \"%s\" WHERE section_name = %Q", xtable,
188 			   section);
189     free (xtable);
190     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
191     sqlite3_free (sql);
192     if (ret != SQLITE_OK)
193       {
194 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
195 	  goto error;
196       }
197     while (1)
198       {
199 	  ret = sqlite3_step (stmt);
200 	  if (ret == SQLITE_DONE)
201 	      break;
202 	  if (ret == SQLITE_ROW)
203 	    {
204 		*sect_id = sqlite3_column_int64 (stmt, 0);
205 		ok = 1;
206 	    }
207 	  else
208 	    {
209 		fprintf (stderr,
210 			 "SELECT section_info; sqlite3_step() error: %s\n",
211 			 sqlite3_errmsg (handle));
212 		goto error;
213 	    }
214       }
215     sqlite3_finalize (stmt);
216     return ok;
217 
218   error:
219     if (stmt != NULL)
220 	sqlite3_finalize (stmt);
221     return 0;
222 }
223 
224 static int
delete_section_pyramid(sqlite3 * handle,const char * coverage,const char * section)225 delete_section_pyramid (sqlite3 * handle, const char *coverage,
226 			const char *section)
227 {
228 /* attempting to delete a section pyramid */
229     char *sql;
230     char *table;
231     char *xtable;
232     sqlite3_int64 section_id;
233     char sect_id[1024];
234     int ret;
235     char *err_msg = NULL;
236 
237     if (!resolve_section_id (handle, coverage, section, &section_id))
238 	return 0;
239 #if defined(_WIN32) && !defined(__MINGW32__)
240     sprintf (sect_id, "%I64d", section_id);
241 #else
242     sprintf (sect_id, "%lld", section_id);
243 #endif
244 
245     table = sqlite3_mprintf ("%s_tiles", coverage);
246     xtable = gaiaDoubleQuotedSql (table);
247     sqlite3_free (table);
248     sql =
249 	sqlite3_mprintf
250 	("DELETE FROM \"%s\" WHERE pyramid_level > 0 AND section_id = %s",
251 	 xtable, sect_id);
252     free (xtable);
253     ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg);
254     sqlite3_free (sql);
255     if (ret != SQLITE_OK)
256       {
257 	  fprintf (stderr, "DELETE FROM \"%s_tiles\" error: %s\n", coverage,
258 		   err_msg);
259 	  sqlite3_free (err_msg);
260 	  return 0;
261       }
262     return 1;
263 }
264 
265 static int
check_section_pyramid(sqlite3 * handle,const char * coverage,const char * section)266 check_section_pyramid (sqlite3 * handle, const char *coverage,
267 		       const char *section)
268 {
269 /* checking if a section's pyramid already exists */
270     char *sql;
271     char *table;
272     char *xtable;
273     sqlite3_int64 section_id;
274     char sect_id[1024];
275     sqlite3_stmt *stmt = NULL;
276     int ret;
277     int count = 0;
278 
279     if (!resolve_section_id (handle, coverage, section, &section_id))
280 	return 1;
281 #if defined(_WIN32) && !defined(__MINGW32__)
282     sprintf (sect_id, "%I64d", section_id);
283 #else
284     sprintf (sect_id, "%lld", section_id);
285 #endif
286 
287     table = sqlite3_mprintf ("%s_tiles", coverage);
288     xtable = gaiaDoubleQuotedSql (table);
289     sqlite3_free (table);
290     sql =
291 	sqlite3_mprintf ("SELECT Count(*) FROM \"%s\" "
292 			 "WHERE section_id = %s AND pyramid_level > 0", xtable,
293 			 sect_id);
294     free (xtable);
295     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
296     sqlite3_free (sql);
297     if (ret != SQLITE_OK)
298 	return 1;
299     while (1)
300       {
301 	  ret = sqlite3_step (stmt);
302 	  if (ret == SQLITE_DONE)
303 	      break;
304 	  if (ret == SQLITE_ROW)
305 	      count = sqlite3_column_int (stmt, 0);
306 	  else
307 	    {
308 		fprintf (stderr,
309 			 "SELECT pyramid_exists; sqlite3_step() error: %s\n",
310 			 sqlite3_errmsg (handle));
311 		count = 0;
312 		break;
313 	    }
314       }
315     sqlite3_finalize (stmt);
316     if (count == 0)
317 	return 1;
318     return 0;
319 }
320 
321 static int
get_section_infos(sqlite3 * handle,const char * coverage,const char * section,sqlite3_int64 * sect_id,unsigned int * sect_width,unsigned int * sect_height,double * minx,double * miny,double * maxx,double * maxy,rl2PalettePtr * palette,rl2PixelPtr * no_data)322 get_section_infos (sqlite3 * handle, const char *coverage, const char *section,
323 		   sqlite3_int64 * sect_id, unsigned int *sect_width,
324 		   unsigned int *sect_height, double *minx, double *miny,
325 		   double *maxx, double *maxy, rl2PalettePtr * palette,
326 		   rl2PixelPtr * no_data)
327 {
328 /* retrieving the Section most relevant infos */
329     char *table;
330     char *xtable;
331     char *sql;
332     sqlite3_stmt *stmt = NULL;
333     int ret;
334     int ok = 0;
335 
336 /* Section infos */
337     table = sqlite3_mprintf ("%s_sections", coverage);
338     xtable = gaiaDoubleQuotedSql (table);
339     sqlite3_free (table);
340     sql =
341 	sqlite3_mprintf ("SELECT section_id, width, height, MbrMinX(geometry), "
342 			 "MbrMinY(geometry), MbrMaxX(geometry), MbrMaxY(geometry) "
343 			 "FROM \"%s\" WHERE section_name = %Q", xtable,
344 			 section);
345     free (xtable);
346     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
347     sqlite3_free (sql);
348     if (ret != SQLITE_OK)
349       {
350 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
351 	  goto error;
352       }
353     while (1)
354       {
355 	  ret = sqlite3_step (stmt);
356 	  if (ret == SQLITE_DONE)
357 	      break;
358 	  if (ret == SQLITE_ROW)
359 	    {
360 		*sect_id = sqlite3_column_int64 (stmt, 0);
361 		*sect_width = sqlite3_column_int (stmt, 1);
362 		*sect_height = sqlite3_column_int (stmt, 2);
363 		*minx = sqlite3_column_double (stmt, 3);
364 		*miny = sqlite3_column_double (stmt, 4);
365 		*maxx = sqlite3_column_double (stmt, 5);
366 		*maxy = sqlite3_column_double (stmt, 6);
367 		ok = 1;
368 	    }
369 	  else
370 	    {
371 		fprintf (stderr,
372 			 "SELECT section_info; sqlite3_step() error: %s\n",
373 			 sqlite3_errmsg (handle));
374 		goto error;
375 	    }
376       }
377     sqlite3_finalize (stmt);
378     if (!ok)
379 	goto error;
380 
381 /* Coverage's palette and no-data */
382     sql = sqlite3_mprintf ("SELECT palette, nodata_pixel FROM raster_coverages "
383 			   "WHERE Lower(coverage_name) = Lower(%Q)", coverage);
384     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
385     sqlite3_free (sql);
386     if (ret != SQLITE_OK)
387       {
388 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
389 	  goto error;
390       }
391     while (1)
392       {
393 	  ret = sqlite3_step (stmt);
394 	  if (ret == SQLITE_DONE)
395 	      break;
396 	  if (ret == SQLITE_ROW)
397 	    {
398 		if (sqlite3_column_type (stmt, 0) == SQLITE_BLOB)
399 		  {
400 		      const unsigned char *blob = sqlite3_column_blob (stmt, 0);
401 		      int blob_sz = sqlite3_column_bytes (stmt, 0);
402 		      *palette = rl2_deserialize_dbms_palette (blob, blob_sz);
403 		  }
404 		if (sqlite3_column_type (stmt, 1) == SQLITE_BLOB)
405 		  {
406 		      const unsigned char *blob = sqlite3_column_blob (stmt, 1);
407 		      int blob_sz = sqlite3_column_bytes (stmt, 1);
408 		      *no_data = rl2_deserialize_dbms_pixel (blob, blob_sz);
409 		  }
410 	    }
411 	  else
412 	    {
413 		fprintf (stderr,
414 			 "SELECT section_info; sqlite3_step() error: %s\n",
415 			 sqlite3_errmsg (handle));
416 		goto error;
417 	    }
418       }
419     sqlite3_finalize (stmt);
420     return 1;
421 
422   error:
423     if (stmt != NULL)
424 	sqlite3_finalize (stmt);
425     return 0;
426 }
427 
428 static SectionPyramidTileInPtr
alloc_section_pyramid_tile(sqlite3_int64 tile_id,double minx,double miny,double maxx,double maxy)429 alloc_section_pyramid_tile (sqlite3_int64 tile_id, double minx, double miny,
430 			    double maxx, double maxy)
431 {
432 /* allocating a Section Pyramid Tile object */
433     SectionPyramidTileInPtr tile = malloc (sizeof (SectionPyramidTileIn));
434     if (tile == NULL)
435 	return NULL;
436     tile->tile_id = tile_id;
437     tile->cx = minx + ((maxx - minx) / 2.0);
438     tile->cy = miny + ((maxy - miny) / 2.0);
439     tile->next = NULL;
440     return tile;
441 }
442 
443 static SectionPyramidPtr
alloc_sect_pyramid(sqlite3_int64 sect_id,unsigned int sect_width,unsigned int sect_height,unsigned char sample_type,unsigned char pixel_type,unsigned char num_samples,unsigned char compression,int quality,int srid,double res_x,double res_y,double tile_width,double tile_height,double minx,double miny,double maxx,double maxy,int scale)444 alloc_sect_pyramid (sqlite3_int64 sect_id, unsigned int sect_width,
445 		    unsigned int sect_height, unsigned char sample_type,
446 		    unsigned char pixel_type, unsigned char num_samples,
447 		    unsigned char compression, int quality, int srid,
448 		    double res_x, double res_y, double tile_width,
449 		    double tile_height, double minx, double miny, double maxx,
450 		    double maxy, int scale)
451 {
452 /* allocating a Section Pyramid object */
453     double ext_x = maxx - minx;
454     double ext_y = maxy - miny;
455     SectionPyramidPtr pyr = malloc (sizeof (SectionPyramid));
456     if (pyr == NULL)
457 	return NULL;
458     pyr->section_id = sect_id;
459     pyr->scale = scale;
460     pyr->full_width = sect_width;
461     pyr->full_height = sect_height;
462     pyr->sample_type = sample_type;
463     pyr->pixel_type = pixel_type;
464     pyr->num_samples = num_samples;
465     pyr->compression = compression;
466     pyr->quality = quality;
467     pyr->srid = srid;
468     pyr->res_x = res_x;
469     pyr->res_y = res_y;
470     pyr->scaled_width = ext_x / res_x;
471     pyr->scaled_height = ext_y / res_y;
472     pyr->tile_width = tile_width;
473     pyr->tile_height = tile_height;
474     pyr->minx = minx;
475     pyr->miny = miny;
476     pyr->maxx = maxx;
477     pyr->maxy = maxy;
478     pyr->first_in = NULL;
479     pyr->last_in = NULL;
480     pyr->first_out = NULL;
481     pyr->last_out = NULL;
482     return pyr;
483 }
484 
485 static void
delete_sect_pyramid(SectionPyramidPtr pyr)486 delete_sect_pyramid (SectionPyramidPtr pyr)
487 {
488 /* memory cleanup - destroying a Section Pyramid object */
489     SectionPyramidTileInPtr tile_in;
490     SectionPyramidTileInPtr tile_in_n;
491     SectionPyramidTileOutPtr tile_out;
492     SectionPyramidTileOutPtr tile_out_n;
493     if (pyr == NULL)
494 	return;
495     tile_out = pyr->first_out;
496     while (tile_out != NULL)
497       {
498 	  SectionPyramidTileRefPtr ref;
499 	  SectionPyramidTileRefPtr ref_n;
500 	  tile_out_n = tile_out->next;
501 	  ref = tile_out->first;
502 	  while (ref != NULL)
503 	    {
504 		ref_n = ref->next;
505 		free (ref);
506 		ref = ref_n;
507 	    }
508 	  free (tile_out);
509 	  tile_out = tile_out_n;
510       }
511     tile_in = pyr->first_in;
512     while (tile_in != NULL)
513       {
514 	  tile_in_n = tile_in->next;
515 	  free (tile_in);
516 	  tile_in = tile_in_n;
517       }
518     free (pyr);
519 }
520 
521 static int
insert_tile_into_section_pyramid(SectionPyramidPtr pyr,sqlite3_int64 tile_id,double minx,double miny,double maxx,double maxy)522 insert_tile_into_section_pyramid (SectionPyramidPtr pyr, sqlite3_int64 tile_id,
523 				  double minx, double miny, double maxx,
524 				  double maxy)
525 {
526 /* inserting a base tile into the Pyramid level */
527     SectionPyramidTileInPtr tile;
528     if (pyr == NULL)
529 	return 0;
530     tile = alloc_section_pyramid_tile (tile_id, minx, miny, maxx, maxy);
531     if (tile == NULL)
532 	return 0;
533     if (pyr->first_in == NULL)
534 	pyr->first_in = tile;
535     if (pyr->last_in != NULL)
536 	pyr->last_in->next = tile;
537     pyr->last_in = tile;
538     return 1;
539 }
540 
541 static SectionPyramidTileOutPtr
add_pyramid_out_tile(SectionPyramidPtr pyr,unsigned int row,unsigned int col,double minx,double miny,double maxx,double maxy)542 add_pyramid_out_tile (SectionPyramidPtr pyr, unsigned int row,
543 		      unsigned int col, double minx, double miny, double maxx,
544 		      double maxy)
545 {
546 /* inserting a Parent tile (output) */
547     SectionPyramidTileOutPtr tile;
548     if (pyr == NULL)
549 	return NULL;
550     tile = malloc (sizeof (SectionPyramidTileOut));
551     if (tile == NULL)
552 	return NULL;
553     tile->row = row;
554     tile->col = col;
555     tile->minx = minx;
556     tile->miny = miny;
557     tile->maxx = maxx;
558     tile->maxy = maxy;
559     tile->first = NULL;
560     tile->last = NULL;
561     tile->next = NULL;
562     if (pyr->first_out == NULL)
563 	pyr->first_out = tile;
564     if (pyr->last_out != NULL)
565 	pyr->last_out->next = tile;
566     pyr->last_out = tile;
567     return tile;
568 }
569 
570 static void
add_pyramid_sub_tile(SectionPyramidTileOutPtr parent,SectionPyramidTileInPtr child)571 add_pyramid_sub_tile (SectionPyramidTileOutPtr parent,
572 		      SectionPyramidTileInPtr child)
573 {
574 /* inserting a Child tile (input) */
575     SectionPyramidTileRefPtr ref;
576     if (parent == NULL)
577 	return;
578     ref = malloc (sizeof (SectionPyramidTileRef));
579     if (ref == NULL)
580 	return;
581     ref->child = child;
582     ref->next = NULL;
583     if (parent->first == NULL)
584 	parent->first = ref;
585     if (parent->last != NULL)
586 	parent->last->next = ref;
587     parent->last = ref;
588 }
589 
590 static void
set_pyramid_tile_destination(SectionPyramidPtr pyr,double minx,double miny,double maxx,double maxy,unsigned int row,unsigned int col)591 set_pyramid_tile_destination (SectionPyramidPtr pyr, double minx, double miny,
592 			      double maxx, double maxy, unsigned int row,
593 			      unsigned int col)
594 {
595 /* aggregating lower level tiles */
596     int first = 1;
597     SectionPyramidTileOutPtr out = NULL;
598     SectionPyramidTileInPtr tile = pyr->first_in;
599     while (tile != NULL)
600       {
601 	  if (tile->cx > minx && tile->cx < maxx && tile->cy > miny
602 	      && tile->cy < maxy)
603 	    {
604 		if (first)
605 		  {
606 		      out =
607 			  add_pyramid_out_tile (pyr, row, col, minx, miny, maxx,
608 						maxy);
609 		      first = 0;
610 		  }
611 		if (out != NULL)
612 		    add_pyramid_sub_tile (out, tile);
613 	    }
614 	  tile = tile->next;
615       }
616 }
617 
618 static unsigned char *
load_tile_base(sqlite3_stmt * stmt,sqlite3_int64 tile_id,rl2PalettePtr palette,rl2PixelPtr no_data)619 load_tile_base (sqlite3_stmt * stmt, sqlite3_int64 tile_id,
620 		rl2PalettePtr palette, rl2PixelPtr no_data)
621 {
622 /* attempting to read a lower-level tile */
623     int ret;
624     const unsigned char *blob_odd = NULL;
625     int blob_odd_sz = 0;
626     const unsigned char *blob_even = NULL;
627     int blob_even_sz = 0;
628     rl2RasterPtr raster = NULL;
629     rl2PalettePtr plt = NULL;
630     unsigned char *rgba_tile = NULL;
631     int rgba_sz;
632     rl2PixelPtr nd;
633 
634     sqlite3_reset (stmt);
635     sqlite3_clear_bindings (stmt);
636     sqlite3_bind_int64 (stmt, 1, tile_id);
637     while (1)
638       {
639 	  /* scrolling the result set rows */
640 	  ret = sqlite3_step (stmt);
641 	  if (ret == SQLITE_DONE)
642 	      break;		/* end of result set */
643 	  if (ret == SQLITE_ROW)
644 	    {
645 		if (sqlite3_column_type (stmt, 0) == SQLITE_BLOB)
646 		  {
647 		      blob_odd = sqlite3_column_blob (stmt, 0);
648 		      blob_odd_sz = sqlite3_column_bytes (stmt, 0);
649 		  }
650 		if (sqlite3_column_type (stmt, 1) == SQLITE_BLOB)
651 		  {
652 		      blob_even = sqlite3_column_blob (stmt, 1);
653 		      blob_even_sz = sqlite3_column_bytes (stmt, 1);
654 		  }
655 		plt = rl2_clone_palette (palette);
656 		raster =
657 		    rl2_raster_decode (RL2_SCALE_1, blob_odd, blob_odd_sz,
658 				       blob_even, blob_even_sz, plt);
659 		if (raster == NULL)
660 		  {
661 		      fprintf (stderr, ERR_FRMT64, tile_id);
662 		      return NULL;
663 		  }
664 		nd = rl2_clone_pixel (no_data);
665 		rl2_set_raster_no_data (raster, nd);
666 		if (rl2_raster_data_to_RGBA (raster, &rgba_tile, &rgba_sz) !=
667 		    RL2_OK)
668 		    rgba_tile = NULL;
669 		rl2_destroy_raster (raster);
670 		break;
671 	    }
672 	  else
673 	      return NULL;
674       }
675     return rgba_tile;
676 }
677 
678 static rl2RasterPtr
load_tile_base_generic(sqlite3_stmt * stmt,sqlite3_int64 tile_id)679 load_tile_base_generic (sqlite3_stmt * stmt, sqlite3_int64 tile_id)
680 {
681 /* attempting to read a lower-level tile */
682     int ret;
683     const unsigned char *blob_odd = NULL;
684     int blob_odd_sz = 0;
685     const unsigned char *blob_even = NULL;
686     int blob_even_sz = 0;
687     rl2RasterPtr raster = NULL;
688 
689     sqlite3_reset (stmt);
690     sqlite3_clear_bindings (stmt);
691     sqlite3_bind_int64 (stmt, 1, tile_id);
692     while (1)
693       {
694 	  /* scrolling the result set rows */
695 	  ret = sqlite3_step (stmt);
696 	  if (ret == SQLITE_DONE)
697 	      break;		/* end of result set */
698 	  if (ret == SQLITE_ROW)
699 	    {
700 		if (sqlite3_column_type (stmt, 0) == SQLITE_BLOB)
701 		  {
702 		      blob_odd = sqlite3_column_blob (stmt, 0);
703 		      blob_odd_sz = sqlite3_column_bytes (stmt, 0);
704 		  }
705 		if (sqlite3_column_type (stmt, 1) == SQLITE_BLOB)
706 		  {
707 		      blob_even = sqlite3_column_blob (stmt, 1);
708 		      blob_even_sz = sqlite3_column_bytes (stmt, 1);
709 		  }
710 		raster =
711 		    rl2_raster_decode (RL2_SCALE_1, blob_odd, blob_odd_sz,
712 				       blob_even, blob_even_sz, NULL);
713 		if (raster == NULL)
714 		  {
715 		      fprintf (stderr, ERR_FRMT64, tile_id);
716 		      return NULL;
717 		  }
718 		return raster;
719 	    }
720       }
721     return NULL;
722 }
723 
724 static double
rescale_pixel_int8(const char * buf_in,unsigned int tileWidth,unsigned int tileHeight,int x,int y,char nd)725 rescale_pixel_int8 (const char *buf_in, unsigned int tileWidth,
726 		    unsigned int tileHeight, int x, int y, char nd)
727 {
728 /* rescaling a DataGrid pixel (8x8) - INT8 */
729     unsigned int row;
730     unsigned int col;
731     int nodata = 0;
732     int valid = 0;
733     double sum = 0.0;
734 
735     for (row = 0; row < 8; row++)
736       {
737 	  const char *p_in_base;
738 	  unsigned int yy = y + row;
739 	  if (yy >= tileHeight)
740 	      break;
741 	  p_in_base = buf_in + (yy * tileWidth);
742 	  for (col = 0; col < 8; col++)
743 	    {
744 		const char *p_in;
745 		unsigned int xx = x + col;
746 		if (xx >= tileWidth)
747 		    break;
748 		p_in = p_in_base + x;
749 		if (*p_in == nd)
750 		    nodata++;
751 		else
752 		  {
753 		      valid++;
754 		      sum += *p_in;
755 		  }
756 	    }
757       }
758 
759     if (nodata >= valid)
760 	return nd;
761     return (char) (sum / (double) valid);
762 }
763 
764 static void
rescale_grid_int8(char * buf_out,unsigned int tileWidth,unsigned int tileHeight,const char * buf_in,int x,int y,int tic_x,int tic_y,rl2PixelPtr no_data)765 rescale_grid_int8 (char *buf_out, unsigned int tileWidth,
766 		   unsigned int tileHeight, const char *buf_in, int x, int y,
767 		   int tic_x, int tic_y, rl2PixelPtr no_data)
768 {
769 /* rescaling a DataGrid tile - int 8 bit */
770     unsigned int row;
771     unsigned int col;
772     char nd = 0;
773     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) no_data;
774 
775     if (pxl != NULL)
776       {
777 	  /* retrieving the NO-DATA value */
778 	  if (pxl->sampleType == RL2_SAMPLE_INT8 && pxl->nBands == 1)
779 	    {
780 		rl2PrivSamplePtr sample = pxl->Samples + 0;
781 		nd = sample->int8;
782 	    }
783       }
784 
785     for (row = 0; row < (unsigned) tic_y; row++)
786       {
787 	  unsigned int yy = row + y;
788 	  char *p_out_base = buf_out + (yy * tileWidth);
789 	  if (yy >= tileHeight)
790 	      break;
791 	  for (col = 0; col < (unsigned int) tic_x; col++)
792 	    {
793 		unsigned int xx = col + x;
794 		char *p_out = p_out_base + xx;
795 		if (xx >= tileWidth)
796 		    break;
797 		*p_out =
798 		    rescale_pixel_int8 (buf_in, tileWidth, tileHeight, col * 8,
799 					row * 8, nd);
800 	    }
801       }
802 }
803 
804 static double
rescale_pixel_uint8(const unsigned char * buf_in,unsigned int tileWidth,unsigned int tileHeight,int x,int y,unsigned char nd)805 rescale_pixel_uint8 (const unsigned char *buf_in, unsigned int tileWidth,
806 		     unsigned int tileHeight, int x, int y, unsigned char nd)
807 {
808 /* rescaling a DataGrid pixel (8x8) - UINT8 */
809     unsigned int row;
810     unsigned int col;
811     int nodata = 0;
812     int valid = 0;
813     double sum = 0.0;
814 
815     for (row = 0; row < 8; row++)
816       {
817 	  const unsigned char *p_in_base;
818 	  unsigned int yy = y + row;
819 	  if (yy >= tileHeight)
820 	      break;
821 	  p_in_base = buf_in + (yy * tileWidth);
822 	  for (col = 0; col < 8; col++)
823 	    {
824 		const unsigned char *p_in;
825 		unsigned int xx = x + col;
826 		if (xx >= tileWidth)
827 		    break;
828 		p_in = p_in_base + x;
829 		if (*p_in == nd)
830 		    nodata++;
831 		else
832 		  {
833 		      valid++;
834 		      sum += *p_in;
835 		  }
836 	    }
837       }
838 
839     if (nodata >= valid)
840 	return nd;
841     return (unsigned char) (sum / (double) valid);
842 }
843 
844 static void
rescale_grid_uint8(unsigned char * buf_out,unsigned int tileWidth,unsigned int tileHeight,const unsigned char * buf_in,int x,int y,int tic_x,int tic_y,rl2PixelPtr no_data)845 rescale_grid_uint8 (unsigned char *buf_out, unsigned int tileWidth,
846 		    unsigned int tileHeight, const unsigned char *buf_in,
847 		    int x, int y, int tic_x, int tic_y, rl2PixelPtr no_data)
848 {
849 /* rescaling a DataGrid tile - unsigned int 8 bit */
850     unsigned int row;
851     unsigned int col;
852     unsigned char nd = 0;
853     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) no_data;
854 
855     if (pxl != NULL)
856       {
857 	  /* retrieving the NO-DATA value */
858 	  if (pxl->sampleType == RL2_SAMPLE_UINT8 && pxl->nBands == 1)
859 	    {
860 		rl2PrivSamplePtr sample = pxl->Samples + 0;
861 		nd = sample->uint8;
862 	    }
863       }
864 
865     for (row = 0; row < (unsigned int) tic_y; row++)
866       {
867 	  unsigned int yy = row + y;
868 	  unsigned char *p_out_base = buf_out + (yy * tileWidth);
869 	  if (yy >= tileHeight)
870 	      break;
871 	  for (col = 0; col < (unsigned int) tic_x; col++)
872 	    {
873 		unsigned int xx = col + x;
874 		unsigned char *p_out = p_out_base + xx;
875 		if (xx >= tileWidth)
876 		    break;
877 		*p_out =
878 		    rescale_pixel_uint8 (buf_in, tileWidth, tileHeight, col * 8,
879 					 row * 8, nd);
880 	    }
881       }
882 }
883 
884 static double
rescale_pixel_int16(const short * buf_in,unsigned int tileWidth,unsigned int tileHeight,int x,int y,short nd)885 rescale_pixel_int16 (const short *buf_in, unsigned int tileWidth,
886 		     unsigned int tileHeight, int x, int y, short nd)
887 {
888 /* rescaling a DataGrid pixel (8x8) - INT32 */
889     unsigned int row;
890     unsigned int col;
891     int nodata = 0;
892     int valid = 0;
893     double sum = 0.0;
894 
895     for (row = 0; row < 8; row++)
896       {
897 	  const short *p_in_base;
898 	  unsigned int yy = y + row;
899 	  if (yy >= tileHeight)
900 	      break;
901 	  p_in_base = buf_in + (yy * tileWidth);
902 	  for (col = 0; col < 8; col++)
903 	    {
904 		const short *p_in;
905 		unsigned int xx = x + col;
906 		if (xx >= tileWidth)
907 		    break;
908 		p_in = p_in_base + x;
909 		if (*p_in == nd)
910 		    nodata++;
911 		else
912 		  {
913 		      valid++;
914 		      sum += *p_in;
915 		  }
916 	    }
917       }
918 
919     if (nodata >= valid)
920 	return nd;
921     return (short) (sum / (double) valid);
922 }
923 
924 static void
rescale_grid_int16(short * buf_out,unsigned int tileWidth,unsigned int tileHeight,const short * buf_in,int x,int y,int tic_x,int tic_y,rl2PixelPtr no_data)925 rescale_grid_int16 (short *buf_out, unsigned int tileWidth,
926 		    unsigned int tileHeight, const short *buf_in, int x,
927 		    int y, int tic_x, int tic_y, rl2PixelPtr no_data)
928 {
929 /* rescaling a DataGrid tile - int 16 bit */
930     unsigned int row;
931     unsigned int col;
932     short nd = 0;
933     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) no_data;
934 
935     if (pxl != NULL)
936       {
937 	  /* retrieving the NO-DATA value */
938 	  if (pxl->sampleType == RL2_SAMPLE_INT16 && pxl->nBands == 1)
939 	    {
940 		rl2PrivSamplePtr sample = pxl->Samples + 0;
941 		nd = sample->int16;
942 	    }
943       }
944 
945     for (row = 0; row < (unsigned int) tic_y; row++)
946       {
947 	  unsigned int yy = row + y;
948 	  short *p_out_base = buf_out + (yy * tileWidth);
949 	  if (yy >= tileHeight)
950 	      break;
951 	  for (col = 0; col < (unsigned int) tic_x; col++)
952 	    {
953 		unsigned int xx = col + x;
954 		short *p_out = p_out_base + xx;
955 		if (xx >= tileWidth)
956 		    break;
957 		*p_out =
958 		    rescale_pixel_int16 (buf_in, tileWidth, tileHeight, col * 8,
959 					 row * 8, nd);
960 	    }
961       }
962 }
963 
964 static double
rescale_pixel_uint16(const unsigned short * buf_in,unsigned int tileWidth,unsigned int tileHeight,int x,int y,unsigned short nd)965 rescale_pixel_uint16 (const unsigned short *buf_in, unsigned int tileWidth,
966 		      unsigned int tileHeight, int x, int y, unsigned short nd)
967 {
968 /* rescaling a DataGrid pixel (8x8) - UINT16 */
969     unsigned int row;
970     unsigned int col;
971     int nodata = 0;
972     int valid = 0;
973     double sum = 0.0;
974 
975     for (row = 0; row < 8; row++)
976       {
977 	  const unsigned short *p_in_base;
978 	  unsigned int yy = y + row;
979 	  if (yy >= tileHeight)
980 	      break;
981 	  p_in_base = buf_in + (yy * tileWidth);
982 	  for (col = 0; col < 8; col++)
983 	    {
984 		const unsigned short *p_in;
985 		unsigned int xx = x + col;
986 		if (xx >= tileWidth)
987 		    break;
988 		p_in = p_in_base + x;
989 		if (*p_in == nd)
990 		    nodata++;
991 		else
992 		  {
993 		      valid++;
994 		      sum += *p_in;
995 		  }
996 	    }
997       }
998 
999     if (nodata >= valid)
1000 	return nd;
1001     return (unsigned short) (sum / (double) valid);
1002 }
1003 
1004 static void
rescale_grid_uint16(unsigned short * buf_out,unsigned int tileWidth,unsigned int tileHeight,const unsigned short * buf_in,int x,int y,int tic_x,int tic_y,rl2PixelPtr no_data)1005 rescale_grid_uint16 (unsigned short *buf_out, unsigned int tileWidth,
1006 		     unsigned int tileHeight, const unsigned short *buf_in,
1007 		     int x, int y, int tic_x, int tic_y, rl2PixelPtr no_data)
1008 {
1009 /* rescaling a DataGrid tile - unsigned int 16 bit */
1010     unsigned int row;
1011     unsigned int col;
1012     unsigned short nd = 0;
1013     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) no_data;
1014 
1015     if (pxl != NULL)
1016       {
1017 	  /* retrieving the NO-DATA value */
1018 	  if (pxl->sampleType == RL2_SAMPLE_UINT16 && pxl->nBands == 1)
1019 	    {
1020 		rl2PrivSamplePtr sample = pxl->Samples + 0;
1021 		nd = sample->uint16;
1022 	    }
1023       }
1024 
1025     for (row = 0; row < (unsigned int) tic_y; row++)
1026       {
1027 	  unsigned int yy = row + y;
1028 	  unsigned short *p_out_base = buf_out + (yy * tileWidth);
1029 	  if (yy >= tileHeight)
1030 	      break;
1031 	  for (col = 0; col < (unsigned int) tic_x; col++)
1032 	    {
1033 		unsigned int xx = col + x;
1034 		unsigned short *p_out = p_out_base + xx;
1035 		if (xx >= tileWidth)
1036 		    break;
1037 		*p_out =
1038 		    rescale_pixel_uint16 (buf_in, tileWidth, tileHeight,
1039 					  col * 8, row * 8, nd);
1040 	    }
1041       }
1042 }
1043 
1044 static double
rescale_pixel_int32(const int * buf_in,unsigned int tileWidth,unsigned int tileHeight,int x,int y,int nd)1045 rescale_pixel_int32 (const int *buf_in, unsigned int tileWidth,
1046 		     unsigned int tileHeight, int x, int y, int nd)
1047 {
1048 /* rescaling a DataGrid pixel (8x8) - INT32 */
1049     unsigned int row;
1050     unsigned int col;
1051     int nodata = 0;
1052     int valid = 0;
1053     double sum = 0.0;
1054 
1055     for (row = 0; row < 8; row++)
1056       {
1057 	  const int *p_in_base;
1058 	  unsigned int yy = y + row;
1059 	  if (yy >= tileHeight)
1060 	      break;
1061 	  p_in_base = buf_in + (yy * tileWidth);
1062 	  for (col = 0; col < 8; col++)
1063 	    {
1064 		const int *p_in;
1065 		unsigned int xx = x + col;
1066 		if (xx >= tileWidth)
1067 		    break;
1068 		p_in = p_in_base + x;
1069 		if (*p_in == nd)
1070 		    nodata++;
1071 		else
1072 		  {
1073 		      valid++;
1074 		      sum += *p_in;
1075 		  }
1076 	    }
1077       }
1078 
1079     if (nodata >= valid)
1080 	return nd;
1081     return (int) (sum / (double) valid);
1082 }
1083 
1084 static void
rescale_grid_int32(int * buf_out,unsigned int tileWidth,unsigned int tileHeight,const int * buf_in,int x,int y,int tic_x,int tic_y,rl2PixelPtr no_data)1085 rescale_grid_int32 (int *buf_out, unsigned int tileWidth,
1086 		    unsigned int tileHeight, const int *buf_in, int x, int y,
1087 		    int tic_x, int tic_y, rl2PixelPtr no_data)
1088 {
1089 /* rescaling a DataGrid tile - int 32 bit */
1090     unsigned int row;
1091     unsigned int col;
1092     int nd = 0;
1093     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) no_data;
1094 
1095     if (pxl != NULL)
1096       {
1097 	  /* retrieving the NO-DATA value */
1098 	  if (pxl->sampleType == RL2_SAMPLE_INT32 && pxl->nBands == 1)
1099 	    {
1100 		rl2PrivSamplePtr sample = pxl->Samples + 0;
1101 		nd = sample->int32;
1102 	    }
1103       }
1104 
1105     for (row = 0; row < (unsigned int) tic_y; row++)
1106       {
1107 	  unsigned int yy = row + y;
1108 	  int *p_out_base = buf_out + (yy * tileWidth);
1109 	  if (yy >= tileHeight)
1110 	      break;
1111 	  for (col = 0; col < (unsigned int) tic_x; col++)
1112 	    {
1113 		unsigned int xx = col + x;
1114 		int *p_out = p_out_base + xx;
1115 		if (xx >= tileWidth)
1116 		    break;
1117 		*p_out =
1118 		    rescale_pixel_int32 (buf_in, tileWidth, tileHeight, col * 8,
1119 					 row * 8, nd);
1120 	    }
1121       }
1122 }
1123 
1124 static double
rescale_pixel_uint32(const unsigned int * buf_in,unsigned int tileWidth,unsigned int tileHeight,int x,int y,unsigned int nd)1125 rescale_pixel_uint32 (const unsigned int *buf_in, unsigned int tileWidth,
1126 		      unsigned int tileHeight, int x, int y, unsigned int nd)
1127 {
1128 /* rescaling a DataGrid pixel (8x8) - UINT32 */
1129     unsigned int row;
1130     unsigned int col;
1131     int nodata = 0;
1132     int valid = 0;
1133     double sum = 0.0;
1134 
1135     for (row = 0; row < 8; row++)
1136       {
1137 	  const unsigned int *p_in_base;
1138 	  unsigned int yy = y + row;
1139 	  if (yy >= tileHeight)
1140 	      break;
1141 	  p_in_base = buf_in + (yy * tileWidth);
1142 	  for (col = 0; col < 8; col++)
1143 	    {
1144 		const unsigned int *p_in;
1145 		unsigned int xx = x + col;
1146 		if (xx >= tileWidth)
1147 		    break;
1148 		p_in = p_in_base + x;
1149 		if (*p_in == nd)
1150 		    nodata++;
1151 		else
1152 		  {
1153 		      valid++;
1154 		      sum += *p_in;
1155 		  }
1156 	    }
1157       }
1158 
1159     if (nodata >= valid)
1160 	return nd;
1161     return (unsigned int) (sum / (double) valid);
1162 }
1163 
1164 static void
rescale_grid_uint32(unsigned int * buf_out,unsigned int tileWidth,unsigned int tileHeight,const unsigned int * buf_in,int x,int y,int tic_x,int tic_y,rl2PixelPtr no_data)1165 rescale_grid_uint32 (unsigned int *buf_out, unsigned int tileWidth,
1166 		     unsigned int tileHeight, const unsigned int *buf_in,
1167 		     int x, int y, int tic_x, int tic_y, rl2PixelPtr no_data)
1168 {
1169 /* rescaling a DataGrid tile - unsigned int 32 bit */
1170     unsigned int row;
1171     unsigned int col;
1172     unsigned int nd = 0;
1173     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) no_data;
1174 
1175     if (pxl != NULL)
1176       {
1177 	  /* retrieving the NO-DATA value */
1178 	  if (pxl->sampleType == RL2_SAMPLE_UINT32 && pxl->nBands == 1)
1179 	    {
1180 		rl2PrivSamplePtr sample = pxl->Samples + 0;
1181 		nd = sample->uint32;
1182 	    }
1183       }
1184 
1185     for (row = 0; row < (unsigned int) tic_y; row++)
1186       {
1187 	  unsigned int yy = row + y;
1188 	  unsigned int *p_out_base = buf_out + (yy * tileWidth);
1189 	  if (yy >= tileHeight)
1190 	      break;
1191 	  for (col = 0; col < (unsigned int) tic_x; col++)
1192 	    {
1193 		unsigned int xx = col + x;
1194 		unsigned int *p_out = p_out_base + xx;
1195 		if (xx >= tileWidth)
1196 		    break;
1197 		*p_out =
1198 		    rescale_pixel_uint32 (buf_in, tileWidth, tileHeight,
1199 					  col * 8, row * 8, nd);
1200 	    }
1201       }
1202 }
1203 
1204 static double
rescale_pixel_float(const float * buf_in,unsigned int tileWidth,unsigned int tileHeight,int x,int y,float nd)1205 rescale_pixel_float (const float *buf_in, unsigned int tileWidth,
1206 		     unsigned int tileHeight, int x, int y, float nd)
1207 {
1208 /* rescaling a DataGrid pixel (8x8) - Float */
1209     unsigned int row;
1210     unsigned int col;
1211     int nodata = 0;
1212     int valid = 0;
1213     double sum = 0.0;
1214 
1215     for (row = 0; row < 8; row++)
1216       {
1217 	  const float *p_in_base;
1218 	  unsigned int yy = y + row;
1219 	  if (yy >= tileHeight)
1220 	      break;
1221 	  p_in_base = buf_in + (yy * tileWidth);
1222 	  for (col = 0; col < 8; col++)
1223 	    {
1224 		const float *p_in;
1225 		unsigned int xx = x + col;
1226 		if (xx >= tileWidth)
1227 		    break;
1228 		p_in = p_in_base + x;
1229 		if (*p_in == nd)
1230 		    nodata++;
1231 		else
1232 		  {
1233 		      valid++;
1234 		      sum += *p_in;
1235 		  }
1236 	    }
1237       }
1238 
1239     if (nodata >= valid)
1240 	return nd;
1241     return (float) (sum / (double) valid);
1242 }
1243 
1244 static void
rescale_grid_float(float * buf_out,unsigned int tileWidth,unsigned int tileHeight,const float * buf_in,int x,int y,int tic_x,int tic_y,rl2PixelPtr no_data)1245 rescale_grid_float (float *buf_out, unsigned int tileWidth,
1246 		    unsigned int tileHeight, const float *buf_in, int x,
1247 		    int y, int tic_x, int tic_y, rl2PixelPtr no_data)
1248 {
1249 /* rescaling a DataGrid tile - Float */
1250     unsigned int row;
1251     unsigned int col;
1252     float nd = 0.0;
1253     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) no_data;
1254 
1255     if (pxl != NULL)
1256       {
1257 	  /* retrieving the NO-DATA value */
1258 	  if (pxl->sampleType == RL2_SAMPLE_FLOAT && pxl->nBands == 1)
1259 	    {
1260 		rl2PrivSamplePtr sample = pxl->Samples + 0;
1261 		nd = sample->float32;
1262 	    }
1263       }
1264 
1265     for (row = 0; row < (unsigned int) tic_y; row++)
1266       {
1267 	  unsigned int yy = row + y;
1268 	  float *p_out_base = buf_out + (yy * tileWidth);
1269 	  if (yy >= tileHeight)
1270 	      break;
1271 	  for (col = 0; col < (unsigned int) tic_x; col++)
1272 	    {
1273 		unsigned int xx = col + x;
1274 		float *p_out = p_out_base + xx;
1275 		if (xx >= tileWidth)
1276 		    break;
1277 		*p_out =
1278 		    rescale_pixel_float (buf_in, tileWidth, tileHeight, col * 8,
1279 					 row * 8, nd);
1280 	    }
1281       }
1282 }
1283 
1284 static double
rescale_pixel_double(const double * buf_in,unsigned int tileWidth,unsigned int tileHeight,int x,int y,double nd)1285 rescale_pixel_double (const double *buf_in, unsigned int tileWidth,
1286 		      unsigned int tileHeight, int x, int y, double nd)
1287 {
1288 /* rescaling a DataGrid pixel (8x8) - Double */
1289     unsigned int row;
1290     unsigned int col;
1291     int nodata = 0;
1292     int valid = 0;
1293     double sum = 0.0;
1294 
1295     for (row = 0; row < 8; row++)
1296       {
1297 	  const double *p_in_base;
1298 	  unsigned int yy = y + row;
1299 	  if (yy >= tileHeight)
1300 	      break;
1301 	  p_in_base = buf_in + (yy * tileWidth);
1302 	  for (col = 0; col < 8; col++)
1303 	    {
1304 		const double *p_in;
1305 		unsigned int xx = x + col;
1306 		if (xx >= tileWidth)
1307 		    break;
1308 		p_in = p_in_base + x;
1309 		if (*p_in == nd)
1310 		    nodata++;
1311 		else
1312 		  {
1313 		      valid++;
1314 		      sum += *p_in;
1315 		  }
1316 	    }
1317       }
1318 
1319     if (nodata >= valid)
1320 	return nd;
1321     return sum / (double) valid;
1322 }
1323 
1324 static void
rescale_grid_double(double * buf_out,unsigned int tileWidth,unsigned int tileHeight,const double * buf_in,int x,int y,int tic_x,int tic_y,rl2PixelPtr no_data)1325 rescale_grid_double (double *buf_out, unsigned int tileWidth,
1326 		     unsigned int tileHeight, const double *buf_in, int x,
1327 		     int y, int tic_x, int tic_y, rl2PixelPtr no_data)
1328 {
1329 /* rescaling a DataGrid tile - Double */
1330     unsigned int row;
1331     unsigned int col;
1332     double nd = 0.0;
1333     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) no_data;
1334 
1335     if (pxl != NULL)
1336       {
1337 	  /* retrieving the NO-DATA value */
1338 	  if (pxl->sampleType == RL2_SAMPLE_DOUBLE && pxl->nBands == 1)
1339 	    {
1340 		rl2PrivSamplePtr sample = pxl->Samples + 0;
1341 		nd = sample->float64;
1342 	    }
1343       }
1344 
1345     for (row = 0; row < (unsigned int) tic_y; row++)
1346       {
1347 	  unsigned int yy = row + y;
1348 	  double *p_out_base = buf_out + (yy * tileWidth);
1349 	  if (yy >= tileHeight)
1350 	      break;
1351 	  for (col = 0; col < (unsigned int) tic_x; col++)
1352 	    {
1353 		unsigned int xx = col + x;
1354 		double *p_out = p_out_base + xx;
1355 		if (xx >= tileWidth)
1356 		    break;
1357 		*p_out =
1358 		    rescale_pixel_double (buf_in, tileWidth, tileHeight,
1359 					  col * 8, row * 8, nd);
1360 	    }
1361       }
1362 }
1363 
1364 static void
rescale_grid(void * buf_out,unsigned int tileWidth,unsigned int tileHeight,const void * buf_in,unsigned char sample_type,int x,int y,int tic_x,int tic_y,rl2PixelPtr no_data)1365 rescale_grid (void *buf_out, unsigned int tileWidth,
1366 	      unsigned int tileHeight, const void *buf_in,
1367 	      unsigned char sample_type, int x, int y, int tic_x, int tic_y,
1368 	      rl2PixelPtr no_data)
1369 {
1370 /* rescaling a DataGrid tile */
1371     switch (sample_type)
1372       {
1373       case RL2_SAMPLE_INT8:
1374 	  rescale_grid_int8 ((char *) buf_out, tileWidth, tileHeight,
1375 			     (const char *) buf_in, x, y, tic_x, tic_y,
1376 			     no_data);
1377 	  break;
1378       case RL2_SAMPLE_UINT8:
1379 	  rescale_grid_uint8 ((unsigned char *) buf_out, tileWidth, tileHeight,
1380 			      (const unsigned char *) buf_in, x, y, tic_x,
1381 			      tic_y, no_data);
1382 	  break;
1383       case RL2_SAMPLE_INT16:
1384 	  rescale_grid_int16 ((short *) buf_out, tileWidth, tileHeight,
1385 			      (const short *) buf_in, x, y, tic_x, tic_y,
1386 			      no_data);
1387 	  break;
1388       case RL2_SAMPLE_UINT16:
1389 	  rescale_grid_uint16 ((unsigned short *) buf_out, tileWidth,
1390 			       tileHeight, (const unsigned short *) buf_in, x,
1391 			       y, tic_x, tic_y, no_data);
1392 	  break;
1393       case RL2_SAMPLE_INT32:
1394 	  rescale_grid_int32 ((int *) buf_out, tileWidth, tileHeight,
1395 			      (const int *) buf_in, x, y, tic_x, tic_y,
1396 			      no_data);
1397 	  break;
1398       case RL2_SAMPLE_UINT32:
1399 	  rescale_grid_uint32 ((unsigned int *) buf_out, tileWidth, tileHeight,
1400 			       (const unsigned int *) buf_in, x, y, tic_x,
1401 			       tic_y, no_data);
1402 	  break;
1403       case RL2_SAMPLE_FLOAT:
1404 	  rescale_grid_float ((float *) buf_out, tileWidth, tileHeight,
1405 			      (const float *) buf_in, x, y, tic_x, tic_y,
1406 			      no_data);
1407 	  break;
1408       case RL2_SAMPLE_DOUBLE:
1409 	  rescale_grid_double ((double *) buf_out, tileWidth, tileHeight,
1410 			       (const double *) buf_in, x, y, tic_x, tic_y,
1411 			       no_data);
1412 	  break;
1413       };
1414 }
1415 
1416 static int
update_sect_pyramid_grid(sqlite3 * handle,sqlite3_stmt * stmt_rd,sqlite3_stmt * stmt_tils,sqlite3_stmt * stmt_data,SectionPyramid * pyr,unsigned int tileWidth,unsigned int tileHeight,int id_level,rl2PixelPtr no_data,unsigned char sample_type)1417 update_sect_pyramid_grid (sqlite3 * handle, sqlite3_stmt * stmt_rd,
1418 			  sqlite3_stmt * stmt_tils, sqlite3_stmt * stmt_data,
1419 			  SectionPyramid * pyr, unsigned int tileWidth,
1420 			  unsigned int tileHeight, int id_level,
1421 			  rl2PixelPtr no_data, unsigned char sample_type)
1422 {
1423 /* creating and inserting Pyramid tiles */
1424     unsigned char *buf_out = NULL;
1425     unsigned char *mask = NULL;
1426     SectionPyramidTileOutPtr tile_out;
1427     SectionPyramidTileRefPtr tile_in;
1428     unsigned int x;
1429     unsigned int y;
1430     unsigned int row;
1431     unsigned int col;
1432     int tic_x;
1433     int tic_y;
1434     double pos_y;
1435     double pos_x;
1436     double geo_x;
1437     double geo_y;
1438     rl2PixelPtr nd = NULL;
1439     rl2RasterPtr raster_out = NULL;
1440     rl2RasterPtr raster_in = NULL;
1441     unsigned char *blob_odd;
1442     int blob_odd_sz;
1443     unsigned char *blob_even;
1444     int blob_even_sz;
1445     int pixel_sz = 1;
1446     int out_sz;
1447     int mask_sz = 0;
1448 
1449     if (pyr == NULL)
1450 	goto error;
1451     tic_x = tileWidth / pyr->scale;
1452     tic_y = tileHeight / pyr->scale;
1453     geo_x = (double) tic_x *pyr->res_x;
1454     geo_y = (double) tic_y *pyr->res_y;
1455 
1456     switch (sample_type)
1457       {
1458       case RL2_SAMPLE_INT16:
1459       case RL2_SAMPLE_UINT16:
1460 	  pixel_sz = 2;
1461 	  break;
1462       case RL2_SAMPLE_INT32:
1463       case RL2_SAMPLE_UINT32:
1464       case RL2_SAMPLE_FLOAT:
1465 	  pixel_sz = 4;
1466 	  break;
1467       case RL2_SAMPLE_DOUBLE:
1468 	  pixel_sz = 8;
1469 	  break;
1470       };
1471     out_sz = tileWidth * tileHeight * pixel_sz;
1472 
1473     tile_out = pyr->first_out;
1474     while (tile_out != NULL)
1475       {
1476 	  rl2PrivRasterPtr rst;
1477 	  /* allocating the output buffer */
1478 	  buf_out = malloc (out_sz);
1479 	  if (buf_out == NULL)
1480 	      goto error;
1481 	  rl2_prime_void_tile (buf_out, tileWidth, tileHeight, sample_type, 1,
1482 			       no_data);
1483 
1484 	  if (tile_out->col + tileWidth > pyr->scaled_width
1485 	      || tile_out->row + tileHeight > pyr->scaled_height)
1486 	    {
1487 		/* allocating and initializing a transparency mask */
1488 		unsigned char *p;
1489 		mask_sz = tileWidth * tileHeight;
1490 		mask = malloc (mask_sz);
1491 		if (mask == NULL)
1492 		    goto error;
1493 		p = mask;
1494 		for (row = 0; row < tileHeight; row++)
1495 		  {
1496 		      unsigned int x_row = tile_out->row + row;
1497 		      for (col = 0; col < tileWidth; col++)
1498 			{
1499 			    unsigned int x_col = tile_out->col + col;
1500 			    if (x_row >= pyr->scaled_height
1501 				|| x_col >= pyr->scaled_width)
1502 			      {
1503 				  /* masking any portion of the tile exceeding the scaled section size */
1504 				  *p++ = 0;
1505 			      }
1506 			    else
1507 				*p++ = 1;
1508 			}
1509 		  }
1510 	    }
1511 	  else
1512 	    {
1513 		mask = NULL;
1514 		mask_sz = 0;
1515 	    }
1516 
1517 	  /* creating the output (rescaled) tile */
1518 	  tile_in = tile_out->first;
1519 	  while (tile_in != NULL)
1520 	    {
1521 		/* loading and rescaling the base tiles */
1522 		raster_in =
1523 		    load_tile_base_generic (stmt_rd, tile_in->child->tile_id);
1524 		if (raster_in == NULL)
1525 		    goto error;
1526 		pos_y = tile_out->maxy;
1527 		x = 0;
1528 		y = 0;
1529 		for (row = 0; row < tileHeight; row += tic_y)
1530 		  {
1531 		      pos_x = tile_out->minx;
1532 		      for (col = 0; col < tileWidth; col += tic_x)
1533 			{
1534 			    if (tile_in->child->cy < pos_y
1535 				&& tile_in->child->cy > (pos_y - geo_y)
1536 				&& tile_in->child->cx > pos_x
1537 				&& tile_in->child->cx < (pos_x + geo_x))
1538 			      {
1539 				  x = col;
1540 				  y = row;
1541 				  break;
1542 			      }
1543 			    pos_x += geo_x;
1544 			}
1545 		      pos_y -= geo_y;
1546 		  }
1547 		rst = (rl2PrivRasterPtr) raster_in;
1548 		rescale_grid (buf_out, tileWidth, tileHeight, rst->rasterBuffer,
1549 			      sample_type, x, y, tic_x, tic_y, no_data);
1550 		rl2_destroy_raster (raster_in);
1551 		raster_in = NULL;
1552 		tile_in = tile_in->next;
1553 	    }
1554 
1555 	  raster_out = NULL;
1556 	  raster_out =
1557 	      rl2_create_raster (tileWidth, tileHeight, sample_type,
1558 				 RL2_PIXEL_DATAGRID, 1, buf_out,
1559 				 out_sz, NULL, mask, mask_sz, nd);
1560 	  buf_out = NULL;
1561 	  mask = NULL;
1562 	  if (raster_out == NULL)
1563 	    {
1564 		fprintf (stderr, "ERROR: unable to create a Pyramid Tile\n");
1565 		goto error;
1566 	    }
1567 	  if (rl2_raster_encode
1568 	      (raster_out, RL2_COMPRESSION_DEFLATE, &blob_odd, &blob_odd_sz,
1569 	       &blob_even, &blob_even_sz, 100, 1) != RL2_OK)
1570 	    {
1571 		fprintf (stderr, "ERROR: unable to encode a Pyramid tile\n");
1572 		goto error;
1573 	    }
1574 	  rl2_destroy_raster (raster_out);
1575 	  raster_out = NULL;
1576 
1577 	  /* INSERTing the tile */
1578 	  if (!do_insert_pyramid_tile
1579 	      (handle, blob_odd, blob_odd_sz, blob_even, blob_even_sz, id_level,
1580 	       pyr->section_id, pyr->srid, tile_out->minx, tile_out->miny,
1581 	       tile_out->maxx, tile_out->maxy, stmt_tils, stmt_data))
1582 	      goto error;
1583 
1584 	  tile_out = tile_out->next;
1585       }
1586 
1587     return 1;
1588 
1589   error:
1590     if (raster_in != NULL)
1591 	rl2_destroy_raster (raster_in);
1592     if (raster_out != NULL)
1593 	rl2_destroy_raster (raster_out);
1594     if (buf_out != NULL)
1595 	free (buf_out);
1596     if (mask != NULL)
1597 	free (mask);
1598     return 0;
1599 }
1600 
1601 static double
rescale_mb_pixel_uint8(const unsigned char * buf_in,unsigned int tileWidth,unsigned int tileHeight,unsigned int x,unsigned int y,unsigned char nd,unsigned char nb,unsigned char num_bands)1602 rescale_mb_pixel_uint8 (const unsigned char *buf_in, unsigned int tileWidth,
1603 			unsigned int tileHeight, unsigned int x, unsigned int y,
1604 			unsigned char nd, unsigned char nb,
1605 			unsigned char num_bands)
1606 {
1607 /* rescaling a MultiBand pixel sample (8x8) - UINT8 */
1608     unsigned int row;
1609     unsigned int col;
1610     int nodata = 0;
1611     int valid = 0;
1612     double sum = 0.0;
1613 
1614     for (row = 0; row < 8; row++)
1615       {
1616 	  const unsigned char *p_in_base;
1617 	  unsigned int yy = y + row;
1618 	  if (yy >= tileHeight)
1619 	      break;
1620 	  p_in_base = buf_in + (yy * tileWidth * num_bands);
1621 	  for (col = 0; col < 8; col++)
1622 	    {
1623 		const unsigned char *p_in;
1624 		unsigned int xx = x + col;
1625 		if (xx >= tileWidth)
1626 		    break;
1627 		p_in = p_in_base + (xx * num_bands) + nb;
1628 		if (*p_in == nd)
1629 		    nodata++;
1630 		else
1631 		  {
1632 		      valid++;
1633 		      sum += *p_in;
1634 		  }
1635 	    }
1636       }
1637 
1638     if (nodata >= valid)
1639 	return nd;
1640     return (unsigned char) (sum / (double) valid);
1641 }
1642 
1643 static void
rescale_multiband_uint8(unsigned char * buf_out,unsigned int tileWidth,unsigned int tileHeight,const unsigned char * buf_in,unsigned int x,unsigned int y,unsigned int tic_x,unsigned int tic_y,unsigned char num_bands,rl2PixelPtr no_data)1644 rescale_multiband_uint8 (unsigned char *buf_out, unsigned int tileWidth,
1645 			 unsigned int tileHeight, const unsigned char *buf_in,
1646 			 unsigned int x, unsigned int y, unsigned int tic_x,
1647 			 unsigned int tic_y, unsigned char num_bands,
1648 			 rl2PixelPtr no_data)
1649 {
1650 /* rescaling a MultiBand tile - unsigned int 8 bit */
1651     unsigned int row;
1652     unsigned int col;
1653     unsigned char nb;
1654     unsigned char nd = 0;
1655     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) no_data;
1656 
1657     for (row = 0; row < tic_y; row++)
1658       {
1659 	  unsigned int yy = row + y;
1660 	  unsigned char *p_out_base = buf_out + (yy * tileWidth * num_bands);
1661 	  if (yy >= tileHeight)
1662 	      break;
1663 	  for (col = 0; col < tic_x; col++)
1664 	    {
1665 		unsigned int xx = col + x;
1666 		unsigned char *p_out = p_out_base + (xx * num_bands);
1667 		if (xx >= tileWidth)
1668 		    break;
1669 		for (nb = 0; nb < num_bands; nb++)
1670 		  {
1671 		      if (pxl != NULL)
1672 			{
1673 			    if (pxl->sampleType == RL2_SAMPLE_UINT8
1674 				&& pxl->nBands == num_bands)
1675 			      {
1676 				  rl2PrivSamplePtr sample = pxl->Samples + nb;
1677 				  nd = sample->uint8;
1678 			      }
1679 			}
1680 		      *(p_out + nb) =
1681 			  rescale_mb_pixel_uint8 (buf_in, tileWidth, tileHeight,
1682 						  col * 8, row * 8, nd, nb,
1683 						  num_bands);
1684 		  }
1685 	    }
1686       }
1687 }
1688 
1689 static double
rescale_mb_pixel_uint16(const unsigned short * buf_in,unsigned int tileWidth,unsigned int tileHeight,unsigned int x,unsigned int y,unsigned short nd,unsigned char nb,unsigned char num_bands)1690 rescale_mb_pixel_uint16 (const unsigned short *buf_in, unsigned int tileWidth,
1691 			 unsigned int tileHeight, unsigned int x,
1692 			 unsigned int y, unsigned short nd, unsigned char nb,
1693 			 unsigned char num_bands)
1694 {
1695 /* rescaling a MultiBand pixel sample (8x8) - UINT16 */
1696     unsigned int row;
1697     unsigned int col;
1698     int nodata = 0;
1699     int valid = 0;
1700     double sum = 0.0;
1701 
1702     for (row = 0; row < 8; row++)
1703       {
1704 	  const unsigned short *p_in_base;
1705 	  unsigned int yy = y + row;
1706 	  if (yy >= tileHeight)
1707 	      break;
1708 	  p_in_base = buf_in + (yy * tileWidth * num_bands);
1709 	  for (col = 0; col < 8; col++)
1710 	    {
1711 		const unsigned short *p_in;
1712 		unsigned int xx = x + col;
1713 		if (xx >= tileWidth)
1714 		    break;
1715 		p_in = p_in_base + (xx * num_bands) + nb;
1716 		if (*p_in == nd)
1717 		    nodata++;
1718 		else
1719 		  {
1720 		      valid++;
1721 		      sum += *p_in;
1722 		  }
1723 	    }
1724       }
1725 
1726     if (nodata >= valid)
1727 	return nd;
1728     return (unsigned short) (sum / (double) valid);
1729 }
1730 
1731 static void
rescale_multiband_uint16(unsigned short * buf_out,unsigned int tileWidth,unsigned int tileHeight,const unsigned short * buf_in,unsigned int x,unsigned int y,unsigned int tic_x,unsigned int tic_y,unsigned char num_bands,rl2PixelPtr no_data)1732 rescale_multiband_uint16 (unsigned short *buf_out, unsigned int tileWidth,
1733 			  unsigned int tileHeight,
1734 			  const unsigned short *buf_in, unsigned int x,
1735 			  unsigned int y, unsigned int tic_x,
1736 			  unsigned int tic_y, unsigned char num_bands,
1737 			  rl2PixelPtr no_data)
1738 {
1739 /* rescaling a MultiBand tile - unsigned int 16 bit */
1740     unsigned int row;
1741     unsigned int col;
1742     unsigned char nb;
1743     unsigned short nd = 0;
1744     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) no_data;
1745 
1746     for (row = 0; row < tic_y; row++)
1747       {
1748 	  unsigned int yy = row + y;
1749 	  unsigned short *p_out_base = buf_out + (yy * tileWidth * num_bands);
1750 	  if (yy >= tileHeight)
1751 	      break;
1752 	  for (col = 0; col < tic_x; col++)
1753 	    {
1754 		unsigned int xx = col + x;
1755 		unsigned short *p_out = p_out_base + (xx * num_bands);
1756 		if (xx >= tileWidth)
1757 		    break;
1758 		for (nb = 0; nb < num_bands; nb++)
1759 		  {
1760 		      if (pxl != NULL)
1761 			{
1762 			    if (pxl->sampleType == RL2_SAMPLE_UINT16
1763 				&& pxl->nBands == num_bands)
1764 			      {
1765 				  rl2PrivSamplePtr sample = pxl->Samples + nb;
1766 				  nd = sample->uint16;
1767 			      }
1768 			}
1769 		      *(p_out + nb) =
1770 			  rescale_mb_pixel_uint16 (buf_in, tileWidth,
1771 						   tileHeight, col * 8, row * 8,
1772 						   nd, nb, num_bands);
1773 		  }
1774 	    }
1775       }
1776 }
1777 
1778 static void
rescale_multiband(void * buf_out,unsigned int tileWidth,unsigned int tileHeight,const void * buf_in,unsigned char sample_type,unsigned char num_bands,unsigned int x,unsigned int y,unsigned int tic_x,unsigned int tic_y,rl2PixelPtr no_data)1779 rescale_multiband (void *buf_out, unsigned int tileWidth,
1780 		   unsigned int tileHeight, const void *buf_in,
1781 		   unsigned char sample_type, unsigned char num_bands,
1782 		   unsigned int x, unsigned int y, unsigned int tic_x,
1783 		   unsigned int tic_y, rl2PixelPtr no_data)
1784 {
1785 /* rescaling a Multiband tile */
1786     switch (sample_type)
1787       {
1788       case RL2_SAMPLE_UINT8:
1789 	  rescale_multiband_uint8 ((unsigned char *) buf_out, tileWidth,
1790 				   tileHeight, (const unsigned char *) buf_in,
1791 				   x, y, tic_x, tic_y, num_bands, no_data);
1792 	  break;
1793       case RL2_SAMPLE_UINT16:
1794 	  rescale_multiband_uint16 ((unsigned short *) buf_out, tileWidth,
1795 				    tileHeight, (const unsigned short *) buf_in,
1796 				    x, y, tic_x, tic_y, num_bands, no_data);
1797 	  break;
1798       };
1799 }
1800 
1801 static int
update_sect_pyramid_multiband(sqlite3 * handle,sqlite3_stmt * stmt_rd,sqlite3_stmt * stmt_tils,sqlite3_stmt * stmt_data,SectionPyramid * pyr,unsigned int tileWidth,unsigned int tileHeight,int id_level,rl2PixelPtr no_data,unsigned char sample_type,unsigned char num_bands)1802 update_sect_pyramid_multiband (sqlite3 * handle, sqlite3_stmt * stmt_rd,
1803 			       sqlite3_stmt * stmt_tils,
1804 			       sqlite3_stmt * stmt_data, SectionPyramid * pyr,
1805 			       unsigned int tileWidth,
1806 			       unsigned int tileHeight, int id_level,
1807 			       rl2PixelPtr no_data, unsigned char sample_type,
1808 			       unsigned char num_bands)
1809 {
1810 /* creating and inserting Pyramid tiles */
1811     unsigned char *buf_out = NULL;
1812     unsigned char *mask = NULL;
1813     SectionPyramidTileOutPtr tile_out;
1814     SectionPyramidTileRefPtr tile_in;
1815     unsigned int x;
1816     unsigned int y;
1817     unsigned int row;
1818     unsigned int col;
1819     unsigned int tic_x;
1820     unsigned int tic_y;
1821     double pos_y;
1822     double pos_x;
1823     double geo_x;
1824     double geo_y;
1825     rl2PixelPtr nd = NULL;
1826     rl2RasterPtr raster_out = NULL;
1827     rl2RasterPtr raster_in = NULL;
1828     unsigned char *blob_odd;
1829     int blob_odd_sz;
1830     unsigned char *blob_even;
1831     int blob_even_sz;
1832     int pixel_sz = 1;
1833     int out_sz;
1834     int mask_sz = 0;
1835 
1836     if (pyr == NULL)
1837 	goto error;
1838     tic_x = tileWidth / pyr->scale;
1839     tic_y = tileHeight / pyr->scale;
1840     geo_x = (double) tic_x *pyr->res_x;
1841     geo_y = (double) tic_y *pyr->res_y;
1842 
1843     switch (sample_type)
1844       {
1845       case RL2_SAMPLE_UINT16:
1846 	  pixel_sz = 2;
1847 	  break;
1848       };
1849     out_sz = tileWidth * tileHeight * pixel_sz * num_bands;
1850 
1851     tile_out = pyr->first_out;
1852     while (tile_out != NULL)
1853       {
1854 	  rl2PrivRasterPtr rst;
1855 	  /* allocating the output buffer */
1856 	  buf_out = malloc (out_sz);
1857 	  if (buf_out == NULL)
1858 	      goto error;
1859 	  rl2_prime_void_tile (buf_out, tileWidth, tileHeight, sample_type,
1860 			       num_bands, no_data);
1861 
1862 	  if (tile_out->col + tileWidth > pyr->scaled_width
1863 	      || tile_out->row + tileHeight > pyr->scaled_height)
1864 	    {
1865 		/* allocating and initializing a transparency mask */
1866 		unsigned char *p;
1867 		mask_sz = tileWidth * tileHeight;
1868 		mask = malloc (mask_sz);
1869 		if (mask == NULL)
1870 		    goto error;
1871 		p = mask;
1872 		for (row = 0; row < tileHeight; row++)
1873 		  {
1874 		      unsigned int x_row = tile_out->row + row;
1875 		      for (col = 0; col < tileWidth; col++)
1876 			{
1877 			    unsigned int x_col = tile_out->col + col;
1878 			    if (x_row >= pyr->scaled_height
1879 				|| x_col >= pyr->scaled_width)
1880 			      {
1881 				  /* masking any portion of the tile exceeding the scaled section size */
1882 				  *p++ = 0;
1883 			      }
1884 			    else
1885 				*p++ = 1;
1886 			}
1887 		  }
1888 	    }
1889 	  else
1890 	    {
1891 		mask = NULL;
1892 		mask_sz = 0;
1893 	    }
1894 
1895 	  /* creating the output (rescaled) tile */
1896 	  tile_in = tile_out->first;
1897 	  while (tile_in != NULL)
1898 	    {
1899 		/* loading and rescaling the base tiles */
1900 		raster_in =
1901 		    load_tile_base_generic (stmt_rd, tile_in->child->tile_id);
1902 		if (raster_in == NULL)
1903 		    goto error;
1904 		pos_y = tile_out->maxy;
1905 		x = 0;
1906 		y = 0;
1907 		for (row = 0; row < tileHeight; row += tic_y)
1908 		  {
1909 		      pos_x = tile_out->minx;
1910 		      for (col = 0; col < tileWidth; col += tic_x)
1911 			{
1912 			    if (tile_in->child->cy < pos_y
1913 				&& tile_in->child->cy > (pos_y - geo_y)
1914 				&& tile_in->child->cx > pos_x
1915 				&& tile_in->child->cx < (pos_x + geo_x))
1916 			      {
1917 				  x = col;
1918 				  y = row;
1919 				  break;
1920 			      }
1921 			    pos_x += geo_x;
1922 			}
1923 		      pos_y -= geo_y;
1924 		  }
1925 		rst = (rl2PrivRasterPtr) raster_in;
1926 		rescale_multiband (buf_out, tileWidth, tileHeight,
1927 				   rst->rasterBuffer, sample_type, num_bands, x,
1928 				   y, tic_x, tic_y, no_data);
1929 		rl2_destroy_raster (raster_in);
1930 		raster_in = NULL;
1931 		tile_in = tile_in->next;
1932 	    }
1933 
1934 	  raster_out = NULL;
1935 	  raster_out =
1936 	      rl2_create_raster (tileWidth, tileHeight, sample_type,
1937 				 RL2_PIXEL_MULTIBAND, num_bands, buf_out,
1938 				 out_sz, NULL, mask, mask_sz, nd);
1939 	  buf_out = NULL;
1940 	  mask = NULL;
1941 	  if (raster_out == NULL)
1942 	    {
1943 		fprintf (stderr, "ERROR: unable to create a Pyramid Tile\n");
1944 		goto error;
1945 	    }
1946 	  if (rl2_raster_encode
1947 	      (raster_out, RL2_COMPRESSION_DEFLATE, &blob_odd, &blob_odd_sz,
1948 	       &blob_even, &blob_even_sz, 100, 1) != RL2_OK)
1949 	    {
1950 		fprintf (stderr, "ERROR: unable to encode a Pyramid tile\n");
1951 		goto error;
1952 	    }
1953 	  rl2_destroy_raster (raster_out);
1954 	  raster_out = NULL;
1955 
1956 	  /* INSERTing the tile */
1957 	  if (!do_insert_pyramid_tile
1958 	      (handle, blob_odd, blob_odd_sz, blob_even, blob_even_sz, id_level,
1959 	       pyr->section_id, pyr->srid, tile_out->minx, tile_out->miny,
1960 	       tile_out->maxx, tile_out->maxy, stmt_tils, stmt_data))
1961 	      goto error;
1962 
1963 	  tile_out = tile_out->next;
1964       }
1965 
1966     return 1;
1967 
1968   error:
1969     if (raster_in != NULL)
1970 	rl2_destroy_raster (raster_in);
1971     if (raster_out != NULL)
1972 	rl2_destroy_raster (raster_out);
1973     if (buf_out != NULL)
1974 	free (buf_out);
1975     if (mask != NULL)
1976 	free (mask);
1977     return 0;
1978 }
1979 
1980 static int
update_sect_pyramid(sqlite3 * handle,sqlite3_stmt * stmt_rd,sqlite3_stmt * stmt_tils,sqlite3_stmt * stmt_data,SectionPyramid * pyr,unsigned int tileWidth,unsigned int tileHeight,int id_level,rl2PalettePtr palette,rl2PixelPtr no_data)1981 update_sect_pyramid (sqlite3 * handle, sqlite3_stmt * stmt_rd,
1982 		     sqlite3_stmt * stmt_tils, sqlite3_stmt * stmt_data,
1983 		     SectionPyramid * pyr, unsigned int tileWidth,
1984 		     unsigned int tileHeight, int id_level,
1985 		     rl2PalettePtr palette, rl2PixelPtr no_data)
1986 {
1987 /* creating and inserting Pyramid tiles */
1988     unsigned char *buf_in;
1989     SectionPyramidTileOutPtr tile_out;
1990     SectionPyramidTileRefPtr tile_in;
1991     rl2GraphicsBitmapPtr base_tile;
1992     rl2GraphicsContextPtr ctx = NULL;
1993     unsigned int x;
1994     unsigned int y;
1995     unsigned int row;
1996     unsigned int col;
1997     unsigned int tic_x;
1998     unsigned int tic_y;
1999     double pos_y;
2000     double pos_x;
2001     double geo_x;
2002     double geo_y;
2003     unsigned char *rgb = NULL;
2004     unsigned char *alpha = NULL;
2005     rl2PixelPtr nd = NULL;
2006     rl2RasterPtr raster = NULL;
2007     unsigned char *blob_odd;
2008     int blob_odd_sz;
2009     unsigned char *blob_even;
2010     int blob_even_sz;
2011     unsigned char *p;
2012     unsigned char compression = RL2_COMPRESSION_NONE;
2013 
2014     if (pyr == NULL)
2015 	goto error;
2016     tic_x = tileWidth / pyr->scale;
2017     tic_y = tileHeight / pyr->scale;
2018     geo_x = (double) tic_x *pyr->res_x;
2019     geo_y = (double) tic_y *pyr->res_y;
2020 
2021     tile_out = pyr->first_out;
2022     while (tile_out != NULL)
2023       {
2024 	  /* creating the output (rescaled) tile */
2025 	  ctx = rl2_graph_create_context (tileWidth, tileHeight);
2026 	  if (ctx == NULL)
2027 	      goto error;
2028 	  tile_in = tile_out->first;
2029 	  while (tile_in != NULL)
2030 	    {
2031 		/* loading and rescaling the base tiles */
2032 		buf_in =
2033 		    load_tile_base (stmt_rd, tile_in->child->tile_id, palette,
2034 				    no_data);
2035 		if (buf_in == NULL)
2036 		    goto error;
2037 		base_tile =
2038 		    rl2_graph_create_bitmap (buf_in, tileWidth, tileHeight);
2039 		if (base_tile == NULL)
2040 		  {
2041 		      free (buf_in);
2042 		      goto error;
2043 		  }
2044 		pos_y = tile_out->maxy;
2045 		x = 0;
2046 		y = 0;
2047 		for (row = 0; row < tileHeight; row += tic_y)
2048 		  {
2049 		      pos_x = tile_out->minx;
2050 		      for (col = 0; col < tileWidth; col += tic_x)
2051 			{
2052 			    if (tile_in->child->cy < pos_y
2053 				&& tile_in->child->cy > (pos_y - geo_y)
2054 				&& tile_in->child->cx > pos_x
2055 				&& tile_in->child->cx < (pos_x + geo_x))
2056 			      {
2057 				  x = col;
2058 				  y = row;
2059 				  break;
2060 			      }
2061 			    pos_x += geo_x;
2062 			}
2063 		      pos_y -= geo_y;
2064 		  }
2065 		rl2_graph_draw_rescaled_bitmap (ctx, base_tile,
2066 						1.0 / pyr->scale,
2067 						1.0 / pyr->scale, x, y);
2068 		rl2_graph_destroy_bitmap (base_tile);
2069 		tile_in = tile_in->next;
2070 	    }
2071 
2072 	  rgb = rl2_graph_get_context_rgb_array (ctx);
2073 	  if (rgb == NULL)
2074 	      goto error;
2075 	  alpha = rl2_graph_get_context_alpha_array (ctx);
2076 	  if (alpha == NULL)
2077 	      goto error;
2078 	  p = alpha;
2079 	  for (row = 0; row < tileHeight; row++)
2080 	    {
2081 		unsigned int x_row = tile_out->row + row;
2082 		for (col = 0; col < tileWidth; col++)
2083 		  {
2084 		      unsigned int x_col = tile_out->col + col;
2085 		      if (x_row >= pyr->scaled_height
2086 			  || x_col >= pyr->scaled_width)
2087 			{
2088 			    /* masking any portion of the tile exceeding the scaled section size */
2089 			    *p++ = 0;
2090 			}
2091 		      else
2092 			{
2093 			    if (*p == 0)
2094 				p++;
2095 			    else
2096 				*p++ = 1;
2097 			}
2098 		  }
2099 	    }
2100 
2101 	  raster = NULL;
2102 	  if (pyr->pixel_type == RL2_PIXEL_GRAYSCALE
2103 	      || pyr->pixel_type == RL2_PIXEL_MONOCHROME)
2104 	    {
2105 		/* Grayscale Pyramid */
2106 		unsigned char *p_in;
2107 		unsigned char *p_out;
2108 		unsigned char *gray = malloc (tileWidth * tileHeight);
2109 		if (gray == NULL)
2110 		    goto error;
2111 		p_in = rgb;
2112 		p_out = gray;
2113 		for (row = 0; row < tileHeight; row++)
2114 		  {
2115 		      for (col = 0; col < tileWidth; col++)
2116 			{
2117 			    *p_out++ = *p_in++;
2118 			    p_in += 2;
2119 			}
2120 		  }
2121 		free (rgb);
2122 		if (pyr->pixel_type == RL2_PIXEL_MONOCHROME)
2123 		  {
2124 		      if (no_data == NULL)
2125 			  nd = NULL;
2126 		      else
2127 			{
2128 			    /* converting the NO-DATA pixel */
2129 			    rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) no_data;
2130 			    rl2PrivSamplePtr sample = pxl->Samples + 0;
2131 			    nd = rl2_create_pixel (RL2_SAMPLE_UINT8,
2132 						   RL2_PIXEL_GRAYSCALE, 1);
2133 			    if (sample->uint8 == 0)
2134 				rl2_set_pixel_sample_uint8 (nd,
2135 							    RL2_GRAYSCALE_BAND,
2136 							    255);
2137 			    else
2138 				rl2_set_pixel_sample_uint8 (nd,
2139 							    RL2_GRAYSCALE_BAND,
2140 							    0);
2141 			}
2142 		      compression = RL2_COMPRESSION_PNG;
2143 		  }
2144 		else
2145 		  {
2146 		      nd = rl2_clone_pixel (no_data);
2147 		      compression = RL2_COMPRESSION_JPEG;
2148 		  }
2149 		raster =
2150 		    rl2_create_raster (tileWidth, tileHeight, RL2_SAMPLE_UINT8,
2151 				       RL2_PIXEL_GRAYSCALE, 1, gray,
2152 				       tileWidth * tileHeight, NULL, alpha,
2153 				       tileWidth * tileHeight, nd);
2154 	    }
2155 	  else if (pyr->pixel_type == RL2_PIXEL_RGB)
2156 	    {
2157 		/* RGB Pyramid */
2158 		nd = rl2_clone_pixel (no_data);
2159 		raster =
2160 		    rl2_create_raster (tileWidth, tileHeight, RL2_SAMPLE_UINT8,
2161 				       RL2_PIXEL_RGB, 3, rgb,
2162 				       tileWidth * tileHeight * 3, NULL, alpha,
2163 				       tileWidth * tileHeight, nd);
2164 		compression = RL2_COMPRESSION_JPEG;
2165 	    }
2166 	  if (raster == NULL)
2167 	    {
2168 		fprintf (stderr, "ERROR: unable to create a Pyramid Tile\n");
2169 		goto error;
2170 	    }
2171 	  if (rl2_raster_encode
2172 	      (raster, compression, &blob_odd, &blob_odd_sz, &blob_even,
2173 	       &blob_even_sz, 80, 1) != RL2_OK)
2174 	    {
2175 		fprintf (stderr, "ERROR: unable to encode a Pyramid tile\n");
2176 		goto error;
2177 	    }
2178 	  rl2_destroy_raster (raster);
2179 	  raster = NULL;
2180 	  rl2_graph_destroy_context (ctx);
2181 	  ctx = NULL;
2182 
2183 	  /* INSERTing the tile */
2184 	  if (!do_insert_pyramid_tile
2185 	      (handle, blob_odd, blob_odd_sz, blob_even, blob_even_sz, id_level,
2186 	       pyr->section_id, pyr->srid, tile_out->minx, tile_out->miny,
2187 	       tile_out->maxx, tile_out->maxy, stmt_tils, stmt_data))
2188 	      goto error;
2189 
2190 	  tile_out = tile_out->next;
2191       }
2192 
2193     return 1;
2194 
2195   error:
2196     if (raster != NULL)
2197 	rl2_destroy_raster (raster);
2198     if (ctx != NULL)
2199 	rl2_graph_destroy_context (ctx);
2200     return 0;
2201 }
2202 
2203 static int
rescale_monolithic_rgba(int id_level,unsigned int tileWidth,unsigned int tileHeight,int factor,double res_x,double res_y,double minx,double miny,double maxx,double maxy,unsigned char * buffer,int buf_size,unsigned char * mask,int * mask_size,rl2PalettePtr palette,rl2PixelPtr no_data,sqlite3_stmt * stmt_geo,sqlite3_stmt * stmt_data)2204 rescale_monolithic_rgba (int id_level,
2205 			 unsigned int tileWidth, unsigned int tileHeight,
2206 			 int factor, double res_x, double res_y, double minx,
2207 			 double miny, double maxx, double maxy,
2208 			 unsigned char *buffer, int buf_size,
2209 			 unsigned char *mask, int *mask_size,
2210 			 rl2PalettePtr palette, rl2PixelPtr no_data,
2211 			 sqlite3_stmt * stmt_geo, sqlite3_stmt * stmt_data)
2212 {
2213 /* rescaling a monolithic RGBA tile */
2214     rl2GraphicsContextPtr ctx = NULL;
2215     rl2GraphicsBitmapPtr base_tile = NULL;
2216     unsigned char *rgba = NULL;
2217     unsigned int x;
2218     unsigned int y;
2219     int ret;
2220     double shift_x;
2221     double shift_y;
2222     double scale_x;
2223     double scale_y;
2224     unsigned char *rgb = NULL;
2225     unsigned char *alpha = NULL;
2226     int valid_mask = 0;
2227     unsigned char *p_in;
2228     unsigned char *p_out;
2229     unsigned char *p_msk;
2230 
2231 /* creating a graphics context */
2232     ctx = rl2_graph_create_context (tileWidth, tileHeight);
2233     if (ctx == NULL)
2234 	goto error;
2235 /* binding the BBOX to be queried */
2236     sqlite3_reset (stmt_geo);
2237     sqlite3_clear_bindings (stmt_geo);
2238     sqlite3_bind_int (stmt_geo, 1, id_level);
2239     sqlite3_bind_double (stmt_geo, 2, minx);
2240     sqlite3_bind_double (stmt_geo, 3, miny);
2241     sqlite3_bind_double (stmt_geo, 4, maxx);
2242     sqlite3_bind_double (stmt_geo, 5, maxy);
2243     while (1)
2244       {
2245 	  /* scrolling the result set rows */
2246 	  ret = sqlite3_step (stmt_geo);
2247 	  if (ret == SQLITE_DONE)
2248 	      break;		/* end of result set */
2249 	  if (ret == SQLITE_ROW)
2250 	    {
2251 		sqlite3_int64 tile_id = sqlite3_column_int64 (stmt_geo, 0);
2252 		double tile_x = sqlite3_column_double (stmt_geo, 1);
2253 		double tile_y = sqlite3_column_double (stmt_geo, 2);
2254 
2255 		rgba = load_tile_base (stmt_data, tile_id, palette, no_data);
2256 		if (rgba == NULL)
2257 		    goto error;
2258 		base_tile =
2259 		    rl2_graph_create_bitmap (rgba, tileWidth, tileHeight);
2260 		if (base_tile == NULL)
2261 		  {
2262 		      free (rgba);
2263 		      goto error;
2264 		  }
2265 		shift_x = tile_x - minx;
2266 		shift_y = maxy - tile_y;
2267 		scale_x = 1.0 / (double) factor;
2268 		scale_y = 1.0 / (double) factor;
2269 		x = (int) (shift_x / res_x);
2270 		y = (int) (shift_y / res_y);
2271 		rl2_graph_draw_rescaled_bitmap (ctx, base_tile,
2272 						scale_x, scale_y, x, y);
2273 		rl2_graph_destroy_bitmap (base_tile);
2274 	    }
2275       }
2276 
2277     rgb = rl2_graph_get_context_rgb_array (ctx);
2278     if (rgb == NULL)
2279 	goto error;
2280     alpha = rl2_graph_get_context_alpha_array (ctx);
2281     if (alpha == NULL)
2282 	goto error;
2283     rl2_graph_destroy_context (ctx);
2284     if (buf_size == (int) (tileWidth * tileHeight))
2285       {
2286 	  /* Grayscale */
2287 	  p_in = rgb;
2288 	  p_msk = alpha;
2289 	  p_out = buffer;
2290 	  for (y = 0; y < tileHeight; y++)
2291 	    {
2292 		for (x = 0; x < tileWidth; x++)
2293 		  {
2294 		      if (*p_msk++ < 128)
2295 			{
2296 			    /* skipping a transparent pixel */
2297 			    p_in += 3;
2298 			    p_out += 3;
2299 			}
2300 		      else
2301 			{
2302 			    /* copying an opaque pixel */
2303 			    *p_out++ = *p_in++;
2304 			    p_in += 2;
2305 			}
2306 		  }
2307 	    }
2308       }
2309     else
2310       {
2311 	  /* RGB */
2312 	  p_in = rgb;
2313 	  p_msk = alpha;
2314 	  p_out = buffer;
2315 	  for (y = 0; y < tileHeight; y++)
2316 	    {
2317 		for (x = 0; x < tileWidth; x++)
2318 		  {
2319 		      if (*p_msk++ < 128)
2320 			{
2321 			    /* skipping a transparent pixel */
2322 			    p_in += 3;
2323 			    p_out += 3;
2324 			}
2325 		      else
2326 			{
2327 			    /* copying an opaque pixel */
2328 			    *p_out++ = *p_in++;
2329 			    *p_out++ = *p_in++;
2330 			    *p_out++ = *p_in++;
2331 			}
2332 		  }
2333 	    }
2334       }
2335     free (rgb);
2336     p_in = alpha;
2337     p_out = mask;
2338     for (y = 0; y < tileHeight; y++)
2339       {
2340 	  for (x = 0; x < tileWidth; x++)
2341 	    {
2342 		if (*p_in++ < 128)
2343 		  {
2344 		      *p_out++ = 0;
2345 		      valid_mask = 1;
2346 		  }
2347 		else
2348 		    *p_out++ = 1;
2349 	    }
2350       }
2351     free (alpha);
2352     if (!valid_mask)
2353       {
2354 	  free (mask);
2355 	  *mask_size = 0;
2356       }
2357 
2358     return 1;
2359   error:
2360     if (rgb != NULL)
2361 	free (rgb);
2362     if (alpha != NULL)
2363 	free (alpha);
2364     if (ctx != NULL)
2365 	rl2_graph_destroy_context (ctx);
2366     return 0;
2367 }
2368 
2369 #define floor2(exp) ((long) exp)
2370 
2371 static rl2RasterPtr
create_124_rescaled_raster(const unsigned char * rgba,unsigned char pixel_type,unsigned int tileWidth,unsigned int tileHeight,int scale)2372 create_124_rescaled_raster (const unsigned char *rgba, unsigned char pixel_type,
2373 			    unsigned int tileWidth, unsigned int tileHeight,
2374 			    int scale)
2375 {
2376 /* creating a rescaled raster (1,2 or 4 bit pyramids)
2377 /
2378 / this function builds an high quality rescaled sub-image by applying pixel interpolation
2379 /
2380 / this code is widely inspired by the original GD gdImageCopyResampled() function
2381 */
2382     rl2RasterPtr raster;
2383     unsigned int x;
2384     unsigned int y;
2385     double sy1;
2386     double sy2;
2387     double sx1;
2388     double sx2;
2389     unsigned char r;
2390     unsigned char g;
2391     unsigned char b;
2392     unsigned char a;
2393     unsigned char *rgb = NULL;
2394     int rgb_sz;
2395     unsigned char *mask = NULL;
2396     int mask_sz;
2397     unsigned char num_bands;
2398     const unsigned char *p_in;
2399     unsigned char *p_out;
2400     unsigned char *p_msk;
2401     unsigned int out_width = tileWidth / scale;
2402     unsigned int out_height = tileHeight / scale;
2403 
2404     mask_sz = out_width * out_height;
2405     if (pixel_type == RL2_PIXEL_RGB)
2406       {
2407 	  num_bands = 3;
2408 	  rgb_sz = out_width * out_height * 3;
2409 	  rgb = malloc (rgb_sz);
2410 	  if (rgb == NULL)
2411 	      return NULL;
2412 	  mask = malloc (mask_sz);
2413 	  if (mask == NULL)
2414 	    {
2415 		free (rgb);
2416 		return NULL;
2417 	    }
2418       }
2419     else
2420       {
2421 	  num_bands = 1;
2422 	  rgb_sz = out_width * out_height;
2423 	  rgb = malloc (rgb_sz);
2424 	  if (rgb == NULL)
2425 	      return NULL;
2426 	  mask = malloc (mask_sz);
2427 	  if (mask == NULL)
2428 	    {
2429 		free (rgb);
2430 		return NULL;
2431 	    }
2432       }
2433     memset (mask, 0, mask_sz);
2434 
2435     for (y = 0; y < out_height; y++)
2436       {
2437 	  sy1 = ((double) y) * (double) tileHeight / (double) out_height;
2438 	  sy2 = ((double) (y + 1)) * (double) tileHeight / (double) out_height;
2439 	  for (x = 0; x < out_width; x++)
2440 	    {
2441 		double sx;
2442 		double sy;
2443 		double spixels = 0;
2444 		double red = 0.0;
2445 		double green = 0.0;
2446 		double blue = 0.0;
2447 		double alpha = 0.0;
2448 		sx1 = ((double) x) * (double) tileWidth / (double) out_width;
2449 		sx2 =
2450 		    ((double) (x + 1)) * (double) tileWidth /
2451 		    (double) out_width;
2452 		sy = sy1;
2453 		do
2454 		  {
2455 		      double yportion;
2456 		      if (floor2 (sy) == floor2 (sy1))
2457 			{
2458 			    yportion = 1.0 - (sy - floor2 (sy));
2459 			    if (yportion > sy2 - sy1)
2460 			      {
2461 				  yportion = sy2 - sy1;
2462 			      }
2463 			    sy = floor2 (sy);
2464 			}
2465 		      else if (sy == floor2 (sy2))
2466 			{
2467 			    yportion = sy2 - floor2 (sy2);
2468 			}
2469 		      else
2470 			{
2471 			    yportion = 1.0;
2472 			}
2473 		      sx = sx1;
2474 		      do
2475 			{
2476 			    double xportion;
2477 			    double pcontribution;
2478 			    if (floor2 (sx) == floor2 (sx1))
2479 			      {
2480 				  xportion = 1.0 - (sx - floor2 (sx));
2481 				  if (xportion > sx2 - sx1)
2482 				    {
2483 					xportion = sx2 - sx1;
2484 				    }
2485 				  sx = floor2 (sx);
2486 			      }
2487 			    else if (sx == floor2 (sx2))
2488 			      {
2489 				  xportion = sx2 - floor2 (sx2);
2490 			      }
2491 			    else
2492 			      {
2493 				  xportion = 1.0;
2494 			      }
2495 			    pcontribution = xportion * yportion;
2496 			    /* retrieving the origin pixel */
2497 			    p_in = rgba + ((unsigned int) sy * tileWidth * 4);
2498 			    p_in += (unsigned int) sx *4;
2499 			    r = *p_in++;
2500 			    g = *p_in++;
2501 			    b = *p_in++;
2502 			    a = *p_in++;
2503 
2504 			    red += r * pcontribution;
2505 			    green += g * pcontribution;
2506 			    blue += b * pcontribution;
2507 			    alpha += a * pcontribution;
2508 			    spixels += xportion * yportion;
2509 			    sx += 1.0;
2510 			}
2511 		      while (sx < sx2);
2512 		      sy += 1.0;
2513 		  }
2514 		while (sy < sy2);
2515 		if (spixels != 0.0)
2516 		  {
2517 		      red /= spixels;
2518 		      green /= spixels;
2519 		      blue /= spixels;
2520 		  }
2521 		if (red > 255.0)
2522 		    red = 255.0;
2523 		if (green > 255.0)
2524 		    green = 255.0;
2525 		if (blue > 255.0)
2526 		    blue = 255.0;
2527 		if (alpha < 192.0)
2528 		  {
2529 		      /* skipping almost transparent pixels */
2530 		      continue;
2531 		  }
2532 		/* setting the destination pixel */
2533 		if (pixel_type == RL2_PIXEL_RGB)
2534 		    p_out = rgb + (y * out_width * 3);
2535 		else
2536 		    p_out = rgb + (y * out_width);
2537 		p_msk = mask + (y * out_width);
2538 		if (pixel_type == RL2_PIXEL_RGB)
2539 		  {
2540 		      p_out += x * 3;
2541 		      *p_out++ = (unsigned char) red;
2542 		      *p_out++ = (unsigned char) green;
2543 		      *p_out = (unsigned char) blue;
2544 		      p_msk += x;
2545 		      *p_msk = 1;
2546 		  }
2547 		else
2548 		  {
2549 		      if (red <= 224.0)
2550 			{
2551 			    p_out += x;
2552 			    *p_out = (unsigned char) red;
2553 			    p_msk += x;
2554 			    *p_msk = 1;
2555 			}
2556 		  }
2557 	    }
2558       }
2559 
2560     raster =
2561 	rl2_create_raster (out_width, out_height, RL2_SAMPLE_UINT8, pixel_type,
2562 			   num_bands, rgb, rgb_sz, NULL, mask, mask_sz, NULL);
2563     return raster;
2564 }
2565 
2566 static void
copy_124_rescaled(rl2RasterPtr raster_out,rl2RasterPtr raster_in,unsigned int base_x,unsigned int base_y)2567 copy_124_rescaled (rl2RasterPtr raster_out, rl2RasterPtr raster_in,
2568 		   unsigned int base_x, unsigned int base_y)
2569 {
2570 /* copying pixels from rescaled to destination tile buffer */
2571     rl2PrivRasterPtr rst_in = (rl2PrivRasterPtr) raster_in;
2572     rl2PrivRasterPtr rst_out = (rl2PrivRasterPtr) raster_out;
2573     unsigned int x;
2574     unsigned int y;
2575     int dx;
2576     int dy;
2577     unsigned char *p_in;
2578     unsigned char *p_out;
2579     unsigned char *p_msk_in;
2580     unsigned char *p_msk_out;
2581 
2582     if (rst_in->sampleType == RL2_SAMPLE_UINT8
2583 	&& rst_out->sampleType == RL2_SAMPLE_UINT8
2584 	&& rst_in->pixelType == RL2_PIXEL_GRAYSCALE
2585 	&& rst_out->pixelType == RL2_PIXEL_GRAYSCALE && rst_in->nBands == 1
2586 	&& rst_out->nBands == 1 && rst_in->maskBuffer != NULL
2587 	&& rst_out->maskBuffer != NULL)
2588       {
2589 	  /* Grayscale */
2590 	  p_in = rst_in->rasterBuffer;
2591 	  p_msk_in = rst_in->maskBuffer;
2592 	  for (y = 0; y < rst_in->height; y++)
2593 	    {
2594 		dy = base_y + y;
2595 		if (dy < 0 || dy >= (int) (rst_out->height))
2596 		  {
2597 		      p_in += rst_in->width;
2598 		      p_msk_in += rst_in->width;
2599 		      continue;
2600 		  }
2601 		for (x = 0; x < rst_in->width; x++)
2602 		  {
2603 		      dx = base_x + x;
2604 		      if (dx < 0 || dx >= (int) (rst_out->width))
2605 			{
2606 			    p_in++;
2607 			    p_msk_in++;
2608 			    continue;
2609 			}
2610 		      p_out =
2611 			  rst_out->rasterBuffer + (dy * rst_out->width) + dx;
2612 		      p_msk_out =
2613 			  rst_out->maskBuffer + (dy * rst_out->width) + dx;
2614 		      if (*p_msk_in++ == 0)
2615 			  p_in++;
2616 		      else
2617 			{
2618 			    *p_out++ = *p_in++;
2619 			    *p_msk_out++ = 1;
2620 			}
2621 		  }
2622 	    }
2623       }
2624     if (rst_in->sampleType == RL2_SAMPLE_UINT8
2625 	&& rst_out->sampleType == RL2_SAMPLE_UINT8
2626 	&& rst_in->pixelType == RL2_PIXEL_RGB
2627 	&& rst_out->pixelType == RL2_PIXEL_RGB && rst_in->nBands == 3
2628 	&& rst_out->nBands == 3 && rst_in->maskBuffer != NULL
2629 	&& rst_out->maskBuffer != NULL)
2630       {
2631 	  /* RGB */
2632 	  p_in = rst_in->rasterBuffer;
2633 	  p_msk_in = rst_in->maskBuffer;
2634 	  for (y = 0; y < rst_in->height; y++)
2635 	    {
2636 		dy = base_y + y;
2637 		if (dy < 0 || dy >= (int) (rst_out->height))
2638 		  {
2639 		      p_in += rst_in->width * 3;
2640 		      p_msk_in += rst_in->width;
2641 		      continue;
2642 		  }
2643 		for (x = 0; x < rst_in->width; x++)
2644 		  {
2645 		      dx = base_x + x;
2646 		      if (dx < 0 || dx >= (int) (rst_out->width))
2647 			{
2648 			    p_in += 3;
2649 			    p_msk_in++;
2650 			    continue;
2651 			}
2652 		      p_out =
2653 			  rst_out->rasterBuffer + (dy * rst_out->width * 3) +
2654 			  (dx * 3);
2655 		      p_msk_out =
2656 			  rst_out->maskBuffer + (dy * rst_out->width) + dx;
2657 		      if (*p_msk_in++ == 0)
2658 			  p_in += 3;
2659 		      else
2660 			{
2661 			    *p_out++ = *p_in++;
2662 			    *p_out++ = *p_in++;
2663 			    *p_out++ = *p_in++;
2664 			    *p_msk_out++ = 1;
2665 			}
2666 		  }
2667 	    }
2668       }
2669 }
2670 
2671 static int
rescale_monolithic_124(int id_level,unsigned int tileWidth,unsigned int tileHeight,int factor,unsigned char pixel_type,double res_x,double res_y,double minx,double miny,double maxx,double maxy,unsigned char * buffer,int buf_size,unsigned char * mask,int * mask_size,rl2PalettePtr palette,rl2PixelPtr no_data,sqlite3_stmt * stmt_geo,sqlite3_stmt * stmt_data)2672 rescale_monolithic_124 (int id_level,
2673 			unsigned int tileWidth, unsigned int tileHeight,
2674 			int factor, unsigned char pixel_type, double res_x,
2675 			double res_y, double minx, double miny, double maxx,
2676 			double maxy, unsigned char *buffer, int buf_size,
2677 			unsigned char *mask, int *mask_size,
2678 			rl2PalettePtr palette, rl2PixelPtr no_data,
2679 			sqlite3_stmt * stmt_geo, sqlite3_stmt * stmt_data)
2680 {
2681 /* rescaling a monolithic 1,2 or 4 bit tile */
2682     rl2RasterPtr raster = NULL;
2683     rl2RasterPtr base_tile = NULL;
2684     rl2PrivRasterPtr rst;
2685     unsigned char *rgba = NULL;
2686     unsigned int x;
2687     unsigned int y;
2688     int ret;
2689     double shift_x;
2690     double shift_y;
2691     int valid_mask = 0;
2692     unsigned char *p_in;
2693     unsigned char *p_out;
2694     unsigned char out_pixel_type;
2695     unsigned char out_num_bands;
2696     rl2PixelPtr nd = NULL;
2697 
2698 /* creating the output buffers */
2699     if (pixel_type == RL2_PIXEL_MONOCHROME)
2700       {
2701 	  out_pixel_type = RL2_PIXEL_GRAYSCALE;
2702 	  out_num_bands = 1;
2703 	  p_out = buffer;
2704 	  for (y = 0; y < tileHeight; y++)
2705 	    {
2706 		/* priming the background color */
2707 		for (x = 0; x < tileWidth; x++)
2708 		    *p_out++ = 255;
2709 	    }
2710 	  nd = rl2_create_pixel (RL2_SAMPLE_UINT8, RL2_PIXEL_GRAYSCALE, 1);
2711 	  rl2_set_pixel_sample_uint8 (nd, RL2_GRAYSCALE_BAND, 255);
2712       }
2713     else
2714       {
2715 	  out_pixel_type = RL2_PIXEL_RGB;
2716 	  out_num_bands = 3;
2717 	  p_out = buffer;
2718 	  for (y = 0; y < tileHeight; y++)
2719 	    {
2720 		/* priming the background color */
2721 		for (x = 0; x < tileWidth; x++)
2722 		  {
2723 		      *p_out++ = 255;
2724 		      *p_out++ = 255;
2725 		      *p_out++ = 255;
2726 		  }
2727 	    }
2728 	  nd = rl2_create_pixel (RL2_SAMPLE_UINT8, RL2_PIXEL_RGB, 3);
2729 	  rl2_set_pixel_sample_uint8 (nd, RL2_RED_BAND, 255);
2730 	  rl2_set_pixel_sample_uint8 (nd, RL2_GREEN_BAND, 255);
2731 	  rl2_set_pixel_sample_uint8 (nd, RL2_BLUE_BAND, 255);
2732       }
2733     p_out = mask;
2734     for (y = 0; y < tileHeight; y++)
2735       {
2736 	  /* priming full transparency */
2737 	  for (x = 0; x < tileWidth; x++)
2738 	      *p_out++ = 0;
2739       }
2740 /* creating the output raster */
2741     raster =
2742 	rl2_create_raster (tileWidth, tileHeight, RL2_SAMPLE_UINT8,
2743 			   out_pixel_type, out_num_bands, buffer, buf_size,
2744 			   NULL, mask, *mask_size, nd);
2745     if (raster == NULL)
2746 	goto error;
2747 
2748 /* binding the BBOX to be queried */
2749     sqlite3_reset (stmt_geo);
2750     sqlite3_clear_bindings (stmt_geo);
2751     sqlite3_bind_int (stmt_geo, 1, id_level);
2752     sqlite3_bind_double (stmt_geo, 2, minx);
2753     sqlite3_bind_double (stmt_geo, 3, miny);
2754     sqlite3_bind_double (stmt_geo, 4, maxx);
2755     sqlite3_bind_double (stmt_geo, 5, maxy);
2756     while (1)
2757       {
2758 	  /* scrolling the result set rows */
2759 	  ret = sqlite3_step (stmt_geo);
2760 	  if (ret == SQLITE_DONE)
2761 	      break;		/* end of result set */
2762 	  if (ret == SQLITE_ROW)
2763 	    {
2764 		sqlite3_int64 tile_id = sqlite3_column_int64 (stmt_geo, 0);
2765 		double tile_x = sqlite3_column_double (stmt_geo, 1);
2766 		double tile_y = sqlite3_column_double (stmt_geo, 2);
2767 
2768 		rgba = load_tile_base (stmt_data, tile_id, palette, no_data);
2769 		if (rgba == NULL)
2770 		    goto error;
2771 		base_tile =
2772 		    create_124_rescaled_raster (rgba, out_pixel_type, tileWidth,
2773 						tileHeight, factor);
2774 		free (rgba);
2775 		if (base_tile == NULL)
2776 		    goto error;
2777 		shift_x = tile_x - minx;
2778 		shift_y = maxy - tile_y;
2779 		x = (int) (shift_x / res_x);
2780 		y = (int) (shift_y / res_y);
2781 		copy_124_rescaled (raster, base_tile, x, y);
2782 		rl2_destroy_raster (base_tile);
2783 	    }
2784       }
2785 
2786 /* releasing buffers ownership */
2787     rst = (rl2PrivRasterPtr) raster;
2788     rst->rasterBuffer = NULL;
2789     rst->maskBuffer = NULL;
2790     rl2_destroy_raster (raster);
2791 
2792     p_in = mask;
2793     for (y = 0; y < tileHeight; y++)
2794       {
2795 	  for (x = 0; x < tileWidth; x++)
2796 	    {
2797 		if (*p_in++ == 0)
2798 		    valid_mask = 1;
2799 	    }
2800       }
2801     if (!valid_mask)
2802       {
2803 	  free (mask);
2804 	  *mask_size = 0;
2805       }
2806 
2807     return 1;
2808   error:
2809     if (raster != NULL)
2810       {
2811 	  /* releasing buffers ownership */
2812 	  rst = (rl2PrivRasterPtr) raster;
2813 	  rst->rasterBuffer = NULL;
2814 	  rst->maskBuffer = NULL;
2815 	  rl2_destroy_raster (raster);
2816       }
2817     return 0;
2818 }
2819 
2820 static void
copy_multiband_rescaled(rl2RasterPtr raster_out,rl2RasterPtr raster_in,unsigned int base_x,unsigned int base_y)2821 copy_multiband_rescaled (rl2RasterPtr raster_out, rl2RasterPtr raster_in,
2822 			 unsigned int base_x, unsigned int base_y)
2823 {
2824 /* copying pixels from rescaled to destination tile buffer */
2825     rl2PrivRasterPtr rst_in = (rl2PrivRasterPtr) raster_in;
2826     rl2PrivRasterPtr rst_out = (rl2PrivRasterPtr) raster_out;
2827     unsigned int x;
2828     unsigned int y;
2829     int dx;
2830     int dy;
2831     unsigned char *p_in_u8;
2832     unsigned char *p_out_u8;
2833     unsigned short *p_in_u16;
2834     unsigned short *p_out_u16;
2835     unsigned char *p_msk_in;
2836     unsigned char *p_msk_out;
2837     int mismatch = 0;
2838     int ib;
2839 
2840     if (rst_in->sampleType != rst_out->sampleType)
2841 	mismatch = 1;
2842     if (rst_in->pixelType != RL2_PIXEL_MULTIBAND
2843 	|| rst_out->pixelType != RL2_PIXEL_MULTIBAND)
2844 	mismatch = 1;
2845     if (rst_in->nBands != rst_out->nBands)
2846 	mismatch = 1;
2847     if (rst_in->maskBuffer == NULL || rst_out->maskBuffer == NULL)
2848 	mismatch = 1;
2849     if (mismatch)
2850       {
2851 	  fprintf (stderr,
2852 		   "ERROR: Copy MultiBand Rescaled mismatching in/out\n");
2853 	  return;
2854       }
2855 
2856     switch (rst_in->sampleType)
2857       {
2858       case RL2_SAMPLE_UINT8:
2859 	  p_in_u8 = (unsigned char *) (rst_in->rasterBuffer);
2860 	  break;
2861       case RL2_SAMPLE_UINT16:
2862 	  p_in_u16 = (unsigned short *) (rst_in->rasterBuffer);
2863 	  break;
2864       };
2865     p_msk_in = rst_in->maskBuffer;
2866     for (y = 0; y < rst_in->height; y++)
2867       {
2868 	  dy = base_y + y;
2869 	  if (dy < 0 || dy >= (int) (rst_out->height))
2870 	    {
2871 		switch (rst_in->sampleType)
2872 		  {
2873 		  case RL2_SAMPLE_UINT8:
2874 		      p_in_u8 += rst_in->width * rst_in->nBands;
2875 		      break;
2876 		  case RL2_SAMPLE_UINT16:
2877 		      p_in_u16 += rst_in->width * rst_in->nBands;
2878 		      break;
2879 		  };
2880 		p_msk_in += rst_in->width;
2881 		continue;
2882 	    }
2883 	  for (x = 0; x < rst_in->width; x++)
2884 	    {
2885 		dx = base_x + x;
2886 		if (dx < 0 || dx >= (int) (rst_out->width))
2887 		  {
2888 		      switch (rst_in->sampleType)
2889 			{
2890 			case RL2_SAMPLE_UINT8:
2891 			    p_in_u8 += rst_in->nBands;
2892 			    break;
2893 			case RL2_SAMPLE_UINT16:
2894 			    p_in_u16 += rst_in->nBands;
2895 			    break;
2896 			};
2897 		      p_msk_in++;
2898 		      continue;
2899 		  }
2900 		switch (rst_out->sampleType)
2901 		  {
2902 		  case RL2_SAMPLE_UINT8:
2903 		      p_out_u8 = (unsigned char *) (rst_out->rasterBuffer);
2904 		      p_out_u8 +=
2905 			  (dy * rst_out->width * rst_out->nBands) +
2906 			  (dx * rst_out->nBands);
2907 		      break;
2908 		  case RL2_SAMPLE_UINT16:
2909 		      p_out_u16 = (unsigned short *) (rst_out->rasterBuffer);
2910 		      p_out_u16 +=
2911 			  (dy * rst_out->width * rst_out->nBands) +
2912 			  (dx * rst_out->nBands);
2913 		      break;
2914 		  };
2915 		p_msk_out = rst_out->maskBuffer + (dy * rst_out->width) + dx;
2916 		if (*p_msk_in++ == 0)
2917 		  {
2918 		      switch (rst_in->sampleType)
2919 			{
2920 			case RL2_SAMPLE_UINT8:
2921 			    p_in_u8 += rst_out->nBands;
2922 			    break;
2923 			case RL2_SAMPLE_UINT16:
2924 			    p_in_u16 += rst_out->nBands;
2925 			    break;
2926 			};
2927 		  }
2928 		else
2929 		  {
2930 		      for (ib = 0; ib < rst_out->nBands; ib++)
2931 			{
2932 			    switch (rst_out->sampleType)
2933 			      {
2934 			      case RL2_SAMPLE_UINT8:
2935 				  *p_out_u8++ = *p_in_u8++;
2936 				  break;
2937 			      case RL2_SAMPLE_UINT16:
2938 				  *p_out_u16++ = *p_in_u16++;
2939 				  break;
2940 			      };
2941 			}
2942 		      *p_msk_out++ = 1;
2943 		  }
2944 	    }
2945       }
2946 }
2947 
2948 static int
is_mb_nodata_u8(const unsigned char * pixel,unsigned char num_bands,rl2PixelPtr no_data)2949 is_mb_nodata_u8 (const unsigned char *pixel, unsigned char num_bands,
2950 		 rl2PixelPtr no_data)
2951 {
2952 /* testing for NO-DATA pixel */
2953     int is_valid = 0;
2954     rl2PrivPixelPtr nd = (rl2PrivPixelPtr) no_data;
2955     unsigned char ib;
2956     const unsigned char *p_in = pixel;
2957     if (nd != NULL)
2958       {
2959 	  if (nd->nBands == num_bands && nd->sampleType == RL2_SAMPLE_UINT8
2960 	      && nd->pixelType == RL2_PIXEL_MULTIBAND)
2961 	      is_valid = 1;
2962       }
2963     if (!is_valid)
2964 	return 0;
2965     for (ib = 0; ib < num_bands; ib++)
2966       {
2967 	  if (*p_in++ != (nd->Samples + ib)->uint8)
2968 	      return 0;
2969       }
2970     return 1;
2971 }
2972 
2973 static void
rescale_multiband_u8(unsigned int tileWidth,unsigned int tileHeight,unsigned char num_bands,unsigned int out_width,unsigned int out_height,unsigned int factor,unsigned char * buf_in,const unsigned char * mask_in,unsigned char * buf_out,unsigned char * mask,unsigned int x,unsigned int y,unsigned int ox,unsigned int oy,rl2PixelPtr no_data)2974 rescale_multiband_u8 (unsigned int tileWidth, unsigned int tileHeight,
2975 		      unsigned char num_bands, unsigned int out_width,
2976 		      unsigned int out_height, unsigned int factor,
2977 		      unsigned char *buf_in, const unsigned char *mask_in,
2978 		      unsigned char *buf_out, unsigned char *mask,
2979 		      unsigned int x, unsigned int y, unsigned int ox,
2980 		      unsigned int oy, rl2PixelPtr no_data)
2981 {
2982 /* rescaling a MultiBand (monolithic)- UINT8 */
2983     unsigned int row;
2984     unsigned int col;
2985     int nodata = 0;
2986     int valid = 0;
2987     unsigned char ib;
2988     double *sum;
2989     unsigned char *p_out;
2990     unsigned char *p_msk;
2991 
2992     if (ox >= out_width || oy >= out_height)
2993 	return;
2994     p_out = buf_out + (out_width * oy * num_bands) + (ox * num_bands);
2995     p_msk = mask + (out_width * oy) + ox;
2996     sum = malloc (sizeof (double) * num_bands);
2997     for (ib = 0; ib < num_bands; ib++)
2998 	*(sum + ib) = 0.0;
2999 
3000     for (row = 0; row < factor; row++)
3001       {
3002 	  const unsigned char *p_in_base;
3003 	  unsigned int yy = y + row;
3004 	  if (yy >= tileHeight)
3005 	      break;
3006 	  p_in_base = buf_in + (yy * tileWidth * num_bands);
3007 	  for (col = 0; col < factor; col++)
3008 	    {
3009 		const unsigned char *p_in;
3010 		unsigned int xx = x + col;
3011 		if (xx >= tileWidth)
3012 		    break;
3013 		p_in = p_in_base + (xx * num_bands);
3014 		if (mask_in != NULL)
3015 		  {
3016 		      /* checking the transparency mask */
3017 		      const unsigned char *p_msk_in =
3018 			  mask_in + (yy * tileWidth) + xx;
3019 		      if (*p_msk_in == 0)
3020 			{
3021 			    nodata++;
3022 			    continue;
3023 			}
3024 		  }
3025 		if (is_mb_nodata_u8 (p_in, num_bands, no_data))
3026 		    nodata++;
3027 		else
3028 		  {
3029 		      valid++;
3030 		      for (ib = 0; ib < num_bands; ib++)
3031 			  *(sum + ib) += *p_in++;
3032 		  }
3033 	    }
3034       }
3035 
3036     if (nodata >= valid)
3037       {
3038 	  free (sum);
3039 	  return;
3040       }
3041     for (ib = 0; ib < num_bands; ib++)
3042 	*p_out++ = (unsigned char) (*(sum + ib) / (double) valid);
3043     free (sum);
3044     *p_msk = 1;
3045 }
3046 
3047 static int
is_mb_nodata_u16(const unsigned short * pixel,unsigned char num_bands,rl2PixelPtr no_data)3048 is_mb_nodata_u16 (const unsigned short *pixel, unsigned char num_bands,
3049 		  rl2PixelPtr no_data)
3050 {
3051 /* testing for NO-DATA pixel */
3052     int is_valid = 0;
3053     rl2PrivPixelPtr nd = (rl2PrivPixelPtr) no_data;
3054     unsigned char ib;
3055     const unsigned short *p_in = pixel;
3056     if (nd != NULL)
3057       {
3058 	  if (nd->nBands == num_bands && nd->sampleType == RL2_SAMPLE_UINT16
3059 	      && nd->pixelType == RL2_PIXEL_MULTIBAND)
3060 	      is_valid = 1;
3061       }
3062     if (!is_valid)
3063 	return 0;
3064     for (ib = 0; ib < num_bands; ib++)
3065       {
3066 	  if (*p_in++ != (nd->Samples + ib)->uint16)
3067 	      return 0;
3068       }
3069     return 1;
3070 }
3071 
3072 static void
rescale_multiband_u16(unsigned int tileWidth,unsigned int tileHeight,unsigned char num_bands,unsigned int out_width,unsigned int out_height,unsigned int factor,unsigned short * buf_in,const unsigned char * mask_in,unsigned short * buf_out,unsigned char * mask,unsigned int x,unsigned int y,unsigned int ox,unsigned int oy,rl2PixelPtr no_data)3073 rescale_multiband_u16 (unsigned int tileWidth, unsigned int tileHeight,
3074 		       unsigned char num_bands, unsigned int out_width,
3075 		       unsigned int out_height, unsigned int factor,
3076 		       unsigned short *buf_in, const unsigned char *mask_in,
3077 		       unsigned short *buf_out, unsigned char *mask,
3078 		       unsigned int x, unsigned int y, unsigned int ox,
3079 		       unsigned int oy, rl2PixelPtr no_data)
3080 {
3081 /* rescaling a MultiBand (monolithic)- UINT16 */
3082     unsigned int row;
3083     unsigned int col;
3084     int nodata = 0;
3085     int valid = 0;
3086     unsigned char ib;
3087     double *sum;
3088     unsigned short *p_out;
3089     unsigned char *p_msk;
3090 
3091     if (ox >= out_width || oy >= out_height)
3092 	return;
3093     p_out = buf_out + (out_width * oy * num_bands) + (ox * num_bands);
3094     p_msk = mask + (out_width * oy) + ox;
3095     sum = malloc (sizeof (double) * num_bands);
3096     for (ib = 0; ib < num_bands; ib++)
3097 	*(sum + ib) = 0.0;
3098 
3099     for (row = 0; row < factor; row++)
3100       {
3101 	  const unsigned short *p_in_base;
3102 	  unsigned int yy = y + row;
3103 	  if (yy >= tileHeight)
3104 	      break;
3105 	  p_in_base = buf_in + (yy * tileWidth * num_bands);
3106 	  for (col = 0; col < factor; col++)
3107 	    {
3108 		const unsigned short *p_in;
3109 		unsigned int xx = x + col;
3110 		if (xx >= tileWidth)
3111 		    break;
3112 		if (mask_in != NULL)
3113 		  {
3114 		      /* checking the transparency mask */
3115 		      const unsigned char *p_msk_in =
3116 			  mask_in + (yy * tileWidth) + xx;
3117 		      if (*p_msk_in == 0)
3118 			{
3119 			    nodata++;
3120 			    continue;
3121 			}
3122 		  }
3123 		p_in = p_in_base + (xx * num_bands);
3124 		if (is_mb_nodata_u16 (p_in, num_bands, no_data))
3125 		    nodata++;
3126 		else
3127 		  {
3128 		      valid++;
3129 		      for (ib = 0; ib < num_bands; ib++)
3130 			  *(sum + ib) += *p_in++;
3131 		  }
3132 	    }
3133       }
3134 
3135     if (nodata >= valid)
3136       {
3137 	  free (sum);
3138 	  return;
3139       }
3140     for (ib = 0; ib < num_bands; ib++)
3141 	*p_out++ = (unsigned char) (*(sum + ib) / (double) valid);
3142     free (sum);
3143     *p_msk = 1;
3144 }
3145 
3146 static void
mb_prime_nodata_u8(unsigned char * buf,unsigned int width,unsigned int height,unsigned char num_bands,rl2PixelPtr no_data)3147 mb_prime_nodata_u8 (unsigned char *buf, unsigned int width, unsigned int height,
3148 		    unsigned char num_bands, rl2PixelPtr no_data)
3149 {
3150 /* priming a void buffer */
3151     rl2PrivPixelPtr nd = (rl2PrivPixelPtr) no_data;
3152     unsigned int x;
3153     unsigned int y;
3154     unsigned char ib;
3155     unsigned char *p = buf;
3156     int is_valid = 0;
3157 
3158     if (nd != NULL)
3159       {
3160 	  if (nd->nBands == num_bands && nd->sampleType == RL2_SAMPLE_UINT8
3161 	      && nd->pixelType == RL2_PIXEL_MULTIBAND)
3162 	      is_valid = 1;
3163       }
3164     for (y = 0; y < height; y++)
3165       {
3166 	  for (x = 0; x < width; x++)
3167 	    {
3168 		for (ib = 0; ib < num_bands; ib++)
3169 		  {
3170 		      if (is_valid)
3171 			  *p++ = (nd->Samples + ib)->uint8;
3172 		      else
3173 			  *p++ = 0;
3174 		  }
3175 	    }
3176       }
3177 }
3178 
3179 static void
mb_prime_nodata_u16(unsigned short * buf,unsigned int width,unsigned int height,unsigned char num_bands,rl2PixelPtr no_data)3180 mb_prime_nodata_u16 (unsigned short *buf, unsigned int width,
3181 		     unsigned int height, unsigned char num_bands,
3182 		     rl2PixelPtr no_data)
3183 {
3184 /* priming a void buffer */
3185     rl2PrivPixelPtr nd = (rl2PrivPixelPtr) no_data;
3186     unsigned int x;
3187     unsigned int y;
3188     unsigned char ib;
3189     unsigned short *p = buf;
3190     int is_valid = 0;
3191 
3192     if (nd != NULL)
3193       {
3194 	  if (nd->nBands == num_bands && nd->sampleType == RL2_SAMPLE_UINT16
3195 	      && nd->pixelType == RL2_PIXEL_MULTIBAND)
3196 	      is_valid = 1;
3197       }
3198     for (y = 0; y < height; y++)
3199       {
3200 	  for (x = 0; x < width; x++)
3201 	    {
3202 		for (ib = 0; ib < num_bands; ib++)
3203 		  {
3204 		      if (is_valid)
3205 			  *p++ = (nd->Samples + ib)->uint16;
3206 		      else
3207 			  *p++ = 0;
3208 		  }
3209 	    }
3210       }
3211 }
3212 
3213 static rl2RasterPtr
create_rescaled_multiband_raster(unsigned int factor,unsigned int tileWidth,unsigned int tileHeight,const void * buf_in,const unsigned char * mask_in,unsigned char sample_type,unsigned char num_bands,rl2PixelPtr no_data)3214 create_rescaled_multiband_raster (unsigned int factor, unsigned int tileWidth,
3215 				  unsigned int tileHeight, const void *buf_in,
3216 				  const unsigned char *mask_in,
3217 				  unsigned char sample_type,
3218 				  unsigned char num_bands, rl2PixelPtr no_data)
3219 {
3220 /* rescaling a Multiband tile */
3221     unsigned int x;
3222     unsigned int y;
3223     unsigned int ox;
3224     unsigned int oy;
3225     rl2RasterPtr raster = NULL;
3226     unsigned char *mask;
3227     void *buf;
3228     unsigned int mask_sz;
3229     unsigned char pix_sz = 1;
3230     unsigned int buf_sz;
3231     unsigned int out_width = tileWidth / factor;
3232     unsigned int out_height = tileHeight / factor;
3233 
3234     mask_sz = out_width * out_height;
3235     switch (sample_type)
3236       {
3237       case RL2_SAMPLE_INT16:
3238       case RL2_SAMPLE_UINT16:
3239 	  pix_sz = 2;
3240 	  break;
3241       };
3242     buf_sz = out_width * out_height * pix_sz * num_bands;
3243     buf = malloc (buf_sz);
3244     if (buf == NULL)
3245 	return NULL;
3246     mask = malloc (mask_sz);
3247     if (mask == NULL)
3248       {
3249 	  free (buf);
3250 	  return NULL;
3251       }
3252     memset (mask, 0, mask_sz);
3253     if (sample_type == RL2_SAMPLE_UINT16)
3254 	mb_prime_nodata_u16 (buf, out_width, out_height, num_bands, no_data);
3255     else
3256 	mb_prime_nodata_u8 (buf, out_width, out_height, num_bands, no_data);
3257 
3258     oy = 0;
3259     for (y = 0; y < tileHeight; y += factor)
3260       {
3261 	  ox = 0;
3262 	  for (x = 0; x < tileWidth; x += factor)
3263 	    {
3264 		switch (sample_type)
3265 		  {
3266 		  case RL2_SAMPLE_UINT8:
3267 		      rescale_multiband_u8 (tileWidth, tileHeight, num_bands,
3268 					    out_width, out_height, factor,
3269 					    (unsigned char *) buf_in, mask_in,
3270 					    (unsigned char *) buf, mask, x, y,
3271 					    ox, oy, no_data);
3272 		      break;
3273 		  case RL2_SAMPLE_UINT16:
3274 		      rescale_multiband_u16 (tileWidth, tileHeight, num_bands,
3275 					     out_width, out_height, factor,
3276 					     (unsigned short *) buf_in, mask_in,
3277 					     (unsigned short *) buf, mask, x, y,
3278 					     ox, oy, no_data);
3279 		      break;
3280 		  };
3281 		ox++;
3282 	    }
3283 	  oy++;
3284       }
3285 
3286     raster =
3287 	rl2_create_raster (out_width, out_height, sample_type,
3288 			   RL2_PIXEL_MULTIBAND, num_bands, buf, buf_sz, NULL,
3289 			   mask, mask_sz, NULL);
3290     return raster;
3291 }
3292 
3293 static void
copy_datagrid_rescaled(rl2RasterPtr raster_out,rl2RasterPtr raster_in,unsigned int base_x,unsigned int base_y)3294 copy_datagrid_rescaled (rl2RasterPtr raster_out, rl2RasterPtr raster_in,
3295 			unsigned int base_x, unsigned int base_y)
3296 {
3297 /* copying pixels from rescaled to destination tile buffer */
3298     rl2PrivRasterPtr rst_in = (rl2PrivRasterPtr) raster_in;
3299     rl2PrivRasterPtr rst_out = (rl2PrivRasterPtr) raster_out;
3300     unsigned int x;
3301     unsigned int y;
3302     int dx;
3303     int dy;
3304     char *p_in_8;
3305     char *p_out_8;
3306     unsigned char *p_in_u8;
3307     unsigned char *p_out_u8;
3308     short *p_in_16;
3309     short *p_out_16;
3310     unsigned short *p_in_u16;
3311     unsigned short *p_out_u16;
3312     int *p_in_32;
3313     int *p_out_32;
3314     unsigned int *p_in_u32;
3315     unsigned int *p_out_u32;
3316     float *p_in_flt;
3317     float *p_out_flt;
3318     double *p_in_dbl;
3319     double *p_out_dbl;
3320     unsigned char *p_msk_in;
3321     unsigned char *p_msk_out;
3322     int mismatch = 0;
3323 
3324     if (rst_in->sampleType != rst_out->sampleType)
3325 	mismatch = 1;
3326     if (rst_in->pixelType != RL2_PIXEL_DATAGRID
3327 	|| rst_out->pixelType != RL2_PIXEL_DATAGRID)
3328 	mismatch = 1;
3329     if (rst_in->nBands != 1 || rst_out->nBands != 1)
3330 	mismatch = 1;
3331     if (rst_in->maskBuffer == NULL || rst_out->maskBuffer == NULL)
3332 	mismatch = 1;
3333     if (mismatch)
3334       {
3335 	  fprintf (stderr,
3336 		   "ERROR: Copy DataGrid Rescaled mismatching in/out\n");
3337 	  return;
3338       }
3339 
3340     switch (rst_in->sampleType)
3341       {
3342       case RL2_SAMPLE_INT8:
3343 	  p_in_8 = (char *) (rst_in->rasterBuffer);
3344 	  break;
3345       case RL2_SAMPLE_UINT8:
3346 	  p_in_u8 = (unsigned char *) (rst_in->rasterBuffer);
3347 	  break;
3348       case RL2_SAMPLE_INT16:
3349 	  p_in_16 = (short *) (rst_in->rasterBuffer);
3350 	  break;
3351       case RL2_SAMPLE_UINT16:
3352 	  p_in_u16 = (unsigned short *) (rst_in->rasterBuffer);
3353 	  break;
3354       case RL2_SAMPLE_INT32:
3355 	  p_in_32 = (int *) (rst_in->rasterBuffer);
3356 	  break;
3357       case RL2_SAMPLE_UINT32:
3358 	  p_in_u32 = (unsigned int *) (rst_in->rasterBuffer);
3359 	  break;
3360       case RL2_SAMPLE_FLOAT:
3361 	  p_in_flt = (float *) (rst_in->rasterBuffer);
3362 	  break;
3363       case RL2_SAMPLE_DOUBLE:
3364 	  p_in_dbl = (double *) (rst_in->rasterBuffer);
3365 	  break;
3366       };
3367     p_msk_in = rst_in->maskBuffer;
3368     for (y = 0; y < rst_in->height; y++)
3369       {
3370 	  dy = base_y + y;
3371 	  if (dy < 0 || dy >= (int) (rst_out->height))
3372 	    {
3373 		switch (rst_in->sampleType)
3374 		  {
3375 		  case RL2_SAMPLE_INT8:
3376 		      p_in_8 += rst_in->width;
3377 		      break;
3378 		  case RL2_SAMPLE_UINT8:
3379 		      p_in_u8 += rst_in->width;
3380 		      break;
3381 		  case RL2_SAMPLE_INT16:
3382 		      p_in_16 += rst_in->width;
3383 		      break;
3384 		  case RL2_SAMPLE_UINT16:
3385 		      p_in_u16 += rst_in->width;
3386 		      break;
3387 		  case RL2_SAMPLE_INT32:
3388 		      p_in_32 += rst_in->width;
3389 		      break;
3390 		  case RL2_SAMPLE_UINT32:
3391 		      p_in_u32 += rst_in->width;
3392 		      break;
3393 		  case RL2_SAMPLE_FLOAT:
3394 		      p_in_flt += rst_in->width;
3395 		      break;
3396 		  case RL2_SAMPLE_DOUBLE:
3397 		      p_in_dbl += rst_in->width;
3398 		      break;
3399 		  };
3400 		p_msk_in += rst_in->width;
3401 		continue;
3402 	    }
3403 	  for (x = 0; x < rst_in->width; x++)
3404 	    {
3405 		dx = base_x + x;
3406 		if (dx < 0 || dx >= (int) (rst_out->width))
3407 		  {
3408 		      switch (rst_in->sampleType)
3409 			{
3410 			case RL2_SAMPLE_INT8:
3411 			    p_in_8++;
3412 			    break;
3413 			case RL2_SAMPLE_UINT8:
3414 			    p_in_u8++;
3415 			    break;
3416 			case RL2_SAMPLE_INT16:
3417 			    p_in_16++;
3418 			    break;
3419 			case RL2_SAMPLE_UINT16:
3420 			    p_in_u16++;
3421 			    break;
3422 			case RL2_SAMPLE_INT32:
3423 			    p_in_32++;
3424 			    break;
3425 			case RL2_SAMPLE_UINT32:
3426 			    p_in_u32++;
3427 			    break;
3428 			case RL2_SAMPLE_FLOAT:
3429 			    p_in_flt++;
3430 			    break;
3431 			case RL2_SAMPLE_DOUBLE:
3432 			    p_in_dbl++;
3433 			    break;
3434 			};
3435 		      p_msk_in++;
3436 		      continue;
3437 		  }
3438 		switch (rst_out->sampleType)
3439 		  {
3440 		  case RL2_SAMPLE_INT8:
3441 		      p_out_8 = (char *) (rst_out->rasterBuffer);
3442 		      p_out_8 += (dy * rst_out->width) + dx;
3443 		      break;
3444 		  case RL2_SAMPLE_UINT8:
3445 		      p_out_u8 = (unsigned char *) (rst_out->rasterBuffer);
3446 		      p_out_u8 += (dy * rst_out->width) + dx;
3447 		      break;
3448 		  case RL2_SAMPLE_INT16:
3449 		      p_out_16 = (short *) (rst_out->rasterBuffer);
3450 		      p_out_16 += (dy * rst_out->width) + dx;
3451 		      break;
3452 		  case RL2_SAMPLE_UINT16:
3453 		      p_out_u16 = (unsigned short *) (rst_out->rasterBuffer);
3454 		      p_out_u16 += (dy * rst_out->width) + dx;
3455 		      break;
3456 		  case RL2_SAMPLE_INT32:
3457 		      p_out_32 = (int *) (rst_out->rasterBuffer);
3458 		      p_out_32 += (dy * rst_out->width) + dx;
3459 		      break;
3460 		  case RL2_SAMPLE_UINT32:
3461 		      p_out_u32 = (unsigned int *) (rst_out->rasterBuffer);
3462 		      p_out_u32 += (dy * rst_out->width) + dx;
3463 		      break;
3464 		  case RL2_SAMPLE_FLOAT:
3465 		      p_out_flt = (float *) (rst_out->rasterBuffer);
3466 		      p_out_flt += (dy * rst_out->width) + dx;
3467 		      break;
3468 		  case RL2_SAMPLE_DOUBLE:
3469 		      p_out_dbl = (double *) (rst_out->rasterBuffer);
3470 		      p_out_dbl += (dy * rst_out->width) + dx;
3471 		      break;
3472 		  };
3473 		p_msk_out = rst_out->maskBuffer + (dy * rst_out->width) + dx;
3474 		if (*p_msk_in++ == 0)
3475 		  {
3476 		      switch (rst_in->sampleType)
3477 			{
3478 			case RL2_SAMPLE_INT8:
3479 			    p_in_8++;
3480 			    break;
3481 			case RL2_SAMPLE_UINT8:
3482 			    p_in_u8++;
3483 			    break;
3484 			case RL2_SAMPLE_INT16:
3485 			    p_in_16++;
3486 			    break;
3487 			case RL2_SAMPLE_UINT16:
3488 			    p_in_u16++;
3489 			    break;
3490 			case RL2_SAMPLE_INT32:
3491 			    p_in_32++;
3492 			    break;
3493 			case RL2_SAMPLE_UINT32:
3494 			    p_in_u32++;
3495 			    break;
3496 			case RL2_SAMPLE_FLOAT:
3497 			    p_in_flt++;
3498 			    break;
3499 			case RL2_SAMPLE_DOUBLE:
3500 			    p_in_dbl++;
3501 			    break;
3502 			};
3503 		  }
3504 		else
3505 		  {
3506 		      switch (rst_out->sampleType)
3507 			{
3508 			case RL2_SAMPLE_INT8:
3509 			    *p_out_8++ = *p_in_8++;
3510 			    break;
3511 			case RL2_SAMPLE_UINT8:
3512 			    *p_out_u8 = *p_in_u8++;
3513 			    break;
3514 			case RL2_SAMPLE_INT16:
3515 			    *p_out_16 = *p_in_16++;
3516 			    break;
3517 			case RL2_SAMPLE_UINT16:
3518 			    *p_out_u16 = *p_in_u16++;
3519 			    break;
3520 			case RL2_SAMPLE_INT32:
3521 			    *p_out_32 = *p_in_32++;
3522 			    break;
3523 			case RL2_SAMPLE_UINT32:
3524 			    *p_out_u32 = *p_in_u32++;
3525 			    break;
3526 			case RL2_SAMPLE_FLOAT:
3527 			    *p_out_flt = *p_in_flt++;
3528 			    break;
3529 			case RL2_SAMPLE_DOUBLE:
3530 			    *p_out_dbl = *p_in_dbl++;
3531 			    break;
3532 			};
3533 		      *p_msk_out++ = 1;
3534 		  }
3535 	    }
3536       }
3537 }
3538 
3539 static void
rescale_datagrid_8(unsigned int tileWidth,unsigned int tileHeight,unsigned int out_width,unsigned int out_height,unsigned int factor,char * buf_in,char * buf_out,unsigned char * mask,unsigned int x,unsigned int y,unsigned int ox,unsigned int oy,char nd)3540 rescale_datagrid_8 (unsigned int tileWidth, unsigned int tileHeight,
3541 		    unsigned int out_width, unsigned int out_height,
3542 		    unsigned int factor, char *buf_in, char *buf_out,
3543 		    unsigned char *mask, unsigned int x, unsigned int y,
3544 		    unsigned int ox, unsigned int oy, char nd)
3545 {
3546 /* rescaling a DataGrid (monolithic)- INT8 */
3547     unsigned int row;
3548     unsigned int col;
3549     int nodata = 0;
3550     int valid = 0;
3551     double sum = 0.0;
3552     char *p_out;
3553     unsigned char *p_msk;
3554 
3555     if (ox >= out_width || oy >= out_height)
3556 	return;
3557     p_out = buf_out + (out_width * oy) + ox;
3558     p_msk = mask + (out_width * oy) + ox;
3559 
3560     for (row = 0; row < factor; row++)
3561       {
3562 	  const char *p_in_base;
3563 	  unsigned int yy = y + row;
3564 	  if (yy >= tileHeight)
3565 	      break;
3566 	  p_in_base = buf_in + (yy * tileWidth);
3567 	  for (col = 0; col < factor; col++)
3568 	    {
3569 		const char *p_in;
3570 		unsigned int xx = x + col;
3571 		if (xx >= tileWidth)
3572 		    break;
3573 		p_in = p_in_base + xx;
3574 		if (*p_in == nd)
3575 		    nodata++;
3576 		else
3577 		  {
3578 		      valid++;
3579 		      sum += *p_in;
3580 		  }
3581 	    }
3582       }
3583 
3584     if (nodata >= valid)
3585 	return;
3586     *p_out = (char) (sum / (double) valid);
3587     *p_msk = 1;
3588 }
3589 
3590 static void
rescale_datagrid_u8(unsigned int tileWidth,unsigned int tileHeight,unsigned int out_width,unsigned int out_height,unsigned int factor,unsigned char * buf_in,unsigned char * buf_out,unsigned char * mask,unsigned int x,unsigned int y,unsigned int ox,unsigned int oy,unsigned char nd)3591 rescale_datagrid_u8 (unsigned int tileWidth, unsigned int tileHeight,
3592 		     unsigned int out_width, unsigned int out_height,
3593 		     unsigned int factor, unsigned char *buf_in,
3594 		     unsigned char *buf_out, unsigned char *mask,
3595 		     unsigned int x, unsigned int y, unsigned int ox,
3596 		     unsigned int oy, unsigned char nd)
3597 {
3598 /* rescaling a DataGrid (monolithic)- UINT8 */
3599     unsigned int row;
3600     unsigned int col;
3601     int nodata = 0;
3602     int valid = 0;
3603     double sum = 0.0;
3604     unsigned char *p_out;
3605     unsigned char *p_msk;
3606 
3607     if (ox >= out_width || oy >= out_height)
3608 	return;
3609     p_out = buf_out + (out_width * oy) + ox;
3610     p_msk = mask + (out_width * oy) + ox;
3611 
3612     for (row = 0; row < factor; row++)
3613       {
3614 	  const unsigned char *p_in_base;
3615 	  unsigned int yy = y + row;
3616 	  if (yy >= tileHeight)
3617 	      break;
3618 	  p_in_base = buf_in + (yy * tileWidth);
3619 	  for (col = 0; col < factor; col++)
3620 	    {
3621 		const unsigned char *p_in;
3622 		unsigned int xx = x + col;
3623 		if (xx >= tileWidth)
3624 		    break;
3625 		p_in = p_in_base + xx;
3626 		if (*p_in == nd)
3627 		    nodata++;
3628 		else
3629 		  {
3630 		      valid++;
3631 		      sum += *p_in;
3632 		  }
3633 	    }
3634       }
3635 
3636     if (nodata >= valid)
3637 	return;
3638     *p_out = (unsigned char) (sum / (double) valid);
3639     *p_msk = 1;
3640 }
3641 
3642 static void
rescale_datagrid_16(unsigned int tileWidth,unsigned int tileHeight,unsigned int out_width,unsigned int out_height,unsigned int factor,short * buf_in,short * buf_out,unsigned char * mask,unsigned int x,unsigned int y,unsigned int ox,unsigned int oy,short nd)3643 rescale_datagrid_16 (unsigned int tileWidth, unsigned int tileHeight,
3644 		     unsigned int out_width, unsigned int out_height,
3645 		     unsigned int factor, short *buf_in, short *buf_out,
3646 		     unsigned char *mask, unsigned int x, unsigned int y,
3647 		     unsigned int ox, unsigned int oy, short nd)
3648 {
3649 /* rescaling a DataGrid (monolithic)- INT16 */
3650     unsigned int row;
3651     unsigned int col;
3652     int nodata = 0;
3653     int valid = 0;
3654     double sum = 0.0;
3655     short *p_out;
3656     unsigned char *p_msk;
3657 
3658     if (ox >= out_width || oy >= out_height)
3659 	return;
3660     p_out = buf_out + (out_width * oy) + ox;
3661     p_msk = mask + (out_width * oy) + ox;
3662 
3663     for (row = 0; row < factor; row++)
3664       {
3665 	  const short *p_in_base;
3666 	  unsigned int yy = y + row;
3667 	  if (yy >= tileHeight)
3668 	      break;
3669 	  p_in_base = buf_in + (yy * tileWidth);
3670 	  for (col = 0; col < factor; col++)
3671 	    {
3672 		const short *p_in;
3673 		unsigned int xx = x + col;
3674 		if (xx >= tileWidth)
3675 		    break;
3676 		p_in = p_in_base + xx;
3677 		if (*p_in == nd)
3678 		    nodata++;
3679 		else
3680 		  {
3681 		      valid++;
3682 		      sum += *p_in;
3683 		  }
3684 	    }
3685       }
3686 
3687     if (nodata >= valid)
3688 	return;
3689     *p_out = (short) (sum / (double) valid);
3690     *p_msk = 1;
3691 }
3692 
3693 static void
rescale_datagrid_u16(unsigned int tileWidth,unsigned int tileHeight,unsigned int out_width,unsigned int out_height,unsigned int factor,unsigned short * buf_in,unsigned short * buf_out,unsigned char * mask,unsigned int x,unsigned int y,unsigned int ox,unsigned int oy,unsigned short nd)3694 rescale_datagrid_u16 (unsigned int tileWidth, unsigned int tileHeight,
3695 		      unsigned int out_width, unsigned int out_height,
3696 		      unsigned int factor, unsigned short *buf_in,
3697 		      unsigned short *buf_out, unsigned char *mask,
3698 		      unsigned int x, unsigned int y, unsigned int ox,
3699 		      unsigned int oy, unsigned short nd)
3700 {
3701 /* rescaling a DataGrid (monolithic)- UINT16 */
3702     unsigned int row;
3703     unsigned int col;
3704     int nodata = 0;
3705     int valid = 0;
3706     double sum = 0.0;
3707     unsigned short *p_out;
3708     unsigned char *p_msk;
3709 
3710     if (ox >= out_width || oy >= out_height)
3711 	return;
3712     p_out = buf_out + (out_width * oy) + ox;
3713     p_msk = mask + (out_width * oy) + ox;
3714 
3715     for (row = 0; row < factor; row++)
3716       {
3717 	  const unsigned short *p_in_base;
3718 	  unsigned int yy = y + row;
3719 	  if (yy >= tileHeight)
3720 	      break;
3721 	  p_in_base = buf_in + (yy * tileWidth);
3722 	  for (col = 0; col < factor; col++)
3723 	    {
3724 		const unsigned short *p_in;
3725 		unsigned int xx = x + col;
3726 		if (xx >= tileWidth)
3727 		    break;
3728 		p_in = p_in_base + xx;
3729 		if (*p_in == nd)
3730 		    nodata++;
3731 		else
3732 		  {
3733 		      valid++;
3734 		      sum += *p_in;
3735 		  }
3736 	    }
3737       }
3738 
3739     if (nodata >= valid)
3740 	return;
3741     *p_out = (unsigned short) (sum / (double) valid);
3742     *p_msk = 1;
3743 }
3744 
3745 static void
rescale_datagrid_32(unsigned int tileWidth,unsigned int tileHeight,unsigned int out_width,unsigned int out_height,unsigned int factor,int * buf_in,int * buf_out,unsigned char * mask,unsigned int x,unsigned int y,unsigned int ox,unsigned int oy,int nd)3746 rescale_datagrid_32 (unsigned int tileWidth, unsigned int tileHeight,
3747 		     unsigned int out_width, unsigned int out_height,
3748 		     unsigned int factor, int *buf_in, int *buf_out,
3749 		     unsigned char *mask, unsigned int x, unsigned int y,
3750 		     unsigned int ox, unsigned int oy, int nd)
3751 {
3752 /* rescaling a DataGrid (monolithic)- INT32 */
3753     unsigned int row;
3754     unsigned int col;
3755     int nodata = 0;
3756     int valid = 0;
3757     double sum = 0.0;
3758     int *p_out;
3759     unsigned char *p_msk;
3760 
3761     if (ox >= out_width || oy >= out_height)
3762 	return;
3763     p_out = buf_out + (out_width * oy) + ox;
3764     p_msk = mask + (out_width * oy) + ox;
3765 
3766     for (row = 0; row < factor; row++)
3767       {
3768 	  const int *p_in_base;
3769 	  unsigned int yy = y + row;
3770 	  if (yy >= tileHeight)
3771 	      break;
3772 	  p_in_base = buf_in + (yy * tileWidth);
3773 	  for (col = 0; col < factor; col++)
3774 	    {
3775 		const int *p_in;
3776 		unsigned int xx = x + col;
3777 		if (xx >= tileWidth)
3778 		    break;
3779 		p_in = p_in_base + xx;
3780 		if (*p_in == nd)
3781 		    nodata++;
3782 		else
3783 		  {
3784 		      valid++;
3785 		      sum += *p_in;
3786 		  }
3787 	    }
3788       }
3789 
3790     if (nodata >= valid)
3791 	return;
3792     *p_out = (int) (sum / (double) valid);
3793     *p_msk = 1;
3794 }
3795 
3796 static void
rescale_datagrid_u32(unsigned int tileWidth,unsigned int tileHeight,unsigned int out_width,unsigned int out_height,unsigned int factor,unsigned int * buf_in,unsigned int * buf_out,unsigned char * mask,unsigned int x,unsigned int y,unsigned int ox,unsigned int oy,unsigned int nd)3797 rescale_datagrid_u32 (unsigned int tileWidth, unsigned int tileHeight,
3798 		      unsigned int out_width, unsigned int out_height,
3799 		      unsigned int factor, unsigned int *buf_in,
3800 		      unsigned int *buf_out, unsigned char *mask,
3801 		      unsigned int x, unsigned int y, unsigned int ox,
3802 		      unsigned int oy, unsigned int nd)
3803 {
3804 /* rescaling a DataGrid (monolithic)- UINT32 */
3805     unsigned int row;
3806     unsigned int col;
3807     int nodata = 0;
3808     int valid = 0;
3809     double sum = 0.0;
3810     unsigned int *p_out;
3811     unsigned char *p_msk;
3812 
3813     if (ox >= out_width || oy >= out_height)
3814 	return;
3815     p_out = buf_out + (out_width * oy) + ox;
3816     p_msk = mask + (out_width * oy) + ox;
3817 
3818     for (row = 0; row < factor; row++)
3819       {
3820 	  const unsigned int *p_in_base;
3821 	  unsigned int yy = y + row;
3822 	  if (yy >= tileHeight)
3823 	      break;
3824 	  p_in_base = buf_in + (yy * tileWidth);
3825 	  for (col = 0; col < factor; col++)
3826 	    {
3827 		const unsigned int *p_in;
3828 		unsigned int xx = x + col;
3829 		if (xx >= tileWidth)
3830 		    break;
3831 		p_in = p_in_base + xx;
3832 		if (*p_in == nd)
3833 		    nodata++;
3834 		else
3835 		  {
3836 		      valid++;
3837 		      sum += *p_in;
3838 		  }
3839 	    }
3840       }
3841 
3842     if (nodata >= valid)
3843 	return;
3844     *p_out = (unsigned int) (sum / (double) valid);
3845     *p_msk = 1;
3846 }
3847 
3848 static void
rescale_datagrid_flt(unsigned int tileWidth,unsigned int tileHeight,unsigned int out_width,unsigned int out_height,unsigned int factor,float * buf_in,float * buf_out,unsigned char * mask,unsigned int x,unsigned int y,unsigned int ox,unsigned int oy,float nd)3849 rescale_datagrid_flt (unsigned int tileWidth, unsigned int tileHeight,
3850 		      unsigned int out_width, unsigned int out_height,
3851 		      unsigned int factor, float *buf_in, float *buf_out,
3852 		      unsigned char *mask, unsigned int x, unsigned int y,
3853 		      unsigned int ox, unsigned int oy, float nd)
3854 {
3855 /* rescaling a DataGrid (monolithic)- FLOAT */
3856     unsigned int row;
3857     unsigned int col;
3858     int nodata = 0;
3859     int valid = 0;
3860     double sum = 0.0;
3861     float *p_out;
3862     unsigned char *p_msk;
3863 
3864     if (ox >= out_width || oy >= out_height)
3865 	return;
3866     p_out = buf_out + (out_width * oy) + ox;
3867     p_msk = mask + (out_width * oy) + ox;
3868 
3869     for (row = 0; row < factor; row++)
3870       {
3871 	  const float *p_in_base;
3872 	  unsigned int yy = y + row;
3873 	  if (yy >= tileHeight)
3874 	      break;
3875 	  p_in_base = buf_in + (yy * tileWidth);
3876 	  for (col = 0; col < factor; col++)
3877 	    {
3878 		const float *p_in;
3879 		unsigned int xx = x + col;
3880 		if (xx >= tileWidth)
3881 		    break;
3882 		p_in = p_in_base + xx;
3883 		if (*p_in == nd)
3884 		    nodata++;
3885 		else
3886 		  {
3887 		      valid++;
3888 		      sum += *p_in;
3889 		  }
3890 	    }
3891       }
3892 
3893     if (nodata >= valid)
3894 	return;
3895     *p_out = (float) (sum / (double) valid);
3896     *p_msk = 1;
3897 }
3898 
3899 static void
rescale_datagrid_dbl(unsigned int tileWidth,unsigned int tileHeight,unsigned int out_width,unsigned int out_height,unsigned int factor,double * buf_in,double * buf_out,unsigned char * mask,unsigned int x,unsigned int y,unsigned int ox,unsigned int oy,double nd)3900 rescale_datagrid_dbl (unsigned int tileWidth, unsigned int tileHeight,
3901 		      unsigned int out_width, unsigned int out_height,
3902 		      unsigned int factor, double *buf_in, double *buf_out,
3903 		      unsigned char *mask, unsigned int x, unsigned int y,
3904 		      unsigned int ox, unsigned int oy, double nd)
3905 {
3906 /* rescaling a DataGrid (monolithic)- DOUBLE */
3907     unsigned int row;
3908     unsigned int col;
3909     int nodata = 0;
3910     int valid = 0;
3911     double sum = 0.0;
3912     double *p_out;
3913     unsigned char *p_msk;
3914 
3915     if (ox >= out_width || oy >= out_height)
3916 	return;
3917     p_out = buf_out + (out_width * oy) + ox;
3918     p_msk = mask + (out_width * oy) + ox;
3919 
3920     for (row = 0; row < factor; row++)
3921       {
3922 	  const double *p_in_base;
3923 	  unsigned int yy = y + row;
3924 	  if (yy >= tileHeight)
3925 	      break;
3926 	  p_in_base = buf_in + (yy * tileWidth);
3927 	  for (col = 0; col < factor; col++)
3928 	    {
3929 		const double *p_in;
3930 		unsigned int xx = x + col;
3931 		if (xx >= tileWidth)
3932 		    break;
3933 		p_in = p_in_base + xx;
3934 		if (*p_in == nd)
3935 		    nodata++;
3936 		else
3937 		  {
3938 		      valid++;
3939 		      sum += *p_in;
3940 		  }
3941 	    }
3942       }
3943 
3944     if (nodata >= valid)
3945 	return;
3946     *p_out = (double) (sum / (double) valid);
3947     *p_msk = 1;
3948 }
3949 
3950 static rl2RasterPtr
create_rescaled_datagrid_raster(unsigned int factor,unsigned int tileWidth,unsigned int tileHeight,const void * buf_in,unsigned char sample_type,rl2PixelPtr no_data)3951 create_rescaled_datagrid_raster (unsigned int factor, unsigned int tileWidth,
3952 				 unsigned int tileHeight, const void *buf_in,
3953 				 unsigned char sample_type, rl2PixelPtr no_data)
3954 {
3955 /* rescaling a Datagrid tile */
3956     rl2PrivPixelPtr pxl;
3957     unsigned int x;
3958     unsigned int y;
3959     unsigned int ox;
3960     unsigned int oy;
3961     rl2RasterPtr raster = NULL;
3962     unsigned char *mask;
3963     void *buf;
3964     unsigned int mask_sz;
3965     unsigned char pix_sz = 1;
3966     unsigned int buf_sz;
3967     unsigned int out_width = tileWidth / factor;
3968     unsigned int out_height = tileHeight / factor;
3969     char no_data_8 = 0;
3970     unsigned char no_data_u8 = 0;
3971     short no_data_16 = 0;
3972     unsigned short no_data_u16 = 0;
3973     int no_data_32 = 0;
3974     unsigned int no_data_u32 = 0;
3975     float no_data_flt = 0.0;
3976     double no_data_dbl = 0.0;
3977 
3978 /* retrieving NO-DATA */
3979     pxl = (rl2PrivPixelPtr) no_data;
3980     if (pxl != NULL)
3981       {
3982 	  if (pxl->nBands == 1 && pxl->pixelType == RL2_PIXEL_DATAGRID
3983 	      && pxl->sampleType == sample_type)
3984 	    {
3985 		rl2PrivSamplePtr sample = pxl->Samples;
3986 		switch (sample_type)
3987 		  {
3988 		  case RL2_SAMPLE_INT8:
3989 		      no_data_8 = sample->int8;
3990 		      break;
3991 		  case RL2_SAMPLE_UINT8:
3992 		      no_data_u8 = sample->uint8;
3993 		      break;
3994 		  case RL2_SAMPLE_INT16:
3995 		      no_data_16 = sample->int16;
3996 		      break;
3997 		  case RL2_SAMPLE_UINT16:
3998 		      no_data_u16 = sample->uint16;
3999 		      break;
4000 		  case RL2_SAMPLE_INT32:
4001 		      no_data_32 = sample->int32;
4002 		      break;
4003 		  case RL2_SAMPLE_UINT32:
4004 		      no_data_u32 = sample->uint32;
4005 		      break;
4006 		  case RL2_SAMPLE_FLOAT:
4007 		      no_data_flt = sample->float32;
4008 		      break;
4009 		  case RL2_SAMPLE_DOUBLE:
4010 		      no_data_dbl = sample->float64;
4011 		      break;
4012 		  };
4013 	    }
4014       }
4015 /* computing sizes */
4016     mask_sz = out_width * out_height;
4017     switch (sample_type)
4018       {
4019       case RL2_SAMPLE_INT16:
4020       case RL2_SAMPLE_UINT16:
4021 	  pix_sz = 2;
4022 	  break;
4023       case RL2_SAMPLE_INT32:
4024       case RL2_SAMPLE_UINT32:
4025       case RL2_SAMPLE_FLOAT:
4026 	  pix_sz = 4;
4027 	  break;
4028       case RL2_SAMPLE_DOUBLE:
4029 	  pix_sz = 8;
4030 	  break;
4031       };
4032     buf_sz = out_width * out_height * pix_sz;
4033     buf = malloc (buf_sz);
4034     if (buf == NULL)
4035 	return NULL;
4036     mask = malloc (mask_sz);
4037     if (mask == NULL)
4038       {
4039 	  free (buf);
4040 	  return NULL;
4041       }
4042     rl2_prime_void_tile (buf, out_width, out_height, sample_type, 1, no_data);
4043     memset (mask, 0, mask_sz);
4044 
4045     oy = 0;
4046     for (y = 0; y < tileHeight; y += factor)
4047       {
4048 	  ox = 0;
4049 	  for (x = 0; x < tileWidth; x += factor)
4050 	    {
4051 		switch (sample_type)
4052 		  {
4053 		  case RL2_SAMPLE_INT8:
4054 		      rescale_datagrid_8 (tileWidth, tileHeight, out_width,
4055 					  out_height, factor, (char *) buf_in,
4056 					  (char *) buf, mask, x, y, ox, oy,
4057 					  no_data_8);
4058 		      break;
4059 		  case RL2_SAMPLE_UINT8:
4060 		      rescale_datagrid_u8 (tileWidth, tileHeight, out_width,
4061 					   out_height, factor,
4062 					   (unsigned char *) buf_in,
4063 					   (unsigned char *) buf, mask, x, y,
4064 					   ox, oy, no_data_u8);
4065 		      break;
4066 		  case RL2_SAMPLE_INT16:
4067 		      rescale_datagrid_16 (tileWidth, tileHeight, out_width,
4068 					   out_height, factor, (short *) buf_in,
4069 					   (short *) buf, mask, x, y, ox, oy,
4070 					   no_data_16);
4071 		      break;
4072 		  case RL2_SAMPLE_UINT16:
4073 		      rescale_datagrid_u16 (tileWidth, tileHeight, out_width,
4074 					    out_height, factor,
4075 					    (unsigned short *) buf_in,
4076 					    (unsigned short *) buf, mask, x, y,
4077 					    ox, oy, no_data_u16);
4078 		      break;
4079 		  case RL2_SAMPLE_INT32:
4080 		      rescale_datagrid_32 (tileWidth, tileHeight, out_width,
4081 					   out_height, factor, (int *) buf_in,
4082 					   (int *) buf, mask, x, y, ox, oy,
4083 					   no_data_32);
4084 		      break;
4085 		  case RL2_SAMPLE_UINT32:
4086 		      rescale_datagrid_u32 (tileWidth, tileHeight, out_width,
4087 					    out_height, factor,
4088 					    (unsigned int *) buf_in,
4089 					    (unsigned int *) buf, mask, x, y,
4090 					    ox, oy, no_data_u32);
4091 		      break;
4092 		  case RL2_SAMPLE_FLOAT:
4093 		      rescale_datagrid_flt (tileWidth, tileHeight, out_width,
4094 					    out_height, factor,
4095 					    (float *) buf_in, (float *) buf,
4096 					    mask, x, y, ox, oy, no_data_flt);
4097 		      break;
4098 		  case RL2_SAMPLE_DOUBLE:
4099 		      rescale_datagrid_dbl (tileWidth, tileHeight, out_width,
4100 					    out_height, factor,
4101 					    (double *) buf_in, (double *) buf,
4102 					    mask, x, y, ox, oy, no_data_dbl);
4103 		      break;
4104 		  };
4105 		ox++;
4106 	    }
4107 	  oy++;
4108       }
4109 
4110     raster =
4111 	rl2_create_raster (out_width, out_height, sample_type,
4112 			   RL2_PIXEL_DATAGRID, 1, buf, buf_sz, NULL, mask,
4113 			   mask_sz, NULL);
4114     return raster;
4115 }
4116 
4117 static int
rescale_monolithic_multiband(int id_level,unsigned int tileWidth,unsigned int tileHeight,unsigned char sample_type,unsigned char num_bands,int factor,double res_x,double res_y,double minx,double miny,double maxx,double maxy,unsigned char * buffer,int buf_size,unsigned char * mask,int * mask_size,rl2PixelPtr no_data,sqlite3_stmt * stmt_geo,sqlite3_stmt * stmt_data)4118 rescale_monolithic_multiband (int id_level,
4119 			      unsigned int tileWidth, unsigned int tileHeight,
4120 			      unsigned char sample_type,
4121 			      unsigned char num_bands, int factor, double res_x,
4122 			      double res_y, double minx, double miny,
4123 			      double maxx, double maxy, unsigned char *buffer,
4124 			      int buf_size, unsigned char *mask, int *mask_size,
4125 			      rl2PixelPtr no_data, sqlite3_stmt * stmt_geo,
4126 			      sqlite3_stmt * stmt_data)
4127 {
4128 /* rescaling monolithic MultiBand */
4129     rl2RasterPtr raster = NULL;
4130     rl2RasterPtr base_tile = NULL;
4131     rl2PrivRasterPtr rst;
4132     unsigned int x;
4133     unsigned int y;
4134     int ret;
4135     double shift_x;
4136     double shift_y;
4137     int valid_mask = 0;
4138     unsigned char *p_in;
4139     unsigned char *p_out;
4140     rl2PixelPtr nd = NULL;
4141 
4142     nd = rl2_clone_pixel (no_data);
4143     p_out = mask;
4144     for (y = 0; y < tileHeight; y++)
4145       {
4146 	  /* priming full transparency */
4147 	  for (x = 0; x < tileWidth; x++)
4148 	      *p_out++ = 0;
4149       }
4150     rl2_prime_void_tile (buffer, tileWidth, tileHeight, sample_type, num_bands,
4151 			 no_data);
4152 /* creating the output raster */
4153     raster =
4154 	rl2_create_raster (tileWidth, tileHeight, sample_type,
4155 			   RL2_PIXEL_MULTIBAND, num_bands, buffer, buf_size,
4156 			   NULL, mask, *mask_size, nd);
4157     if (raster == NULL)
4158 	goto error;
4159 
4160 /* binding the BBOX to be queried */
4161     sqlite3_reset (stmt_geo);
4162     sqlite3_clear_bindings (stmt_geo);
4163     sqlite3_bind_int (stmt_geo, 1, id_level);
4164     sqlite3_bind_double (stmt_geo, 2, minx);
4165     sqlite3_bind_double (stmt_geo, 3, miny);
4166     sqlite3_bind_double (stmt_geo, 4, maxx);
4167     sqlite3_bind_double (stmt_geo, 5, maxy);
4168     while (1)
4169       {
4170 	  /* scrolling the result set rows */
4171 	  ret = sqlite3_step (stmt_geo);
4172 	  if (ret == SQLITE_DONE)
4173 	      break;		/* end of result set */
4174 	  if (ret == SQLITE_ROW)
4175 	    {
4176 		rl2RasterPtr raster_in = NULL;
4177 		rl2PrivRasterPtr rst_in;
4178 		sqlite3_int64 tile_id = sqlite3_column_int64 (stmt_geo, 0);
4179 		double tile_x = sqlite3_column_double (stmt_geo, 1);
4180 		double tile_y = sqlite3_column_double (stmt_geo, 2);
4181 
4182 		raster_in = load_tile_base_generic (stmt_data, tile_id);
4183 		rst_in = (rl2PrivRasterPtr) raster_in;
4184 		base_tile =
4185 		    create_rescaled_multiband_raster (factor, tileWidth,
4186 						      tileHeight,
4187 						      rst_in->rasterBuffer,
4188 						      rst_in->maskBuffer,
4189 						      sample_type, num_bands,
4190 						      no_data);
4191 		rl2_destroy_raster (raster_in);
4192 		raster_in = NULL;
4193 
4194 		if (base_tile == NULL)
4195 		    goto error;
4196 		shift_x = tile_x - minx;
4197 		shift_y = maxy - tile_y;
4198 		x = (int) (shift_x / res_x);
4199 		y = (int) (shift_y / res_y);
4200 		copy_multiband_rescaled (raster, base_tile, x, y);
4201 		rl2_destroy_raster (base_tile);
4202 	    }
4203       }
4204 
4205 /* releasing buffers ownership */
4206     rst = (rl2PrivRasterPtr) raster;
4207     rst->rasterBuffer = NULL;
4208     rst->maskBuffer = NULL;
4209     rl2_destroy_raster (raster);
4210 
4211     p_in = mask;
4212     for (y = 0; y < tileHeight; y++)
4213       {
4214 	  for (x = 0; x < tileWidth; x++)
4215 	    {
4216 		if (*p_in++ == 0)
4217 		    valid_mask = 1;
4218 	    }
4219       }
4220     if (!valid_mask)
4221       {
4222 	  free (mask);
4223 	  *mask_size = 0;
4224       }
4225 
4226     return 1;
4227   error:
4228     if (raster != NULL)
4229       {
4230 	  /* releasing buffers ownership */
4231 	  rst = (rl2PrivRasterPtr) raster;
4232 	  rst->rasterBuffer = NULL;
4233 	  rst->maskBuffer = NULL;
4234 	  rl2_destroy_raster (raster);
4235       }
4236     return 0;
4237 }
4238 
4239 static int
rescale_monolithic_datagrid(int id_level,unsigned int tileWidth,unsigned int tileHeight,unsigned char sample_type,int factor,double res_x,double res_y,double minx,double miny,double maxx,double maxy,unsigned char * buffer,int buf_size,unsigned char * mask,int * mask_size,rl2PixelPtr no_data,sqlite3_stmt * stmt_geo,sqlite3_stmt * stmt_data)4240 rescale_monolithic_datagrid (int id_level,
4241 			     unsigned int tileWidth, unsigned int tileHeight,
4242 			     unsigned char sample_type, int factor,
4243 			     double res_x, double res_y, double minx,
4244 			     double miny, double maxx, double maxy,
4245 			     unsigned char *buffer, int buf_size,
4246 			     unsigned char *mask, int *mask_size,
4247 			     rl2PixelPtr no_data, sqlite3_stmt * stmt_geo,
4248 			     sqlite3_stmt * stmt_data)
4249 {
4250 /* rescaling monolithic DataGrid */
4251     rl2RasterPtr raster = NULL;
4252     rl2RasterPtr base_tile = NULL;
4253     rl2PrivRasterPtr rst;
4254     unsigned int x;
4255     unsigned int y;
4256     int ret;
4257     double shift_x;
4258     double shift_y;
4259     int valid_mask = 0;
4260     unsigned char *p_in;
4261     unsigned char *p_out;
4262     rl2PixelPtr nd = NULL;
4263 
4264     nd = rl2_clone_pixel (no_data);
4265     p_out = mask;
4266     for (y = 0; y < tileHeight; y++)
4267       {
4268 	  /* priming full transparency */
4269 	  for (x = 0; x < tileWidth; x++)
4270 	      *p_out++ = 0;
4271       }
4272     rl2_prime_void_tile (buffer, tileWidth, tileHeight, sample_type, 1,
4273 			 no_data);
4274 /* creating the output raster */
4275     raster =
4276 	rl2_create_raster (tileWidth, tileHeight, sample_type,
4277 			   RL2_PIXEL_DATAGRID, 1, buffer, buf_size,
4278 			   NULL, mask, *mask_size, nd);
4279     if (raster == NULL)
4280 	goto error;
4281 
4282 /* binding the BBOX to be queried */
4283     sqlite3_reset (stmt_geo);
4284     sqlite3_clear_bindings (stmt_geo);
4285     sqlite3_bind_int (stmt_geo, 1, id_level);
4286     sqlite3_bind_double (stmt_geo, 2, minx);
4287     sqlite3_bind_double (stmt_geo, 3, miny);
4288     sqlite3_bind_double (stmt_geo, 4, maxx);
4289     sqlite3_bind_double (stmt_geo, 5, maxy);
4290     while (1)
4291       {
4292 	  /* scrolling the result set rows */
4293 	  ret = sqlite3_step (stmt_geo);
4294 	  if (ret == SQLITE_DONE)
4295 	      break;		/* end of result set */
4296 	  if (ret == SQLITE_ROW)
4297 	    {
4298 		rl2RasterPtr raster_in = NULL;
4299 		rl2PrivRasterPtr rst_in;
4300 		sqlite3_int64 tile_id = sqlite3_column_int64 (stmt_geo, 0);
4301 		double tile_x = sqlite3_column_double (stmt_geo, 1);
4302 		double tile_y = sqlite3_column_double (stmt_geo, 2);
4303 
4304 		raster_in = load_tile_base_generic (stmt_data, tile_id);
4305 		rst_in = (rl2PrivRasterPtr) raster_in;
4306 		base_tile =
4307 		    create_rescaled_datagrid_raster (factor, tileWidth,
4308 						     tileHeight,
4309 						     rst_in->rasterBuffer,
4310 						     sample_type, no_data);
4311 		rl2_destroy_raster (raster_in);
4312 		raster_in = NULL;
4313 
4314 		if (base_tile == NULL)
4315 		    goto error;
4316 		shift_x = tile_x - minx;
4317 		shift_y = maxy - tile_y;
4318 		x = (int) (shift_x / res_x);
4319 		y = (int) (shift_y / res_y);
4320 		copy_datagrid_rescaled (raster, base_tile, x, y);
4321 		rl2_destroy_raster (base_tile);
4322 	    }
4323       }
4324 
4325 /* releasing buffers ownership */
4326     rst = (rl2PrivRasterPtr) raster;
4327     rst->rasterBuffer = NULL;
4328     rst->maskBuffer = NULL;
4329     rl2_destroy_raster (raster);
4330 
4331     p_in = mask;
4332     for (y = 0; y < tileHeight; y++)
4333       {
4334 	  for (x = 0; x < tileWidth; x++)
4335 	    {
4336 		if (*p_in++ == 0)
4337 		    valid_mask = 1;
4338 	    }
4339       }
4340     if (!valid_mask)
4341       {
4342 	  free (mask);
4343 	  *mask_size = 0;
4344       }
4345 
4346     return 1;
4347   error:
4348     if (raster != NULL)
4349       {
4350 	  /* releasing buffers ownership */
4351 	  rst = (rl2PrivRasterPtr) raster;
4352 	  rst->rasterBuffer = NULL;
4353 	  rst->maskBuffer = NULL;
4354 	  rl2_destroy_raster (raster);
4355       }
4356     return 0;
4357 }
4358 
4359 static int
prepare_section_pyramid_stmts(sqlite3 * handle,const char * coverage,sqlite3_stmt ** xstmt_rd,sqlite3_stmt ** xstmt_levl,sqlite3_stmt ** xstmt_tils,sqlite3_stmt ** xstmt_data)4360 prepare_section_pyramid_stmts (sqlite3 * handle, const char *coverage,
4361 			       sqlite3_stmt ** xstmt_rd,
4362 			       sqlite3_stmt ** xstmt_levl,
4363 			       sqlite3_stmt ** xstmt_tils,
4364 			       sqlite3_stmt ** xstmt_data)
4365 {
4366 /* preparing the section pyramid related SQL statements */
4367     char *table_tile_data;
4368     char *xtable_tile_data;
4369     char *table;
4370     char *xtable;
4371     char *sql;
4372     sqlite3_stmt *stmt_rd = NULL;
4373     sqlite3_stmt *stmt_levl = NULL;
4374     sqlite3_stmt *stmt_tils = NULL;
4375     sqlite3_stmt *stmt_data = NULL;
4376     int ret;
4377 
4378     *xstmt_rd = NULL;
4379     *xstmt_levl = NULL;
4380     *xstmt_tils = NULL;
4381     *xstmt_data = NULL;
4382 
4383     table_tile_data = sqlite3_mprintf ("%s_tile_data", coverage);
4384     xtable_tile_data = gaiaDoubleQuotedSql (table_tile_data);
4385     sqlite3_free (table_tile_data);
4386     sql = sqlite3_mprintf ("SELECT tile_data_odd, tile_data_even "
4387 			   "FROM \"%s\" WHERE tile_id = ?", xtable_tile_data);
4388     free (xtable_tile_data);
4389     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt_rd, NULL);
4390     sqlite3_free (sql);
4391     if (ret != SQLITE_OK)
4392       {
4393 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
4394 	  goto error;
4395       }
4396     table = sqlite3_mprintf ("%s_levels", coverage);
4397     xtable = gaiaDoubleQuotedSql (table);
4398     sqlite3_free (table);
4399     sql =
4400 	sqlite3_mprintf
4401 	("INSERT OR IGNORE INTO \"%s\" (pyramid_level, "
4402 	 "x_resolution_1_1, y_resolution_1_1, "
4403 	 "x_resolution_1_2, y_resolution_1_2, x_resolution_1_4, "
4404 	 "y_resolution_1_4, x_resolution_1_8, y_resolution_1_8) "
4405 	 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", xtable);
4406     free (xtable);
4407     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt_levl, NULL);
4408     sqlite3_free (sql);
4409     if (ret != SQLITE_OK)
4410       {
4411 	  printf ("INSERT INTO levels SQL error: %s\n",
4412 		  sqlite3_errmsg (handle));
4413 	  goto error;
4414       }
4415 
4416     table = sqlite3_mprintf ("%s_tiles", coverage);
4417     xtable = gaiaDoubleQuotedSql (table);
4418     sqlite3_free (table);
4419     sql =
4420 	sqlite3_mprintf
4421 	("INSERT INTO \"%s\" (tile_id, pyramid_level, section_id, geometry) "
4422 	 "VALUES (NULL, ?, ?, ?)", xtable);
4423     free (xtable);
4424     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt_tils, NULL);
4425     sqlite3_free (sql);
4426     if (ret != SQLITE_OK)
4427       {
4428 	  printf ("INSERT INTO tiles SQL error: %s\n", sqlite3_errmsg (handle));
4429 	  goto error;
4430       }
4431 
4432     table = sqlite3_mprintf ("%s_tile_data", coverage);
4433     xtable = gaiaDoubleQuotedSql (table);
4434     sqlite3_free (table);
4435     sql =
4436 	sqlite3_mprintf
4437 	("INSERT INTO \"%s\" (tile_id, tile_data_odd, tile_data_even) "
4438 	 "VALUES (?, ?, ?)", xtable);
4439     free (xtable);
4440     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt_data, NULL);
4441     sqlite3_free (sql);
4442     if (ret != SQLITE_OK)
4443       {
4444 	  printf ("INSERT INTO tile_data SQL error: %s\n",
4445 		  sqlite3_errmsg (handle));
4446 	  goto error;
4447       }
4448 
4449     *xstmt_rd = stmt_rd;
4450     *xstmt_levl = stmt_levl;
4451     *xstmt_tils = stmt_tils;
4452     *xstmt_data = stmt_data;
4453     return 1;
4454 
4455   error:
4456     if (stmt_rd != NULL)
4457 	sqlite3_finalize (stmt_rd);
4458     if (stmt_levl != NULL)
4459 	sqlite3_finalize (stmt_levl);
4460     if (stmt_tils != NULL)
4461 	sqlite3_finalize (stmt_tils);
4462     if (stmt_data != NULL)
4463 	sqlite3_finalize (stmt_data);
4464     return 0;
4465 }
4466 
4467 static int
do_build_section_pyramid(sqlite3 * handle,const char * coverage,const char * section,unsigned char sample_type,unsigned char pixel_type,unsigned char num_samples,unsigned char compression,int quality,int srid,unsigned int tileWidth,unsigned int tileHeight)4468 do_build_section_pyramid (sqlite3 * handle, const char *coverage,
4469 			  const char *section, unsigned char sample_type,
4470 			  unsigned char pixel_type, unsigned char num_samples,
4471 			  unsigned char compression, int quality, int srid,
4472 			  unsigned int tileWidth, unsigned int tileHeight)
4473 {
4474 /* attempting to (re)build a section pyramid from scratch */
4475     char *table_levels;
4476     char *xtable_levels;
4477     char *table_tiles;
4478     char *xtable_tiles;
4479     char *sql;
4480     int id_level = 0;
4481     double new_res_x;
4482     double new_res_y;
4483     sqlite3_int64 sect_id;
4484     unsigned int sect_width;
4485     unsigned int sect_height;
4486     double minx;
4487     double miny;
4488     double maxx;
4489     double maxy;
4490     unsigned int row;
4491     unsigned int col;
4492     double out_minx;
4493     double out_miny;
4494     double out_maxx;
4495     double out_maxy;
4496     sqlite3_stmt *stmt = NULL;
4497     sqlite3_stmt *stmt_rd = NULL;
4498     sqlite3_stmt *stmt_levl = NULL;
4499     sqlite3_stmt *stmt_tils = NULL;
4500     sqlite3_stmt *stmt_data = NULL;
4501     SectionPyramid *pyr = NULL;
4502     int ret;
4503     int first;
4504     int scale;
4505     rl2PalettePtr palette = NULL;
4506     rl2PixelPtr no_data = NULL;
4507 
4508     if (!get_section_infos
4509 	(handle, coverage, section, &sect_id, &sect_width, &sect_height, &minx,
4510 	 &miny, &maxx, &maxy, &palette, &no_data))
4511 	goto error;
4512 
4513     if (!prepare_section_pyramid_stmts
4514 	(handle, coverage, &stmt_rd, &stmt_levl, &stmt_tils, &stmt_data))
4515 	goto error;
4516 
4517     while (1)
4518       {
4519 	  /* looping on pyramid levels */
4520 	  table_levels = sqlite3_mprintf ("%s_levels", coverage);
4521 	  xtable_levels = gaiaDoubleQuotedSql (table_levels);
4522 	  sqlite3_free (table_levels);
4523 	  table_tiles = sqlite3_mprintf ("%s_tiles", coverage);
4524 	  xtable_tiles = gaiaDoubleQuotedSql (table_tiles);
4525 	  sqlite3_free (table_tiles);
4526 	  sql =
4527 	      sqlite3_mprintf ("SELECT l.x_resolution_1_1, l.y_resolution_1_1, "
4528 			       "t.tile_id, MbrMinX(t.geometry), MbrMinY(t.geometry), "
4529 			       "MbrMaxX(t.geometry), MbrMaxY(t.geometry) "
4530 			       "FROM \"%s\" AS l "
4531 			       "JOIN \"%s\" AS t ON (l.pyramid_level = t.pyramid_level) "
4532 			       "WHERE l.pyramid_level = %d AND t.section_id = %d",
4533 			       xtable_levels, xtable_tiles, id_level, sect_id);
4534 	  free (xtable_levels);
4535 	  free (xtable_tiles);
4536 	  ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
4537 	  sqlite3_free (sql);
4538 	  if (ret != SQLITE_OK)
4539 	    {
4540 		fprintf (stderr, "SQL error: %s\n%s\n", sql,
4541 			 sqlite3_errmsg (handle));
4542 		goto error;
4543 	    }
4544 	  first = 1;
4545 	  while (1)
4546 	    {
4547 		ret = sqlite3_step (stmt);
4548 		if (ret == SQLITE_DONE)
4549 		    break;
4550 		if (ret == SQLITE_ROW)
4551 		  {
4552 		      double res_x = sqlite3_column_double (stmt, 0);
4553 		      double res_y = sqlite3_column_double (stmt, 1);
4554 		      sqlite3_int64 tile_id = sqlite3_column_int64 (stmt, 2);
4555 		      double tminx = sqlite3_column_double (stmt, 3);
4556 		      double tminy = sqlite3_column_double (stmt, 4);
4557 		      double tmaxx = sqlite3_column_double (stmt, 5);
4558 		      double tmaxy = sqlite3_column_double (stmt, 6);
4559 		      new_res_x = res_x * 8.0;
4560 		      new_res_y = res_y * 8.0;
4561 		      scale = 8;
4562 		      if (first)
4563 			{
4564 			    pyr =
4565 				alloc_sect_pyramid (sect_id, sect_width,
4566 						    sect_height, sample_type,
4567 						    pixel_type, num_samples,
4568 						    compression, quality, srid,
4569 						    new_res_x, new_res_y,
4570 						    (double) tileWidth *
4571 						    new_res_x,
4572 						    (double) tileHeight *
4573 						    new_res_y, minx, miny, maxx,
4574 						    maxy, scale);
4575 			    first = 0;
4576 			    if (pyr == NULL)
4577 				goto error;
4578 			}
4579 		      if (!insert_tile_into_section_pyramid
4580 			  (pyr, tile_id, tminx, tminy, tmaxx, tmaxy))
4581 			  goto error;
4582 		  }
4583 		else
4584 		  {
4585 		      fprintf (stderr,
4586 			       "SELECT base level; sqlite3_step() error: %s\n",
4587 			       sqlite3_errmsg (handle));
4588 		      goto error;
4589 		  }
4590 	    }
4591 	  sqlite3_finalize (stmt);
4592 	  stmt = NULL;
4593 	  if (pyr == NULL)
4594 	      goto error;
4595 
4596 	  out_maxy = maxy;
4597 	  for (row = 0; row < pyr->scaled_height; row += tileHeight)
4598 	    {
4599 		out_miny = out_maxy - pyr->tile_height;
4600 		out_minx = minx;
4601 		for (col = 0; col < pyr->scaled_width; col += tileWidth)
4602 		  {
4603 		      out_maxx = out_minx + pyr->tile_width;
4604 		      set_pyramid_tile_destination (pyr, out_minx, out_miny,
4605 						    out_maxx, out_maxy, row,
4606 						    col);
4607 		      out_minx += pyr->tile_width;
4608 		  }
4609 		out_maxy -= pyr->tile_height;
4610 	    }
4611 	  id_level++;
4612 	  if (pyr->scaled_width <= tileWidth
4613 	      && pyr->scaled_height <= tileHeight)
4614 	      break;
4615 	  if (!do_insert_pyramid_levels
4616 	      (handle, id_level, pyr->res_x, pyr->res_y, stmt_levl))
4617 	      goto error;
4618 	  if (pixel_type == RL2_PIXEL_DATAGRID)
4619 	    {
4620 		/* DataGrid Pyramid */
4621 		if (!update_sect_pyramid_grid
4622 		    (handle, stmt_rd, stmt_tils, stmt_data, pyr, tileWidth,
4623 		     tileHeight, id_level, no_data, sample_type))
4624 		    goto error;
4625 	    }
4626 	  else if (pixel_type == RL2_PIXEL_MULTIBAND)
4627 	    {
4628 		/* MultiBand Pyramid */
4629 		if (!update_sect_pyramid_multiband
4630 		    (handle, stmt_rd, stmt_tils, stmt_data, pyr, tileWidth,
4631 		     tileHeight, id_level, no_data, sample_type, num_samples))
4632 		    goto error;
4633 	    }
4634 	  else
4635 	    {
4636 		/* any other Pyramid [not a DataGrid] */
4637 		if (!update_sect_pyramid
4638 		    (handle, stmt_rd, stmt_tils, stmt_data, pyr, tileWidth,
4639 		     tileHeight, id_level, palette, no_data))
4640 		    goto error;
4641 	    }
4642 	  delete_sect_pyramid (pyr);
4643 	  pyr = NULL;
4644       }
4645 
4646     if (pyr != NULL)
4647       {
4648 	  if (!do_insert_pyramid_levels
4649 	      (handle, id_level, pyr->res_x, pyr->res_y, stmt_levl))
4650 	      goto error;
4651 	  if (pixel_type == RL2_PIXEL_DATAGRID)
4652 	    {
4653 		/* DataGrid Pyramid */
4654 		if (!update_sect_pyramid_grid
4655 		    (handle, stmt_rd, stmt_tils, stmt_data, pyr, tileWidth,
4656 		     tileHeight, id_level, no_data, sample_type))
4657 		    goto error;
4658 	    }
4659 	  else if (pixel_type == RL2_PIXEL_MULTIBAND)
4660 	    {
4661 		/* MultiBand Pyramid */
4662 		if (!update_sect_pyramid_multiband
4663 		    (handle, stmt_rd, stmt_tils, stmt_data, pyr, tileWidth,
4664 		     tileHeight, id_level, no_data, sample_type, num_samples))
4665 		    goto error;
4666 	    }
4667 	  else
4668 	    {
4669 		/* any other Pyramid [not a DataGrid] */
4670 		if (!update_sect_pyramid
4671 		    (handle, stmt_rd, stmt_tils, stmt_data, pyr, tileWidth,
4672 		     tileHeight, id_level, palette, no_data))
4673 		    goto error;
4674 	    }
4675 	  delete_sect_pyramid (pyr);
4676       }
4677     sqlite3_finalize (stmt_rd);
4678     sqlite3_finalize (stmt_levl);
4679     sqlite3_finalize (stmt_tils);
4680     sqlite3_finalize (stmt_data);
4681     if (no_data != NULL)
4682 	rl2_destroy_pixel (no_data);
4683     return 1;
4684 
4685   error:
4686     if (stmt != NULL)
4687 	sqlite3_finalize (stmt);
4688     if (stmt_rd != NULL)
4689 	sqlite3_finalize (stmt_rd);
4690     if (pyr != NULL)
4691 	delete_sect_pyramid (pyr);
4692     if (stmt_levl != NULL)
4693 	sqlite3_finalize (stmt_levl);
4694     if (stmt_tils != NULL)
4695 	sqlite3_finalize (stmt_tils);
4696     if (stmt_data != NULL)
4697 	sqlite3_finalize (stmt_data);
4698     if (no_data != NULL)
4699 	rl2_destroy_pixel (no_data);
4700     return 0;
4701 }
4702 
4703 static int
get_coverage_extent(sqlite3 * handle,const char * coverage,double * minx,double * miny,double * maxx,double * maxy)4704 get_coverage_extent (sqlite3 * handle, const char *coverage, double *minx,
4705 		     double *miny, double *maxx, double *maxy)
4706 {
4707 /* attempting to get the Extent from a Coverage Object */
4708     char *sql;
4709     int ret;
4710     sqlite3_stmt *stmt;
4711     double extent_minx;
4712     double extent_miny;
4713     double extent_maxx;
4714     double extent_maxy;
4715     int ok = 0;
4716 
4717 /* querying the Coverage metadata defs */
4718     sql =
4719 	"SELECT extent_minx, extent_miny, extent_maxx, extent_maxy "
4720 	"FROM raster_coverages WHERE Lower(coverage_name) = Lower(?)";
4721     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
4722     if (ret != SQLITE_OK)
4723       {
4724 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
4725 	  return 0;
4726       }
4727     sqlite3_reset (stmt);
4728     sqlite3_clear_bindings (stmt);
4729     sqlite3_bind_text (stmt, 1, coverage, strlen (coverage), SQLITE_STATIC);
4730     while (1)
4731       {
4732 	  /* scrolling the result set rows */
4733 	  ret = sqlite3_step (stmt);
4734 	  if (ret == SQLITE_DONE)
4735 	      break;		/* end of result set */
4736 	  if (ret == SQLITE_ROW)
4737 	    {
4738 		int ok_minx = 0;
4739 		int ok_miny = 0;
4740 		int ok_maxx = 0;
4741 		int ok_maxy = 0;
4742 		if (sqlite3_column_type (stmt, 0) == SQLITE_FLOAT)
4743 		  {
4744 		      extent_minx = sqlite3_column_double (stmt, 0);
4745 		      ok_minx = 1;
4746 		  }
4747 		if (sqlite3_column_type (stmt, 1) == SQLITE_FLOAT)
4748 		  {
4749 		      extent_miny = sqlite3_column_double (stmt, 1);
4750 		      ok_miny = 1;
4751 		  }
4752 		if (sqlite3_column_type (stmt, 2) == SQLITE_FLOAT)
4753 		  {
4754 		      extent_maxx = sqlite3_column_double (stmt, 2);
4755 		      ok_maxx = 1;
4756 		  }
4757 		if (sqlite3_column_type (stmt, 3) == SQLITE_FLOAT)
4758 		  {
4759 		      extent_maxy = sqlite3_column_double (stmt, 3);
4760 		      ok_maxy = 1;
4761 		  }
4762 		if (ok_minx && ok_miny && ok_maxx && ok_maxy)
4763 		    ok = 1;
4764 	    }
4765       }
4766     sqlite3_finalize (stmt);
4767 
4768     if (!ok)
4769 	return 0;
4770     *minx = extent_minx;
4771     *miny = extent_miny;
4772     *maxx = extent_maxx;
4773     *maxy = extent_maxy;
4774     return 1;
4775 }
4776 
4777 static int
find_base_resolution(sqlite3 * handle,const char * coverage,double * x_res,double * y_res)4778 find_base_resolution (sqlite3 * handle, const char *coverage,
4779 		      double *x_res, double *y_res)
4780 {
4781 /* attempting to identify the base resolution level */
4782     int ret;
4783     int found = 0;
4784     double xx_res;
4785     double yy_res;
4786     char *xcoverage;
4787     char *xxcoverage;
4788     char *sql;
4789     sqlite3_stmt *stmt = NULL;
4790 
4791     xcoverage = sqlite3_mprintf ("%s_levels", coverage);
4792     xxcoverage = gaiaDoubleQuotedSql (xcoverage);
4793     sqlite3_free (xcoverage);
4794     sql =
4795 	sqlite3_mprintf ("SELECT x_resolution_1_1, y_resolution_1_1 "
4796 			 "FROM \"%s\" WHERE pyramid_level = 0", xxcoverage);
4797     free (xxcoverage);
4798     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
4799     if (ret != SQLITE_OK)
4800       {
4801 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
4802 	  goto error;
4803       }
4804     sqlite3_free (sql);
4805 
4806     while (1)
4807       {
4808 	  /* scrolling the result set rows */
4809 	  ret = sqlite3_step (stmt);
4810 	  if (ret == SQLITE_DONE)
4811 	      break;		/* end of result set */
4812 	  if (ret == SQLITE_ROW)
4813 	    {
4814 		if (sqlite3_column_type (stmt, 0) == SQLITE_FLOAT
4815 		    && sqlite3_column_type (stmt, 1) == SQLITE_FLOAT)
4816 		  {
4817 		      found = 1;
4818 		      xx_res = sqlite3_column_double (stmt, 0);
4819 		      yy_res = sqlite3_column_double (stmt, 1);
4820 		  }
4821 	    }
4822 	  else
4823 	    {
4824 		fprintf (stderr, "SQL error: %s\n%s\n", sql,
4825 			 sqlite3_errmsg (handle));
4826 		goto error;
4827 	    }
4828       }
4829     sqlite3_finalize (stmt);
4830     if (found)
4831       {
4832 	  *x_res = xx_res;
4833 	  *y_res = yy_res;
4834 	  return 1;
4835       }
4836     return 0;
4837 
4838   error:
4839     if (stmt != NULL)
4840 	sqlite3_finalize (stmt);
4841     return 0;
4842 }
4843 
4844 static int
get_section_raw_raster_data(sqlite3 * handle,const char * coverage,sqlite3_int64 sect_id,unsigned int width,unsigned int height,unsigned char sample_type,unsigned char pixel_type,unsigned char num_bands,double minx,double maxy,double x_res,double y_res,unsigned char ** buffer,int * buf_size,rl2PalettePtr palette,rl2PixelPtr no_data)4845 get_section_raw_raster_data (sqlite3 * handle, const char *coverage,
4846 			     sqlite3_int64 sect_id, unsigned int width,
4847 			     unsigned int height, unsigned char sample_type,
4848 			     unsigned char pixel_type, unsigned char num_bands,
4849 			     double minx, double maxy,
4850 			     double x_res, double y_res, unsigned char **buffer,
4851 			     int *buf_size, rl2PalettePtr palette,
4852 			     rl2PixelPtr no_data)
4853 {
4854 /* attempting to return a buffer containing raw pixels from the whole DBMS Section */
4855     unsigned char *bufpix = NULL;
4856     int bufpix_size;
4857     char *xtiles;
4858     char *xxtiles;
4859     char *xdata;
4860     char *xxdata;
4861     char *sql;
4862     sqlite3_stmt *stmt_tiles = NULL;
4863     sqlite3_stmt *stmt_data = NULL;
4864     int ret;
4865 
4866     switch (sample_type)
4867       {
4868       case RL2_SAMPLE_1_BIT:
4869       case RL2_SAMPLE_2_BIT:
4870       case RL2_SAMPLE_4_BIT:
4871 	  break;
4872       case RL2_SAMPLE_UINT8:
4873 	  if (pixel_type != RL2_PIXEL_PALETTE)
4874 	      goto error;
4875 	  break;
4876       default:
4877 	  goto error;
4878 	  break;
4879       };
4880     bufpix_size = num_bands * width * height;
4881     bufpix = malloc (bufpix_size);
4882     if (bufpix == NULL)
4883       {
4884 	  fprintf (stderr,
4885 		   "get_section_raw_raster_data: Insufficient Memory !!!\n");
4886 	  goto error;
4887       }
4888     memset (bufpix, 0, bufpix_size);
4889 
4890 /* preparing the "tiles" SQL query */
4891     xtiles = sqlite3_mprintf ("%s_tiles", coverage);
4892     xxtiles = gaiaDoubleQuotedSql (xtiles);
4893     sql =
4894 	sqlite3_mprintf ("SELECT tile_id, MbrMinX(geometry), MbrMaxY(geometry) "
4895 			 "FROM \"%s\" "
4896 			 "WHERE pyramid_level = 0 AND section_id = ?", xxtiles);
4897     sqlite3_free (xtiles);
4898     free (xxtiles);
4899     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt_tiles, NULL);
4900     sqlite3_free (sql);
4901     if (ret != SQLITE_OK)
4902       {
4903 	  printf ("SELECT section raw tiles SQL error: %s\n",
4904 		  sqlite3_errmsg (handle));
4905 	  goto error;
4906       }
4907 
4908 /* preparing the data SQL query - both ODD and EVEN */
4909     xdata = sqlite3_mprintf ("%s_tile_data", coverage);
4910     xxdata = gaiaDoubleQuotedSql (xdata);
4911     sqlite3_free (xdata);
4912     sql = sqlite3_mprintf ("SELECT tile_data_odd, tile_data_even "
4913 			   "FROM \"%s\" WHERE tile_id = ?", xxdata);
4914     free (xxdata);
4915     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt_data, NULL);
4916     sqlite3_free (sql);
4917     if (ret != SQLITE_OK)
4918       {
4919 	  printf ("SELECT section raw tiles data(2) SQL error: %s\n",
4920 		  sqlite3_errmsg (handle));
4921 	  goto error;
4922       }
4923 
4924 /* preparing a raw pixels buffer */
4925     if (pixel_type == RL2_PIXEL_PALETTE)
4926 	void_raw_buffer_palette (bufpix, width, height, no_data);
4927     else
4928 	void_raw_buffer (bufpix, width, height, sample_type, num_bands,
4929 			 no_data);
4930     if (!load_dbms_tiles_section
4931 	(handle, sect_id, stmt_tiles, stmt_data, bufpix, width, height,
4932 	 sample_type, num_bands, x_res, y_res, minx, maxy, RL2_SCALE_1, palette,
4933 	 no_data))
4934 	goto error;
4935     sqlite3_finalize (stmt_tiles);
4936     sqlite3_finalize (stmt_data);
4937     *buffer = bufpix;
4938     *buf_size = bufpix_size;
4939     return 1;
4940 
4941   error:
4942     if (stmt_tiles != NULL)
4943 	sqlite3_finalize (stmt_tiles);
4944     if (stmt_data != NULL)
4945 	sqlite3_finalize (stmt_data);
4946     if (bufpix != NULL)
4947 	free (bufpix);
4948     return 0;
4949 }
4950 
4951 static void
raster_tile_124_rescaled(unsigned char * outbuf,unsigned char pixel_type,const unsigned char * inbuf,unsigned int section_width,unsigned int section_height,unsigned int out_width,unsigned int out_height,rl2PalettePtr palette)4952 raster_tile_124_rescaled (unsigned char *outbuf,
4953 			  unsigned char pixel_type, const unsigned char *inbuf,
4954 			  unsigned int section_width,
4955 			  unsigned int section_height, unsigned int out_width,
4956 			  unsigned int out_height, rl2PalettePtr palette)
4957 {
4958 /*
4959 / this function builds an high quality rescaled sub-image by applying pixel interpolation
4960 /
4961 / this code is widely inspired by the original GD gdImageCopyResampled() function
4962 */
4963     unsigned int x;
4964     unsigned int y;
4965     double sy1;
4966     double sy2;
4967     double sx1;
4968     double sx2;
4969     unsigned char r;
4970     unsigned char g;
4971     unsigned char b;
4972     const unsigned char *p_in;
4973     unsigned char *p_out;
4974 
4975     if (pixel_type == RL2_PIXEL_PALETTE && palette == NULL)
4976 	return;
4977 
4978     for (y = 0; y < out_height; y++)
4979       {
4980 	  sy1 = ((double) y) * (double) section_height / (double) out_height;
4981 	  sy2 =
4982 	      ((double) (y + 1)) * (double) section_height /
4983 	      (double) out_height;
4984 	  for (x = 0; x < out_width; x++)
4985 	    {
4986 		double sx;
4987 		double sy;
4988 		double spixels = 0;
4989 		double red = 0.0;
4990 		double green = 0.0;
4991 		double blue = 0.0;
4992 		sx1 =
4993 		    ((double) x) * (double) section_width / (double) out_width;
4994 		sx2 =
4995 		    ((double) (x + 1)) * (double) section_width /
4996 		    (double) out_width;
4997 		sy = sy1;
4998 		do
4999 		  {
5000 		      double yportion;
5001 		      if (floor2 (sy) == floor2 (sy1))
5002 			{
5003 			    yportion = 1.0 - (sy - floor2 (sy));
5004 			    if (yportion > sy2 - sy1)
5005 			      {
5006 				  yportion = sy2 - sy1;
5007 			      }
5008 			    sy = floor2 (sy);
5009 			}
5010 		      else if (sy == floor2 (sy2))
5011 			{
5012 			    yportion = sy2 - floor2 (sy2);
5013 			}
5014 		      else
5015 			{
5016 			    yportion = 1.0;
5017 			}
5018 		      sx = sx1;
5019 		      do
5020 			{
5021 			    double xportion;
5022 			    double pcontribution;
5023 			    if (floor2 (sx) == floor2 (sx1))
5024 			      {
5025 				  xportion = 1.0 - (sx - floor2 (sx));
5026 				  if (xportion > sx2 - sx1)
5027 				    {
5028 					xportion = sx2 - sx1;
5029 				    }
5030 				  sx = floor2 (sx);
5031 			      }
5032 			    else if (sx == floor2 (sx2))
5033 			      {
5034 				  xportion = sx2 - floor2 (sx2);
5035 			      }
5036 			    else
5037 			      {
5038 				  xportion = 1.0;
5039 			      }
5040 			    pcontribution = xportion * yportion;
5041 			    /* retrieving the origin pixel */
5042 			    if (pixel_type == RL2_PIXEL_RGB)
5043 				p_in =
5044 				    inbuf +
5045 				    ((unsigned int) sy * section_width * 3);
5046 			    else
5047 				p_in =
5048 				    inbuf + ((unsigned int) sy * section_width);
5049 			    if (pixel_type == RL2_PIXEL_PALETTE)
5050 			      {
5051 				  rl2PrivPalettePtr plt =
5052 				      (rl2PrivPalettePtr) palette;
5053 				  unsigned char index;
5054 				  p_in += (unsigned int) sx;
5055 				  index = *p_in;
5056 				  if (index < plt->nEntries)
5057 				    {
5058 					/* resolving the Palette color by index */
5059 					rl2PrivPaletteEntryPtr entry =
5060 					    plt->entries + index;
5061 					r = entry->red;
5062 					g = entry->green;
5063 					b = entry->red;
5064 				    }
5065 				  else
5066 				    {
5067 					r = 0;
5068 					g = 0;
5069 					b = 0;
5070 				    }
5071 			      }
5072 			    else
5073 			      {
5074 				  p_in += (unsigned int) sx;
5075 				  if (*p_in == 1)
5076 				    {
5077 					/* black monochrome pixel */
5078 					r = 0;
5079 					g = 0;
5080 					b = 0;
5081 				    }
5082 				  else
5083 				    {
5084 					/* white monochrome pixel */
5085 					r = 255;
5086 					g = 255;
5087 					b = 255;
5088 				    }
5089 			      }
5090 			    red += r * pcontribution;
5091 			    green += g * pcontribution;
5092 			    blue += b * pcontribution;
5093 			    spixels += xportion * yportion;
5094 			    sx += 1.0;
5095 			}
5096 		      while (sx < sx2);
5097 		      sy += 1.0;
5098 		  }
5099 		while (sy < sy2);
5100 		if (spixels != 0.0)
5101 		  {
5102 		      red /= spixels;
5103 		      green /= spixels;
5104 		      blue /= spixels;
5105 		  }
5106 		if (red > 255.0)
5107 		    red = 255.0;
5108 		if (green > 255.0)
5109 		    green = 255.0;
5110 		if (blue > 255.0)
5111 		    blue = 255.0;
5112 		/* setting the destination pixel */
5113 		if (pixel_type == RL2_PIXEL_PALETTE)
5114 		    p_out = outbuf + (y * out_width * 3);
5115 		else
5116 		    p_out = outbuf + (y * out_width);
5117 		if (pixel_type == RL2_PIXEL_PALETTE)
5118 		  {
5119 		      p_out += x * 3;
5120 		      *p_out++ = (unsigned char) red;
5121 		      *p_out++ = (unsigned char) green;
5122 		      *p_out = (unsigned char) blue;
5123 		  }
5124 		else
5125 		  {
5126 		      if (red <= 224.0)
5127 			{
5128 			    p_out += x;
5129 			    if (red < *p_out)
5130 				*p_out = (unsigned char) red;
5131 			}
5132 		  }
5133 	    }
5134       }
5135 }
5136 
5137 static int
copy_124_tile(unsigned char pixel_type,const unsigned char * outbuf,unsigned char ** tilebuf,int * tilebuf_sz,unsigned char ** tilemask,int * tilemask_sz,unsigned int row,unsigned int col,unsigned int out_width,unsigned int out_height,unsigned int tileWidth,unsigned int tileHeight,rl2PixelPtr no_data)5138 copy_124_tile (unsigned char pixel_type, const unsigned char *outbuf,
5139 	       unsigned char **tilebuf,
5140 	       int *tilebuf_sz, unsigned char **tilemask, int *tilemask_sz,
5141 	       unsigned int row, unsigned int col, unsigned int out_width,
5142 	       unsigned int out_height, unsigned int tileWidth,
5143 	       unsigned int tileHeight, rl2PixelPtr no_data)
5144 {
5145 /* allocating and initializing the resized tile buffers */
5146     unsigned char *pixels = NULL;
5147     int pixels_sz = 0;
5148     unsigned char *mask = NULL;
5149     int mask_sz = 0;
5150     int has_mask = 0;
5151     unsigned int x;
5152     unsigned int y;
5153     const unsigned char *p_inp;
5154     unsigned char *p_outp;
5155 
5156     if (pixel_type == RL2_PIXEL_RGB)
5157 	pixels_sz = tileWidth * tileHeight * 3;
5158     else
5159 	pixels_sz = tileWidth * tileHeight;
5160     pixels = malloc (pixels_sz);
5161     if (pixels == NULL)
5162 	goto error;
5163 
5164     if (pixel_type == RL2_PIXEL_RGB)
5165 	rl2_prime_void_tile (pixels, tileWidth, tileHeight, RL2_SAMPLE_UINT8,
5166 			     3, no_data);
5167     else
5168 	rl2_prime_void_tile (pixels, tileWidth, tileHeight, RL2_SAMPLE_UINT8,
5169 			     1, no_data);
5170 
5171     if (row + tileHeight > out_height)
5172 	has_mask = 1;
5173     if (col + tileWidth > out_width)
5174 	has_mask = 1;
5175     if (has_mask)
5176       {
5177 	  /* masking the unused portion of this tile */
5178 	  mask_sz = tileWidth * tileHeight;
5179 	  mask = malloc (mask_sz);
5180 	  if (mask == NULL)
5181 	      goto error;
5182 	  memset (mask, 0, mask_sz);
5183 	  for (y = 0; y < tileHeight; y++)
5184 	    {
5185 		unsigned int y_in = y + row;
5186 		if (y_in >= out_height)
5187 		    continue;
5188 		for (x = 0; x < tileWidth; x++)
5189 		  {
5190 		      unsigned int x_in = x + col;
5191 		      if (x_in >= out_width)
5192 			  continue;
5193 		      p_outp = mask + (y * tileWidth);
5194 		      p_outp += x;
5195 		      *p_outp = 1;
5196 		  }
5197 	    }
5198       }
5199 
5200     for (y = 0; y < tileHeight; y++)
5201       {
5202 	  unsigned int y_in = y + row;
5203 	  if (y_in >= out_height)
5204 	      continue;
5205 	  for (x = 0; x < tileWidth; x++)
5206 	    {
5207 		unsigned int x_in = x + col;
5208 		if (x_in >= out_width)
5209 		    continue;
5210 		if (pixel_type == RL2_PIXEL_RGB)
5211 		  {
5212 		      p_inp = outbuf + (y_in * out_width * 3);
5213 		      p_inp += x_in * 3;
5214 		      p_outp = pixels + (y * tileWidth * 3);
5215 		      p_outp += x * 3;
5216 		      *p_outp++ = *p_inp++;
5217 		      *p_outp++ = *p_inp++;
5218 		      *p_outp = *p_inp;
5219 		  }
5220 		else
5221 		  {
5222 		      p_inp = outbuf + (y_in * out_width);
5223 		      p_inp += x_in;
5224 		      p_outp = pixels + (y * tileWidth);
5225 		      p_outp += x;
5226 		      *p_outp = *p_inp;
5227 		  }
5228 	    }
5229       }
5230 
5231     *tilebuf = pixels;
5232     *tilebuf_sz = pixels_sz;
5233     *tilemask = mask;
5234     *tilemask_sz = mask_sz;
5235     return 1;
5236 
5237   error:
5238     if (pixels != NULL)
5239 	free (pixels);
5240     return 0;
5241 }
5242 
5243 static int
do_build_124_bit_section_pyramid(sqlite3 * handle,const char * coverage,const char * section,unsigned char sample_type,unsigned char pixel_type,unsigned char num_samples,int srid,unsigned int tileWidth,unsigned int tileHeight,unsigned char bgRed,unsigned char bgGreen,unsigned char bgBlue)5244 do_build_124_bit_section_pyramid (sqlite3 * handle, const char *coverage,
5245 				  const char *section,
5246 				  unsigned char sample_type,
5247 				  unsigned char pixel_type,
5248 				  unsigned char num_samples, int srid,
5249 				  unsigned int tileWidth,
5250 				  unsigned int tileHeight,
5251 				  unsigned char bgRed, unsigned char bgGreen,
5252 				  unsigned char bgBlue)
5253 {
5254 /* attempting to (re)build a 1,2,4-bit section pyramid from scratch */
5255     double base_res_x;
5256     double base_res_y;
5257     sqlite3_int64 sect_id;
5258     unsigned int sect_width;
5259     unsigned int sect_height;
5260     int id_level = 0;
5261     int scale;
5262     double x_res;
5263     double y_res;
5264     double minx;
5265     double miny;
5266     double maxx;
5267     double maxy;
5268     unsigned int row;
5269     unsigned int col;
5270     sqlite3_stmt *stmt = NULL;
5271     sqlite3_stmt *stmt_rd = NULL;
5272     sqlite3_stmt *stmt_levl = NULL;
5273     sqlite3_stmt *stmt_tils = NULL;
5274     sqlite3_stmt *stmt_data = NULL;
5275     rl2PalettePtr palette = NULL;
5276     rl2PixelPtr no_data = NULL;
5277     rl2PixelPtr nd = NULL;
5278     unsigned char *inbuf = NULL;
5279     int inbuf_size = 0;
5280     unsigned char *outbuf = NULL;
5281     int outbuf_sz = 0;
5282     unsigned char out_pixel_type;
5283     unsigned char out_bands;
5284     unsigned char *tilebuf = NULL;
5285     int tilebuf_sz = 0;
5286     unsigned char *tilemask = NULL;
5287     int tilemask_sz = 0;
5288     unsigned char *blob_odd = NULL;
5289     unsigned char *blob_even = NULL;
5290     int blob_odd_sz;
5291     int blob_even_sz;
5292     unsigned int x;
5293     unsigned int y;
5294     unsigned char *p_out;
5295 
5296     if (!get_section_infos
5297 	(handle, coverage, section, &sect_id, &sect_width, &sect_height, &minx,
5298 	 &miny, &maxx, &maxy, &palette, &no_data))
5299 	goto error;
5300 
5301     if (!find_base_resolution (handle, coverage, &base_res_x, &base_res_y))
5302 	goto error;
5303     if (!get_section_raw_raster_data
5304 	(handle, coverage, sect_id, sect_width, sect_height, sample_type,
5305 	 pixel_type, num_samples, minx, maxy, base_res_x,
5306 	 base_res_y, &inbuf, &inbuf_size, palette, no_data))
5307 	goto error;
5308 
5309     if (!prepare_section_pyramid_stmts
5310 	(handle, coverage, &stmt_rd, &stmt_levl, &stmt_tils, &stmt_data))
5311 	goto error;
5312 
5313     id_level = 1;
5314     scale = 2;
5315     x_res = base_res_x * 2.0;
5316     y_res = base_res_y * 2.0;
5317     while (1)
5318       {
5319 	  /* looping on Pyramid levels */
5320 	  double t_minx;
5321 	  double t_miny;
5322 	  double t_maxx;
5323 	  double t_maxy;
5324 	  unsigned int out_width = sect_width / scale;
5325 	  unsigned int out_height = sect_height / scale;
5326 	  rl2RasterPtr raster = NULL;
5327 
5328 	  if (pixel_type == RL2_PIXEL_MONOCHROME)
5329 	    {
5330 		out_pixel_type = RL2_PIXEL_GRAYSCALE;
5331 		out_bands = 1;
5332 		outbuf_sz = out_width * out_height;
5333 		outbuf = malloc (outbuf_sz);
5334 		if (outbuf == NULL)
5335 		    goto error;
5336 		p_out = outbuf;
5337 		for (y = 0; y < out_height; y++)
5338 		  {
5339 		      /* priming the background color */
5340 		      for (x = 0; x < out_width; x++)
5341 			  *p_out++ = bgRed;
5342 		  }
5343 	    }
5344 	  else
5345 	    {
5346 		out_pixel_type = RL2_PIXEL_RGB;
5347 		out_bands = 3;
5348 		outbuf_sz = out_width * out_height * 3;
5349 		outbuf = malloc (outbuf_sz);
5350 		if (outbuf == NULL)
5351 		    goto error;
5352 		p_out = outbuf;
5353 		for (y = 0; y < out_height; y++)
5354 		  {
5355 		      /* priming the background color */
5356 		      for (x = 0; x < out_width; x++)
5357 			{
5358 			    *p_out++ = bgRed;
5359 			    *p_out++ = bgGreen;
5360 			    *p_out++ = bgBlue;
5361 			}
5362 		  }
5363 	    }
5364 	  t_maxy = maxy;
5365 	  raster_tile_124_rescaled (outbuf, pixel_type, inbuf,
5366 				    sect_width, sect_height, out_width,
5367 				    out_height, palette);
5368 
5369 	  if (!do_insert_pyramid_levels
5370 	      (handle, id_level, x_res, y_res, stmt_levl))
5371 	      goto error;
5372 
5373 	  for (row = 0; row < out_height; row += tileHeight)
5374 	    {
5375 		t_minx = minx;
5376 		t_miny = t_maxy - (tileHeight * y_res);
5377 		for (col = 0; col < out_width; col += tileWidth)
5378 		  {
5379 		      if (pixel_type == RL2_PIXEL_MONOCHROME)
5380 			{
5381 			    if (no_data == NULL)
5382 				nd = NULL;
5383 			    else
5384 			      {
5385 				  /* creating a NO-DATA pixel */
5386 				  nd = rl2_create_pixel (RL2_SAMPLE_UINT8,
5387 							 RL2_PIXEL_GRAYSCALE,
5388 							 1);
5389 				  rl2_set_pixel_sample_uint8 (nd,
5390 							      RL2_GRAYSCALE_BAND,
5391 							      bgRed);
5392 			      }
5393 			}
5394 		      else
5395 			{
5396 			    if (no_data == NULL)
5397 				nd = NULL;
5398 			    else
5399 			      {
5400 				  /* converting the NO-DATA pixel */
5401 				  nd = rl2_create_pixel (RL2_SAMPLE_UINT8,
5402 							 RL2_PIXEL_RGB, 3);
5403 				  rl2_set_pixel_sample_uint8 (nd, RL2_RED_BAND,
5404 							      bgRed);
5405 				  rl2_set_pixel_sample_uint8 (nd,
5406 							      RL2_GREEN_BAND,
5407 							      bgGreen);
5408 				  rl2_set_pixel_sample_uint8 (nd, RL2_BLUE_BAND,
5409 							      bgBlue);
5410 			      }
5411 			}
5412 		      t_maxx = t_minx + (tileWidth * x_res);
5413 		      if (!copy_124_tile
5414 			  (out_pixel_type, outbuf, &tilebuf,
5415 			   &tilebuf_sz, &tilemask, &tilemask_sz, row, col,
5416 			   out_width, out_height, tileWidth, tileHeight,
5417 			   no_data))
5418 			{
5419 			    fprintf (stderr,
5420 				     "ERROR: unable to extract a Pyramid Tile\n");
5421 			    goto error;
5422 			}
5423 
5424 		      raster =
5425 			  rl2_create_raster (tileWidth, tileHeight,
5426 					     RL2_SAMPLE_UINT8, out_pixel_type,
5427 					     out_bands, tilebuf, tilebuf_sz,
5428 					     NULL, tilemask, tilemask_sz, nd);
5429 		      tilebuf = NULL;
5430 		      tilemask = NULL;
5431 		      if (raster == NULL)
5432 			{
5433 			    fprintf (stderr,
5434 				     "ERROR: unable to create a Pyramid Tile\n");
5435 			    goto error;
5436 			}
5437 		      if (rl2_raster_encode
5438 			  (raster, RL2_COMPRESSION_PNG, &blob_odd, &blob_odd_sz,
5439 			   &blob_even, &blob_even_sz, 100, 1) != RL2_OK)
5440 			{
5441 			    fprintf (stderr,
5442 				     "ERROR: unable to encode a Pyramid tile\n");
5443 			    goto error;
5444 			}
5445 
5446 		      /* INSERTing the tile */
5447 		      if (!do_insert_pyramid_tile
5448 			  (handle, blob_odd, blob_odd_sz, blob_even,
5449 			   blob_even_sz, id_level, sect_id, srid, t_minx,
5450 			   t_miny, t_maxx, t_maxy, stmt_tils, stmt_data))
5451 			  goto error;
5452 		      rl2_destroy_raster (raster);
5453 		      t_minx += (tileWidth * x_res);
5454 		  }
5455 		t_maxy -= (tileHeight * y_res);
5456 	    }
5457 
5458 	  free (outbuf);
5459 	  if (out_width < tileWidth && out_height < tileHeight)
5460 	      break;
5461 	  x_res *= 2.0;
5462 	  y_res *= 2.0;
5463 	  scale *= 2;
5464 	  id_level++;
5465       }
5466 
5467     free (inbuf);
5468     sqlite3_finalize (stmt_rd);
5469     sqlite3_finalize (stmt_levl);
5470     sqlite3_finalize (stmt_tils);
5471     sqlite3_finalize (stmt_data);
5472     if (no_data != NULL)
5473 	rl2_destroy_pixel (no_data);
5474     if (palette != NULL)
5475 	rl2_destroy_palette (palette);
5476     return 1;
5477 
5478   error:
5479     if (outbuf != NULL)
5480 	free (outbuf);
5481     if (tilebuf != NULL)
5482 	free (tilebuf);
5483     if (tilemask != NULL)
5484 	free (tilemask);
5485     if (inbuf != NULL)
5486 	free (inbuf);
5487     if (stmt != NULL)
5488 	sqlite3_finalize (stmt);
5489     if (stmt_rd != NULL)
5490 	sqlite3_finalize (stmt_rd);
5491     if (stmt_levl != NULL)
5492 	sqlite3_finalize (stmt_levl);
5493     if (stmt_tils != NULL)
5494 	sqlite3_finalize (stmt_tils);
5495     if (stmt_data != NULL)
5496 	sqlite3_finalize (stmt_data);
5497     if (no_data != NULL)
5498 	rl2_destroy_pixel (no_data);
5499     if (palette != NULL)
5500 	rl2_destroy_palette (palette);
5501     return 0;
5502 }
5503 
5504 static int
do_build_palette_section_pyramid(sqlite3 * handle,const char * coverage,const char * section,int srid,unsigned int tileWidth,unsigned int tileHeight,unsigned char bgRed,unsigned char bgGreen,unsigned char bgBlue)5505 do_build_palette_section_pyramid (sqlite3 * handle, const char *coverage,
5506 				  const char *section, int srid,
5507 				  unsigned int tileWidth,
5508 				  unsigned int tileHeight,
5509 				  unsigned char bgRed, unsigned char bgGreen,
5510 				  unsigned char bgBlue)
5511 {
5512 /* attempting to (re)build a Palette section pyramid from scratch */
5513     double base_res_x;
5514     double base_res_y;
5515     sqlite3_int64 sect_id;
5516     unsigned int sect_width;
5517     unsigned int sect_height;
5518     int id_level = 0;
5519     int scale;
5520     double x_res;
5521     double y_res;
5522     double minx;
5523     double miny;
5524     double maxx;
5525     double maxy;
5526     unsigned int row;
5527     unsigned int col;
5528     sqlite3_stmt *stmt = NULL;
5529     sqlite3_stmt *stmt_rd = NULL;
5530     sqlite3_stmt *stmt_levl = NULL;
5531     sqlite3_stmt *stmt_tils = NULL;
5532     sqlite3_stmt *stmt_data = NULL;
5533     rl2PalettePtr palette = NULL;
5534     rl2PixelPtr no_data = NULL;
5535     rl2PixelPtr nd = NULL;
5536     unsigned char *inbuf = NULL;
5537     int inbuf_size = 0;
5538     unsigned char *outbuf = NULL;
5539     int outbuf_sz = 0;
5540     unsigned char out_pixel_type;
5541     unsigned char out_bands;
5542     unsigned char *tilebuf = NULL;
5543     int tilebuf_sz = 0;
5544     unsigned char *tilemask = NULL;
5545     int tilemask_sz = 0;
5546     unsigned char *blob_odd = NULL;
5547     unsigned char *blob_even = NULL;
5548     int blob_odd_sz;
5549     int blob_even_sz;
5550     unsigned int x;
5551     unsigned int y;
5552     unsigned char *p_out;
5553 
5554     if (!get_section_infos
5555 	(handle, coverage, section, &sect_id, &sect_width, &sect_height, &minx,
5556 	 &miny, &maxx, &maxy, &palette, &no_data))
5557 	goto error;
5558     if (palette == NULL)
5559 	goto error;
5560 
5561     if (!find_base_resolution (handle, coverage, &base_res_x, &base_res_y))
5562 	goto error;
5563     if (!get_section_raw_raster_data
5564 	(handle, coverage, sect_id, sect_width, sect_height, RL2_SAMPLE_UINT8,
5565 	 RL2_PIXEL_PALETTE, 1, minx, maxy, base_res_x,
5566 	 base_res_y, &inbuf, &inbuf_size, palette, no_data))
5567 	goto error;
5568 
5569     if (!prepare_section_pyramid_stmts
5570 	(handle, coverage, &stmt_rd, &stmt_levl, &stmt_tils, &stmt_data))
5571 	goto error;
5572 
5573     id_level = 1;
5574     scale = 2;
5575     x_res = base_res_x * 2.0;
5576     y_res = base_res_y * 2.0;
5577     while (1)
5578       {
5579 	  /* looping on Pyramid levels */
5580 	  double t_minx;
5581 	  double t_miny;
5582 	  double t_maxx;
5583 	  double t_maxy;
5584 	  unsigned int out_width = sect_width / scale;
5585 	  unsigned int out_height = sect_height / scale;
5586 	  rl2RasterPtr raster = NULL;
5587 
5588 	  out_pixel_type = RL2_PIXEL_RGB;
5589 	  out_bands = 3;
5590 	  outbuf_sz = out_width * out_height * 3;
5591 	  outbuf = malloc (outbuf_sz);
5592 	  if (outbuf == NULL)
5593 	      goto error;
5594 	  p_out = outbuf;
5595 	  for (y = 0; y < out_height; y++)
5596 	    {
5597 		/* priming the background color */
5598 		for (x = 0; x < out_width; x++)
5599 		  {
5600 		      *p_out++ = bgRed;
5601 		      *p_out++ = bgGreen;
5602 		      *p_out++ = bgBlue;
5603 		  }
5604 	    }
5605 	  t_maxy = maxy;
5606 	  raster_tile_124_rescaled (outbuf, RL2_PIXEL_PALETTE, inbuf,
5607 				    sect_width, sect_height, out_width,
5608 				    out_height, palette);
5609 
5610 	  if (!do_insert_pyramid_levels
5611 	      (handle, id_level, x_res, y_res, stmt_levl))
5612 	      goto error;
5613 
5614 	  for (row = 0; row < out_height; row += tileHeight)
5615 	    {
5616 		t_minx = minx;
5617 		t_miny = t_maxy - (tileHeight * y_res);
5618 		for (col = 0; col < out_width; col += tileWidth)
5619 		  {
5620 		      if (no_data == NULL)
5621 			  nd = NULL;
5622 		      else
5623 			{
5624 			    /* converting the NO-DATA pixel */
5625 			    nd = rl2_create_pixel (RL2_SAMPLE_UINT8,
5626 						   RL2_PIXEL_RGB, 3);
5627 			    rl2_set_pixel_sample_uint8 (nd, RL2_RED_BAND,
5628 							bgRed);
5629 			    rl2_set_pixel_sample_uint8 (nd,
5630 							RL2_GREEN_BAND,
5631 							bgGreen);
5632 			    rl2_set_pixel_sample_uint8 (nd, RL2_BLUE_BAND,
5633 							bgBlue);
5634 			}
5635 		      t_maxx = t_minx + (tileWidth * x_res);
5636 		      if (!copy_124_tile (out_pixel_type, outbuf, &tilebuf,
5637 					  &tilebuf_sz, &tilemask, &tilemask_sz,
5638 					  row, col, out_width, out_height,
5639 					  tileWidth, tileHeight, no_data))
5640 			{
5641 			    fprintf (stderr,
5642 				     "ERROR: unable to extract a Pyramid Tile\n");
5643 			    goto error;
5644 			}
5645 
5646 		      raster =
5647 			  rl2_create_raster (tileWidth, tileHeight,
5648 					     RL2_SAMPLE_UINT8, out_pixel_type,
5649 					     out_bands, tilebuf, tilebuf_sz,
5650 					     NULL, tilemask, tilemask_sz, nd);
5651 		      tilebuf = NULL;
5652 		      tilemask = NULL;
5653 		      if (raster == NULL)
5654 			{
5655 			    fprintf (stderr,
5656 				     "ERROR: unable to create a Pyramid Tile\n");
5657 			    goto error;
5658 			}
5659 		      if (rl2_raster_encode
5660 			  (raster, RL2_COMPRESSION_JPEG, &blob_odd,
5661 			   &blob_odd_sz, &blob_even, &blob_even_sz, 100,
5662 			   1) != RL2_OK)
5663 			{
5664 			    fprintf (stderr,
5665 				     "ERROR: unable to encode a Pyramid tile\n");
5666 			    goto error;
5667 			}
5668 
5669 		      /* INSERTing the tile */
5670 		      if (!do_insert_pyramid_tile
5671 			  (handle, blob_odd, blob_odd_sz, blob_even,
5672 			   blob_even_sz, id_level, sect_id, srid, t_minx,
5673 			   t_miny, t_maxx, t_maxy, stmt_tils, stmt_data))
5674 			  goto error;
5675 		      rl2_destroy_raster (raster);
5676 		      t_minx += (tileWidth * x_res);
5677 		  }
5678 		t_maxy -= (tileHeight * y_res);
5679 	    }
5680 
5681 	  free (outbuf);
5682 	  if (out_width < tileWidth && out_height < tileHeight)
5683 	      break;
5684 	  x_res *= 4.0;
5685 	  y_res *= 4.0;
5686 	  scale *= 4;
5687 	  id_level++;
5688       }
5689 
5690     free (inbuf);
5691     sqlite3_finalize (stmt_rd);
5692     sqlite3_finalize (stmt_levl);
5693     sqlite3_finalize (stmt_tils);
5694     sqlite3_finalize (stmt_data);
5695     if (no_data != NULL)
5696 	rl2_destroy_pixel (no_data);
5697     if (palette != NULL)
5698 	rl2_destroy_palette (palette);
5699     return 1;
5700 
5701   error:
5702     if (outbuf != NULL)
5703 	free (outbuf);
5704     if (tilebuf != NULL)
5705 	free (tilebuf);
5706     if (tilemask != NULL)
5707 	free (tilemask);
5708     if (inbuf != NULL)
5709 	free (inbuf);
5710     if (stmt != NULL)
5711 	sqlite3_finalize (stmt);
5712     if (stmt_rd != NULL)
5713 	sqlite3_finalize (stmt_rd);
5714     if (stmt_levl != NULL)
5715 	sqlite3_finalize (stmt_levl);
5716     if (stmt_tils != NULL)
5717 	sqlite3_finalize (stmt_tils);
5718     if (stmt_data != NULL)
5719 	sqlite3_finalize (stmt_data);
5720     if (no_data != NULL)
5721 	rl2_destroy_pixel (no_data);
5722     if (palette != NULL)
5723 	rl2_destroy_palette (palette);
5724     return 0;
5725 }
5726 
5727 static void
get_background_color(sqlite3 * handle,rl2CoveragePtr coverage,unsigned char * bgRed,unsigned char * bgGreen,unsigned char * bgBlue)5728 get_background_color (sqlite3 * handle, rl2CoveragePtr coverage,
5729 		      unsigned char *bgRed, unsigned char *bgGreen,
5730 		      unsigned char *bgBlue)
5731 {
5732 /* retrieving the background color for 1,2,4 bit samples */
5733     sqlite3_stmt *stmt = NULL;
5734     char *sql;
5735     int ret;
5736     rl2PrivPalettePtr plt;
5737     rl2PalettePtr palette = NULL;
5738     rl2PrivSamplePtr smp;
5739     rl2PrivPixelPtr pxl;
5740     rl2PrivCoveragePtr cvg = (rl2PrivCoveragePtr) coverage;
5741     unsigned char index;
5742     *bgRed = 255;
5743     *bgGreen = 255;
5744     *bgBlue = 255;
5745 
5746     if (cvg == NULL)
5747 	return;
5748     if (cvg->noData == NULL)
5749 	return;
5750     pxl = (rl2PrivPixelPtr) (cvg->noData);
5751     smp = pxl->Samples;
5752     index = smp->uint8;
5753 
5754     if (cvg->pixelType == RL2_PIXEL_MONOCHROME)
5755       {
5756 	  if (index == 1)
5757 	    {
5758 		*bgRed = 0;
5759 		*bgGreen = 0;
5760 		*bgBlue = 0;
5761 	    }
5762 	  return;
5763       }
5764 
5765 /* Coverage's palette */
5766     sql = sqlite3_mprintf ("SELECT palette FROM raster_coverages "
5767 			   "WHERE Lower(coverage_name) = Lower(%Q)",
5768 			   cvg->coverageName);
5769     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
5770     sqlite3_free (sql);
5771     if (ret != SQLITE_OK)
5772       {
5773 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
5774 	  goto error;
5775       }
5776     while (1)
5777       {
5778 	  ret = sqlite3_step (stmt);
5779 	  if (ret == SQLITE_DONE)
5780 	      break;
5781 	  if (ret == SQLITE_ROW)
5782 	    {
5783 		if (sqlite3_column_type (stmt, 0) == SQLITE_BLOB)
5784 		  {
5785 		      const unsigned char *blob = sqlite3_column_blob (stmt, 0);
5786 		      int blob_sz = sqlite3_column_bytes (stmt, 0);
5787 		      palette = rl2_deserialize_dbms_palette (blob, blob_sz);
5788 		  }
5789 	    }
5790 	  else
5791 	    {
5792 		fprintf (stderr,
5793 			 "SELECT section_info; sqlite3_step() error: %s\n",
5794 			 sqlite3_errmsg (handle));
5795 		goto error;
5796 	    }
5797       }
5798     sqlite3_finalize (stmt);
5799     if (palette == NULL)
5800 	goto error;
5801 
5802     plt = (rl2PrivPalettePtr) palette;
5803     if (index < plt->nEntries)
5804       {
5805 	  rl2PrivPaletteEntryPtr rgb = plt->entries + index;
5806 	  *bgRed = rgb->red;
5807 	  *bgGreen = rgb->green;
5808 	  *bgBlue = rgb->blue;
5809       }
5810     rl2_destroy_palette (palette);
5811     return;
5812 
5813   error:
5814     if (stmt != NULL)
5815 	sqlite3_finalize (stmt);
5816     if (palette != NULL)
5817 	rl2_destroy_palette (palette);
5818 }
5819 
5820 RL2_DECLARE int
rl2_build_section_pyramid(sqlite3 * handle,const char * coverage,const char * section,int forced_rebuild)5821 rl2_build_section_pyramid (sqlite3 * handle, const char *coverage,
5822 			   const char *section, int forced_rebuild)
5823 {
5824 /* (re)building section-level pyramid for a single Section */
5825     rl2CoveragePtr cvg = NULL;
5826     unsigned char sample_type;
5827     unsigned char pixel_type;
5828     unsigned char num_bands;
5829     unsigned char compression;
5830     int quality;
5831     unsigned int tileWidth;
5832     unsigned int tileHeight;
5833     int srid;
5834     int build = 0;
5835     unsigned char bgRed;
5836     unsigned char bgGreen;
5837     unsigned char bgBlue;
5838 
5839     cvg = rl2_create_coverage_from_dbms (handle, coverage);
5840     if (cvg == NULL)
5841 	goto error;
5842 
5843     if (rl2_get_coverage_type (cvg, &sample_type, &pixel_type, &num_bands) !=
5844 	RL2_OK)
5845 	goto error;
5846     if (rl2_get_coverage_compression (cvg, &compression, &quality) != RL2_OK)
5847 	goto error;
5848     if (rl2_get_coverage_tile_size (cvg, &tileWidth, &tileHeight) != RL2_OK)
5849 	goto error;
5850     if (rl2_get_coverage_srid (cvg, &srid) != RL2_OK)
5851 	goto error;
5852 
5853     if (!forced_rebuild)
5854       {
5855 	  /* checking if the section pyramid already exists */
5856 	  build = check_section_pyramid (handle, coverage, section);
5857       }
5858     else
5859       {
5860 	  /* unconditional rebuilding */
5861 	  build = 1;
5862       }
5863 
5864     if (build)
5865       {
5866 	  /* attempting to delete the section pyramid */
5867 	  if (!delete_section_pyramid (handle, coverage, section))
5868 	      goto error;
5869 	  /* attempting to (re)build the section pyramid */
5870 	  if ((sample_type == RL2_SAMPLE_1_BIT
5871 	       && pixel_type == RL2_PIXEL_MONOCHROME && num_bands == 1)
5872 	      || (sample_type == RL2_SAMPLE_1_BIT
5873 		  && pixel_type == RL2_PIXEL_PALETTE && num_bands == 1)
5874 	      || (sample_type == RL2_SAMPLE_2_BIT
5875 		  && pixel_type == RL2_PIXEL_PALETTE && num_bands == 1)
5876 	      || (sample_type == RL2_SAMPLE_4_BIT
5877 		  && pixel_type == RL2_PIXEL_PALETTE && num_bands == 1))
5878 	    {
5879 		/* special case: 1,2,4 bit Pyramid */
5880 		get_background_color (handle, cvg, &bgRed, &bgGreen, &bgBlue);
5881 		if (!do_build_124_bit_section_pyramid
5882 		    (handle, coverage, section, sample_type, pixel_type,
5883 		     num_bands, srid, tileWidth, tileHeight, bgRed, bgGreen,
5884 		     bgBlue))
5885 		    goto error;
5886 	    }
5887 	  else if (sample_type == RL2_SAMPLE_UINT8
5888 		   && pixel_type == RL2_PIXEL_PALETTE && num_bands == 1)
5889 	    {
5890 		/* special case: 8 bit Palette Pyramid */
5891 		get_background_color (handle, cvg, &bgRed, &bgGreen, &bgBlue);
5892 		if (!do_build_palette_section_pyramid
5893 		    (handle, coverage, section, srid, tileWidth, tileHeight,
5894 		     bgRed, bgGreen, bgBlue))
5895 		    goto error;
5896 	    }
5897 	  else
5898 	    {
5899 		/* ordinary RGB, Grayscale, MultiBand or DataGrid Pyramid */
5900 		if (!do_build_section_pyramid
5901 		    (handle, coverage, section, sample_type, pixel_type,
5902 		     num_bands, compression, quality, srid, tileWidth,
5903 		     tileHeight))
5904 		    goto error;
5905 	    }
5906 	  printf ("  ----------\n");
5907 	  printf ("    Pyramid levels successfully built for: %s\n", section);
5908       }
5909     rl2_destroy_coverage (cvg);
5910 
5911     return RL2_OK;
5912 
5913   error:
5914     if (cvg != NULL)
5915 	rl2_destroy_coverage (cvg);
5916     return RL2_ERROR;
5917 }
5918 
5919 RL2_DECLARE int
rl2_build_all_section_pyramids(sqlite3 * handle,const char * coverage,int forced_rebuild)5920 rl2_build_all_section_pyramids (sqlite3 * handle, const char *coverage,
5921 				int forced_rebuild)
5922 {
5923 /* (re)building section-level pyramids for a whole Coverage */
5924     char *table;
5925     char *xtable;
5926     int ret;
5927     int i;
5928     char **results;
5929     int rows;
5930     int columns;
5931     char *sql;
5932 
5933     table = sqlite3_mprintf ("%s_sections", coverage);
5934     xtable = gaiaDoubleQuotedSql (table);
5935     sqlite3_free (table);
5936     sql = sqlite3_mprintf ("SELECT section_name FROM \"%s\"", xtable);
5937     free (xtable);
5938     ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
5939     sqlite3_free (sql);
5940     if (ret != SQLITE_OK)
5941 	goto error;
5942     if (rows < 1)
5943 	;
5944     else
5945       {
5946 	  for (i = 1; i <= rows; i++)
5947 	    {
5948 		const char *section = results[(i * columns) + 0];
5949 		if (rl2_build_section_pyramid
5950 		    (handle, coverage, section, forced_rebuild) != RL2_OK)
5951 		    goto error;
5952 	    }
5953       }
5954     sqlite3_free_table (results);
5955     return RL2_OK;
5956 
5957   error:
5958     return RL2_ERROR;
5959 }
5960 
5961 static int
is_full_mask(const unsigned char * mask,int mask_size)5962 is_full_mask (const unsigned char *mask, int mask_size)
5963 {
5964 /* testing for a completely transparent mask */
5965     const unsigned char *p = mask;
5966     int i;
5967     int count = 0;
5968     if (mask == NULL)
5969 	return 0;
5970     for (i = 0; i < mask_size; i++)
5971       {
5972 	  if (*p++ == 0)
5973 	      count++;
5974       }
5975     if (count == mask_size)
5976 	return 1;
5977     return 0;
5978 }
5979 
5980 RL2_DECLARE int
rl2_build_monolithic_pyramid(sqlite3 * handle,const char * coverage,int virt_levels)5981 rl2_build_monolithic_pyramid (sqlite3 * handle, const char *coverage,
5982 			      int virt_levels)
5983 {
5984 /* (re)building monolithic pyramid for a whole coverage */
5985     rl2CoveragePtr cvg = NULL;
5986     rl2PrivCoveragePtr cov;
5987     unsigned char sample_type;
5988     unsigned char pixel_type;
5989     unsigned char num_bands;
5990     unsigned char compression;
5991     int quality;
5992     unsigned int tileWidth;
5993     unsigned int tileHeight;
5994     int srid;
5995     double minx;
5996     double miny;
5997     double maxx;
5998     double maxy;
5999     unsigned int row;
6000     unsigned int col;
6001     unsigned int tot_rows;
6002     double res_x;
6003     double res_y;
6004     int factor;
6005     int resize_factor;
6006     int id_level = 0;
6007     unsigned char out_sample_type;
6008     unsigned char out_pixel_type;
6009     unsigned char out_num_bands;
6010     unsigned char out_compression;
6011     int out_quality;
6012     rl2PixelPtr no_data = NULL;
6013     rl2PixelPtr nd = NULL;
6014     rl2PalettePtr palette = NULL;
6015     unsigned char *buffer = NULL;
6016     int buf_size;
6017     int sample_sz;
6018     unsigned char *mask = NULL;
6019     int mask_size;
6020     rl2RasterPtr raster = NULL;
6021     unsigned char *blob_odd = NULL;
6022     unsigned char *blob_even = NULL;
6023     int blob_odd_sz;
6024     int blob_even_sz;
6025     sqlite3_stmt *stmt_geo = NULL;
6026     sqlite3_stmt *stmt_rd = NULL;
6027     sqlite3_stmt *stmt_levl = NULL;
6028     sqlite3_stmt *stmt_tils = NULL;
6029     sqlite3_stmt *stmt_data = NULL;
6030     char *xtiles;
6031     char *xxtiles;
6032     int ret;
6033     char *sql;
6034     double tile_minx;
6035     double tile_miny;
6036     double tile_maxx;
6037     double tile_maxy;
6038     double end_x;
6039     double end_y;
6040     int stop = 0;
6041 
6042 /* preparing the "tiles" SQL query */
6043     xtiles = sqlite3_mprintf ("%s_tiles", coverage);
6044     xxtiles = gaiaDoubleQuotedSql (xtiles);
6045     sql =
6046 	sqlite3_mprintf
6047 	("SELECT tile_id, MbrMinX(geometry), MbrMaxY(geometry) FROM \"%s\" "
6048 	 "WHERE pyramid_level = ? AND ROWID IN (SELECT ROWID FROM SpatialIndex "
6049 	 "WHERE f_table_name = %Q AND search_frame = BuildMBR(?, ?, ?, ?)) "
6050 	 "ORDER BY ST_Area(geometry)", xxtiles, xtiles);
6051     sqlite3_free (xtiles);
6052     free (xxtiles);
6053     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt_geo, NULL);
6054     sqlite3_free (sql);
6055     if (ret != SQLITE_OK)
6056       {
6057 	  printf ("SELECT monolithic RGBA tiles SQL error: %s\n",
6058 		  sqlite3_errmsg (handle));
6059 	  goto error;
6060       }
6061 
6062     cvg = rl2_create_coverage_from_dbms (handle, coverage);
6063     if (cvg == NULL)
6064 	goto error;
6065     cov = (rl2PrivCoveragePtr) cvg;
6066 
6067     if (rl2_get_coverage_type (cvg, &sample_type, &pixel_type, &num_bands) !=
6068 	RL2_OK)
6069 	goto error;
6070     if (rl2_get_coverage_compression (cvg, &compression, &quality) != RL2_OK)
6071 	goto error;
6072     if (rl2_get_coverage_tile_size (cvg, &tileWidth, &tileHeight) != RL2_OK)
6073 	goto error;
6074     if (rl2_get_coverage_srid (cvg, &srid) != RL2_OK)
6075 	goto error;
6076     if (!get_coverage_extent (handle, coverage, &minx, &miny, &maxx, &maxy))
6077 	goto error;
6078     no_data = rl2_get_coverage_no_data (cvg);
6079     palette = rl2_get_dbms_palette (handle, coverage);
6080     if (!prepare_section_pyramid_stmts
6081 	(handle, coverage, &stmt_rd, &stmt_levl, &stmt_tils, &stmt_data))
6082 	goto error;
6083 
6084     if (sample_type == RL2_SAMPLE_1_BIT
6085 	&& pixel_type == RL2_PIXEL_MONOCHROME && num_bands == 1)
6086       {
6087 	  /* monochrome: output colorspace is Grayscale */
6088 	  out_sample_type = RL2_SAMPLE_UINT8;
6089 	  out_pixel_type = RL2_PIXEL_GRAYSCALE;
6090 	  out_num_bands = 1;
6091 	  out_compression = RL2_COMPRESSION_PNG;
6092 	  out_quality = 100;
6093 	  factor = 2;
6094 	  resize_factor = 2;
6095       }
6096     else if ((sample_type == RL2_SAMPLE_1_BIT
6097 	      && pixel_type == RL2_PIXEL_PALETTE && num_bands == 1)
6098 	     || (sample_type == RL2_SAMPLE_2_BIT
6099 		 && pixel_type == RL2_PIXEL_PALETTE && num_bands == 1)
6100 	     || (sample_type == RL2_SAMPLE_4_BIT))
6101       {
6102 	  /* palette 1,2,4: output colorspace is RGB */
6103 	  out_sample_type = RL2_SAMPLE_UINT8;
6104 	  out_pixel_type = RL2_PIXEL_RGB;
6105 	  out_num_bands = 3;
6106 	  out_compression = RL2_COMPRESSION_PNG;
6107 	  out_quality = 100;
6108 	  factor = 2;
6109 	  resize_factor = 2;
6110       }
6111     else if (sample_type == RL2_SAMPLE_UINT8 && pixel_type == RL2_PIXEL_PALETTE
6112 	     && num_bands == 1)
6113       {
6114 	  /* palette 8: RGB JPEG pyramid level */
6115 	  out_sample_type = RL2_SAMPLE_UINT8;
6116 	  out_pixel_type = RL2_PIXEL_RGB;
6117 	  out_num_bands = 3;
6118 	  out_compression = RL2_COMPRESSION_JPEG;
6119 	  out_quality = 80;
6120       }
6121     else
6122       {
6123 	  /* unaltered output colorspace */
6124 	  out_sample_type = sample_type;
6125 	  out_pixel_type = pixel_type;
6126 	  out_num_bands = num_bands;
6127 	  if (sample_type == RL2_SAMPLE_UINT8
6128 	      && ((pixel_type == RL2_PIXEL_RGB && num_bands == 3)
6129 		  || (pixel_type == RL2_PIXEL_GRAYSCALE && num_bands == 1)))
6130 	    {
6131 		out_compression = RL2_COMPRESSION_JPEG;
6132 		out_quality = quality;
6133 	    }
6134 	  else
6135 	    {
6136 		out_compression = RL2_COMPRESSION_DEFLATE;
6137 		out_quality = 100;
6138 	    }
6139 	  /* setting the requested virt_levels */
6140 	  switch (virt_levels)
6141 	    {
6142 	    case 1:		/* separating each physical level */
6143 		resize_factor = 2;
6144 		break;
6145 	    case 2:		/* one physical + one virtual */
6146 		resize_factor = 4;
6147 		break;
6148 	    case 3:		/* one physical + two virtuals */
6149 		resize_factor = 8;
6150 		break;
6151 	    default:
6152 		resize_factor = 8;
6153 		break;
6154 	    };
6155 	  factor = resize_factor;
6156       }
6157 
6158 /* computing output tile buffers */
6159     switch (out_sample_type)
6160       {
6161       case RL2_SAMPLE_INT16:
6162       case RL2_SAMPLE_UINT16:
6163 	  sample_sz = 2;
6164 	  break;
6165       case RL2_SAMPLE_INT32:
6166       case RL2_SAMPLE_UINT32:
6167       case RL2_SAMPLE_FLOAT:
6168 	  sample_sz = 4;
6169 	  break;
6170       case RL2_SAMPLE_DOUBLE:
6171 	  sample_sz = 8;
6172 	  break;
6173       default:
6174 	  sample_sz = 1;
6175 	  break;
6176       }
6177     buf_size = tileWidth * tileHeight * out_num_bands * sample_sz;
6178 
6179 /* attempting to delete the section pyramid */
6180     if (rl2_delete_all_pyramids (handle, coverage) != RL2_OK)
6181 	goto error;
6182 
6183 /* attempting to (re)build the section pyramid */
6184     while (1)
6185       {
6186 	  /* looping on pyramid levels */
6187 	  tile_maxy = maxy;
6188 	  row = 0;
6189 	  res_x = cov->hResolution * (double) factor;
6190 	  res_y = cov->vResolution * (double) factor;
6191 	  if (!do_insert_pyramid_levels
6192 	      (handle, id_level + 1, res_x, res_y, stmt_levl))
6193 	      goto error;
6194 	  tot_rows = 0;
6195 	  while (1)
6196 	    {
6197 		/* pre-computing the max row-number */
6198 		tile_miny = tile_maxy - ((double) tileHeight * res_y);
6199 		tile_minx = minx;
6200 		if (tile_maxy < miny)
6201 		    break;
6202 		tot_rows++;
6203 		tile_maxy = tile_miny;
6204 	    }
6205 
6206 	  tile_maxy = maxy;
6207 	  while (1)
6208 	    {
6209 		/* looping on rows */
6210 		tile_miny = tile_maxy - ((double) tileHeight * res_y);
6211 		tile_minx = minx;
6212 		if (tile_maxy < miny)
6213 		    break;
6214 		col = 0;
6215 		while (1)
6216 		  {
6217 		      /* looping on columns */
6218 		      tile_maxx = tile_minx + ((double) tileWidth * res_x);
6219 		      if (tile_minx > maxx)
6220 			  break;
6221 		      /* allocating output tile buffers */
6222 		      buffer = malloc (buf_size);
6223 		      if (buffer == NULL)
6224 			  goto error;
6225 		      mask_size = tileWidth * tileHeight;
6226 		      mask = malloc (mask_size);
6227 		      if (mask == NULL)
6228 			  goto error;
6229 		      end_x = tile_maxx;
6230 		      if (tile_maxx > maxx)
6231 			  end_x = maxx;
6232 		      end_y = tile_miny;
6233 		      if (tile_miny < miny)
6234 			  end_y = miny;
6235 
6236 		      if ((sample_type == RL2_SAMPLE_UINT8
6237 			   && pixel_type == RL2_PIXEL_GRAYSCALE
6238 			   && num_bands == 1)
6239 			  || (sample_type == RL2_SAMPLE_UINT8
6240 			      && pixel_type == RL2_PIXEL_RGB && num_bands == 3)
6241 			  || (sample_type == RL2_SAMPLE_UINT8
6242 			      && pixel_type == RL2_PIXEL_PALETTE
6243 			      && num_bands == 1))
6244 			{
6245 			    /* RGB, PALETTE or GRAYSCALE datasource (UINT8) */
6246 			    if (!rescale_monolithic_rgba
6247 				(id_level, tileWidth, tileHeight, resize_factor,
6248 				 res_x, res_y, tile_minx, tile_miny,
6249 				 tile_maxx, tile_maxy, buffer, buf_size, mask,
6250 				 &mask_size, palette, no_data, stmt_geo,
6251 				 stmt_rd))
6252 				goto error;
6253 			    if (mask_size == 0)
6254 				mask = NULL;
6255 			}
6256 		      else if (((sample_type == RL2_SAMPLE_1_BIT
6257 				 || sample_type == RL2_SAMPLE_2_BIT
6258 				 || sample_type == RL2_SAMPLE_4_BIT)
6259 				&& pixel_type == RL2_PIXEL_PALETTE
6260 				&& num_bands == 1)
6261 			       || (sample_type == RL2_SAMPLE_1_BIT
6262 				   && pixel_type == RL2_PIXEL_MONOCHROME
6263 				   && num_bands == 1))
6264 			{
6265 			    /* MONOCHROME and 1,2,4 bit PALETTE */
6266 			    if (!rescale_monolithic_124
6267 				(id_level, tileWidth,
6268 				 tileHeight, resize_factor, pixel_type,
6269 				 res_x, res_y, tile_minx, tile_miny,
6270 				 tile_maxx, tile_maxy, buffer, buf_size, mask,
6271 				 &mask_size, palette, no_data, stmt_geo,
6272 				 stmt_rd))
6273 				goto error;
6274 			    if (mask_size == 0)
6275 				mask = NULL;
6276 			}
6277 		      else if (pixel_type == RL2_PIXEL_MULTIBAND)
6278 			{
6279 			    /* MultiBand */
6280 			    if (!rescale_monolithic_multiband
6281 				(id_level, tileWidth, tileHeight, sample_type,
6282 				 num_bands, resize_factor, res_x, res_y,
6283 				 tile_minx, tile_miny, tile_maxx, tile_maxy,
6284 				 buffer, buf_size, mask, &mask_size, no_data,
6285 				 stmt_geo, stmt_rd))
6286 				goto error;
6287 			    if (mask_size == 0)
6288 				mask = NULL;
6289 			}
6290 		      else if (pixel_type == RL2_PIXEL_DATAGRID)
6291 			{
6292 			    /* DataGrid */
6293 			    if (!rescale_monolithic_datagrid
6294 				(id_level, tileWidth, tileHeight, sample_type,
6295 				 resize_factor, res_x, res_y, tile_minx,
6296 				 tile_miny, tile_maxx, tile_maxy, buffer,
6297 				 buf_size, mask, &mask_size, no_data, stmt_geo,
6298 				 stmt_rd))
6299 				goto error;
6300 			    if (mask_size == 0)
6301 				mask = NULL;
6302 			}
6303 		      else
6304 			{
6305 			    /* unknown */
6306 			    fprintf (stderr,
6307 				     "ERROR: unsupported Monolithic pyramid type\n");
6308 			    goto error;
6309 			}
6310 		      if (is_full_mask (mask, mask_size))
6311 			{
6312 			    /* skipping a completely void tile */
6313 			    free (buffer);
6314 			    free (mask);
6315 			    buffer = NULL;
6316 			    mask = NULL;
6317 			    goto done;
6318 			}
6319 
6320 		      if (pixel_type == RL2_PIXEL_MONOCHROME)
6321 			{
6322 			    if (no_data == NULL)
6323 				nd = NULL;
6324 			    else
6325 			      {
6326 				  rl2PrivPixelPtr pxl =
6327 				      (rl2PrivPixelPtr) no_data;
6328 				  rl2PrivSamplePtr sample = pxl->Samples + 0;
6329 				  nd = rl2_create_pixel (RL2_SAMPLE_UINT8,
6330 							 RL2_PIXEL_GRAYSCALE,
6331 							 1);
6332 				  if (sample->uint8 == 0)
6333 				      rl2_set_pixel_sample_uint8 (nd,
6334 								  RL2_GRAYSCALE_BAND,
6335 								  255);
6336 				  else
6337 				      rl2_set_pixel_sample_uint8 (nd,
6338 								  RL2_GRAYSCALE_BAND,
6339 								  0);
6340 			      }
6341 			}
6342 		      else if (pixel_type == RL2_PIXEL_PALETTE)
6343 			{
6344 			    if (no_data == NULL)
6345 				nd = NULL;
6346 			    else
6347 			      {
6348 				  nd = rl2_create_pixel (RL2_SAMPLE_UINT8,
6349 							 RL2_PIXEL_RGB, 3);
6350 				  rl2_set_pixel_sample_uint8 (nd, RL2_RED_BAND,
6351 							      255);
6352 				  rl2_set_pixel_sample_uint8 (nd,
6353 							      RL2_GREEN_BAND,
6354 							      255);
6355 				  rl2_set_pixel_sample_uint8 (nd, RL2_BLUE_BAND,
6356 							      255);
6357 			      }
6358 			}
6359 		      else
6360 			  nd = rl2_clone_pixel (no_data);
6361 
6362 		      raster =
6363 			  rl2_create_raster (tileWidth, tileHeight,
6364 					     out_sample_type, out_pixel_type,
6365 					     out_num_bands, buffer, buf_size,
6366 					     NULL, mask, mask_size, nd);
6367 		      buffer = NULL;
6368 		      mask = NULL;
6369 		      if (raster == NULL)
6370 			{
6371 			    fprintf (stderr,
6372 				     "ERROR: unable to create a Pyramid Tile\n");
6373 			    goto error;
6374 			}
6375 		      if (rl2_raster_encode
6376 			  (raster, out_compression, &blob_odd, &blob_odd_sz,
6377 			   &blob_even, &blob_even_sz, out_quality, 1) != RL2_OK)
6378 			{
6379 			    fprintf (stderr,
6380 				     "ERROR: unable to encode a Pyramid tile\n");
6381 			    goto error;
6382 			}
6383 
6384 		      /* INSERTing the tile */
6385 		      if (!do_insert_pyramid_tile
6386 			  (handle, blob_odd, blob_odd_sz, blob_even,
6387 			   blob_even_sz, id_level + 1, -1, srid, tile_minx,
6388 			   end_y, end_x, tile_maxy, stmt_tils, stmt_data))
6389 			  goto error;
6390 		      rl2_destroy_raster (raster);
6391 		      raster = NULL;
6392 
6393 		    done:
6394 		      tile_minx = tile_maxx;
6395 		      col++;
6396 		  }
6397 		tile_maxy = tile_miny;
6398 		row++;
6399 		printf ("  ----------\n");
6400 		printf
6401 		    ("    %s: Monolithic Pyramid Level %d - Row %d of %d  successfully built\n",
6402 		     coverage, id_level + 1, row, tot_rows);
6403 	    }
6404 	  if (stop)
6405 	      break;
6406 	  if ((minx +
6407 	       ((double) tileWidth * res_x) > maxx)
6408 	      && (maxy - ((double) tileHeight * res_y) < maxy))
6409 	      stop = 1;
6410 	  /* setting the requested virt_levels */
6411 	  switch (virt_levels)
6412 	    {
6413 	    case 1:		/* separating each physical level */
6414 		resize_factor = 2;
6415 		break;
6416 	    case 2:		/* one physical + one virtual */
6417 		resize_factor = 4;
6418 		break;
6419 	    case 3:		/* one physical + two virtuals */
6420 		resize_factor = 8;
6421 		break;
6422 	    };
6423 	  factor *= resize_factor;
6424 	  id_level++;
6425 	  if (palette != NULL)
6426 	    {
6427 		/* destroying an eventual Palette after completing the first level */
6428 		rl2_destroy_palette (palette);
6429 		palette = NULL;
6430 	    }
6431       }
6432     sqlite3_finalize (stmt_geo);
6433     sqlite3_finalize (stmt_rd);
6434     sqlite3_finalize (stmt_levl);
6435     sqlite3_finalize (stmt_tils);
6436     sqlite3_finalize (stmt_data);
6437     printf ("  ----------\n");
6438     printf ("    Monolithic Pyramid levels successfully built for: %s\n",
6439 	    coverage);
6440     free (buffer);
6441     free (mask);
6442     rl2_destroy_coverage (cvg);
6443 
6444     return RL2_OK;
6445 
6446   error:
6447     if (stmt_geo != NULL)
6448 	sqlite3_finalize (stmt_geo);
6449     if (stmt_rd != NULL)
6450 	sqlite3_finalize (stmt_rd);
6451     if (stmt_levl != NULL)
6452 	sqlite3_finalize (stmt_levl);
6453     if (stmt_tils != NULL)
6454 	sqlite3_finalize (stmt_tils);
6455     if (stmt_data != NULL)
6456 	sqlite3_finalize (stmt_data);
6457     if (buffer != NULL)
6458 	free (buffer);
6459     if (mask != NULL)
6460 	free (mask);
6461     if (cvg != NULL)
6462 	rl2_destroy_coverage (cvg);
6463     if (palette != NULL)
6464 	rl2_destroy_palette (palette);
6465     if (raster != NULL)
6466 	rl2_destroy_raster (raster);
6467     return RL2_ERROR;
6468 }
6469 
6470 RL2_DECLARE int
rl2_delete_all_pyramids(sqlite3 * handle,const char * coverage)6471 rl2_delete_all_pyramids (sqlite3 * handle, const char *coverage)
6472 {
6473 /* deleting all pyramids for a whole Coverage */
6474     char *sql;
6475     char *table;
6476     char *xtable;
6477     int ret;
6478     char *err_msg = NULL;
6479 
6480     table = sqlite3_mprintf ("%s_tiles", coverage);
6481     xtable = gaiaDoubleQuotedSql (table);
6482     sqlite3_free (table);
6483     sql =
6484 	sqlite3_mprintf ("DELETE FROM \"%s\" WHERE pyramid_level > 0", xtable);
6485     free (xtable);
6486     ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg);
6487     sqlite3_free (sql);
6488     if (ret != SQLITE_OK)
6489       {
6490 	  fprintf (stderr, "DELETE FROM \"%s_tiles\" error: %s\n", coverage,
6491 		   err_msg);
6492 	  sqlite3_free (err_msg);
6493 	  return RL2_ERROR;
6494       }
6495 
6496     table = sqlite3_mprintf ("%s_levels", coverage);
6497     xtable = gaiaDoubleQuotedSql (table);
6498     sqlite3_free (table);
6499     sql =
6500 	sqlite3_mprintf ("DELETE FROM \"%s\" WHERE pyramid_level > 0", xtable);
6501     free (xtable);
6502     ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg);
6503     sqlite3_free (sql);
6504     if (ret != SQLITE_OK)
6505       {
6506 	  fprintf (stderr, "DELETE FROM \"%s_levels\" error: %s\n", coverage,
6507 		   err_msg);
6508 	  sqlite3_free (err_msg);
6509 	  return RL2_ERROR;
6510       }
6511     return RL2_OK;
6512 }
6513 
6514 RL2_DECLARE int
rl2_delete_section_pyramid(sqlite3 * handle,const char * coverage,const char * section)6515 rl2_delete_section_pyramid (sqlite3 * handle, const char *coverage,
6516 			    const char *section)
6517 {
6518 /* deleting section-level pyramid for a single Section */
6519     if (!delete_section_pyramid (handle, coverage, section))
6520 	return RL2_ERROR;
6521     return RL2_OK;
6522 }
6523