1 /*
2 
3  rl2sqlaux -- private SQL helper methods
4 
5  version 0.1, 2014 February 28
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 #include <limits.h>
49 #include <stdint.h>
50 #include <inttypes.h>
51 
52 #ifdef _WIN32
53 #include <io.h>
54 #else
55 #include <unistd.h>
56 #endif
57 
58 #include "config.h"
59 
60 #ifdef LOADABLE_EXTENSION
61 #include "rasterlite2/sqlite.h"
62 #endif
63 
64 #include "rasterlite2/rasterlite2.h"
65 #include "rasterlite2/rl2wms.h"
66 #include "rasterlite2/rl2graphics.h"
67 #include "rasterlite2_private.h"
68 
69 #include <spatialite/gaiaaux.h>
70 
71 #define RL2_UNUSED() if (argc || argv) argc = argc;
72 
73 RL2_PRIVATE int
get_coverage_sample_bands(sqlite3 * sqlite,const char * coverage,unsigned char * sample_type,unsigned char * num_bands)74 get_coverage_sample_bands (sqlite3 * sqlite, const char *coverage,
75 			   unsigned char *sample_type, unsigned char *num_bands)
76 {
77 /* attempting to retrieve the SampleType and NumBands from a Coverage */
78     int i;
79     char **results;
80     int rows;
81     int columns;
82     char *sql;
83     int ret;
84     const char *sample;
85     int bands;
86     unsigned char xsample_type = RL2_SAMPLE_UNKNOWN;
87     unsigned char xnum_bands = RL2_BANDS_UNKNOWN;
88 
89     sql =
90 	sqlite3_mprintf ("SELECT sample_type, num_bands FROM raster_coverages "
91 			 "WHERE Lower(coverage_name) = Lower(%Q)", coverage);
92     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, NULL);
93     sqlite3_free (sql);
94     if (ret != SQLITE_OK)
95 	return 0;
96     if (rows < 1)
97 	;
98     else
99       {
100 	  for (i = 1; i <= rows; i++)
101 	    {
102 		sample = results[(i * columns) + 0];
103 		if (strcmp (sample, "1-BIT") == 0)
104 		    xsample_type = RL2_SAMPLE_1_BIT;
105 		if (strcmp (sample, "2-BIT") == 0)
106 		    xsample_type = RL2_SAMPLE_2_BIT;
107 		if (strcmp (sample, "4-BIT") == 0)
108 		    xsample_type = RL2_SAMPLE_4_BIT;
109 		if (strcmp (sample, "INT8") == 0)
110 		    xsample_type = RL2_SAMPLE_INT8;
111 		if (strcmp (sample, "UINT8") == 0)
112 		    xsample_type = RL2_SAMPLE_UINT8;
113 		if (strcmp (sample, "INT16") == 0)
114 		    xsample_type = RL2_SAMPLE_INT16;
115 		if (strcmp (sample, "UINT16") == 0)
116 		    xsample_type = RL2_SAMPLE_UINT16;
117 		if (strcmp (sample, "INT32") == 0)
118 		    xsample_type = RL2_SAMPLE_INT32;
119 		if (strcmp (sample, "UINT32") == 0)
120 		    xsample_type = RL2_SAMPLE_UINT32;
121 		if (strcmp (sample, "FLOAT") == 0)
122 		    xsample_type = RL2_SAMPLE_FLOAT;
123 		if (strcmp (sample, "DOUBLE") == 0)
124 		    xsample_type = RL2_SAMPLE_DOUBLE;
125 		bands = atoi (results[(i * columns) + 1]);
126 		if (bands > 0 && bands < 256)
127 		    xnum_bands = bands;
128 	    }
129       }
130     sqlite3_free_table (results);
131     if (xsample_type == RL2_SAMPLE_UNKNOWN || xnum_bands == RL2_BANDS_UNKNOWN)
132 	return 0;
133     *sample_type = xsample_type;
134     *num_bands = xnum_bands;
135     return 1;
136 }
137 
138 RL2_PRIVATE int
get_coverage_defs(sqlite3 * sqlite,const char * coverage,unsigned int * tile_width,unsigned int * tile_height,unsigned char * sample_type,unsigned char * pixel_type,unsigned char * num_bands,unsigned char * compression)139 get_coverage_defs (sqlite3 * sqlite, const char *coverage,
140 		   unsigned int *tile_width, unsigned int *tile_height,
141 		   unsigned char *sample_type, unsigned char *pixel_type,
142 		   unsigned char *num_bands, unsigned char *compression)
143 {
144 /* attempting to retrieve the main definitions from a Coverage */
145     int i;
146     char **results;
147     int rows;
148     int columns;
149     char *sql;
150     int ret;
151     const char *sample;
152     const char *pixel;
153     const char *compr;
154     int bands;
155     unsigned char xsample_type = RL2_SAMPLE_UNKNOWN;
156     unsigned char xpixel_type = RL2_PIXEL_UNKNOWN;
157     unsigned char xnum_bands = RL2_BANDS_UNKNOWN;
158     unsigned char xcompression = RL2_COMPRESSION_UNKNOWN;
159     unsigned short xtile_width = RL2_TILESIZE_UNDEFINED;
160     unsigned short xtile_height = RL2_TILESIZE_UNDEFINED;
161 
162     sql = sqlite3_mprintf ("SELECT sample_type, pixel_type, num_bands, "
163 			   "compression, tile_width, tile_height FROM raster_coverages "
164 			   "WHERE Lower(coverage_name) = Lower(%Q)", coverage);
165     ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, NULL);
166     sqlite3_free (sql);
167     if (ret != SQLITE_OK)
168 	return 0;
169     if (rows < 1)
170 	;
171     else
172       {
173 	  for (i = 1; i <= rows; i++)
174 	    {
175 		sample = results[(i * columns) + 0];
176 		if (strcmp (sample, "1-BIT") == 0)
177 		    xsample_type = RL2_SAMPLE_1_BIT;
178 		if (strcmp (sample, "2-BIT") == 0)
179 		    xsample_type = RL2_SAMPLE_2_BIT;
180 		if (strcmp (sample, "4-BIT") == 0)
181 		    xsample_type = RL2_SAMPLE_4_BIT;
182 		if (strcmp (sample, "INT8") == 0)
183 		    xsample_type = RL2_SAMPLE_INT8;
184 		if (strcmp (sample, "UINT8") == 0)
185 		    xsample_type = RL2_SAMPLE_UINT8;
186 		if (strcmp (sample, "INT16") == 0)
187 		    xsample_type = RL2_SAMPLE_INT16;
188 		if (strcmp (sample, "UINT16") == 0)
189 		    xsample_type = RL2_SAMPLE_UINT16;
190 		if (strcmp (sample, "INT32") == 0)
191 		    xsample_type = RL2_SAMPLE_INT32;
192 		if (strcmp (sample, "UINT32") == 0)
193 		    xsample_type = RL2_SAMPLE_UINT32;
194 		if (strcmp (sample, "FLOAT") == 0)
195 		    xsample_type = RL2_SAMPLE_FLOAT;
196 		if (strcmp (sample, "DOUBLE") == 0)
197 		    xsample_type = RL2_SAMPLE_DOUBLE;
198 		pixel = results[(i * columns) + 1];
199 		if (strcmp (pixel, "MONOCHROME") == 0)
200 		    xpixel_type = RL2_PIXEL_MONOCHROME;
201 		if (strcmp (pixel, "PALETTE") == 0)
202 		    xpixel_type = RL2_PIXEL_PALETTE;
203 		if (strcmp (pixel, "GRAYSCALE") == 0)
204 		    xpixel_type = RL2_PIXEL_GRAYSCALE;
205 		if (strcmp (pixel, "RGB") == 0)
206 		    xpixel_type = RL2_PIXEL_RGB;
207 		if (strcmp (pixel, "MULTIBAND") == 0)
208 		    xpixel_type = RL2_PIXEL_MULTIBAND;
209 		if (strcmp (pixel, "DATAGRID") == 0)
210 		    xpixel_type = RL2_PIXEL_DATAGRID;
211 		bands = atoi (results[(i * columns) + 2]);
212 		if (bands > 0 && bands < 256)
213 		    xnum_bands = bands;
214 		compr = results[(i * columns) + 3];
215 		if (strcmp (compr, "NONE") == 0)
216 		    xcompression = RL2_COMPRESSION_NONE;
217 		if (strcmp (compr, "DEFLATE") == 0)
218 		    xcompression = RL2_COMPRESSION_DEFLATE;
219 		if (strcmp (compr, "LZMA") == 0)
220 		    xcompression = RL2_COMPRESSION_LZMA;
221 		if (strcmp (compr, "GIF") == 0)
222 		    xcompression = RL2_COMPRESSION_GIF;
223 		if (strcmp (compr, "PNG") == 0)
224 		    xcompression = RL2_COMPRESSION_PNG;
225 		if (strcmp (compr, "JPEG") == 0)
226 		    xcompression = RL2_COMPRESSION_JPEG;
227 		if (strcmp (compr, "LOSSY_WEBP") == 0)
228 		    xcompression = RL2_COMPRESSION_LOSSY_WEBP;
229 		if (strcmp (compr, "LOSSLESS_WEBP") == 0)
230 		    xcompression = RL2_COMPRESSION_LOSSLESS_WEBP;
231 		if (strcmp (compr, "CCITTFAX4") == 0)
232 		    xcompression = RL2_COMPRESSION_CCITTFAX4;
233 		xtile_width = atoi (results[(i * columns) + 4]);
234 		xtile_height = atoi (results[(i * columns) + 5]);
235 	    }
236       }
237     sqlite3_free_table (results);
238     if (xsample_type == RL2_SAMPLE_UNKNOWN || xpixel_type == RL2_PIXEL_UNKNOWN
239 	|| xnum_bands == RL2_BANDS_UNKNOWN
240 	|| xcompression == RL2_COMPRESSION_UNKNOWN
241 	|| xtile_width == RL2_TILESIZE_UNDEFINED
242 	|| xtile_height == RL2_TILESIZE_UNDEFINED)
243 	return 0;
244     *sample_type = xsample_type;
245     *pixel_type = xpixel_type;
246     *num_bands = xnum_bands;
247     *compression = xcompression;
248     *tile_width = xtile_width;
249     *tile_height = xtile_height;
250     return 1;
251 }
252 
253 RL2_PRIVATE rl2PixelPtr
default_nodata(unsigned char sample,unsigned char pixel,unsigned char num_bands)254 default_nodata (unsigned char sample, unsigned char pixel,
255 		unsigned char num_bands)
256 {
257 /* creating a default NO-DATA value */
258     int nb;
259     rl2PixelPtr pxl = rl2_create_pixel (sample, pixel, num_bands);
260     if (pxl == NULL)
261 	return NULL;
262     switch (pixel)
263       {
264       case RL2_PIXEL_MONOCHROME:
265 	  rl2_set_pixel_sample_1bit (pxl, 0);
266 	  break;
267       case RL2_PIXEL_PALETTE:
268 	  switch (sample)
269 	    {
270 	    case RL2_SAMPLE_1_BIT:
271 		rl2_set_pixel_sample_1bit (pxl, 0);
272 		break;
273 	    case RL2_SAMPLE_2_BIT:
274 		rl2_set_pixel_sample_2bit (pxl, 0);
275 		break;
276 	    case RL2_SAMPLE_4_BIT:
277 		rl2_set_pixel_sample_4bit (pxl, 0);
278 		break;
279 	    case RL2_SAMPLE_UINT8:
280 		rl2_set_pixel_sample_uint8 (pxl, 0, 0);
281 		break;
282 	    };
283 	  break;
284       case RL2_PIXEL_GRAYSCALE:
285 	  switch (sample)
286 	    {
287 	    case RL2_SAMPLE_1_BIT:
288 		rl2_set_pixel_sample_1bit (pxl, 1);
289 		break;
290 	    case RL2_SAMPLE_2_BIT:
291 		rl2_set_pixel_sample_2bit (pxl, 3);
292 		break;
293 	    case RL2_SAMPLE_4_BIT:
294 		rl2_set_pixel_sample_4bit (pxl, 15);
295 		break;
296 	    case RL2_SAMPLE_UINT8:
297 		rl2_set_pixel_sample_uint8 (pxl, 0, 255);
298 		break;
299 	    case RL2_SAMPLE_UINT16:
300 		rl2_set_pixel_sample_uint16 (pxl, 0, 0);
301 		break;
302 	    };
303 	  break;
304       case RL2_PIXEL_RGB:
305 	  switch (sample)
306 	    {
307 	    case RL2_SAMPLE_UINT8:
308 		rl2_set_pixel_sample_uint8 (pxl, 0, 255);
309 		rl2_set_pixel_sample_uint8 (pxl, 1, 255);
310 		rl2_set_pixel_sample_uint8 (pxl, 2, 255);
311 		break;
312 	    case RL2_SAMPLE_UINT16:
313 		rl2_set_pixel_sample_uint16 (pxl, 0, 0);
314 		rl2_set_pixel_sample_uint16 (pxl, 1, 0);
315 		rl2_set_pixel_sample_uint16 (pxl, 2, 0);
316 		break;
317 	    };
318 	  break;
319       case RL2_PIXEL_DATAGRID:
320 	  switch (sample)
321 	    {
322 	    case RL2_SAMPLE_INT8:
323 		rl2_set_pixel_sample_int8 (pxl, 0);
324 		break;
325 	    case RL2_SAMPLE_UINT8:
326 		rl2_set_pixel_sample_uint8 (pxl, 0, 0);
327 		break;
328 	    case RL2_SAMPLE_INT16:
329 		rl2_set_pixel_sample_int16 (pxl, 0);
330 		break;
331 	    case RL2_SAMPLE_UINT16:
332 		rl2_set_pixel_sample_uint16 (pxl, 0, 0);
333 		break;
334 	    case RL2_SAMPLE_INT32:
335 		rl2_set_pixel_sample_int32 (pxl, 0);
336 		break;
337 	    case RL2_SAMPLE_UINT32:
338 		rl2_set_pixel_sample_uint32 (pxl, 0);
339 		break;
340 	    case RL2_SAMPLE_FLOAT:
341 		rl2_set_pixel_sample_float (pxl, 0.0);
342 		break;
343 	    case RL2_SAMPLE_DOUBLE:
344 		rl2_set_pixel_sample_double (pxl, 0.0);
345 		break;
346 	    };
347 	  break;
348       case RL2_PIXEL_MULTIBAND:
349 	  switch (sample)
350 	    {
351 	    case RL2_SAMPLE_UINT8:
352 		for (nb = 0; nb < num_bands; nb++)
353 		    rl2_set_pixel_sample_uint8 (pxl, nb, 255);
354 		break;
355 	    case RL2_SAMPLE_UINT16:
356 		for (nb = 0; nb < num_bands; nb++)
357 		    rl2_set_pixel_sample_uint16 (pxl, nb, 0);
358 		break;
359 	    };
360 	  break;
361       };
362     return pxl;
363 }
364 
365 RL2_PRIVATE WmsRetryListPtr
alloc_retry_list()366 alloc_retry_list ()
367 {
368 /* initializing an empty WMS retry-list */
369     WmsRetryListPtr lst = malloc (sizeof (WmsRetryList));
370     lst->first = NULL;
371     lst->last = NULL;
372     return lst;
373 }
374 
375 RL2_PRIVATE void
free_retry_list(WmsRetryListPtr lst)376 free_retry_list (WmsRetryListPtr lst)
377 {
378 /* memory cleanup - destroying a list of WMS retry requests */
379     WmsRetryItemPtr p;
380     WmsRetryItemPtr pn;
381     if (lst == NULL)
382 	return;
383     p = lst->first;
384     while (p != NULL)
385       {
386 	  pn = p->next;
387 	  free (p);
388 	  p = pn;
389       }
390     free (lst);
391 }
392 
393 RL2_PRIVATE void
add_retry(WmsRetryListPtr lst,double minx,double miny,double maxx,double maxy)394 add_retry (WmsRetryListPtr lst, double minx, double miny, double maxx,
395 	   double maxy)
396 {
397 /* inserting a WMS retry request into the list */
398     WmsRetryItemPtr p;
399     if (lst == NULL)
400 	return;
401     p = malloc (sizeof (WmsRetryItem));
402     p->done = 0;
403     p->count = 0;
404     p->minx = minx;
405     p->miny = miny;
406     p->maxx = maxx;
407     p->maxy = maxy;
408     p->next = NULL;
409     if (lst->first == NULL)
410 	lst->first = p;
411     if (lst->last != NULL)
412 	lst->last->next = p;
413     lst->last = p;
414 }
415 
416 RL2_PRIVATE gaiaGeomCollPtr
build_extent(int srid,double minx,double miny,double maxx,double maxy)417 build_extent (int srid, double minx, double miny, double maxx, double maxy)
418 {
419 /* building an MBR (Envelope) */
420     gaiaPolygonPtr pg;
421     gaiaRingPtr rng;
422     gaiaGeomCollPtr geom = gaiaAllocGeomColl ();
423     geom->Srid = srid;
424     pg = gaiaAddPolygonToGeomColl (geom, 5, 0);
425     rng = pg->Exterior;
426     gaiaSetPoint (rng->Coords, 0, minx, miny);
427     gaiaSetPoint (rng->Coords, 1, maxx, miny);
428     gaiaSetPoint (rng->Coords, 2, maxx, maxy);
429     gaiaSetPoint (rng->Coords, 3, minx, maxy);
430     gaiaSetPoint (rng->Coords, 4, minx, miny);
431     return geom;
432 }
433 
434 RL2_PRIVATE int
do_insert_wms_tile(sqlite3 * handle,unsigned char * blob_odd,int blob_odd_sz,unsigned char * blob_even,int blob_even_sz,sqlite3_int64 section_id,int srid,double res_x,double res_y,unsigned int tile_w,unsigned int tile_h,double miny,double maxx,double tile_minx,double tile_miny,double tile_maxx,double tile_maxy,rl2PalettePtr aux_palette,rl2PixelPtr no_data,sqlite3_stmt * stmt_tils,sqlite3_stmt * stmt_data,rl2RasterStatisticsPtr section_stats)435 do_insert_wms_tile (sqlite3 * handle, unsigned char *blob_odd, int blob_odd_sz,
436 		    unsigned char *blob_even, int blob_even_sz,
437 		    sqlite3_int64 section_id, int srid, double res_x,
438 		    double res_y, unsigned int tile_w, unsigned int tile_h,
439 		    double miny, double maxx, double tile_minx,
440 		    double tile_miny, double tile_maxx, double tile_maxy,
441 		    rl2PalettePtr aux_palette, rl2PixelPtr no_data,
442 		    sqlite3_stmt * stmt_tils, sqlite3_stmt * stmt_data,
443 		    rl2RasterStatisticsPtr section_stats)
444 {
445 /* INSERTing the tile */
446     int ret;
447     sqlite3_int64 tile_id;
448     unsigned char *blob;
449     int blob_size;
450     gaiaGeomCollPtr geom;
451     rl2RasterStatisticsPtr stats = NULL;
452 
453     stats = rl2_get_raster_statistics
454 	(blob_odd, blob_odd_sz, blob_even, blob_even_sz, aux_palette, no_data);
455     if (stats == NULL)
456 	goto error;
457     rl2_aggregate_raster_statistics (stats, section_stats);
458     sqlite3_reset (stmt_tils);
459     sqlite3_clear_bindings (stmt_tils);
460     sqlite3_bind_int64 (stmt_tils, 1, section_id);
461     tile_maxx = tile_minx + ((double) tile_w * res_x);
462     if (tile_maxx > maxx)
463 	tile_maxx = maxx;
464     tile_miny = tile_maxy - ((double) tile_h * res_y);
465     if (tile_miny < miny)
466 	tile_miny = miny;
467     geom = build_extent (srid, tile_minx, tile_miny, tile_maxx, tile_maxy);
468     gaiaToSpatiaLiteBlobWkb (geom, &blob, &blob_size);
469     gaiaFreeGeomColl (geom);
470     sqlite3_bind_blob (stmt_tils, 2, blob, blob_size, free);
471     ret = sqlite3_step (stmt_tils);
472     if (ret == SQLITE_DONE || ret == SQLITE_ROW)
473 	;
474     else
475       {
476 	  fprintf (stderr,
477 		   "INSERT INTO tiles; sqlite3_step() error: %s\n",
478 		   sqlite3_errmsg (handle));
479 	  goto error;
480       }
481     tile_id = sqlite3_last_insert_rowid (handle);
482     /* INSERTing tile data */
483     sqlite3_reset (stmt_data);
484     sqlite3_clear_bindings (stmt_data);
485     sqlite3_bind_int64 (stmt_data, 1, tile_id);
486     sqlite3_bind_blob (stmt_data, 2, blob_odd, blob_odd_sz, free);
487     if (blob_even == NULL)
488 	sqlite3_bind_null (stmt_data, 3);
489     else
490 	sqlite3_bind_blob (stmt_data, 3, blob_even, blob_even_sz, free);
491     ret = sqlite3_step (stmt_data);
492     if (ret == SQLITE_DONE || ret == SQLITE_ROW)
493 	;
494     else
495       {
496 	  fprintf (stderr,
497 		   "INSERT INTO tile_data; sqlite3_step() error: %s\n",
498 		   sqlite3_errmsg (handle));
499 	  goto error;
500       }
501     rl2_destroy_raster_statistics (stats);
502     return 1;
503   error:
504     if (stats != NULL)
505 	rl2_destroy_raster_statistics (stats);
506     return 0;
507 }
508 
509 RL2_PRIVATE int
do_insert_levels(sqlite3 * handle,double base_res_x,double base_res_y,double factor,unsigned char sample_type,sqlite3_stmt * stmt_levl)510 do_insert_levels (sqlite3 * handle, double base_res_x, double base_res_y,
511 		  double factor, unsigned char sample_type,
512 		  sqlite3_stmt * stmt_levl)
513 {
514 /* INSERTing the base-levels */
515     int ret;
516     double res_x = base_res_x * factor;
517     double res_y = base_res_y * factor;
518     sqlite3_reset (stmt_levl);
519     sqlite3_clear_bindings (stmt_levl);
520     sqlite3_bind_double (stmt_levl, 1, res_x);
521     sqlite3_bind_double (stmt_levl, 2, res_y);
522     if (sample_type == RL2_SAMPLE_1_BIT || sample_type == RL2_SAMPLE_2_BIT
523 	|| sample_type == RL2_SAMPLE_4_BIT)
524       {
525 	  sqlite3_bind_null (stmt_levl, 3);
526 	  sqlite3_bind_null (stmt_levl, 4);
527 	  sqlite3_bind_null (stmt_levl, 5);
528 	  sqlite3_bind_null (stmt_levl, 6);
529 	  sqlite3_bind_null (stmt_levl, 7);
530 	  sqlite3_bind_null (stmt_levl, 8);
531       }
532     else
533       {
534 	  sqlite3_bind_double (stmt_levl, 3, res_x * 2.0);
535 	  sqlite3_bind_double (stmt_levl, 4, res_y * 2.0);
536 	  sqlite3_bind_double (stmt_levl, 5, res_x * 4.0);
537 	  sqlite3_bind_double (stmt_levl, 6, res_y * 4.0);
538 	  sqlite3_bind_double (stmt_levl, 7, res_x * 8.0);
539 	  sqlite3_bind_double (stmt_levl, 8, res_y * 8.0);
540       }
541     ret = sqlite3_step (stmt_levl);
542     if (ret == SQLITE_DONE || ret == SQLITE_ROW)
543 	;
544     else
545       {
546 	  fprintf (stderr,
547 		   "INSERT INTO levels; sqlite3_step() error: %s\n",
548 		   sqlite3_errmsg (handle));
549 	  goto error;
550       }
551     return 1;
552   error:
553     return 0;
554 }
555 
556 RL2_PRIVATE int
do_insert_stats(sqlite3 * handle,rl2RasterStatisticsPtr section_stats,sqlite3_int64 section_id,sqlite3_stmt * stmt_upd_sect)557 do_insert_stats (sqlite3 * handle, rl2RasterStatisticsPtr section_stats,
558 		 sqlite3_int64 section_id, sqlite3_stmt * stmt_upd_sect)
559 {
560 /* updating the Section's Statistics */
561     unsigned char *blob_stats;
562     int blob_stats_sz;
563     int ret;
564 
565     sqlite3_reset (stmt_upd_sect);
566     sqlite3_clear_bindings (stmt_upd_sect);
567     rl2_serialize_dbms_raster_statistics (section_stats, &blob_stats,
568 					  &blob_stats_sz);
569     sqlite3_bind_blob (stmt_upd_sect, 1, blob_stats, blob_stats_sz, free);
570     sqlite3_bind_int64 (stmt_upd_sect, 2, section_id);
571     ret = sqlite3_step (stmt_upd_sect);
572     if (ret == SQLITE_DONE || ret == SQLITE_ROW)
573 	;
574     else
575       {
576 	  fprintf (stderr,
577 		   "UPDATE sections; sqlite3_step() error: %s\n",
578 		   sqlite3_errmsg (handle));
579 	  goto error;
580       }
581     return 1;
582   error:
583     return 0;
584 }
585 
586 RL2_PRIVATE char *
get_section_name(const char * src_path)587 get_section_name (const char *src_path)
588 {
589 /* attempting to extract the section name from source path */
590     int pos1 = 0;
591     int pos2 = 0;
592     int xpos2;
593     int len;
594     char *name;
595     const char *p;
596     if (src_path == NULL)
597 	return NULL;
598     pos2 = strlen (src_path) - 1;
599     xpos2 = pos2;
600     pos1 = 0;
601     p = src_path + pos2;
602     while (p >= src_path)
603       {
604 	  if (*p == '.' && pos2 == xpos2)
605 	      pos2 = (p - 1) - src_path;
606 	  if (*p == '/')
607 	    {
608 		pos1 = (p + 1) - src_path;
609 		break;
610 	    }
611 	  p--;
612       }
613     len = pos2 - pos1 + 1;
614     name = malloc (len + 1);
615     memset (name, '\0', len + 1);
616     memcpy (name, src_path + pos1, len);
617     return name;
618 }
619 
620 RL2_PRIVATE int
do_insert_section(sqlite3 * handle,const char * src_path,const char * section,int srid,unsigned int width,unsigned int height,double minx,double miny,double maxx,double maxy,sqlite3_stmt * stmt_sect,sqlite3_int64 * id)621 do_insert_section (sqlite3 * handle, const char *src_path,
622 		   const char *section, int srid, unsigned int width,
623 		   unsigned int height, double minx, double miny,
624 		   double maxx, double maxy, sqlite3_stmt * stmt_sect,
625 		   sqlite3_int64 * id)
626 {
627 /* INSERTing the section */
628     int ret;
629     unsigned char *blob;
630     int blob_size;
631     gaiaGeomCollPtr geom;
632     sqlite3_int64 section_id;
633 
634     sqlite3_reset (stmt_sect);
635     sqlite3_clear_bindings (stmt_sect);
636     if (section != NULL)
637 	sqlite3_bind_text (stmt_sect, 1, section, strlen (section),
638 			   SQLITE_STATIC);
639     else
640       {
641 	  char *sect_name = get_section_name (src_path);
642 	  if (sect_name != NULL)
643 	      sqlite3_bind_text (stmt_sect, 1, sect_name, strlen (sect_name),
644 				 free);
645       }
646     sqlite3_bind_text (stmt_sect, 2, src_path, strlen (src_path),
647 		       SQLITE_STATIC);
648     sqlite3_bind_int (stmt_sect, 3, width);
649     sqlite3_bind_int (stmt_sect, 4, height);
650     geom = build_extent (srid, minx, miny, maxx, maxy);
651     gaiaToSpatiaLiteBlobWkb (geom, &blob, &blob_size);
652     gaiaFreeGeomColl (geom);
653     sqlite3_bind_blob (stmt_sect, 5, blob, blob_size, free);
654     ret = sqlite3_step (stmt_sect);
655     if (ret == SQLITE_DONE || ret == SQLITE_ROW)
656 	section_id = sqlite3_last_insert_rowid (handle);
657     else
658       {
659 	  fprintf (stderr,
660 		   "INSERT INTO sections; sqlite3_step() error: %s\n",
661 		   sqlite3_errmsg (handle));
662 	  goto error;
663       }
664     *id = section_id;
665     return 1;
666   error:
667     return 0;
668 }
669 
670 RL2_PRIVATE rl2RasterPtr
build_wms_tile(rl2CoveragePtr coverage,const unsigned char * rgba_tile)671 build_wms_tile (rl2CoveragePtr coverage, const unsigned char *rgba_tile)
672 {
673 /* building a raster starting from an RGBA buffer */
674     rl2PrivCoveragePtr cvg = (rl2PrivCoveragePtr) coverage;
675     rl2RasterPtr raster = NULL;
676     rl2PalettePtr palette = NULL;
677     unsigned char *pixels = NULL;
678     int pixels_sz = 0;
679     unsigned char *mask = NULL;
680     int mask_size = 0;
681     const unsigned char *p_in;
682     unsigned char *p_out;
683     unsigned char *p_msk;
684     int requires_mask = 0;
685     unsigned int x;
686     unsigned int y;
687 
688     if (coverage == NULL || rgba_tile == NULL)
689 	return NULL;
690 
691     /* supporting only RGB, GRAYSCALE or MONOCHROME coverages */
692     if (cvg->pixelType == RL2_PIXEL_RGB && cvg->nBands == 3)
693 	pixels_sz = cvg->tileWidth * cvg->tileHeight * 3;
694     if (cvg->pixelType == RL2_PIXEL_GRAYSCALE && cvg->nBands == 1)
695 	pixels_sz = cvg->tileWidth * cvg->tileHeight;
696     if (cvg->pixelType == RL2_PIXEL_MONOCHROME && cvg->nBands == 1)
697 	pixels_sz = cvg->tileWidth * cvg->tileHeight;
698     if (pixels_sz <= 0)
699 	return NULL;
700     mask_size = cvg->tileWidth * cvg->tileHeight;
701 
702     /* allocating the raster and mask buffers */
703     pixels = malloc (pixels_sz);
704     if (pixels == NULL)
705 	return NULL;
706     mask = malloc (mask_size);
707     if (mask == NULL)
708       {
709 	  free (pixels);
710 	  return NULL;
711       }
712 
713     p_msk = mask;
714     for (x = 0; x < (unsigned int) mask_size; x++)
715       {
716 	  /* priming a full opaque mask */
717 	  *p_msk++ = 1;
718       }
719 
720     /* copying pixels */
721     p_in = rgba_tile;
722     p_out = pixels;
723     p_msk = mask;
724     if (cvg->pixelType == RL2_PIXEL_RGB && cvg->nBands == 3)
725       {
726 	  for (y = 0; y < cvg->tileHeight; y++)
727 	    {
728 		for (x = 0; x < cvg->tileWidth; x++)
729 		  {
730 		      unsigned char red = *p_in++;
731 		      unsigned char green = *p_in++;
732 		      unsigned char blue = *p_in++;
733 		      *p_out++ = red;
734 		      *p_out++ = green;
735 		      *p_out++ = blue;
736 		  }
737 	    }
738       }
739     if (cvg->pixelType == RL2_PIXEL_GRAYSCALE && cvg->nBands == 1)
740       {
741 	  for (y = 0; y < cvg->tileHeight; y++)
742 	    {
743 		for (x = 0; x < cvg->tileWidth; x++)
744 		  {
745 		      unsigned char red = *p_in++;
746 		      p_in += 3;
747 		      *p_out++ = red;
748 		  }
749 	    }
750       }
751     if (cvg->pixelType == RL2_PIXEL_MONOCHROME && cvg->nBands == 1)
752       {
753 	  for (y = 0; y < cvg->tileHeight; y++)
754 	    {
755 		for (x = 0; x < cvg->tileWidth; x++)
756 		  {
757 		      unsigned char red = *p_in++;
758 		      p_in += 3;
759 		      if (red == 255)
760 			  *p_out++ = 0;
761 		      else
762 			  *p_out++ = 1;
763 		  }
764 	    }
765       }
766 
767     if (!requires_mask)
768       {
769 	  /* no mask required */
770 	  free (mask);
771 	  mask = NULL;
772 	  mask_size = 0;
773       }
774 
775     raster =
776 	rl2_create_raster (cvg->tileWidth, cvg->tileHeight,
777 			   cvg->sampleType, cvg->pixelType,
778 			   cvg->nBands, pixels, pixels_sz, NULL, mask,
779 			   mask_size, NULL);
780     if (raster == NULL)
781 	goto error;
782     return raster;
783 
784   error:
785     if (palette != NULL)
786 	rl2_destroy_palette (palette);
787     if (pixels != NULL)
788 	free (pixels);
789     if (mask != NULL)
790 	free (mask);
791     return NULL;
792 }
793 
794 RL2_PRIVATE int
insert_wms_tile(InsertWmsPtr ptr,int * first,rl2RasterStatisticsPtr * section_stats,sqlite3_int64 * section_id)795 insert_wms_tile (InsertWmsPtr ptr, int *first,
796 		 rl2RasterStatisticsPtr * section_stats,
797 		 sqlite3_int64 * section_id)
798 {
799     double tile_minx;
800     double tile_miny;
801     double tile_maxx;
802     double tile_maxy;
803     unsigned char *blob_odd;
804     int blob_odd_sz;
805     unsigned char *blob_even;
806     int blob_even_sz;
807     rl2RasterPtr raster = NULL;
808     double base_res_x;
809     double base_res_y;
810 
811     if (rl2_get_coverage_resolution (ptr->coverage, &base_res_x, &base_res_y) !=
812 	RL2_OK)
813 	goto error;
814     if (*first)
815       {
816 	  /* INSERTing the section */
817 	  *first = 0;
818 	  if (!do_insert_section
819 	      (ptr->sqlite, "WMS Service", ptr->sect_name, ptr->srid,
820 	       ptr->width, ptr->height, ptr->minx, ptr->miny, ptr->maxx,
821 	       ptr->maxy, ptr->stmt_sect, section_id))
822 	      goto error;
823 	  *section_stats =
824 	      rl2_create_raster_statistics (ptr->sample_type, ptr->num_bands);
825 	  if (*section_stats == NULL)
826 	      goto error;
827 	  /* INSERTing the base-levels */
828 	  if (!do_insert_levels
829 	      (ptr->sqlite, base_res_x, base_res_y, 1.0, RL2_SAMPLE_UNKNOWN,
830 	       ptr->stmt_levl))
831 	      goto error;
832       }
833 
834     /* building the raster tile */
835     raster = build_wms_tile (ptr->coverage, ptr->rgba_tile);
836     if (raster == NULL)
837       {
838 	  fprintf (stderr, "ERROR: unable to get a WMS tile\n");
839 	  goto error;
840       }
841     if (rl2_raster_encode
842 	(raster, ptr->compression, &blob_odd, &blob_odd_sz, &blob_even,
843 	 &blob_even_sz, 100, 1) != RL2_OK)
844       {
845 	  fprintf (stderr, "ERROR: unable to encode a WMS tile\n");
846 	  goto error;
847       }
848 
849     /* INSERTing the tile */
850     tile_minx = ptr->x;
851     tile_maxx = tile_minx + ptr->tilew;
852     tile_maxy = ptr->y;
853     tile_miny = tile_maxy - ptr->tileh;
854     if (!do_insert_wms_tile
855 	(ptr->sqlite, blob_odd, blob_odd_sz, blob_even, blob_even_sz,
856 	 *section_id, ptr->srid, ptr->horz_res, ptr->vert_res, ptr->tile_width,
857 	 ptr->tile_height, ptr->minx, ptr->maxy, tile_minx, tile_miny,
858 	 tile_maxx, tile_maxy, NULL, ptr->no_data, ptr->stmt_tils,
859 	 ptr->stmt_data, *section_stats))
860 	goto error;
861     blob_odd = NULL;
862     blob_even = NULL;
863     rl2_destroy_raster (raster);
864     free (ptr->rgba_tile);
865     ptr->rgba_tile = NULL;
866     return 1;
867   error:
868     if (raster != NULL)
869 	rl2_destroy_raster (raster);
870     if (blob_odd != NULL)
871 	free (blob_odd);
872     if (blob_even != NULL)
873 	free (blob_even);
874     free (ptr->rgba_tile);
875     ptr->rgba_tile = NULL;
876     return 0;
877 }
878 
879 RL2_PRIVATE int
is_point(gaiaGeomCollPtr geom)880 is_point (gaiaGeomCollPtr geom)
881 {
882 /* checking if the Geom is a simple Point */
883     int pts = 0;
884     int lns = 0;
885     int pgs = 0;
886     gaiaPointPtr pt;
887     gaiaLinestringPtr ln;
888     gaiaPolygonPtr pg;
889     pt = geom->FirstPoint;
890     while (pt != NULL)
891       {
892 	  pts++;
893 	  pt = pt->Next;
894       }
895     ln = geom->FirstLinestring;
896     while (ln != NULL)
897       {
898 	  lns++;
899 	  ln = ln->Next;
900       }
901     pg = geom->FirstPolygon;
902     while (pg != NULL)
903       {
904 	  pgs++;
905 	  pg = pg->Next;
906       }
907     if (pts == 1 && lns == 0 && pgs == 0)
908 	return 1;
909     return 0;
910 }
911 
912 RL2_PRIVATE ResolutionsListPtr
alloc_resolutions_list()913 alloc_resolutions_list ()
914 {
915 /* allocating an empty list */
916     ResolutionsListPtr list = malloc (sizeof (ResolutionsList));
917     if (list == NULL)
918 	return NULL;
919     list->first = NULL;
920     list->last = NULL;
921     return list;
922 }
923 
924 RL2_PRIVATE void
destroy_resolutions_list(ResolutionsListPtr list)925 destroy_resolutions_list (ResolutionsListPtr list)
926 {
927 /* memory cleanup - destroying a list */
928     ResolutionLevelPtr res;
929     ResolutionLevelPtr resn;
930     if (list == NULL)
931 	return;
932     res = list->first;
933     while (res != NULL)
934       {
935 	  resn = res->next;
936 	  free (res);
937 	  res = resn;
938       }
939     free (list);
940 }
941 
942 RL2_PRIVATE void
add_base_resolution(ResolutionsListPtr list,int level,int scale,double x_res,double y_res)943 add_base_resolution (ResolutionsListPtr list, int level, int scale,
944 		     double x_res, double y_res)
945 {
946 /* inserting a base resolution into the list */
947     ResolutionLevelPtr res;
948     if (list == NULL)
949 	return;
950 
951     res = list->first;
952     while (res != NULL)
953       {
954 	  if (res->x_resolution == x_res && res->y_resolution == y_res)
955 	    {
956 		/* already defined: skipping */
957 		return;
958 	    }
959 	  res = res->next;
960       }
961 
962 /* inserting */
963     res = malloc (sizeof (ResolutionLevel));
964     res->level = level;
965     res->scale = scale;
966     res->x_resolution = x_res;
967     res->y_resolution = y_res;
968     res->prev = list->last;
969     res->next = NULL;
970     if (list->first == NULL)
971 	list->first = res;
972     if (list->last != NULL)
973 	list->last->next = res;
974     list->last = res;
975 }
976 
977 RL2_PRIVATE int
find_best_resolution_level(sqlite3 * handle,const char * coverage,double x_res,double y_res,int * level_id,int * scale,int * real_scale,double * xx_res,double * yy_res)978 find_best_resolution_level (sqlite3 * handle, const char *coverage,
979 			    double x_res, double y_res, int *level_id,
980 			    int *scale, int *real_scale, double *xx_res,
981 			    double *yy_res)
982 {
983 /* attempting to identify the optimal resolution level */
984     int ret;
985     int found = 0;
986     int z_level;
987     int z_scale;
988     int z_real;
989     double z_x_res;
990     double z_y_res;
991     char *xcoverage;
992     char *xxcoverage;
993     char *sql;
994     sqlite3_stmt *stmt = NULL;
995     ResolutionsListPtr list = NULL;
996     ResolutionLevelPtr res;
997 
998     if (coverage == NULL)
999 	return 0;
1000 
1001     xcoverage = sqlite3_mprintf ("%s_levels", coverage);
1002     xxcoverage = gaiaDoubleQuotedSql (xcoverage);
1003     sqlite3_free (xcoverage);
1004     sql =
1005 	sqlite3_mprintf
1006 	("SELECT pyramid_level, x_resolution_1_8, y_resolution_1_8, "
1007 	 "x_resolution_1_4, y_resolution_1_4, x_resolution_1_2, y_resolution_1_2, "
1008 	 "x_resolution_1_1, y_resolution_1_1 FROM \"%s\" "
1009 	 "ORDER BY pyramid_level DESC", xxcoverage);
1010     free (xxcoverage);
1011     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
1012     if (ret != SQLITE_OK)
1013       {
1014 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
1015 	  goto error;
1016       }
1017     sqlite3_free (sql);
1018 
1019     list = alloc_resolutions_list ();
1020     if (list == NULL)
1021 	goto error;
1022 
1023     while (1)
1024       {
1025 	  /* scrolling the result set rows */
1026 	  ret = sqlite3_step (stmt);
1027 	  if (ret == SQLITE_DONE)
1028 	      break;		/* end of result set */
1029 	  if (ret == SQLITE_ROW)
1030 	    {
1031 		int lvl = sqlite3_column_int (stmt, 0);
1032 		if (sqlite3_column_type (stmt, 1) == SQLITE_FLOAT
1033 		    && sqlite3_column_type (stmt, 2) == SQLITE_FLOAT)
1034 		  {
1035 		      z_x_res = sqlite3_column_double (stmt, 1);
1036 		      z_y_res = sqlite3_column_double (stmt, 2);
1037 		      add_base_resolution (list, lvl, RL2_SCALE_8, z_x_res,
1038 					   z_y_res);
1039 		  }
1040 		if (sqlite3_column_type (stmt, 3) == SQLITE_FLOAT
1041 		    && sqlite3_column_type (stmt, 4) == SQLITE_FLOAT)
1042 		  {
1043 		      z_x_res = sqlite3_column_double (stmt, 3);
1044 		      z_y_res = sqlite3_column_double (stmt, 4);
1045 		      add_base_resolution (list, lvl, RL2_SCALE_4, z_x_res,
1046 					   z_y_res);
1047 		  }
1048 		if (sqlite3_column_type (stmt, 5) == SQLITE_FLOAT
1049 		    && sqlite3_column_type (stmt, 6) == SQLITE_FLOAT)
1050 		  {
1051 		      z_x_res = sqlite3_column_double (stmt, 5);
1052 		      z_y_res = sqlite3_column_double (stmt, 6);
1053 		      add_base_resolution (list, lvl, RL2_SCALE_2, z_x_res,
1054 					   z_y_res);
1055 		  }
1056 		if (sqlite3_column_type (stmt, 7) == SQLITE_FLOAT
1057 		    && sqlite3_column_type (stmt, 8) == SQLITE_FLOAT)
1058 		  {
1059 		      z_x_res = sqlite3_column_double (stmt, 7);
1060 		      z_y_res = sqlite3_column_double (stmt, 8);
1061 		      add_base_resolution (list, lvl, RL2_SCALE_1, z_x_res,
1062 					   z_y_res);
1063 		  }
1064 	    }
1065 	  else
1066 	    {
1067 		fprintf (stderr, "SQL error: %s\n%s\n", sql,
1068 			 sqlite3_errmsg (handle));
1069 		goto error;
1070 	    }
1071       }
1072     sqlite3_finalize (stmt);
1073 
1074 /* adjusting real scale factors */
1075     z_real = 1;
1076     res = list->last;
1077     while (res != NULL)
1078       {
1079 	  res->real_scale = z_real;
1080 	  z_real *= 2;
1081 	  res = res->prev;
1082       }
1083 /* retrieving the best resolution level */
1084     found = 0;
1085     res = list->last;
1086     while (res != NULL)
1087       {
1088 	  if (res->x_resolution <= x_res && res->y_resolution <= y_res)
1089 	    {
1090 		found = 1;
1091 		z_level = res->level;
1092 		z_scale = res->scale;
1093 		z_real = res->real_scale;
1094 		z_x_res = res->x_resolution;
1095 		z_y_res = res->y_resolution;
1096 	    }
1097 	  res = res->prev;
1098       }
1099     if (found)
1100       {
1101 	  *level_id = z_level;
1102 	  *scale = z_scale;
1103 	  *real_scale = z_real;
1104 	  *xx_res = z_x_res;
1105 	  *yy_res = z_y_res;
1106       }
1107     else if (list->last != NULL)
1108       {
1109 	  res = list->last;
1110 	  *level_id = res->level;
1111 	  *scale = res->scale;
1112 	  *xx_res = res->x_resolution;
1113 	  *yy_res = res->y_resolution;
1114       }
1115     else
1116 	goto error;
1117     destroy_resolutions_list (list);
1118     return 1;
1119 
1120   error:
1121     if (stmt != NULL)
1122 	sqlite3_finalize (stmt);
1123     if (list != NULL)
1124 	destroy_resolutions_list (list);
1125     return 0;
1126 }
1127 
1128 RL2_PRIVATE unsigned char
get_palette_format(rl2PrivPalettePtr plt)1129 get_palette_format (rl2PrivPalettePtr plt)
1130 {
1131 /* testing for a Grayscale or RGB palette */
1132     int is_gray = 0;
1133     int i;
1134     for (i = 0; i < plt->nEntries; i++)
1135       {
1136 	  rl2PrivPaletteEntryPtr entry = plt->entries + i;
1137 	  if (entry->red == entry->green && entry->red == entry->blue)
1138 	      is_gray++;
1139       }
1140     if (is_gray == plt->nEntries)
1141 	return RL2_PIXEL_GRAYSCALE;
1142     else
1143 	return RL2_PIXEL_RGB;
1144 }
1145 
1146 static unsigned char *
gray_to_rgba(unsigned short width,unsigned short height,unsigned char * gray)1147 gray_to_rgba (unsigned short width, unsigned short height, unsigned char *gray)
1148 {
1149 /* transforming an RGB buffer to RGBA */
1150     unsigned char *rgba = NULL;
1151     unsigned char *p_out;
1152     const unsigned char *p_in;
1153     int x;
1154     int y;
1155 
1156     rgba = malloc (width * height * 4);
1157     if (rgba == NULL)
1158 	return NULL;
1159     p_in = gray;
1160     p_out = rgba;
1161     for (y = 0; y < height; y++)
1162       {
1163 	  for (x = 0; x < width; x++)
1164 	    {
1165 		unsigned char x = *p_in++;
1166 		*p_out++ = x;	/* red */
1167 		*p_out++ = x;	/* green */
1168 		*p_out++ = x;	/* blue */
1169 		*p_out++ = 255;	/* alpha */
1170 	    }
1171       }
1172     return rgba;
1173 }
1174 
1175 static unsigned char *
rgb_to_rgba(unsigned int width,unsigned int height,unsigned char * rgb)1176 rgb_to_rgba (unsigned int width, unsigned int height, unsigned char *rgb)
1177 {
1178 /* transforming an RGB buffer to RGBA */
1179     unsigned char *rgba = NULL;
1180     unsigned char *p_out;
1181     const unsigned char *p_in;
1182     unsigned int x;
1183     unsigned int y;
1184 
1185     rgba = malloc (width * height * 4);
1186     if (rgba == NULL)
1187 	return NULL;
1188     p_in = rgb;
1189     p_out = rgba;
1190     for (y = 0; y < height; y++)
1191       {
1192 	  for (x = 0; x < width; x++)
1193 	    {
1194 		*p_out++ = *p_in++;	/* red */
1195 		*p_out++ = *p_in++;	/* green */
1196 		*p_out++ = *p_in++;	/* blue */
1197 		*p_out++ = 255;	/* alpha */
1198 	    }
1199       }
1200     return rgba;
1201 }
1202 
1203 RL2_PRIVATE int
get_payload_from_monochrome_opaque(unsigned int width,unsigned int height,sqlite3 * handle,double minx,double miny,double maxx,double maxy,int srid,unsigned char * pixels,unsigned char format,int quality,unsigned char ** image,int * image_sz)1204 get_payload_from_monochrome_opaque (unsigned int width, unsigned int height,
1205 				    sqlite3 * handle, double minx, double miny,
1206 				    double maxx, double maxy, int srid,
1207 				    unsigned char *pixels, unsigned char format,
1208 				    int quality, unsigned char **image,
1209 				    int *image_sz)
1210 {
1211 /* input: Monochrome    output: Grayscale */
1212     int ret;
1213     unsigned char *p_in;
1214     unsigned char *p_out;
1215     unsigned char *gray = NULL;
1216     unsigned int row;
1217     unsigned int col;
1218     unsigned char *rgba = NULL;
1219 
1220     gray = malloc (width * height);
1221     if (gray == NULL)
1222 	goto error;
1223     p_in = pixels;
1224     p_out = gray;
1225     for (row = 0; row < height; row++)
1226       {
1227 	  for (col = 0; col < width; col++)
1228 	    {
1229 		if (*p_in++ == 1)
1230 		    *p_out++ = 0;	/* Black */
1231 		else
1232 		    *p_out++ = 255;	/* White */
1233 	    }
1234       }
1235     free (pixels);
1236     pixels = NULL;
1237     if (format == RL2_OUTPUT_FORMAT_JPEG)
1238       {
1239 	  if (rl2_gray_to_jpeg (width, height, gray, quality, image, image_sz)
1240 	      != RL2_OK)
1241 	      goto error;
1242       }
1243     else if (format == RL2_OUTPUT_FORMAT_PNG)
1244       {
1245 	  if (rl2_gray_to_png (width, height, gray, image, image_sz) != RL2_OK)
1246 	      goto error;
1247       }
1248     else if (format == RL2_OUTPUT_FORMAT_TIFF)
1249       {
1250 	  if (srid > 0)
1251 	    {
1252 		if (rl2_gray_to_geotiff
1253 		    (width, height, handle, minx, miny, maxx, maxy, srid, gray,
1254 		     image, image_sz) != RL2_OK)
1255 		    goto error;
1256 	    }
1257 	  else
1258 	    {
1259 		if (rl2_gray_to_tiff (width, height, gray, image, image_sz) !=
1260 		    RL2_OK)
1261 		    goto error;
1262 	    }
1263       }
1264     else if (format == RL2_OUTPUT_FORMAT_PDF)
1265       {
1266 	  rgba = gray_to_rgba (width, height, gray);
1267 	  if (rgba == NULL)
1268 	      goto error;
1269 	  ret = rl2_rgba_to_pdf (width, height, rgba, image, image_sz);
1270 	  rgba = NULL;
1271 	  if (ret != RL2_OK)
1272 	      goto error;
1273       }
1274     else
1275 	goto error;
1276     free (gray);
1277     return 1;
1278 
1279   error:
1280     if (pixels != NULL)
1281 	free (pixels);
1282     if (gray != NULL)
1283 	free (gray);
1284     if (rgba != NULL)
1285 	free (rgba);
1286     return 0;
1287 }
1288 
1289 RL2_PRIVATE int
get_payload_from_monochrome_transparent(unsigned int width,unsigned int height,unsigned char * pixels,unsigned char format,int quality,unsigned char ** image,int * image_sz,double opacity)1290 get_payload_from_monochrome_transparent (unsigned int width,
1291 					 unsigned int height,
1292 					 unsigned char *pixels,
1293 					 unsigned char format, int quality,
1294 					 unsigned char **image, int *image_sz,
1295 					 double opacity)
1296 {
1297 /* input: Monochrome    output: Grayscale */
1298     unsigned char *p_in;
1299     unsigned char *p_out;
1300     unsigned char *p_msk;
1301     unsigned char *gray = NULL;
1302     unsigned char *mask = NULL;
1303     unsigned int row;
1304     unsigned int col;
1305 
1306     if (quality > 100)
1307 	quality = 100;
1308     gray = malloc (width * height);
1309     if (gray == NULL)
1310 	goto error;
1311     mask = malloc (width * height);
1312     if (mask == NULL)
1313 	goto error;
1314     p_in = pixels;
1315     p_out = gray;
1316     p_msk = mask;
1317     for (row = 0; row < height; row++)
1318       {
1319 	  for (col = 0; col < width; col++)
1320 	    {
1321 		if (*p_in++ == 1)
1322 		  {
1323 		      *p_out++ = 0;	/* Black */
1324 		      *p_msk++ = 1;	/* Opaque */
1325 		  }
1326 		else
1327 		  {
1328 		      *p_out++ = 1;	/* White */
1329 		      *p_msk++ = 0;	/* Transparent */
1330 		  }
1331 	    }
1332       }
1333     free (pixels);
1334     pixels = NULL;
1335     if (format == RL2_OUTPUT_FORMAT_PNG)
1336       {
1337 	  if (rl2_gray_alpha_to_png
1338 	      (width, height, gray, mask, image, image_sz, opacity) != RL2_OK)
1339 	      goto error;
1340       }
1341     else
1342 	goto error;
1343     free (gray);
1344     free (mask);
1345     return 1;
1346 
1347   error:
1348     if (pixels != NULL)
1349 	free (pixels);
1350     if (gray != NULL)
1351 	free (gray);
1352     if (mask != NULL)
1353 	free (mask);
1354     return 0;
1355 }
1356 
1357 RL2_PRIVATE int
get_payload_from_palette_opaque(unsigned int width,unsigned int height,sqlite3 * handle,double minx,double miny,double maxx,double maxy,int srid,unsigned char * pixels,rl2PalettePtr palette,unsigned char format,int quality,unsigned char ** image,int * image_sz)1358 get_payload_from_palette_opaque (unsigned int width, unsigned int height,
1359 				 sqlite3 * handle, double minx, double miny,
1360 				 double maxx, double maxy, int srid,
1361 				 unsigned char *pixels, rl2PalettePtr palette,
1362 				 unsigned char format, int quality,
1363 				 unsigned char **image, int *image_sz)
1364 {
1365 /* input: Palette    output: Grayscale or RGB */
1366     int ret;
1367     rl2PrivPalettePtr plt = (rl2PrivPalettePtr) palette;
1368     unsigned char *p_in;
1369     unsigned char *p_out;
1370     unsigned char *gray = NULL;
1371     unsigned char *rgb = NULL;
1372     unsigned int row;
1373     unsigned int col;
1374     unsigned char out_format;
1375     unsigned char *rgba = NULL;
1376 
1377     out_format = get_palette_format (plt);
1378     if (out_format == RL2_PIXEL_RGB)
1379       {
1380 	  /* converting from Palette to RGB */
1381 	  rgb = malloc (width * height * 3);
1382 	  p_in = pixels;
1383 	  p_out = rgb;
1384 	  for (row = 0; row < height; row++)
1385 	    {
1386 		for (col = 0; col < width; col++)
1387 		  {
1388 		      unsigned char red = 0;
1389 		      unsigned char green = 0;
1390 		      unsigned char blue = 0;
1391 		      unsigned char index = *p_in++;
1392 		      if (index < plt->nEntries)
1393 			{
1394 			    rl2PrivPaletteEntryPtr entry = plt->entries + index;
1395 			    red = entry->red;
1396 			    green = entry->green;
1397 			    blue = entry->blue;
1398 			}
1399 		      *p_out++ = red;	/* red */
1400 		      *p_out++ = green;	/* green */
1401 		      *p_out++ = blue;	/* blue */
1402 		  }
1403 	    }
1404 	  free (pixels);
1405 	  if (format == RL2_OUTPUT_FORMAT_JPEG)
1406 	    {
1407 		if (rl2_rgb_to_jpeg
1408 		    (width, height, rgb, quality, image, image_sz) != RL2_OK)
1409 		    goto error;
1410 	    }
1411 	  else if (format == RL2_OUTPUT_FORMAT_PNG)
1412 	    {
1413 		if (rl2_rgb_to_png (width, height, rgb, image, image_sz) !=
1414 		    RL2_OK)
1415 		    goto error;
1416 	    }
1417 	  else if (format == RL2_OUTPUT_FORMAT_TIFF)
1418 	    {
1419 		if (srid > 0)
1420 		  {
1421 		      if (rl2_rgb_to_geotiff
1422 			  (width, height, handle, minx, miny, maxx, maxy, srid,
1423 			   rgb, image, image_sz) != RL2_OK)
1424 			  goto error;
1425 		  }
1426 		else
1427 		  {
1428 		      if (rl2_rgb_to_tiff (width, height, rgb, image, image_sz)
1429 			  != RL2_OK)
1430 			  goto error;
1431 		  }
1432 	    }
1433 	  else if (format == RL2_OUTPUT_FORMAT_PDF)
1434 	    {
1435 		rgba = rgb_to_rgba (width, height, rgb);
1436 		if (rgba == NULL)
1437 		    goto error;
1438 		ret = rl2_rgba_to_pdf (width, height, rgba, image, image_sz);
1439 		rgba = NULL;
1440 		if (ret != RL2_OK)
1441 		    goto error;
1442 	    }
1443 	  else
1444 	      goto error;
1445 	  free (rgb);
1446       }
1447     else if (out_format == RL2_PIXEL_GRAYSCALE)
1448       {
1449 	  /* converting from Palette to Grayscale */
1450 	  gray = malloc (width * height);
1451 	  p_in = pixels;
1452 	  p_out = gray;
1453 	  for (row = 0; row < height; row++)
1454 	    {
1455 		for (col = 0; col < width; col++)
1456 		  {
1457 		      unsigned char value = 0;
1458 		      unsigned char index = *p_in++;
1459 		      if (index < plt->nEntries)
1460 			{
1461 			    rl2PrivPaletteEntryPtr entry = plt->entries + index;
1462 			    value = entry->red;
1463 			}
1464 		      *p_out++ = value;	/* gray */
1465 		  }
1466 	    }
1467 	  free (pixels);
1468 	  if (format == RL2_OUTPUT_FORMAT_JPEG)
1469 	    {
1470 		if (rl2_gray_to_jpeg
1471 		    (width, height, gray, quality, image, image_sz) != RL2_OK)
1472 		    goto error;
1473 	    }
1474 	  else if (format == RL2_OUTPUT_FORMAT_PNG)
1475 	    {
1476 		if (rl2_gray_to_png (width, height, gray, image, image_sz) !=
1477 		    RL2_OK)
1478 		    goto error;
1479 	    }
1480 	  else if (format == RL2_OUTPUT_FORMAT_TIFF)
1481 	    {
1482 		if (srid > 0)
1483 		  {
1484 		      if (rl2_gray_to_geotiff
1485 			  (width, height, handle, minx, miny, maxx, maxy, srid,
1486 			   gray, image, image_sz) != RL2_OK)
1487 			  goto error;
1488 		  }
1489 		else
1490 		  {
1491 		      if (rl2_gray_to_tiff
1492 			  (width, height, gray, image, image_sz) != RL2_OK)
1493 			  goto error;
1494 		  }
1495 	    }
1496 	  else if (format == RL2_OUTPUT_FORMAT_PDF)
1497 	    {
1498 		rgba = gray_to_rgba (width, height, gray);
1499 		if (rgba == NULL)
1500 		    goto error;
1501 		ret = rl2_rgba_to_pdf (width, height, rgba, image, image_sz);
1502 		rgba = NULL;
1503 		if (ret != RL2_OK)
1504 		    goto error;
1505 	    }
1506 	  else
1507 	      goto error;
1508 	  free (gray);
1509       }
1510     else
1511 	goto error;
1512     return 1;
1513 
1514   error:
1515     if (pixels != NULL)
1516 	free (pixels);
1517     if (gray != NULL)
1518 	free (gray);
1519     if (rgb != NULL)
1520 	free (rgb);
1521     if (rgba != NULL)
1522 	free (rgba);
1523     return 0;
1524 }
1525 
1526 RL2_PRIVATE int
get_payload_from_palette_transparent(unsigned int width,unsigned int height,unsigned char * pixels,rl2PalettePtr palette,unsigned char format,int quality,unsigned char ** image,int * image_sz,unsigned char bg_red,unsigned char bg_green,unsigned char bg_blue,double opacity)1527 get_payload_from_palette_transparent (unsigned int width,
1528 				      unsigned int height,
1529 				      unsigned char *pixels,
1530 				      rl2PalettePtr palette,
1531 				      unsigned char format, int quality,
1532 				      unsigned char **image, int *image_sz,
1533 				      unsigned char bg_red,
1534 				      unsigned char bg_green,
1535 				      unsigned char bg_blue, double opacity)
1536 {
1537 /* input: Palette    output: Grayscale or RGB */
1538     rl2PrivPalettePtr plt = (rl2PrivPalettePtr) palette;
1539     unsigned char *p_in;
1540     unsigned char *p_out;
1541     unsigned char *p_msk;
1542     unsigned char *gray = NULL;
1543     unsigned char *rgb = NULL;
1544     unsigned char *mask = NULL;
1545     unsigned int row;
1546     unsigned int col;
1547     unsigned char out_format;
1548 
1549     if (quality > 100)
1550 	quality = 100;
1551     out_format = get_palette_format (plt);
1552     if (out_format == RL2_PIXEL_RGB)
1553       {
1554 	  /* converting from Palette to RGB */
1555 	  rgb = malloc (width * height * 3);
1556 	  if (rgb == NULL)
1557 	      goto error;
1558 	  mask = malloc (width * height);
1559 	  if (mask == NULL)
1560 	      goto error;
1561 	  p_in = pixels;
1562 	  p_out = rgb;
1563 	  p_msk = mask;
1564 	  for (row = 0; row < height; row++)
1565 	    {
1566 		for (col = 0; col < width; col++)
1567 		  {
1568 		      unsigned char red = 0;
1569 		      unsigned char green = 0;
1570 		      unsigned char blue = 0;
1571 		      unsigned char index = *p_in++;
1572 		      if (index < plt->nEntries)
1573 			{
1574 			    rl2PrivPaletteEntryPtr entry = plt->entries + index;
1575 			    red = entry->red;
1576 			    green = entry->green;
1577 			    blue = entry->blue;
1578 			}
1579 		      *p_out++ = red;	/* red */
1580 		      *p_out++ = green;	/* green */
1581 		      *p_out++ = blue;	/* blue */
1582 		      if (red == bg_red && green == bg_green && blue == bg_blue)
1583 			  *p_msk++ = 0;	/* Transparent */
1584 		      else
1585 			  *p_msk++ = 1;	/* Opaque */
1586 		  }
1587 	    }
1588 	  free (pixels);
1589 	  if (format == RL2_OUTPUT_FORMAT_PNG)
1590 	    {
1591 		if (rl2_rgb_to_png (width, height, rgb, image, image_sz) !=
1592 		    RL2_OK)
1593 		    goto error;
1594 	    }
1595 	  else
1596 	      goto error;
1597 	  free (rgb);
1598 	  free (mask);
1599       }
1600     else if (out_format == RL2_PIXEL_GRAYSCALE)
1601       {
1602 	  /* converting from Palette to Grayscale */
1603 	  gray = malloc (width * height);
1604 	  if (gray == NULL)
1605 	      goto error;
1606 	  mask = malloc (width * height);
1607 	  if (mask == NULL)
1608 	      goto error;
1609 	  p_in = pixels;
1610 	  p_out = gray;
1611 	  p_msk = mask;
1612 	  for (row = 0; row < height; row++)
1613 	    {
1614 		for (col = 0; col < width; col++)
1615 		  {
1616 		      unsigned char value = 0;
1617 		      unsigned char index = *p_in++;
1618 		      if (index < plt->nEntries)
1619 			{
1620 			    rl2PrivPaletteEntryPtr entry = plt->entries + index;
1621 			    value = entry->red;
1622 			}
1623 		      *p_out++ = value;	/* gray */
1624 		      if (value == bg_red)
1625 			  *p_msk++ = 0;	/* Transparent */
1626 		      else
1627 			  *p_msk++ = 1;	/* Opaque */
1628 		  }
1629 	    }
1630 	  free (pixels);
1631 	  if (format == RL2_OUTPUT_FORMAT_PNG)
1632 	    {
1633 		if (rl2_gray_alpha_to_png
1634 		    (width, height, gray, mask, image, image_sz,
1635 		     opacity) != RL2_OK)
1636 		    goto error;
1637 	    }
1638 	  else
1639 	      goto error;
1640 	  free (gray);
1641 	  free (mask);
1642       }
1643     else
1644 	goto error;
1645     return 1;
1646 
1647   error:
1648     if (pixels != NULL)
1649 	free (pixels);
1650     if (gray != NULL)
1651 	free (gray);
1652     if (rgb != NULL)
1653 	free (rgb);
1654     if (mask != NULL)
1655 	free (mask);
1656     return 0;
1657 }
1658 
1659 RL2_PRIVATE int
get_payload_from_grayscale_opaque(unsigned int width,unsigned int height,sqlite3 * handle,double minx,double miny,double maxx,double maxy,int srid,unsigned char * pixels,unsigned char format,int quality,unsigned char ** image,int * image_sz)1660 get_payload_from_grayscale_opaque (unsigned int width, unsigned int height,
1661 				   sqlite3 * handle, double minx, double miny,
1662 				   double maxx, double maxy, int srid,
1663 				   unsigned char *pixels, unsigned char format,
1664 				   int quality, unsigned char **image,
1665 				   int *image_sz)
1666 {
1667 /* input: Grayscale    output: Grayscale */
1668     int ret;
1669     unsigned char *rgba = NULL;
1670 
1671     if (format == RL2_OUTPUT_FORMAT_JPEG)
1672       {
1673 	  if (rl2_gray_to_jpeg (width, height, pixels, quality, image, image_sz)
1674 	      != RL2_OK)
1675 	      goto error;
1676       }
1677     else if (format == RL2_OUTPUT_FORMAT_PNG)
1678       {
1679 	  if (rl2_gray_to_png (width, height, pixels, image, image_sz) !=
1680 	      RL2_OK)
1681 	      goto error;
1682       }
1683     else if (format == RL2_OUTPUT_FORMAT_TIFF)
1684       {
1685 	  if (srid > 0)
1686 	    {
1687 		if (rl2_gray_to_geotiff
1688 		    (width, height, handle, minx, miny, maxx, maxy, srid,
1689 		     pixels, image, image_sz) != RL2_OK)
1690 		    goto error;
1691 	    }
1692 	  else
1693 	    {
1694 		if (rl2_gray_to_tiff (width, height, pixels, image, image_sz) !=
1695 		    RL2_OK)
1696 		    goto error;
1697 	    }
1698       }
1699     else if (format == RL2_OUTPUT_FORMAT_PDF)
1700       {
1701 	  rgba = gray_to_rgba (width, height, pixels);
1702 	  if (rgba == NULL)
1703 	      goto error;
1704 	  ret = rl2_rgba_to_pdf (width, height, rgba, image, image_sz);
1705 	  rgba = NULL;
1706 	  if (ret != RL2_OK)
1707 	      goto error;
1708       }
1709     else
1710 	goto error;
1711     free (pixels);
1712     if (rgba != NULL)
1713 	free (rgba);
1714     return 1;
1715 
1716   error:
1717     free (pixels);
1718     return 0;
1719 }
1720 
1721 RL2_PRIVATE int
get_payload_from_grayscale_transparent(unsigned int width,unsigned int height,unsigned char * pixels,unsigned char format,int quality,unsigned char ** image,int * image_sz,unsigned char bg_gray,double opacity)1722 get_payload_from_grayscale_transparent (unsigned int width,
1723 					unsigned int height,
1724 					unsigned char *pixels,
1725 					unsigned char format, int quality,
1726 					unsigned char **image, int *image_sz,
1727 					unsigned char bg_gray, double opacity)
1728 {
1729 /* input: Grayscale    output: Grayscale */
1730     unsigned char *p_in;
1731     unsigned char *p_msk;
1732     unsigned char *mask = NULL;
1733     unsigned short row;
1734     unsigned short col;
1735 
1736     if (quality > 100)
1737 	quality = 100;
1738     mask = malloc (width * height);
1739     if (mask == NULL)
1740 	goto error;
1741     p_in = pixels;
1742     p_msk = mask;
1743     for (row = 0; row < height; row++)
1744       {
1745 	  for (col = 0; col < width; col++)
1746 	    {
1747 		if (*p_in++ == bg_gray)
1748 		    *p_msk++ = 0;	/* Transparent */
1749 		else
1750 		    *p_msk++ = 255;	/* Opaque */
1751 	    }
1752       }
1753     if (format == RL2_OUTPUT_FORMAT_PNG)
1754       {
1755 	  if (rl2_gray_alpha_to_png
1756 	      (width, height, pixels, mask, image, image_sz, opacity) != RL2_OK)
1757 	      goto error;
1758       }
1759     else
1760 	goto error;
1761     free (pixels);
1762     free (mask);
1763     return 1;
1764 
1765   error:
1766     free (pixels);
1767     if (mask != NULL)
1768 	free (mask);
1769     return 0;
1770 }
1771 
1772 RL2_PRIVATE int
get_payload_from_rgb_opaque(unsigned int width,unsigned int height,sqlite3 * handle,double minx,double miny,double maxx,double maxy,int srid,unsigned char * pixels,unsigned char format,int quality,unsigned char ** image,int * image_sz)1773 get_payload_from_rgb_opaque (unsigned int width, unsigned int height,
1774 			     sqlite3 * handle, double minx, double miny,
1775 			     double maxx, double maxy, int srid,
1776 			     unsigned char *pixels, unsigned char format,
1777 			     int quality, unsigned char **image, int *image_sz)
1778 {
1779 /* input: RGB    output: RGB */
1780     int ret;
1781     unsigned char *rgba = NULL;
1782 
1783     if (format == RL2_OUTPUT_FORMAT_JPEG)
1784       {
1785 	  if (rl2_rgb_to_jpeg (width, height, pixels, quality, image, image_sz)
1786 	      != RL2_OK)
1787 	      goto error;
1788       }
1789     else if (format == RL2_OUTPUT_FORMAT_PNG)
1790       {
1791 	  if (rl2_rgb_to_png (width, height, pixels, image, image_sz) != RL2_OK)
1792 	      goto error;
1793       }
1794     else if (format == RL2_OUTPUT_FORMAT_TIFF)
1795       {
1796 	  if (srid > 0)
1797 	    {
1798 		if (rl2_rgb_to_geotiff
1799 		    (width, height, handle, minx, miny, maxx, maxy, srid,
1800 		     pixels, image, image_sz) != RL2_OK)
1801 		    goto error;
1802 	    }
1803 	  else
1804 	    {
1805 		if (rl2_rgb_to_tiff (width, height, pixels, image, image_sz) !=
1806 		    RL2_OK)
1807 		    goto error;
1808 	    }
1809       }
1810     else if (format == RL2_OUTPUT_FORMAT_PDF)
1811       {
1812 	  rgba = rgb_to_rgba (width, height, pixels);
1813 	  if (rgba == NULL)
1814 	      goto error;
1815 	  ret = rl2_rgba_to_pdf (width, height, rgba, image, image_sz);
1816 	  rgba = NULL;
1817 	  if (ret != RL2_OK)
1818 	      goto error;
1819       }
1820     else
1821 	goto error;
1822     free (pixels);
1823     return 1;
1824 
1825   error:
1826     free (pixels);
1827     if (rgba != NULL)
1828 	free (rgba);
1829     return 0;
1830 }
1831 
1832 RL2_PRIVATE int
get_payload_from_rgb_transparent(unsigned int width,unsigned int height,unsigned char * pixels,unsigned char format,int quality,unsigned char ** image,int * image_sz,unsigned char bg_red,unsigned char bg_green,unsigned char bg_blue,double opacity)1833 get_payload_from_rgb_transparent (unsigned int width, unsigned int height,
1834 				  unsigned char *pixels, unsigned char format,
1835 				  int quality, unsigned char **image,
1836 				  int *image_sz, unsigned char bg_red,
1837 				  unsigned char bg_green, unsigned char bg_blue,
1838 				  double opacity)
1839 {
1840 /* input: RGB    output: RGB */
1841     unsigned char *p_in;
1842     unsigned char *p_msk;
1843     unsigned char *mask = NULL;
1844     unsigned int row;
1845     unsigned int col;
1846 
1847     if (quality > 100)
1848 	quality = 100;
1849     mask = malloc (width * height);
1850     if (mask == NULL)
1851 	goto error;
1852     p_in = pixels;
1853     p_msk = mask;
1854     for (row = 0; row < height; row++)
1855       {
1856 	  for (col = 0; col < width; col++)
1857 	    {
1858 		unsigned char red = *p_in++;
1859 		unsigned char green = *p_in++;
1860 		unsigned char blue = *p_in++;
1861 		if (red == bg_red && green == bg_green && blue == bg_blue)
1862 		    *p_msk++ = 0;	/* Transparent */
1863 		else
1864 		    *p_msk++ = 1;	/* Opaque */
1865 	    }
1866       }
1867     if (format == RL2_OUTPUT_FORMAT_PNG)
1868       {
1869 	  if (rl2_rgb_alpha_to_png
1870 	      (width, height, pixels, mask, image, image_sz, opacity) != RL2_OK)
1871 	      goto error;
1872       }
1873     else
1874 	goto error;
1875     free (pixels);
1876     free (mask);
1877     return 1;
1878 
1879   error:
1880     free (pixels);
1881     if (mask != NULL)
1882 	free (mask);
1883     return 0;
1884 }
1885 
1886 static int
test_no_data_8(rl2PrivPixelPtr no_data,unsigned char * p_in)1887 test_no_data_8 (rl2PrivPixelPtr no_data, unsigned char *p_in)
1888 {
1889 /* testing for NO-DATA */
1890     if (no_data != NULL)
1891       {
1892 	  unsigned char band;
1893 	  int match = 0;
1894 	  rl2PrivSamplePtr sample;
1895 	  for (band = 0; band < no_data->nBands; band++)
1896 	    {
1897 		sample = no_data->Samples + band;
1898 		if (*(p_in + band) == sample->uint8)
1899 		    match++;
1900 	    }
1901 	  if (match == no_data->nBands)
1902 	      return 1;
1903       }
1904     return 0;
1905 }
1906 
1907 RL2_PRIVATE int
get_rgba_from_monochrome_mask(unsigned int width,unsigned int height,unsigned char * pixels,unsigned char * mask,rl2PrivPixelPtr no_data,unsigned char * rgba)1908 get_rgba_from_monochrome_mask (unsigned int width, unsigned int height,
1909 			       unsigned char *pixels, unsigned char *mask,
1910 			       rl2PrivPixelPtr no_data, unsigned char *rgba)
1911 {
1912 /* input: Monochrome    output: Grayscale */
1913     unsigned char *p_in;
1914     unsigned char *p_out;
1915     unsigned char *p_msk;
1916     unsigned int row;
1917     unsigned int col;
1918     int transparent;
1919 
1920     p_in = pixels;
1921     p_out = rgba;
1922     p_msk = mask;
1923     for (row = 0; row < height; row++)
1924       {
1925 	  for (col = 0; col < width; col++)
1926 	    {
1927 		unsigned char value = 255;
1928 		transparent = 0;
1929 		if (p_msk != NULL)
1930 		  {
1931 		      if (*p_msk++ == 0)
1932 			  transparent = 1;
1933 		  }
1934 		if (!transparent)
1935 		    transparent = test_no_data_8 (no_data, p_in);
1936 		if (transparent)
1937 		  {
1938 		      p_out += 4;
1939 		      p_in++;
1940 		  }
1941 		else
1942 		  {
1943 		      if (*p_in++ == 1)
1944 			  value = 0;
1945 		      *p_out++ = value;
1946 		      *p_out++ = value;
1947 		      *p_out++ = value;
1948 		      *p_out++ = 255;	/* opaque */
1949 		  }
1950 	    }
1951       }
1952     free (pixels);
1953     if (mask != NULL)
1954 	free (mask);
1955     return 1;
1956 }
1957 
1958 RL2_PRIVATE int
get_rgba_from_monochrome_opaque(unsigned int width,unsigned int height,unsigned char * pixels,unsigned char * rgba)1959 get_rgba_from_monochrome_opaque (unsigned int width, unsigned int height,
1960 				 unsigned char *pixels, unsigned char *rgba)
1961 {
1962 /* input: Monochrome    output: Grayscale */
1963     unsigned char *p_in;
1964     unsigned char *p_out;
1965     unsigned int row;
1966     unsigned int col;
1967     p_in = pixels;
1968     p_out = rgba;
1969     for (row = 0; row < height; row++)
1970       {
1971 	  for (col = 0; col < width; col++)
1972 	    {
1973 		if (*p_in++ == 1)
1974 		  {
1975 		      *p_out++ = 0;	/* Black */
1976 		      *p_out++ = 0;
1977 		      *p_out++ = 0;
1978 		      *p_out++ = 255;	/* alpha */
1979 		  }
1980 		else
1981 		  {
1982 		      *p_out++ = 255;	/* White */
1983 		      *p_out++ = 255;
1984 		      *p_out++ = 255;
1985 		      *p_out++ = 255;	/* alpha */
1986 		  }
1987 	    }
1988       }
1989     free (pixels);
1990     return 1;
1991 }
1992 
1993 RL2_PRIVATE int
get_rgba_from_monochrome_transparent(unsigned int width,unsigned int height,unsigned char * pixels,unsigned char * rgba)1994 get_rgba_from_monochrome_transparent (unsigned int width,
1995 				      unsigned int height,
1996 				      unsigned char *pixels,
1997 				      unsigned char *rgba)
1998 {
1999 /* input: Monochrome    output: Grayscale */
2000     unsigned char *p_in;
2001     unsigned char *p_out;
2002     unsigned int row;
2003     unsigned int col;
2004 
2005     p_in = pixels;
2006     p_out = rgba;
2007     for (row = 0; row < height; row++)
2008       {
2009 	  for (col = 0; col < width; col++)
2010 	    {
2011 		if (*p_in++ == 1)
2012 		  {
2013 		      *p_out++ = 0;	/* Black */
2014 		      *p_out++ = 0;
2015 		      *p_out++ = 0;
2016 		      *p_out++ = 255;	/* alpha */
2017 		  }
2018 		else
2019 		  {
2020 		      *p_out++ = 255;	/* White */
2021 		      *p_out++ = 255;
2022 		      *p_out++ = 255;
2023 		      *p_out++ = 0;	/* alpha */
2024 		  }
2025 	    }
2026       }
2027     free (pixels);
2028     return 1;
2029 }
2030 
2031 RL2_PRIVATE int
get_rgba_from_palette_mask(unsigned int width,unsigned int height,unsigned char * pixels,unsigned char * mask,rl2PalettePtr palette,rl2PrivPixelPtr no_data,unsigned char * rgba)2032 get_rgba_from_palette_mask (unsigned int width, unsigned int height,
2033 			    unsigned char *pixels, unsigned char *mask,
2034 			    rl2PalettePtr palette, rl2PrivPixelPtr no_data,
2035 			    unsigned char *rgba)
2036 {
2037 /* input: Palette    output: Grayscale or RGB */
2038     rl2PrivPalettePtr plt = (rl2PrivPalettePtr) palette;
2039     unsigned char *p_in;
2040     unsigned char *p_out;
2041     unsigned char *p_msk;
2042     unsigned int row;
2043     unsigned int col;
2044     unsigned char out_format;
2045     int transparent;
2046 
2047     p_in = pixels;
2048     p_out = rgba;
2049     p_msk = mask;
2050     out_format = get_palette_format (plt);
2051     if (out_format == RL2_PIXEL_RGB)
2052       {
2053 	  /* converting from Palette to RGB */
2054 	  for (row = 0; row < height; row++)
2055 	    {
2056 		for (col = 0; col < width; col++)
2057 		  {
2058 		      unsigned char red = 0;
2059 		      unsigned char green = 0;
2060 		      unsigned char blue = 0;
2061 		      unsigned char index;
2062 		      transparent = 0;
2063 		      if (p_msk != NULL)
2064 			{
2065 			    if (*p_msk++ == 0)
2066 				transparent = 1;
2067 			}
2068 		      if (!transparent)
2069 			  transparent = test_no_data_8 (no_data, p_in);
2070 		      if (transparent)
2071 			{
2072 			    p_out += 4;
2073 			    p_in++;
2074 			}
2075 		      else
2076 			{
2077 			    index = *p_in++;
2078 			    if (index < plt->nEntries)
2079 			      {
2080 				  rl2PrivPaletteEntryPtr entry =
2081 				      plt->entries + index;
2082 				  red = entry->red;
2083 				  green = entry->green;
2084 				  blue = entry->blue;
2085 			      }
2086 			    *p_out++ = red;	/* red */
2087 			    *p_out++ = green;	/* green */
2088 			    *p_out++ = blue;	/* blue */
2089 			    *p_out++ = 255;	/* opaque */
2090 			}
2091 		  }
2092 	    }
2093       }
2094     else if (out_format == RL2_PIXEL_GRAYSCALE)
2095       {
2096 	  /* converting from Palette to Grayscale */
2097 	  for (row = 0; row < height; row++)
2098 	    {
2099 		for (col = 0; col < width; col++)
2100 		  {
2101 		      unsigned char value = 0;
2102 		      unsigned char index = *p_in++;
2103 		      if (index < plt->nEntries)
2104 			{
2105 			    rl2PrivPaletteEntryPtr entry = plt->entries + index;
2106 			    value = entry->red;
2107 			}
2108 		      transparent = 0;
2109 		      if (p_msk != NULL)
2110 			{
2111 			    if (*p_msk++ == 0)
2112 				transparent = 1;
2113 			}
2114 		      if (transparent)
2115 			  p_out += 4;
2116 		      else
2117 			{
2118 			    *p_out++ = value;	/* red */
2119 			    *p_out++ = value;	/* green */
2120 			    *p_out++ = value;	/* blue */
2121 			    *p_out++ = 255;	/* opaque */
2122 			}
2123 		  }
2124 	    }
2125       }
2126     else
2127 	goto error;
2128     free (pixels);
2129     if (mask)
2130 	free (mask);
2131     return 1;
2132 
2133   error:
2134     free (pixels);
2135     if (mask)
2136 	free (mask);
2137     return 0;
2138 }
2139 
2140 RL2_PRIVATE int
get_rgba_from_palette_opaque(unsigned int width,unsigned int height,unsigned char * pixels,rl2PalettePtr palette,unsigned char * rgba)2141 get_rgba_from_palette_opaque (unsigned int width, unsigned int height,
2142 			      unsigned char *pixels, rl2PalettePtr palette,
2143 			      unsigned char *rgba)
2144 {
2145 /* input: Palette    output: Grayscale or RGB */
2146     rl2PrivPalettePtr plt = (rl2PrivPalettePtr) palette;
2147     unsigned char *p_in;
2148     unsigned char *p_out;
2149     unsigned int row;
2150     unsigned int col;
2151     unsigned char out_format;
2152 
2153     p_in = pixels;
2154     p_out = rgba;
2155     out_format = get_palette_format (plt);
2156     if (out_format == RL2_PIXEL_RGB)
2157       {
2158 	  /* converting from Palette to RGB */
2159 	  for (row = 0; row < height; row++)
2160 	    {
2161 		for (col = 0; col < width; col++)
2162 		  {
2163 		      unsigned char red = 0;
2164 		      unsigned char green = 0;
2165 		      unsigned char blue = 0;
2166 		      unsigned char index = *p_in++;
2167 		      if (index < plt->nEntries)
2168 			{
2169 			    rl2PrivPaletteEntryPtr entry = plt->entries + index;
2170 			    red = entry->red;
2171 			    green = entry->green;
2172 			    blue = entry->blue;
2173 			}
2174 		      *p_out++ = red;	/* red */
2175 		      *p_out++ = green;	/* green */
2176 		      *p_out++ = blue;	/* blue */
2177 		      *p_out++ = 255;	/* alpha */
2178 		  }
2179 	    }
2180       }
2181     else if (out_format == RL2_PIXEL_GRAYSCALE)
2182       {
2183 	  /* converting from Palette to Grayscale */
2184 	  for (row = 0; row < height; row++)
2185 	    {
2186 		for (col = 0; col < width; col++)
2187 		  {
2188 		      unsigned char value = 0;
2189 		      unsigned char index = *p_in++;
2190 		      if (index < plt->nEntries)
2191 			{
2192 			    rl2PrivPaletteEntryPtr entry = plt->entries + index;
2193 			    value = entry->red;
2194 			}
2195 		      *p_out++ = value;	/* red */
2196 		      *p_out++ = value;	/* green */
2197 		      *p_out++ = value;	/* blue */
2198 		      *p_out++ = 255;	/* alpha */
2199 		  }
2200 	    }
2201       }
2202     else
2203 	goto error;
2204     free (pixels);
2205     return 1;
2206 
2207   error:
2208     free (pixels);
2209     return 0;
2210 }
2211 
2212 RL2_PRIVATE int
get_rgba_from_palette_transparent(unsigned int width,unsigned int height,unsigned char * pixels,rl2PalettePtr palette,unsigned char * rgba,unsigned char bg_red,unsigned char bg_green,unsigned char bg_blue)2213 get_rgba_from_palette_transparent (unsigned int width, unsigned int height,
2214 				   unsigned char *pixels, rl2PalettePtr palette,
2215 				   unsigned char *rgba, unsigned char bg_red,
2216 				   unsigned char bg_green,
2217 				   unsigned char bg_blue)
2218 {
2219 /* input: Palette    output: Grayscale or RGB */
2220     rl2PrivPalettePtr plt = (rl2PrivPalettePtr) palette;
2221     unsigned char *p_in;
2222     unsigned char *p_out;
2223     unsigned int row;
2224     unsigned int col;
2225     unsigned char out_format;
2226 
2227     p_in = pixels;
2228     p_out = rgba;
2229     out_format = get_palette_format (plt);
2230     if (out_format == RL2_PIXEL_RGB)
2231       {
2232 	  /* converting from Palette to RGB */
2233 	  for (row = 0; row < height; row++)
2234 	    {
2235 		for (col = 0; col < width; col++)
2236 		  {
2237 		      unsigned char red = 0;
2238 		      unsigned char green = 0;
2239 		      unsigned char blue = 0;
2240 		      unsigned char index = *p_in++;
2241 		      if (index < plt->nEntries)
2242 			{
2243 			    rl2PrivPaletteEntryPtr entry = plt->entries + index;
2244 			    red = entry->red;
2245 			    green = entry->green;
2246 			    blue = entry->blue;
2247 			}
2248 		      *p_out++ = red;	/* red */
2249 		      *p_out++ = green;	/* green */
2250 		      *p_out++ = blue;	/* blue */
2251 		      if (red == bg_red && green == bg_green && blue == bg_blue)
2252 			  *p_out++ = 0;	/* Transparent */
2253 		      else
2254 			  *p_out++ = 255;	/* Opaque */
2255 		  }
2256 	    }
2257       }
2258     else if (out_format == RL2_PIXEL_GRAYSCALE)
2259       {
2260 	  /* converting from Palette to Grayscale */
2261 	  for (row = 0; row < height; row++)
2262 	    {
2263 		for (col = 0; col < width; col++)
2264 		  {
2265 		      unsigned char value = 0;
2266 		      unsigned char index = *p_in++;
2267 		      if (index < plt->nEntries)
2268 			{
2269 			    rl2PrivPaletteEntryPtr entry = plt->entries + index;
2270 			    value = entry->red;
2271 			}
2272 		      *p_out++ = value;	/* red */
2273 		      *p_out++ = value;	/* green */
2274 		      *p_out++ = value;	/* blue */
2275 		      if (value == bg_red)
2276 			  *p_out++ = 0;	/* Transparent */
2277 		      else
2278 			  *p_out++ = 255;	/* Opaque */
2279 		  }
2280 	    }
2281       }
2282     else
2283 	goto error;
2284     free (pixels);
2285     return 1;
2286 
2287   error:
2288     free (pixels);
2289     return 0;
2290 }
2291 
2292 RL2_PRIVATE int
get_rgba_from_grayscale_mask(unsigned int width,unsigned int height,unsigned char * pixels,unsigned char * mask,rl2PrivPixelPtr no_data,unsigned char * rgba)2293 get_rgba_from_grayscale_mask (unsigned int width, unsigned int height,
2294 			      unsigned char *pixels, unsigned char *mask,
2295 			      rl2PrivPixelPtr no_data, unsigned char *rgba)
2296 {
2297 /* input: Grayscale    output: Grayscale */
2298     unsigned char *p_in;
2299     unsigned char *p_out;
2300     unsigned char *p_msk;
2301     unsigned int row;
2302     unsigned int col;
2303     int transparent;
2304 
2305     p_in = pixels;
2306     p_out = rgba;
2307     p_msk = mask;
2308     for (row = 0; row < height; row++)
2309       {
2310 	  for (col = 0; col < width; col++)
2311 	    {
2312 		transparent = 0;
2313 		if (p_msk != NULL)
2314 		  {
2315 		      if (*p_msk++ == 0)
2316 			  transparent = 1;
2317 		  }
2318 		if (!transparent)
2319 		    transparent = test_no_data_8 (no_data, p_in);
2320 		if (transparent)
2321 		  {
2322 		      p_out += 4;
2323 		      p_in++;
2324 		  }
2325 		else
2326 		  {
2327 		      unsigned char gray = *p_in++;
2328 		      *p_out++ = gray;	/* red */
2329 		      *p_out++ = gray;	/* green */
2330 		      *p_out++ = gray;	/* blue */
2331 		      *p_out++ = 255;	/* opaque */
2332 		  }
2333 	    }
2334       }
2335     free (pixels);
2336     if (mask != NULL)
2337 	free (mask);
2338     return 1;
2339 }
2340 
2341 RL2_PRIVATE int
get_rgba_from_grayscale_opaque(unsigned int width,unsigned int height,unsigned char * pixels,unsigned char * rgba)2342 get_rgba_from_grayscale_opaque (unsigned int width, unsigned int height,
2343 				unsigned char *pixels, unsigned char *rgba)
2344 {
2345 /* input: Grayscale    output: Grayscale */
2346     unsigned char *p_in;
2347     unsigned char *p_out;
2348     unsigned int row;
2349     unsigned int col;
2350 
2351     p_in = pixels;
2352     p_out = rgba;
2353     for (row = 0; row < height; row++)
2354       {
2355 	  for (col = 0; col < width; col++)
2356 	    {
2357 		unsigned char gray = *p_in++;
2358 		*p_out++ = gray;	/* red */
2359 		*p_out++ = gray;	/* green */
2360 		*p_out++ = gray;	/* blue */
2361 		*p_out++ = 255;	/* alpha */
2362 	    }
2363       }
2364     free (pixels);
2365     return 1;
2366 }
2367 
2368 RL2_PRIVATE int
get_rgba_from_grayscale_transparent(unsigned int width,unsigned int height,unsigned char * pixels,unsigned char * rgba,unsigned char bg_gray)2369 get_rgba_from_grayscale_transparent (unsigned int width,
2370 				     unsigned int height,
2371 				     unsigned char *pixels, unsigned char *rgba,
2372 				     unsigned char bg_gray)
2373 {
2374 /* input: Grayscale    output: Grayscale */
2375     unsigned char *p_in;
2376     unsigned char *p_out;
2377     unsigned int row;
2378     unsigned int col;
2379 
2380     p_in = pixels;
2381     p_out = rgba;
2382     for (row = 0; row < height; row++)
2383       {
2384 	  for (col = 0; col < width; col++)
2385 	    {
2386 		unsigned char gray = *p_in++;
2387 		*p_out++ = gray;	/* red */
2388 		*p_out++ = gray;	/* green */
2389 		*p_out++ = gray;	/* blue */
2390 		if (gray == bg_gray)
2391 		    *p_out++ = 0;	/* Transparent */
2392 		else
2393 		    *p_out++ = 255;	/* Opaque */
2394 	    }
2395       }
2396     free (pixels);
2397     return 1;
2398 }
2399 
2400 RL2_PRIVATE int
get_rgba_from_rgb_mask(unsigned int width,unsigned int height,unsigned char * pixels,unsigned char * mask,rl2PrivPixelPtr no_data,unsigned char * rgba)2401 get_rgba_from_rgb_mask (unsigned int width, unsigned int height,
2402 			unsigned char *pixels, unsigned char *mask,
2403 			rl2PrivPixelPtr no_data, unsigned char *rgba)
2404 {
2405 /* input: RGB    output: RGB */
2406     unsigned char *p_in;
2407     unsigned char *p_out;
2408     unsigned char *p_msk;
2409     unsigned int row;
2410     unsigned int col;
2411     int transparent;
2412 
2413     p_in = pixels;
2414     p_out = rgba;
2415     p_msk = mask;
2416     for (row = 0; row < height; row++)
2417       {
2418 	  for (col = 0; col < width; col++)
2419 	    {
2420 		transparent = 0;
2421 		if (p_msk != NULL)
2422 		  {
2423 		      if (*p_msk++ == 0)
2424 			  transparent = 1;
2425 		  }
2426 		if (!transparent)
2427 		    transparent = test_no_data_8 (no_data, p_in);
2428 		if (transparent)
2429 		  {
2430 		      p_out += 4;
2431 		      p_in += 3;
2432 		  }
2433 		else
2434 		  {
2435 		      *p_out++ = *p_in++;	/* red */
2436 		      *p_out++ = *p_in++;	/* green */
2437 		      *p_out++ = *p_in++;	/* blue */
2438 		      *p_out++ = 255;	/* opaque */
2439 		  }
2440 	    }
2441       }
2442     free (pixels);
2443     if (mask != NULL)
2444 	free (mask);
2445     return 1;
2446 }
2447 
2448 RL2_PRIVATE int
get_rgba_from_rgb_opaque(unsigned int width,unsigned int height,unsigned char * pixels,unsigned char * rgba)2449 get_rgba_from_rgb_opaque (unsigned int width, unsigned int height,
2450 			  unsigned char *pixels, unsigned char *rgba)
2451 {
2452 /* input: RGB    output: RGB */
2453     unsigned char *p_in;
2454     unsigned char *p_out;
2455     unsigned int row;
2456     unsigned int col;
2457 
2458     p_in = pixels;
2459     p_out = rgba;
2460     for (row = 0; row < height; row++)
2461       {
2462 	  for (col = 0; col < width; col++)
2463 	    {
2464 		*p_out++ = *p_in++;	/* red */
2465 		*p_out++ = *p_in++;	/* green */
2466 		*p_out++ = *p_in++;	/* blue */
2467 		*p_out++ = 255;	/* alpha */
2468 	    }
2469       }
2470     free (pixels);
2471     return 1;
2472 }
2473 
2474 RL2_PRIVATE int
get_rgba_from_rgb_transparent(unsigned int width,unsigned int height,unsigned char * pixels,unsigned char * rgba,unsigned char bg_red,unsigned char bg_green,unsigned char bg_blue)2475 get_rgba_from_rgb_transparent (unsigned int width, unsigned int height,
2476 			       unsigned char *pixels, unsigned char *rgba,
2477 			       unsigned char bg_red, unsigned char bg_green,
2478 			       unsigned char bg_blue)
2479 {
2480 /* input: RGB    output: RGB */
2481     unsigned char *p_in;
2482     unsigned char *p_out;
2483     unsigned int row;
2484     unsigned int col;
2485 
2486     p_in = pixels;
2487     p_out = rgba;
2488     for (row = 0; row < height; row++)
2489       {
2490 	  for (col = 0; col < width; col++)
2491 	    {
2492 		unsigned char red = *p_in++;
2493 		unsigned char green = *p_in++;
2494 		unsigned char blue = *p_in++;
2495 		*p_out++ = red;
2496 		*p_out++ = green;
2497 		*p_out++ = blue;
2498 		if (red == bg_red && green == bg_green && blue == bg_blue)
2499 		    *p_out++ = 0;	/* Transparent */
2500 		else
2501 		    *p_out++ = 255;	/* Opaque */
2502 	    }
2503       }
2504     free (pixels);
2505     return 1;
2506 }
2507 
2508 RL2_PRIVATE int
rgba_from_int8(unsigned int width,unsigned int height,char * pixels,unsigned char * mask,unsigned char * rgba)2509 rgba_from_int8 (unsigned int width, unsigned int height,
2510 		char *pixels, unsigned char *mask, unsigned char *rgba)
2511 {
2512 /* input: DataGrid INT8   output: Grayscale */
2513     char *p_in;
2514     unsigned char *p_out;
2515     unsigned char *p_msk;
2516     unsigned int row;
2517     unsigned int col;
2518     int transparent;
2519 
2520     p_in = pixels;
2521     p_out = rgba;
2522     p_msk = mask;
2523     for (row = 0; row < height; row++)
2524       {
2525 	  for (col = 0; col < width; col++)
2526 	    {
2527 		char gray = 128 + *p_in++;
2528 		transparent = 0;
2529 		if (p_msk != NULL)
2530 		  {
2531 		      if (*p_msk++ == 0)
2532 			  transparent = 1;
2533 		  }
2534 		if (transparent)
2535 		    p_out += 4;
2536 		else
2537 		  {
2538 		      *p_out++ = gray;	/* red */
2539 		      *p_out++ = gray;	/* green */
2540 		      *p_out++ = gray;	/* blue */
2541 		      *p_out++ = 255;	/* opaque */
2542 		  }
2543 	    }
2544       }
2545     free (pixels);
2546     if (mask != NULL)
2547 	free (mask);
2548     return 1;
2549 }
2550 
2551 RL2_PRIVATE int
rgba_from_uint8(unsigned int width,unsigned int height,unsigned char * pixels,unsigned char * mask,unsigned char * rgba)2552 rgba_from_uint8 (unsigned int width, unsigned int height,
2553 		 unsigned char *pixels, unsigned char *mask,
2554 		 unsigned char *rgba)
2555 {
2556 /* input: DataGrid UINT8   output: Grayscale */
2557     unsigned char *p_in;
2558     unsigned char *p_out;
2559     unsigned char *p_msk;
2560     unsigned int row;
2561     unsigned int col;
2562     int transparent;
2563 
2564     p_in = pixels;
2565     p_out = rgba;
2566     p_msk = mask;
2567     for (row = 0; row < height; row++)
2568       {
2569 	  for (col = 0; col < width; col++)
2570 	    {
2571 		unsigned char gray = *p_in++;
2572 		transparent = 0;
2573 		if (p_msk != NULL)
2574 		  {
2575 		      if (*p_msk++ == 0)
2576 			  transparent = 1;
2577 		  }
2578 		if (transparent)
2579 		    p_out += 4;
2580 		else
2581 		  {
2582 		      *p_out++ = gray;	/* red */
2583 		      *p_out++ = gray;	/* green */
2584 		      *p_out++ = gray;	/* blue */
2585 		      *p_out++ = 255;	/* opaque */
2586 		  }
2587 	    }
2588       }
2589     free (pixels);
2590     if (mask != NULL)
2591 	free (mask);
2592     return 1;
2593 }
2594 
2595 RL2_PRIVATE int
rgba_from_int16(unsigned int width,unsigned int height,short * pixels,unsigned char * mask,unsigned char * rgba)2596 rgba_from_int16 (unsigned int width, unsigned int height,
2597 		 short *pixels, unsigned char *mask, unsigned char *rgba)
2598 {
2599 /* input: DataGrid INT16   output: Grayscale */
2600     short *p_in;
2601     unsigned char *p_out;
2602     unsigned char *p_msk;
2603     unsigned int row;
2604     unsigned int col;
2605     short min = SHRT_MAX;
2606     short max = SHRT_MIN;
2607     double min2;
2608     double max2;
2609     double tic;
2610     double tic2;
2611     int transparent;
2612     int i;
2613     int sum;
2614     int total;
2615     double percentile2;
2616     int histogram[1024];
2617 
2618 /* identifying Min/Max values */
2619     total = 0;
2620     p_in = pixels;
2621     p_msk = mask;
2622     for (row = 0; row < height; row++)
2623       {
2624 	  for (col = 0; col < width; col++)
2625 	    {
2626 		short gray = *p_in++;
2627 		if (p_msk != NULL)
2628 		  {
2629 		      if (*p_msk++ == 0)
2630 			  continue;
2631 		  }
2632 		if (min > gray)
2633 		    min = gray;
2634 		if (max < gray)
2635 		    max = gray;
2636 		total++;
2637 	    }
2638       }
2639     tic = (double) (max - min) / 1024.0;
2640     percentile2 = ((double) total / 100.0) * 2.0;
2641 
2642 /* building an histogram */
2643     for (i = 0; i < 1024; i++)
2644 	histogram[i] = 0;
2645     p_in = pixels;
2646     p_msk = mask;
2647     for (row = 0; row < height; row++)
2648       {
2649 	  for (col = 0; col < width; col++)
2650 	    {
2651 		double gray = (double) (*p_in++ - min) / tic;
2652 		if (p_msk != NULL)
2653 		  {
2654 		      if (*p_msk++ == 0)
2655 			  continue;
2656 		  }
2657 		if (gray < 0.0)
2658 		    gray = 0.0;
2659 		if (gray > 1023.0)
2660 		    gray = 1023.0;
2661 		histogram[(int) gray] += 1;
2662 	    }
2663       }
2664     sum = 0;
2665     for (i = 0; i < 1024; i++)
2666       {
2667 	  sum += histogram[i];
2668 	  if (sum >= percentile2)
2669 	    {
2670 		min2 = (double) min + ((double) i * tic);
2671 		break;
2672 	    }
2673       }
2674     sum = 0;
2675     for (i = 1023; i >= 0; i--)
2676       {
2677 	  sum += histogram[i];
2678 	  if (sum >= percentile2)
2679 	    {
2680 		max2 = (double) min + ((double) (i + 1) * tic);
2681 		break;
2682 	    }
2683       }
2684     tic2 = (double) (max2 - min2) / 254.0;
2685 
2686 /* rescaling gray-values 0-255 */
2687     p_in = pixels;
2688     p_out = rgba;
2689     p_msk = mask;
2690     for (row = 0; row < height; row++)
2691       {
2692 	  for (col = 0; col < width; col++)
2693 	    {
2694 		transparent = 0;
2695 		if (p_msk != NULL)
2696 		  {
2697 		      if (*p_msk++ == 0)
2698 			  transparent = 1;
2699 		  }
2700 		if (transparent)
2701 		  {
2702 		      p_in++;
2703 		      p_out += 4;
2704 		  }
2705 		else
2706 		  {
2707 		      double gray;
2708 		      short val = *p_in++;
2709 		      if (val <= min2)
2710 			  gray = 0.0;
2711 		      else if (val >= max2)
2712 			  gray = 255.0;
2713 		      else
2714 			  gray = 1.0 + (((double) val - min2) / tic2);
2715 		      if (gray < 0.0)
2716 			  gray = 0.0;
2717 		      if (gray > 255.0)
2718 			  gray = 255.0;
2719 		      *p_out++ = (unsigned char) gray;	/* red */
2720 		      *p_out++ = (unsigned char) gray;	/* green */
2721 		      *p_out++ = (unsigned char) gray;	/* blue */
2722 		      *p_out++ = 255;	/* opaque */
2723 		  }
2724 	    }
2725       }
2726     free (pixels);
2727     if (mask != NULL)
2728 	free (mask);
2729     return 1;
2730 }
2731 
2732 RL2_PRIVATE int
rgba_from_uint16(unsigned int width,unsigned int height,unsigned short * pixels,unsigned char * mask,unsigned char * rgba)2733 rgba_from_uint16 (unsigned int width, unsigned int height,
2734 		  unsigned short *pixels, unsigned char *mask,
2735 		  unsigned char *rgba)
2736 {
2737 /* input: DataGrid UINT16   output: Grayscale */
2738     unsigned short *p_in;
2739     unsigned char *p_out;
2740     unsigned char *p_msk;
2741     unsigned int row;
2742     unsigned int col;
2743     unsigned short min = USHRT_MAX;
2744     unsigned short max = 0;
2745     double min2;
2746     double max2;
2747     double tic;
2748     double tic2;
2749     int transparent;
2750     int i;
2751     int sum;
2752     int total;
2753     double percentile2;
2754     int histogram[1024];
2755 
2756 /* identifying Min/Max values */
2757     total = 0;
2758     p_in = pixels;
2759     p_msk = mask;
2760     for (row = 0; row < height; row++)
2761       {
2762 	  for (col = 0; col < width; col++)
2763 	    {
2764 		unsigned short gray = *p_in++;
2765 		if (p_msk != NULL)
2766 		  {
2767 		      if (*p_msk++ == 0)
2768 			  continue;
2769 		  }
2770 		if (min > gray)
2771 		    min = gray;
2772 		if (max < gray)
2773 		    max = gray;
2774 		total++;
2775 	    }
2776       }
2777     tic = (double) (max - min) / 1024.0;
2778     percentile2 = ((double) total / 100.0) * 2.0;
2779 
2780 /* building an histogram */
2781     for (i = 0; i < 1024; i++)
2782 	histogram[i] = 0;
2783     p_in = pixels;
2784     p_msk = mask;
2785     for (row = 0; row < height; row++)
2786       {
2787 	  for (col = 0; col < width; col++)
2788 	    {
2789 		double gray = (double) (*p_in++ - min) / tic;
2790 		if (p_msk != NULL)
2791 		  {
2792 		      if (*p_msk++ == 0)
2793 			  continue;
2794 		  }
2795 		if (gray < 0.0)
2796 		    gray = 0.0;
2797 		if (gray > 1023.0)
2798 		    gray = 1023.0;
2799 		histogram[(int) gray] += 1;
2800 	    }
2801       }
2802     sum = 0;
2803     for (i = 0; i < 1024; i++)
2804       {
2805 	  sum += histogram[i];
2806 	  if (sum >= percentile2)
2807 	    {
2808 		min2 = (double) min + ((double) i * tic);
2809 		break;
2810 	    }
2811       }
2812     sum = 0;
2813     for (i = 1023; i >= 0; i--)
2814       {
2815 	  sum += histogram[i];
2816 	  if (sum >= percentile2)
2817 	    {
2818 		max2 = (double) min + ((double) (i + 1) * tic);
2819 		break;
2820 	    }
2821       }
2822     tic2 = (double) (max2 - min2) / 254.0;
2823 
2824 /* rescaling gray-values 0-255 */
2825     p_in = pixels;
2826     p_out = rgba;
2827     p_msk = mask;
2828     for (row = 0; row < height; row++)
2829       {
2830 	  for (col = 0; col < width; col++)
2831 	    {
2832 		transparent = 0;
2833 		if (p_msk != NULL)
2834 		  {
2835 		      if (*p_msk++ == 0)
2836 			  transparent = 1;
2837 		  }
2838 		if (transparent)
2839 		  {
2840 		      p_in++;
2841 		      p_out += 4;
2842 		  }
2843 		else
2844 		  {
2845 		      double gray;
2846 		      unsigned short val = *p_in++;
2847 		      if (val <= min2)
2848 			  gray = 0.0;
2849 		      else if (val >= max2)
2850 			  gray = 255.0;
2851 		      else
2852 			  gray = 1.0 + (((double) val - min2) / tic2);
2853 		      if (gray < 0.0)
2854 			  gray = 0.0;
2855 		      if (gray > 255.0)
2856 			  gray = 255.0;
2857 		      *p_out++ = (unsigned char) gray;	/* red */
2858 		      *p_out++ = (unsigned char) gray;	/* green */
2859 		      *p_out++ = (unsigned char) gray;	/* blue */
2860 		      *p_out++ = 255;	/* opaque */
2861 		  }
2862 	    }
2863       }
2864     free (pixels);
2865     if (mask != NULL)
2866 	free (mask);
2867     return 1;
2868 }
2869 
2870 RL2_PRIVATE int
rgba_from_int32(unsigned int width,unsigned int height,int * pixels,unsigned char * mask,unsigned char * rgba)2871 rgba_from_int32 (unsigned int width, unsigned int height,
2872 		 int *pixels, unsigned char *mask, unsigned char *rgba)
2873 {
2874 /* input: DataGrid INT32   output: Grayscale */
2875     int *p_in;
2876     unsigned char *p_out;
2877     unsigned char *p_msk;
2878     unsigned int row;
2879     unsigned int col;
2880     int min = INT_MAX;
2881     int max = INT_MIN;
2882     double min2;
2883     double max2;
2884     double tic;
2885     double tic2;
2886     int transparent;
2887     int i;
2888     int sum;
2889     int total;
2890     double percentile2;
2891     int histogram[1024];
2892 
2893 /* identifying Min/Max values */
2894     total = 0;
2895     p_in = pixels;
2896     p_msk = mask;
2897     for (row = 0; row < height; row++)
2898       {
2899 	  for (col = 0; col < width; col++)
2900 	    {
2901 		int gray = *p_in++;
2902 		if (p_msk != NULL)
2903 		  {
2904 		      if (*p_msk++ == 0)
2905 			  continue;
2906 		  }
2907 		if (min > gray)
2908 		    min = gray;
2909 		if (max < gray)
2910 		    max = gray;
2911 		total++;
2912 	    }
2913       }
2914     tic = (double) (max - min) / 1024.0;
2915     percentile2 = ((double) total / 100.0) * 2.0;
2916 
2917 /* building an histogram */
2918     for (i = 0; i < 1024; i++)
2919 	histogram[i] = 0;
2920     p_in = pixels;
2921     p_msk = mask;
2922     for (row = 0; row < height; row++)
2923       {
2924 	  for (col = 0; col < width; col++)
2925 	    {
2926 		double gray = (double) (*p_in++ - min) / tic;
2927 		if (p_msk != NULL)
2928 		  {
2929 		      if (*p_msk++ == 0)
2930 			  continue;
2931 		  }
2932 		if (gray < 0.0)
2933 		    gray = 0.0;
2934 		if (gray > 1023.0)
2935 		    gray = 1023.0;
2936 		histogram[(int) gray] += 1;
2937 	    }
2938       }
2939     sum = 0;
2940     for (i = 0; i < 1024; i++)
2941       {
2942 	  sum += histogram[i];
2943 	  if (sum >= percentile2)
2944 	    {
2945 		min2 = (double) min + ((double) i * tic);
2946 		break;
2947 	    }
2948       }
2949     sum = 0;
2950     for (i = 1023; i >= 0; i--)
2951       {
2952 	  sum += histogram[i];
2953 	  if (sum >= percentile2)
2954 	    {
2955 		max2 = (double) min + ((double) (i + 1) * tic);
2956 		break;
2957 	    }
2958       }
2959     tic2 = (double) (max2 - min2) / 254.0;
2960 
2961 /* rescaling gray-values 0-255 */
2962     p_in = pixels;
2963     p_out = rgba;
2964     p_msk = mask;
2965     for (row = 0; row < height; row++)
2966       {
2967 	  for (col = 0; col < width; col++)
2968 	    {
2969 		transparent = 0;
2970 		if (p_msk != NULL)
2971 		  {
2972 		      if (*p_msk++ == 0)
2973 			  transparent = 1;
2974 		  }
2975 		if (transparent)
2976 		  {
2977 		      p_in++;
2978 		      p_out += 4;
2979 		  }
2980 		else
2981 		  {
2982 		      double gray;
2983 		      int val = *p_in++;
2984 		      if (val <= min2)
2985 			  gray = 0.0;
2986 		      else if (val >= max2)
2987 			  gray = 255.0;
2988 		      else
2989 			  gray = 1.0 + (((double) val - min2) / tic2);
2990 		      if (gray < 0.0)
2991 			  gray = 0.0;
2992 		      if (gray > 255.0)
2993 			  gray = 255.0;
2994 		      *p_out++ = (unsigned char) gray;	/* red */
2995 		      *p_out++ = (unsigned char) gray;	/* green */
2996 		      *p_out++ = (unsigned char) gray;	/* blue */
2997 		      *p_out++ = 255;	/* opaque */
2998 		  }
2999 	    }
3000       }
3001     free (pixels);
3002     if (mask != NULL)
3003 	free (mask);
3004     return 1;
3005 }
3006 
3007 RL2_PRIVATE int
rgba_from_uint32(unsigned int width,unsigned int height,unsigned int * pixels,unsigned char * mask,unsigned char * rgba)3008 rgba_from_uint32 (unsigned int width, unsigned int height,
3009 		  unsigned int *pixels, unsigned char *mask,
3010 		  unsigned char *rgba)
3011 {
3012 /* input: DataGrid UINT32   output: Grayscale */
3013     unsigned int *p_in;
3014     unsigned char *p_out;
3015     unsigned char *p_msk;
3016     unsigned int row;
3017     unsigned int col;
3018     unsigned int min = UINT_MAX;
3019     unsigned int max = 0;
3020     double min2;
3021     double max2;
3022     double tic;
3023     double tic2;
3024     int transparent;
3025     int i;
3026     int sum;
3027     int total;
3028     double percentile2;
3029     int histogram[1024];
3030 
3031 /* identifying Min/Max values */
3032     total = 0;
3033     p_in = pixels;
3034     p_msk = mask;
3035     for (row = 0; row < height; row++)
3036       {
3037 	  for (col = 0; col < width; col++)
3038 	    {
3039 		unsigned int gray = *p_in++;
3040 		if (p_msk != NULL)
3041 		  {
3042 		      if (*p_msk++ == 0)
3043 			  continue;
3044 		  }
3045 		if (min > gray)
3046 		    min = gray;
3047 		if (max < gray)
3048 		    max = gray;
3049 		total++;
3050 	    }
3051       }
3052     tic = (double) (max - min) / 1024.0;
3053     percentile2 = ((double) total / 100.0) * 2.0;
3054 
3055 /* building an histogram */
3056     for (i = 0; i < 1024; i++)
3057 	histogram[i] = 0;
3058     p_in = pixels;
3059     p_msk = mask;
3060     for (row = 0; row < height; row++)
3061       {
3062 	  for (col = 0; col < width; col++)
3063 	    {
3064 		double gray = (double) (*p_in++ - min) / tic;
3065 		if (p_msk != NULL)
3066 		  {
3067 		      if (*p_msk++ == 0)
3068 			  continue;
3069 		  }
3070 		if (gray < 0.0)
3071 		    gray = 0.0;
3072 		if (gray > 1023.0)
3073 		    gray = 1023.0;
3074 		histogram[(int) gray] += 1;
3075 	    }
3076       }
3077     sum = 0;
3078     for (i = 0; i < 1024; i++)
3079       {
3080 	  sum += histogram[i];
3081 	  if (sum >= percentile2)
3082 	    {
3083 		min2 = (double) min + ((double) i * tic);
3084 		break;
3085 	    }
3086       }
3087     sum = 0;
3088     for (i = 1023; i >= 0; i--)
3089       {
3090 	  sum += histogram[i];
3091 	  if (sum >= percentile2)
3092 	    {
3093 		max2 = (double) min + ((double) (i + 1) * tic);
3094 		break;
3095 	    }
3096       }
3097     tic2 = (double) (max2 - min2) / 254.0;
3098 
3099 /* rescaling gray-values 0-255 */
3100     p_in = pixels;
3101     p_out = rgba;
3102     p_msk = mask;
3103     for (row = 0; row < height; row++)
3104       {
3105 	  for (col = 0; col < width; col++)
3106 	    {
3107 		transparent = 0;
3108 		if (p_msk != NULL)
3109 		  {
3110 		      if (*p_msk++ == 0)
3111 			  transparent = 1;
3112 		  }
3113 		if (transparent)
3114 		  {
3115 		      p_in++;
3116 		      p_out += 4;
3117 		  }
3118 		else
3119 		  {
3120 		      double gray;
3121 		      unsigned int val = *p_in++;
3122 		      if (val <= min2)
3123 			  gray = 0.0;
3124 		      else if (val >= max2)
3125 			  gray = 255.0;
3126 		      else
3127 			  gray = 1.0 + (((double) val - min2) / tic2);
3128 		      if (gray < 0.0)
3129 			  gray = 0.0;
3130 		      if (gray > 255.0)
3131 			  gray = 255.0;
3132 		      *p_out++ = (unsigned char) gray;	/* red */
3133 		      *p_out++ = (unsigned char) gray;	/* green */
3134 		      *p_out++ = (unsigned char) gray;	/* blue */
3135 		      *p_out++ = 255;	/* opaque */
3136 		  }
3137 	    }
3138       }
3139     free (pixels);
3140     if (mask != NULL)
3141 	free (mask);
3142     return 1;
3143 }
3144 
3145 RL2_PRIVATE int
rgba_from_float(unsigned int width,unsigned int height,float * pixels,unsigned char * mask,unsigned char * rgba)3146 rgba_from_float (unsigned int width, unsigned int height,
3147 		 float *pixels, unsigned char *mask, unsigned char *rgba)
3148 {
3149 /* input: DataGrid FLOAT   output: Grayscale */
3150     float *p_in;
3151     unsigned char *p_out;
3152     unsigned char *p_msk;
3153     unsigned int row;
3154     unsigned int col;
3155     float min = FLT_MAX;
3156     float max = 0.0 - FLT_MAX;
3157     double min2;
3158     double max2;
3159     double tic;
3160     double tic2;
3161     int transparent;
3162     int i;
3163     int sum;
3164     int total;
3165     double percentile2;
3166     int histogram[1024];
3167 
3168 /* identifying Min/Max values */
3169     total = 0;
3170     p_in = pixels;
3171     p_msk = mask;
3172     for (row = 0; row < height; row++)
3173       {
3174 	  for (col = 0; col < width; col++)
3175 	    {
3176 		float gray = *p_in++;
3177 		if (p_msk != NULL)
3178 		  {
3179 		      if (*p_msk++ == 0)
3180 			  continue;
3181 		  }
3182 		if (min > gray)
3183 		    min = gray;
3184 		if (max < gray)
3185 		    max = gray;
3186 		total++;
3187 	    }
3188       }
3189     tic = (double) (max - min) / 1024.0;
3190     percentile2 = ((double) total / 100.0) * 2.0;
3191 
3192 /* building an histogram */
3193     for (i = 0; i < 1024; i++)
3194 	histogram[i] = 0;
3195     p_in = pixels;
3196     p_msk = mask;
3197     for (row = 0; row < height; row++)
3198       {
3199 	  for (col = 0; col < width; col++)
3200 	    {
3201 		double gray = (double) (*p_in++ - min) / tic;
3202 		if (p_msk != NULL)
3203 		  {
3204 		      if (*p_msk++ == 0)
3205 			  continue;
3206 		  }
3207 		if (gray < 0.0)
3208 		    gray = 0.0;
3209 		if (gray > 1023.0)
3210 		    gray = 1023.0;
3211 		histogram[(int) gray] += 1;
3212 	    }
3213       }
3214     sum = 0;
3215     for (i = 0; i < 1024; i++)
3216       {
3217 	  sum += histogram[i];
3218 	  if (sum >= percentile2)
3219 	    {
3220 		min2 = (double) min + ((double) i * tic);
3221 		break;
3222 	    }
3223       }
3224     sum = 0;
3225     for (i = 1023; i >= 0; i--)
3226       {
3227 	  sum += histogram[i];
3228 	  if (sum >= percentile2)
3229 	    {
3230 		max2 = (double) min + ((double) (i + 1) * tic);
3231 		break;
3232 	    }
3233       }
3234     tic2 = (double) (max2 - min2) / 254.0;
3235 
3236 /* rescaling gray-values 0-255 */
3237     p_in = pixels;
3238     p_out = rgba;
3239     p_msk = mask;
3240     for (row = 0; row < height; row++)
3241       {
3242 	  for (col = 0; col < width; col++)
3243 	    {
3244 		transparent = 0;
3245 		if (p_msk != NULL)
3246 		  {
3247 		      if (*p_msk++ == 0)
3248 			  transparent = 1;
3249 		  }
3250 		if (transparent)
3251 		  {
3252 		      p_in++;
3253 		      p_out += 4;
3254 		  }
3255 		else
3256 		  {
3257 		      double gray;
3258 		      float val = *p_in++;
3259 		      if (val <= min2)
3260 			  gray = 0.0;
3261 		      else if (val >= max2)
3262 			  gray = 255.0;
3263 		      else
3264 			  gray = 1.0 + (((double) val - min2) / tic2);
3265 		      if (gray < 0.0)
3266 			  gray = 0.0;
3267 		      if (gray > 255.0)
3268 			  gray = 255.0;
3269 		      *p_out++ = (unsigned char) gray;	/* red */
3270 		      *p_out++ = (unsigned char) gray;	/* green */
3271 		      *p_out++ = (unsigned char) gray;	/* blue */
3272 		      *p_out++ = 255;	/* opaque */
3273 		  }
3274 	    }
3275       }
3276     free (pixels);
3277     if (mask != NULL)
3278 	free (mask);
3279     return 1;
3280 }
3281 
3282 RL2_PRIVATE int
rgba_from_double(unsigned int width,unsigned int height,double * pixels,unsigned char * mask,unsigned char * rgba)3283 rgba_from_double (unsigned int width, unsigned int height,
3284 		  double *pixels, unsigned char *mask, unsigned char *rgba)
3285 {
3286 /* input: DataGrid DOUBLE   output: Grayscale */
3287     double *p_in;
3288     unsigned char *p_out;
3289     unsigned char *p_msk;
3290     unsigned int row;
3291     unsigned int col;
3292     double min = DBL_MAX;
3293     double max = 0.0 - DBL_MAX;
3294     double min2;
3295     double max2;
3296     double tic;
3297     double tic2;
3298     int transparent;
3299     int i;
3300     int sum;
3301     int total;
3302     double percentile2;
3303     int histogram[1024];
3304 
3305 /* identifying Min/Max values */
3306     total = 0;
3307     p_in = pixels;
3308     p_msk = mask;
3309     for (row = 0; row < height; row++)
3310       {
3311 	  for (col = 0; col < width; col++)
3312 	    {
3313 		double gray = *p_in++;
3314 		if (p_msk != NULL)
3315 		  {
3316 		      if (*p_msk++ == 0)
3317 			  continue;
3318 		  }
3319 		if (min > gray)
3320 		    min = gray;
3321 		if (max < gray)
3322 		    max = gray;
3323 		total++;
3324 	    }
3325       }
3326     tic = (double) (max - min) / 1024.0;
3327     percentile2 = ((double) total / 100.0) * 2.0;
3328 
3329 /* building an histogram */
3330     for (i = 0; i < 1024; i++)
3331 	histogram[i] = 0;
3332     p_in = pixels;
3333     p_msk = mask;
3334     for (row = 0; row < height; row++)
3335       {
3336 	  for (col = 0; col < width; col++)
3337 	    {
3338 		double gray = (double) (*p_in++ - min) / tic;
3339 		if (p_msk != NULL)
3340 		  {
3341 		      if (*p_msk++ == 0)
3342 			  continue;
3343 		  }
3344 		if (gray < 0.0)
3345 		    gray = 0.0;
3346 		if (gray > 1023.0)
3347 		    gray = 1023.0;
3348 		histogram[(int) gray] += 1;
3349 	    }
3350       }
3351     sum = 0;
3352     for (i = 0; i < 1024; i++)
3353       {
3354 	  sum += histogram[i];
3355 	  if (sum >= percentile2)
3356 	    {
3357 		min2 = (double) min + ((double) i * tic);
3358 		break;
3359 	    }
3360       }
3361     sum = 0;
3362     for (i = 1023; i >= 0; i--)
3363       {
3364 	  sum += histogram[i];
3365 	  if (sum >= percentile2)
3366 	    {
3367 		max2 = (double) min + ((double) (i + 1) * tic);
3368 		break;
3369 	    }
3370       }
3371     tic2 = (double) (max2 - min2) / 254.0;
3372 
3373 /* rescaling gray-values 0-255 */
3374     p_in = pixels;
3375     p_out = rgba;
3376     p_msk = mask;
3377     for (row = 0; row < height; row++)
3378       {
3379 	  for (col = 0; col < width; col++)
3380 	    {
3381 		transparent = 0;
3382 		if (p_msk != NULL)
3383 		  {
3384 		      if (*p_msk++ == 0)
3385 			  transparent = 1;
3386 		  }
3387 		if (transparent)
3388 		  {
3389 		      p_in++;
3390 		      p_out += 4;
3391 		  }
3392 		else
3393 		  {
3394 		      double gray;
3395 		      double val = *p_in++;
3396 		      if (val <= min2)
3397 			  gray = 0.0;
3398 		      else if (val >= max2)
3399 			  gray = 255.0;
3400 		      else
3401 			  gray = 1.0 + (((double) val - min2) / tic2);
3402 		      if (gray < 0.0)
3403 			  gray = 0.0;
3404 		      if (gray > 255.0)
3405 			  gray = 255.0;
3406 		      *p_out++ = (unsigned char) gray;	/* red */
3407 		      *p_out++ = (unsigned char) gray;	/* green */
3408 		      *p_out++ = (unsigned char) gray;	/* blue */
3409 		      *p_out++ = 255;	/* opaque */
3410 		  }
3411 	    }
3412       }
3413     free (pixels);
3414     if (mask != NULL)
3415 	free (mask);
3416     return 1;
3417 }
3418 
3419 RL2_PRIVATE int
get_rgba_from_datagrid_mask(unsigned int width,unsigned int height,unsigned char sample_type,void * pixels,unsigned char * mask,rl2PrivPixelPtr no_data,unsigned char * rgba)3420 get_rgba_from_datagrid_mask (unsigned int width, unsigned int height,
3421 			     unsigned char sample_type, void *pixels,
3422 			     unsigned char *mask, rl2PrivPixelPtr no_data,
3423 			     unsigned char *rgba)
3424 {
3425 /* input: DataGrid    output: Grayscale */
3426     int ret = 0;
3427     switch (sample_type)
3428       {
3429       case RL2_SAMPLE_INT8:
3430 	  ret = rgba_from_int8 (width, height, (char *) pixels, mask, rgba);
3431 	  break;
3432       case RL2_SAMPLE_UINT8:
3433 	  ret =
3434 	      rgba_from_uint8 (width, height, (unsigned char *) pixels, mask,
3435 			       rgba);
3436 	  break;
3437       case RL2_SAMPLE_INT16:
3438 	  ret = rgba_from_int16 (width, height, (short *) pixels, mask, rgba);
3439 	  break;
3440       case RL2_SAMPLE_UINT16:
3441 	  ret =
3442 	      rgba_from_uint16 (width, height, (unsigned short *) pixels, mask,
3443 				rgba);
3444 	  break;
3445       case RL2_SAMPLE_INT32:
3446 	  ret = rgba_from_int32 (width, height, (int *) pixels, mask, rgba);
3447 	  break;
3448       case RL2_SAMPLE_UINT32:
3449 	  ret =
3450 	      rgba_from_uint32 (width, height, (unsigned int *) pixels, mask,
3451 				rgba);
3452 	  break;
3453       case RL2_SAMPLE_FLOAT:
3454 	  ret = rgba_from_float (width, height, (float *) pixels, mask, rgba);
3455 	  break;
3456       case RL2_SAMPLE_DOUBLE:
3457 	  ret = rgba_from_double (width, height, (double *) pixels, mask, rgba);
3458 	  break;
3459       };
3460     return ret;
3461 }
3462 
3463 RL2_PRIVATE int
get_payload_from_gray_rgba_opaque(unsigned int width,unsigned int height,sqlite3 * handle,double minx,double miny,double maxx,double maxy,int srid,unsigned char * rgb,unsigned char format,int quality,unsigned char ** image,int * image_sz)3464 get_payload_from_gray_rgba_opaque (unsigned int width, unsigned int height,
3465 				   sqlite3 * handle, double minx, double miny,
3466 				   double maxx, double maxy, int srid,
3467 				   unsigned char *rgb, unsigned char format,
3468 				   int quality, unsigned char **image,
3469 				   int *image_sz)
3470 {
3471 /* Grayscale, Opaque */
3472     int ret;
3473     unsigned char *p_in;
3474     unsigned char *p_out;
3475     unsigned int row;
3476     unsigned int col;
3477     unsigned char *rgba = NULL;
3478     unsigned char *gray = malloc (width * height);
3479 
3480     if (gray == NULL)
3481 	goto error;
3482     p_in = rgb;
3483     p_out = gray;
3484     for (row = 0; row < height; row++)
3485       {
3486 	  for (col = 0; col < width; col++)
3487 	    {
3488 		*p_out++ = *p_in++;
3489 		p_in += 2;
3490 	    }
3491       }
3492     free (rgb);
3493     rgb = NULL;
3494     if (format == RL2_OUTPUT_FORMAT_JPEG)
3495       {
3496 	  if (rl2_gray_to_jpeg (width, height, gray, quality, image, image_sz)
3497 	      != RL2_OK)
3498 	      goto error;
3499       }
3500     else if (format == RL2_OUTPUT_FORMAT_PNG)
3501       {
3502 	  if (rl2_gray_to_png (width, height, gray, image, image_sz) != RL2_OK)
3503 	      goto error;
3504       }
3505     else if (format == RL2_OUTPUT_FORMAT_TIFF)
3506       {
3507 	  if (srid > 0)
3508 	    {
3509 		if (rl2_gray_to_geotiff
3510 		    (width, height, handle, minx, miny, maxx, maxy, srid, gray,
3511 		     image, image_sz) != RL2_OK)
3512 		    goto error;
3513 	    }
3514 	  else
3515 	    {
3516 		if (rl2_gray_to_tiff (width, height, gray, image, image_sz) !=
3517 		    RL2_OK)
3518 		    goto error;
3519 	    }
3520       }
3521     else if (format == RL2_OUTPUT_FORMAT_PDF)
3522       {
3523 	  rgba = gray_to_rgba (width, height, gray);
3524 	  if (rgba == NULL)
3525 	      goto error;
3526 	  ret = rl2_rgba_to_pdf (width, height, rgba, image, image_sz);
3527 	  rgba = NULL;
3528 	  if (ret != RL2_OK)
3529 	      goto error;
3530       }
3531     else
3532 	goto error;
3533     free (gray);
3534     return 1;
3535   error:
3536     free (rgb);
3537     if (gray != NULL)
3538 	free (gray);
3539     if (rgba != NULL)
3540 	free (rgba);
3541     return 0;
3542 }
3543 
3544 RL2_PRIVATE int
get_payload_from_gray_rgba_transparent(unsigned int width,unsigned int height,unsigned char * rgb,unsigned char * alpha,unsigned char format,int quality,unsigned char ** image,int * image_sz,double opacity)3545 get_payload_from_gray_rgba_transparent (unsigned int width,
3546 					unsigned int height,
3547 					unsigned char *rgb,
3548 					unsigned char *alpha,
3549 					unsigned char format, int quality,
3550 					unsigned char **image, int *image_sz,
3551 					double opacity)
3552 {
3553 /* Grayscale, Transparent */
3554     unsigned char *p_in;
3555     unsigned char *p_out;
3556     unsigned char *p_msk;
3557     unsigned char *p_alpha;
3558     unsigned short row;
3559     unsigned short col;
3560     unsigned char *gray = malloc (width * height);
3561     unsigned char *mask = malloc (width * height);
3562 
3563     if (quality > 100)
3564 	quality = 100;
3565     if (gray == NULL)
3566 	goto error;
3567     if (mask == NULL)
3568 	goto error;
3569     p_in = rgb;
3570     p_out = gray;
3571     p_msk = mask;
3572     p_alpha = alpha;
3573     for (row = 0; row < height; row++)
3574       {
3575 	  for (col = 0; col < width; col++)
3576 	    {
3577 		*p_out++ = *p_in++;
3578 		p_in += 2;
3579 		if (*p_alpha++ >= 128)
3580 		    *p_msk++ = 1;	/* Opaque */
3581 		else
3582 		    *p_msk++ = 0;	/* Transparent */
3583 	    }
3584       }
3585     free (rgb);
3586     rgb = NULL;
3587     free (alpha);
3588     alpha = NULL;
3589     if (format == RL2_OUTPUT_FORMAT_PNG)
3590       {
3591 	  if (rl2_gray_alpha_to_png
3592 	      (width, height, gray, mask, image, image_sz, opacity) != RL2_OK)
3593 	      goto error;
3594       }
3595     else
3596 	goto error;
3597     free (gray);
3598     free (mask);
3599     return 1;
3600   error:
3601     free (rgb);
3602     if (gray != NULL)
3603 	free (gray);
3604     if (mask != NULL)
3605 	free (mask);
3606     return 0;
3607 }
3608 
3609 RL2_PRIVATE int
get_payload_from_rgb_rgba_opaque(unsigned int width,unsigned int height,sqlite3 * handle,double minx,double miny,double maxx,double maxy,int srid,unsigned char * rgb,unsigned char format,int quality,unsigned char ** image,int * image_sz)3610 get_payload_from_rgb_rgba_opaque (unsigned int width, unsigned int height,
3611 				  sqlite3 * handle, double minx, double miny,
3612 				  double maxx, double maxy, int srid,
3613 				  unsigned char *rgb, unsigned char format,
3614 				  int quality, unsigned char **image,
3615 				  int *image_sz)
3616 {
3617 /* RGB, Opaque */
3618     int ret;
3619     unsigned char *rgba = NULL;
3620 
3621     if (format == RL2_OUTPUT_FORMAT_JPEG)
3622       {
3623 	  if (rl2_rgb_to_jpeg (width, height, rgb, quality, image, image_sz) !=
3624 	      RL2_OK)
3625 	      goto error;
3626       }
3627     else if (format == RL2_OUTPUT_FORMAT_PNG)
3628       {
3629 	  if (rl2_rgb_to_png (width, height, rgb, image, image_sz) != RL2_OK)
3630 	      goto error;
3631       }
3632     else if (format == RL2_OUTPUT_FORMAT_TIFF)
3633       {
3634 	  if (srid > 0)
3635 	    {
3636 		if (rl2_rgb_to_geotiff
3637 		    (width, height, handle, minx, miny, maxx, maxy, srid, rgb,
3638 		     image, image_sz) != RL2_OK)
3639 		    goto error;
3640 	    }
3641 	  else
3642 	    {
3643 		if (rl2_rgb_to_tiff (width, height, rgb, image, image_sz) !=
3644 		    RL2_OK)
3645 		    goto error;
3646 	    }
3647       }
3648     else if (format == RL2_OUTPUT_FORMAT_PDF)
3649       {
3650 	  rgba = rgb_to_rgba (width, height, rgb);
3651 	  if (rgba == NULL)
3652 	      goto error;
3653 	  ret = rl2_rgba_to_pdf (width, height, rgba, image, image_sz);
3654 	  rgba = NULL;
3655 	  if (ret != RL2_OK)
3656 	      goto error;
3657       }
3658     else
3659 	goto error;
3660     free (rgb);
3661     return 1;
3662   error:
3663     free (rgb);
3664     if (rgba != NULL)
3665 	free (rgba);
3666     return 0;
3667 }
3668 
3669 RL2_PRIVATE int
get_payload_from_rgb_rgba_transparent(unsigned int width,unsigned int height,unsigned char * rgb,unsigned char * alpha,unsigned char format,int quality,unsigned char ** image,int * image_sz,double opacity)3670 get_payload_from_rgb_rgba_transparent (unsigned int width,
3671 				       unsigned int height,
3672 				       unsigned char *rgb, unsigned char *alpha,
3673 				       unsigned char format, int quality,
3674 				       unsigned char **image, int *image_sz,
3675 				       double opacity)
3676 {
3677 /* RGB, Transparent */
3678     unsigned char *p_msk;
3679     unsigned char *p_alpha;
3680     unsigned int row;
3681     unsigned int col;
3682     unsigned char *mask = malloc (width * height);
3683 
3684     if (quality > 100)
3685 	quality = 100;
3686     if (mask == NULL)
3687 	goto error;
3688     p_msk = mask;
3689     p_alpha = alpha;
3690     for (row = 0; row < height; row++)
3691       {
3692 	  for (col = 0; col < width; col++)
3693 	    {
3694 		if (*p_alpha++ >= 128)
3695 		    *p_msk++ = 1;	/* Opaque */
3696 		else
3697 		    *p_msk++ = 0;	/* Transparent */
3698 	    }
3699       }
3700     free (alpha);
3701     alpha = NULL;
3702     if (format == RL2_OUTPUT_FORMAT_PNG)
3703       {
3704 	  if (rl2_rgb_alpha_to_png
3705 	      (width, height, rgb, mask, image, image_sz, opacity) != RL2_OK)
3706 	      goto error;
3707       }
3708     else
3709 	goto error;
3710     free (rgb);
3711     free (mask);
3712     return 1;
3713   error:
3714     free (rgb);
3715     if (mask != NULL)
3716 	free (mask);
3717     return 0;
3718 }
3719 
3720 RL2_PRIVATE int
build_rgb_alpha(unsigned int width,unsigned int height,unsigned char * rgba,unsigned char ** rgb,unsigned char ** alpha,unsigned char bg_red,unsigned char bg_green,unsigned char bg_blue)3721 build_rgb_alpha (unsigned int width, unsigned int height,
3722 		 unsigned char *rgba, unsigned char **rgb,
3723 		 unsigned char **alpha, unsigned char bg_red,
3724 		 unsigned char bg_green, unsigned char bg_blue)
3725 {
3726 /* creating separate RGB and Alpha buffers from RGBA */
3727     unsigned int row;
3728     unsigned int col;
3729     unsigned char *p_in = rgba;
3730     unsigned char *p_out;
3731     unsigned char *p_msk;
3732 
3733     *rgb = NULL;
3734     *alpha = NULL;
3735     *rgb = malloc (width * height * 3);
3736     if (*rgb == NULL)
3737 	goto error;
3738     *alpha = malloc (width * height);
3739     if (*alpha == NULL)
3740 	goto error;
3741 
3742     p_out = *rgb;
3743     p_msk = *alpha;
3744     for (row = 0; row < height; row++)
3745       {
3746 	  for (col = 0; col < width; col++)
3747 	    {
3748 		unsigned char r = *p_in++;
3749 		unsigned char g = *p_in++;
3750 		unsigned char b = *p_in++;
3751 		unsigned char alpha = *p_in++;
3752 		*p_out++ = r;
3753 		*p_out++ = g;
3754 		*p_out++ = b;
3755 		if (r == bg_red && g == bg_green && b == bg_blue)
3756 		    alpha = 0;
3757 		*p_msk++ = alpha;
3758 	    }
3759       }
3760     return 1;
3761 
3762   error:
3763     if (*rgb != NULL)
3764 	free (*rgb);
3765     if (*alpha != NULL)
3766 	free (*alpha);
3767     *rgb = NULL;
3768     *alpha = NULL;
3769     return 0;
3770 }
3771 
3772 RL2_PRIVATE int
get_rgba_from_multiband8(unsigned int width,unsigned int height,unsigned char red_band,unsigned char green_band,unsigned char blue_band,unsigned char num_bands,unsigned char * pixels,unsigned char * mask,rl2PrivPixelPtr no_data,unsigned char * rgba)3773 get_rgba_from_multiband8 (unsigned int width, unsigned int height,
3774 			  unsigned char red_band, unsigned char green_band,
3775 			  unsigned char blue_band, unsigned char num_bands,
3776 			  unsigned char *pixels, unsigned char *mask,
3777 			  rl2PrivPixelPtr no_data, unsigned char *rgba)
3778 {
3779 /* input: MULTIBAND UINT8   output: RGB */
3780     unsigned char *p_in;
3781     unsigned char *p_out;
3782     unsigned char *p_msk;
3783     unsigned int row;
3784     unsigned int col;
3785     int transparent;
3786 
3787     p_in = pixels;
3788     p_out = rgba;
3789     p_msk = mask;
3790     for (row = 0; row < height; row++)
3791       {
3792 	  for (col = 0; col < width; col++)
3793 	    {
3794 		transparent = 0;
3795 		if (p_msk != NULL)
3796 		  {
3797 		      if (*p_msk++ == 0)
3798 			  transparent = 1;
3799 		  }
3800 		if (!transparent && no_data != NULL)
3801 		  {
3802 		      /* testing for NO-DATA */
3803 		      int match = 0;
3804 		      rl2PrivSamplePtr sample;
3805 		      unsigned char value;
3806 		      if (red_band < no_data->nBands)
3807 			{
3808 			    sample = no_data->Samples + red_band;
3809 			    value = sample->uint8;
3810 			    if (*(p_in + red_band) == value)
3811 				match++;
3812 			}
3813 		      if (green_band < no_data->nBands)
3814 			{
3815 			    sample = no_data->Samples + green_band;
3816 			    value = sample->uint8;
3817 			    if (*(p_in + green_band) == value)
3818 				match++;
3819 			}
3820 		      if (blue_band < no_data->nBands)
3821 			{
3822 			    sample = no_data->Samples + blue_band;
3823 			    value = sample->uint8;
3824 			    if (*(p_in + blue_band) == value)
3825 				match++;
3826 			}
3827 		      if (match == 3)
3828 			  transparent = 1;
3829 		  }
3830 		if (transparent)
3831 		  {
3832 		      p_out += 4;
3833 		      p_in += num_bands;
3834 		  }
3835 		else
3836 		  {
3837 		      *p_out++ = *(p_in + red_band);	/* red */
3838 		      *p_out++ = *(p_in + green_band);	/* green */
3839 		      *p_out++ = *(p_in + blue_band);	/* blue */
3840 		      *p_out++ = 255;	/* opaque */
3841 		      p_in += num_bands;
3842 		  }
3843 	    }
3844       }
3845     free (pixels);
3846     if (mask != NULL)
3847 	free (mask);
3848     return 1;
3849 }
3850 
3851 static int
test_no_data_16(rl2PrivPixelPtr no_data,unsigned short * p_in)3852 test_no_data_16 (rl2PrivPixelPtr no_data, unsigned short *p_in)
3853 {
3854 /* testing for NO-DATA */
3855     if (no_data != NULL)
3856       {
3857 	  unsigned char band;
3858 	  int match = 0;
3859 	  rl2PrivSamplePtr sample;
3860 	  for (band = 0; band < no_data->nBands; band++)
3861 	    {
3862 		sample = no_data->Samples + band;
3863 		if (*(p_in + band) == sample->uint16)
3864 		    match++;
3865 	    }
3866 	  if (match == no_data->nBands)
3867 	      return 1;
3868       }
3869     return 0;
3870 }
3871 
3872 RL2_PRIVATE int
get_rgba_from_multiband16(unsigned int width,unsigned int height,unsigned char red_band,unsigned char green_band,unsigned char blue_band,unsigned char num_bands,unsigned short * pixels,unsigned char * mask,rl2PrivPixelPtr no_data,unsigned char * rgba)3873 get_rgba_from_multiband16 (unsigned int width, unsigned int height,
3874 			   unsigned char red_band, unsigned char green_band,
3875 			   unsigned char blue_band, unsigned char num_bands,
3876 			   unsigned short *pixels, unsigned char *mask,
3877 			   rl2PrivPixelPtr no_data, unsigned char *rgba)
3878 {
3879 /* input: MULTIBAND UINT16   output: RGB */
3880     unsigned short *p_in;
3881     unsigned char *p_out;
3882     unsigned char *p_msk;
3883     unsigned int row;
3884     unsigned int col;
3885     int transparent;
3886     unsigned short min = USHRT_MAX;
3887     unsigned short max = 0;
3888     double tic;
3889     double red_min;
3890     double red_max;
3891     double red_tic;
3892     double green_min;
3893     double green_max;
3894     double green_tic;
3895     double blue_min;
3896     double blue_max;
3897     double blue_tic;
3898     int i;
3899     int sum;
3900     int total;
3901     int band;
3902     double percentile2;
3903     int histogram[1024];
3904 
3905 /* identifying RED Min/Max values */
3906     total = 0;
3907     p_in = pixels;
3908     p_msk = mask;
3909     for (row = 0; row < height; row++)
3910       {
3911 	  for (col = 0; col < width; col++)
3912 	    {
3913 		if (p_msk != NULL)
3914 		  {
3915 		      if (*p_msk++ == 0)
3916 			{
3917 			    p_in += num_bands;
3918 			    continue;
3919 			}
3920 		  }
3921 		if (test_no_data_16 (no_data, p_in))
3922 		  {
3923 		      p_in += num_bands;
3924 		      continue;
3925 		  }
3926 		for (band = 0; band < num_bands; band++)
3927 		  {
3928 		      unsigned short gray = *p_in++;
3929 		      if (band != red_band)
3930 			  continue;
3931 		      if (min > gray)
3932 			  min = gray;
3933 		      if (max < gray)
3934 			  max = gray;
3935 		      total++;
3936 		  }
3937 	    }
3938       }
3939     tic = (double) (max - min) / 1024.0;
3940     percentile2 = ((double) total / 100.0) * 2.0;
3941 
3942 /* building the RED histogram */
3943     for (i = 0; i < 1024; i++)
3944 	histogram[i] = 0;
3945     p_in = pixels;
3946     p_msk = mask;
3947     for (row = 0; row < height; row++)
3948       {
3949 	  for (col = 0; col < width; col++)
3950 	    {
3951 		if (p_msk != NULL)
3952 		  {
3953 		      if (*p_msk++ == 0)
3954 			{
3955 			    p_in += num_bands;
3956 			    continue;
3957 			}
3958 		  }
3959 		if (test_no_data_16 (no_data, p_in))
3960 		  {
3961 		      p_in += num_bands;
3962 		      continue;
3963 		  }
3964 		for (band = 0; band < num_bands; band++)
3965 		  {
3966 		      double gray = (double) (*p_in++ - min) / tic;
3967 		      if (band != red_band)
3968 			  continue;
3969 		      if (gray < 0.0)
3970 			  gray = 0.0;
3971 		      if (gray > 1023.0)
3972 			  gray = 1023.0;
3973 		      histogram[(int) gray] += 1;
3974 		  }
3975 	    }
3976       }
3977     sum = 0;
3978     for (i = 0; i < 1024; i++)
3979       {
3980 	  sum += histogram[i];
3981 	  if (sum >= percentile2)
3982 	    {
3983 		red_min = (double) min + ((double) i * tic);
3984 		break;
3985 	    }
3986       }
3987     sum = 0;
3988     for (i = 1023; i >= 0; i--)
3989       {
3990 	  sum += histogram[i];
3991 	  if (sum >= percentile2)
3992 	    {
3993 		red_max = (double) min + ((double) (i + 1) * tic);
3994 		break;
3995 	    }
3996       }
3997     red_tic = (double) (red_max - red_min) / 254.0;
3998 
3999 /* identifying GREEN Min/Max values */
4000     total = 0;
4001     p_in = pixels;
4002     p_msk = mask;
4003     for (row = 0; row < height; row++)
4004       {
4005 	  for (col = 0; col < width; col++)
4006 	    {
4007 		if (p_msk != NULL)
4008 		  {
4009 		      if (*p_msk++ == 0)
4010 			{
4011 			    p_in += num_bands;
4012 			    continue;
4013 			}
4014 		  }
4015 		if (test_no_data_16 (no_data, p_in))
4016 		  {
4017 		      p_in += num_bands;
4018 		      continue;
4019 		  }
4020 		for (band = 0; band < num_bands; band++)
4021 		  {
4022 		      unsigned short gray = *p_in++;
4023 		      if (band != green_band)
4024 			  continue;
4025 		      if (min > gray)
4026 			  min = gray;
4027 		      if (max < gray)
4028 			  max = gray;
4029 		      total++;
4030 		  }
4031 	    }
4032       }
4033     tic = (double) (max - min) / 1024.0;
4034     percentile2 = ((double) total / 100.0) * 2.0;
4035 
4036 /* building the GREEN histogram */
4037     for (i = 0; i < 1024; i++)
4038 	histogram[i] = 0;
4039     p_in = pixels;
4040     p_msk = mask;
4041     for (row = 0; row < height; row++)
4042       {
4043 	  for (col = 0; col < width; col++)
4044 	    {
4045 		if (p_msk != NULL)
4046 		  {
4047 		      if (*p_msk++ == 0)
4048 			{
4049 			    p_in += num_bands;
4050 			    continue;
4051 			}
4052 		  }
4053 		if (test_no_data_16 (no_data, p_in))
4054 		  {
4055 		      p_in += num_bands;
4056 		      continue;
4057 		  }
4058 		for (band = 0; band < num_bands; band++)
4059 		  {
4060 		      double gray = (double) (*p_in++ - min) / tic;
4061 		      if (band != green_band)
4062 			  continue;
4063 		      if (gray < 0.0)
4064 			  gray = 0.0;
4065 		      if (gray > 1023.0)
4066 			  gray = 1023.0;
4067 		      histogram[(int) gray] += 1;
4068 		  }
4069 	    }
4070       }
4071     sum = 0;
4072     for (i = 0; i < 1024; i++)
4073       {
4074 	  sum += histogram[i];
4075 	  if (sum >= percentile2)
4076 	    {
4077 		green_min = (double) min + ((double) i * tic);
4078 		break;
4079 	    }
4080       }
4081     sum = 0;
4082     for (i = 1023; i >= 0; i--)
4083       {
4084 	  sum += histogram[i];
4085 	  if (sum >= percentile2)
4086 	    {
4087 		green_max = (double) min + ((double) (i + 1) * tic);
4088 		break;
4089 	    }
4090       }
4091     green_tic = (double) (green_max - green_min) / 254.0;
4092 
4093 /* identifying BLUE Min/Max values */
4094     total = 0;
4095     p_in = pixels;
4096     p_msk = mask;
4097     for (row = 0; row < height; row++)
4098       {
4099 	  for (col = 0; col < width; col++)
4100 	    {
4101 		if (p_msk != NULL)
4102 		  {
4103 		      if (*p_msk++ == 0)
4104 			{
4105 			    p_in += num_bands;
4106 			    continue;
4107 			}
4108 		  }
4109 		if (test_no_data_16 (no_data, p_in))
4110 		  {
4111 		      p_in += num_bands;
4112 		      continue;
4113 		  }
4114 		for (band = 0; band < num_bands; band++)
4115 		  {
4116 		      unsigned short gray = *p_in++;
4117 		      if (band != blue_band)
4118 			  continue;
4119 		      if (min > gray)
4120 			  min = gray;
4121 		      if (max < gray)
4122 			  max = gray;
4123 		      total++;
4124 		  }
4125 	    }
4126       }
4127     tic = (double) (max - min) / 1024.0;
4128     percentile2 = ((double) total / 100.0) * 2.0;
4129 
4130 /* building the BLUE histogram */
4131     for (i = 0; i < 1024; i++)
4132 	histogram[i] = 0;
4133     p_in = pixels;
4134     p_msk = mask;
4135     for (row = 0; row < height; row++)
4136       {
4137 	  for (col = 0; col < width; col++)
4138 	    {
4139 		if (p_msk != NULL)
4140 		  {
4141 		      if (*p_msk++ == 0)
4142 			{
4143 			    p_in += num_bands;
4144 			    continue;
4145 			}
4146 		  }
4147 		if (test_no_data_16 (no_data, p_in))
4148 		  {
4149 		      p_in += num_bands;
4150 		      continue;
4151 		  }
4152 		for (band = 0; band < num_bands; band++)
4153 		  {
4154 		      double gray = (double) (*p_in++ - min) / tic;
4155 		      if (band != blue_band)
4156 			  continue;
4157 		      if (gray < 0.0)
4158 			  gray = 0.0;
4159 		      if (gray > 1023.0)
4160 			  gray = 1023.0;
4161 		      histogram[(int) gray] += 1;
4162 		  }
4163 	    }
4164       }
4165     sum = 0;
4166     for (i = 0; i < 1024; i++)
4167       {
4168 	  sum += histogram[i];
4169 	  if (sum >= percentile2)
4170 	    {
4171 		blue_min = (double) min + ((double) i * tic);
4172 		break;
4173 	    }
4174       }
4175     sum = 0;
4176     for (i = 1023; i >= 0; i--)
4177       {
4178 	  sum += histogram[i];
4179 	  if (sum >= percentile2)
4180 	    {
4181 		blue_max = (double) min + ((double) (i + 1) * tic);
4182 		break;
4183 	    }
4184       }
4185     blue_tic = (double) (blue_max - blue_min) / 254.0;
4186 
4187 /* rescaling RGB-values 0-255 */
4188     p_in = pixels;
4189     p_out = rgba;
4190     p_msk = mask;
4191     for (row = 0; row < height; row++)
4192       {
4193 	  for (col = 0; col < width; col++)
4194 	    {
4195 		transparent = 0;
4196 		if (p_msk != NULL)
4197 		  {
4198 		      if (*p_msk++ == 0)
4199 			  transparent = 1;
4200 		  }
4201 		if (test_no_data_16 (no_data, p_in))
4202 		    transparent = 1;
4203 		if (transparent)
4204 		  {
4205 		      p_out += 4;
4206 		      p_in += num_bands;
4207 		  }
4208 		else
4209 		  {
4210 		      double r;
4211 		      double g;
4212 		      double b;
4213 		      unsigned short red = *(p_in + red_band);
4214 		      unsigned short green = *(p_in + green_band);
4215 		      unsigned short blue = *(p_in + blue_band);
4216 		      if (red <= red_min)
4217 			  r = 0.0;
4218 		      else if (red >= red_max)
4219 			  r = 255.0;
4220 		      else
4221 			  r = 1.0 + (((double) red - red_min) / red_tic);
4222 		      if (r < 0.0)
4223 			  r = 0.0;
4224 		      if (r > 255.0)
4225 			  r = 255.0;
4226 		      if (green <= green_min)
4227 			  g = 0.0;
4228 		      else if (green >= green_max)
4229 			  g = 255.0;
4230 		      else
4231 			  g = 1.0 + (((double) green - green_min) / green_tic);
4232 		      if (g < 0.0)
4233 			  g = 0.0;
4234 		      if (g > 255.0)
4235 			  g = 255.0;
4236 		      if (blue <= blue_min)
4237 			  b = 0.0;
4238 		      else if (blue >= blue_max)
4239 			  b = 255.0;
4240 		      else
4241 			  b = 1.0 + (((double) blue - blue_min) / blue_tic);
4242 		      if (b < 0.0)
4243 			  b = 0.0;
4244 		      if (b > 255.0)
4245 			  b = 255.0;
4246 		      *p_out++ = (unsigned char) r;	/* red */
4247 		      *p_out++ = (unsigned char) g;	/* green */
4248 		      *p_out++ = (unsigned char) b;	/* blue */
4249 		      *p_out++ = 255;	/* opaque */
4250 		      p_in += num_bands;
4251 		  }
4252 	    }
4253       }
4254     free (pixels);
4255     if (mask != NULL)
4256 	free (mask);
4257     return 1;
4258 }
4259 
4260 RL2_PRIVATE int
get_raster_band_histogram(rl2PrivBandStatisticsPtr band,unsigned char ** image,int * image_sz)4261 get_raster_band_histogram (rl2PrivBandStatisticsPtr band,
4262 			   unsigned char **image, int *image_sz)
4263 {
4264 /* attempting to create an in-memory PNG image representing a Band Histogram */
4265     int r;
4266     int c;
4267     int j;
4268     int h;
4269     double count = 0.0;
4270     double max = 0.0;
4271     unsigned short width = 512;
4272     unsigned short height = 128 + 32;
4273     double scale;
4274     unsigned char *raster = malloc (width * height);
4275     unsigned char *p = raster;
4276     for (r = 0; r < height; r++)
4277       {
4278 	  /* priming a WHITE background */
4279 	  for (c = 0; c < width; c++)
4280 	      *p++ = 255;
4281       }
4282     for (j = 1; j < 256; j++)
4283       {
4284 	  /* computing optimal height */
4285 	  double value = *(band->histogram + j);
4286 	  count += value;
4287 	  if (max < value)
4288 	      max = value;
4289       }
4290     scale = 1.0 / (max / count);
4291     for (j = 1; j < 256; j++)
4292       {
4293 	  /* drawing the histogram */
4294 	  double freq = *(band->histogram + j);
4295 	  double high = (height - 32.0) * scale * freq / count;
4296 	  r = (j - 1) * 2;
4297 	  for (c = 0, h = height - 32; c < high; c++, h--)
4298 	    {
4299 		p = raster + (h * width) + r;
4300 		*p++ = 128;
4301 		*p = 128;
4302 	    }
4303       }
4304     for (j = 1; j < 256; j++)
4305       {
4306 	  /* drawing the scale-bar */
4307 	  r = (j - 1) * 2;
4308 	  for (c = 0, h = height - 1; c < 25; c++, h--)
4309 	    {
4310 		p = raster + (h * width) + r;
4311 		*p++ = j;
4312 		*p = j;
4313 	    }
4314       }
4315     if (rl2_data_to_png
4316 	(raster, NULL, 1.0, NULL, width, height, RL2_SAMPLE_UINT8,
4317 	 RL2_PIXEL_GRAYSCALE, image, image_sz) == RL2_OK)
4318 	return RL2_OK;
4319     free (raster);
4320     return RL2_ERROR;
4321 }
4322 
4323 RL2_PRIVATE int
set_coverage_infos(sqlite3 * sqlite,const char * coverage_name,const char * title,const char * abstract)4324 set_coverage_infos (sqlite3 * sqlite, const char *coverage_name,
4325 		    const char *title, const char *abstract)
4326 {
4327 /* auxiliary function: updates the Coverage descriptive infos */
4328     int ret;
4329     const char *sql;
4330     sqlite3_stmt *stmt;
4331     int exists = 0;
4332     int retval = 0;
4333 
4334     /* checking if the Group already exists */
4335     sql = "SELECT coverage_name FROM raster_coverages "
4336 	"WHERE coverage_name = Lower(?)";
4337     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
4338     if (ret != SQLITE_OK)
4339       {
4340 	  fprintf (stderr, "SetCoverageInfos: \"%s\"\n",
4341 		   sqlite3_errmsg (sqlite));
4342 	  goto stop;
4343       }
4344     sqlite3_reset (stmt);
4345     sqlite3_clear_bindings (stmt);
4346     sqlite3_bind_text (stmt, 1, coverage_name, strlen (coverage_name),
4347 		       SQLITE_STATIC);
4348     while (1)
4349       {
4350 	  /* scrolling the result set rows */
4351 	  ret = sqlite3_step (stmt);
4352 	  if (ret == SQLITE_DONE)
4353 	      break;		/* end of result set */
4354 	  if (ret == SQLITE_ROW)
4355 	      exists = 1;
4356       }
4357     sqlite3_finalize (stmt);
4358 
4359     if (!exists)
4360 	return 0;
4361     /* update Coverage */
4362     sql =
4363 	"UPDATE raster_coverages SET title = ?, abstract = ? WHERE coverage_name = ?";
4364     ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
4365     if (ret != SQLITE_OK)
4366       {
4367 	  fprintf (stderr, "SetCoverageInfos: \"%s\"\n",
4368 		   sqlite3_errmsg (sqlite));
4369 	  goto stop;
4370       }
4371     sqlite3_reset (stmt);
4372     sqlite3_clear_bindings (stmt);
4373     sqlite3_bind_text (stmt, 1, title, strlen (title), SQLITE_STATIC);
4374     sqlite3_bind_text (stmt, 2, abstract, strlen (abstract), SQLITE_STATIC);
4375     sqlite3_bind_text (stmt, 3, coverage_name, strlen (coverage_name),
4376 		       SQLITE_STATIC);
4377     ret = sqlite3_step (stmt);
4378     if (ret == SQLITE_DONE || ret == SQLITE_ROW)
4379 	retval = 1;
4380     else
4381 	fprintf (stderr, "SetCoverageInfos() error: \"%s\"\n",
4382 		 sqlite3_errmsg (sqlite));
4383     sqlite3_finalize (stmt);
4384     return retval;
4385   stop:
4386     return 0;
4387 }
4388 
4389 RL2_PRIVATE int
rl2_test_layer_group(sqlite3 * handle,const char * name)4390 rl2_test_layer_group (sqlite3 * handle, const char *name)
4391 {
4392 /* testing for an eventual Layer Group */
4393     int ret;
4394     char **results;
4395     int rows;
4396     int columns;
4397     int i;
4398     int ok = 0;
4399 /* testing if Layer Group exists */
4400     char *sql = sqlite3_mprintf ("SELECT group_name FROM SE_styled_groups "
4401 				 "WHERE Lower(group_name) = Lower(%Q)", name);
4402     ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
4403     sqlite3_free (sql);
4404     if (ret != SQLITE_OK)
4405 	return 0;
4406     for (i = 1; i <= rows; i++)
4407 	ok = 1;
4408     sqlite3_free_table (results);
4409     return ok;
4410 }
4411