1 /*
2 
3  rasterlite2 -- main public functions
4 
5  version 0.1, 2013 March 29
6 
7  Author: Sandro Furieri a.furieri@lqt.it
8 
9  -----------------------------------------------------------------------------
10 
11  Version: MPL 1.1/GPL 2.0/LGPL 2.1
12 
13  The contents of this file are subject to the Mozilla Public License Version
14  1.1 (the "License"); you may not use this file except in compliance with
15  the License. You may obtain a copy of the License at
16  http://www.mozilla.org/MPL/
17 
18 Software distributed under the License is distributed on an "AS IS" basis,
19 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
20 for the specific language governing rights and limitations under the
21 License.
22 
23 The Original Code is the SpatiaLite library
24 
25 The Initial Developer of the Original Code is Alessandro Furieri
26 
27 Portions created by the Initial Developer are Copyright (C) 2008-2013
28 the Initial Developer. All Rights Reserved.
29 
30 Alternatively, the contents of this file may be used under the terms of
31 either the GNU General Public License Version 2 or later (the "GPL"), or
32 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 in which case the provisions of the GPL or the LGPL are applicable instead
34 of those above. If you wish to allow use of your version of this file only
35 under the terms of either the GPL or the LGPL, and not to allow others to
36 use your version of this file under the terms of the MPL, indicate your
37 decision by deleting the provisions above and replace them with the notice
38 and other provisions required by the GPL or the LGPL. If you do not delete
39 the provisions above, a recipient may use your version of this file under
40 the terms of any one of the MPL, the GPL or the LGPL.
41 
42 */
43 
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <float.h>
48 
49 #include "config.h"
50 
51 #ifdef LOADABLE_EXTENSION
52 #include "rasterlite2/sqlite.h"
53 #endif
54 
55 #include "rasterlite2/rasterlite2.h"
56 #include "rasterlite2_private.h"
57 
58 static int
is_valid_sample_type(unsigned char sample_type)59 is_valid_sample_type (unsigned char sample_type)
60 {
61 /* checking a sample-type for validity */
62     switch (sample_type)
63       {
64       case RL2_SAMPLE_1_BIT:
65       case RL2_SAMPLE_2_BIT:
66       case RL2_SAMPLE_4_BIT:
67       case RL2_SAMPLE_INT8:
68       case RL2_SAMPLE_UINT8:
69       case RL2_SAMPLE_INT16:
70       case RL2_SAMPLE_UINT16:
71       case RL2_SAMPLE_INT32:
72       case RL2_SAMPLE_UINT32:
73       case RL2_SAMPLE_FLOAT:
74       case RL2_SAMPLE_DOUBLE:
75 	  return 1;
76       };
77     return 0;
78 }
79 
80 static int
is_valid_pixel_type(unsigned char pixel_type)81 is_valid_pixel_type (unsigned char pixel_type)
82 {
83 /* checking a pixel-type for validity */
84     switch (pixel_type)
85       {
86       case RL2_PIXEL_MONOCHROME:
87       case RL2_PIXEL_PALETTE:
88       case RL2_PIXEL_GRAYSCALE:
89       case RL2_PIXEL_RGB:
90       case RL2_PIXEL_MULTIBAND:
91       case RL2_PIXEL_DATAGRID:
92 	  return 1;
93       };
94     return 0;
95 }
96 
97 static int
is_valid_compression(unsigned char compression)98 is_valid_compression (unsigned char compression)
99 {
100 /* checking a compression-type for validity */
101     switch (compression)
102       {
103       case RL2_COMPRESSION_NONE:
104       case RL2_COMPRESSION_DEFLATE:
105       case RL2_COMPRESSION_LZMA:
106       case RL2_COMPRESSION_GIF:
107       case RL2_COMPRESSION_PNG:
108       case RL2_COMPRESSION_JPEG:
109       case RL2_COMPRESSION_LOSSY_WEBP:
110       case RL2_COMPRESSION_LOSSLESS_WEBP:
111       case RL2_COMPRESSION_CCITTFAX4:
112 	  return 1;
113       };
114     return 0;
115 }
116 
117 static int
check_coverage_self_consistency(unsigned char sample_type,unsigned char pixel_type,unsigned char num_samples,unsigned char compression)118 check_coverage_self_consistency (unsigned char sample_type,
119 				 unsigned char pixel_type,
120 				 unsigned char num_samples,
121 				 unsigned char compression)
122 {
123 /* checking overall self-consistency for coverage params */
124     switch (pixel_type)
125       {
126       case RL2_PIXEL_MONOCHROME:
127 	  if (sample_type != RL2_SAMPLE_1_BIT || num_samples != 1)
128 	      return 0;
129 	  switch (compression)
130 	    {
131 	    case RL2_COMPRESSION_NONE:
132 	    case RL2_COMPRESSION_PNG:
133 	    case RL2_COMPRESSION_CCITTFAX4:
134 		break;
135 	    default:
136 		return 0;
137 	    };
138 	  break;
139       case RL2_PIXEL_PALETTE:
140 	  switch (sample_type)
141 	    {
142 	    case RL2_SAMPLE_1_BIT:
143 	    case RL2_SAMPLE_2_BIT:
144 	    case RL2_SAMPLE_4_BIT:
145 	    case RL2_SAMPLE_UINT8:
146 		break;
147 	    default:
148 		return 0;
149 	    };
150 	  if (num_samples != 1)
151 	      return 0;
152 	  switch (compression)
153 	    {
154 	    case RL2_COMPRESSION_NONE:
155 	    case RL2_COMPRESSION_GIF:
156 	    case RL2_COMPRESSION_PNG:
157 		break;
158 	    default:
159 		return 0;
160 	    };
161 	  break;
162       case RL2_PIXEL_GRAYSCALE:
163 	  switch (sample_type)
164 	    {
165 	    case RL2_SAMPLE_2_BIT:
166 	    case RL2_SAMPLE_4_BIT:
167 	    case RL2_SAMPLE_UINT8:
168 		break;
169 	    default:
170 		return 0;
171 	    };
172 	  if (num_samples != 1)
173 	      return 0;
174 	  switch (compression)
175 	    {
176 	    case RL2_COMPRESSION_NONE:
177 	    case RL2_COMPRESSION_DEFLATE:
178 	    case RL2_COMPRESSION_LZMA:
179 	    case RL2_COMPRESSION_GIF:
180 	    case RL2_COMPRESSION_PNG:
181 	    case RL2_COMPRESSION_JPEG:
182 	    case RL2_COMPRESSION_LOSSY_WEBP:
183 	    case RL2_COMPRESSION_LOSSLESS_WEBP:
184 		break;
185 	    default:
186 		return 0;
187 	    };
188 	  break;
189       case RL2_PIXEL_RGB:
190 	  switch (sample_type)
191 	    {
192 	    case RL2_SAMPLE_UINT8:
193 	    case RL2_SAMPLE_UINT16:
194 		break;
195 	    default:
196 		return 0;
197 	    };
198 	  if (num_samples != 3)
199 	      return 0;
200 	  if (sample_type == RL2_SAMPLE_UINT16)
201 	    {
202 		switch (compression)
203 		  {
204 		  case RL2_COMPRESSION_NONE:
205 		  case RL2_COMPRESSION_DEFLATE:
206 		  case RL2_COMPRESSION_LZMA:
207 		      break;
208 		  default:
209 		      return 0;
210 		  };
211 	    }
212 	  else
213 	    {
214 		switch (compression)
215 		  {
216 		  case RL2_COMPRESSION_NONE:
217 		  case RL2_COMPRESSION_DEFLATE:
218 		  case RL2_COMPRESSION_LZMA:
219 		  case RL2_COMPRESSION_PNG:
220 		  case RL2_COMPRESSION_JPEG:
221 		  case RL2_COMPRESSION_LOSSY_WEBP:
222 		  case RL2_COMPRESSION_LOSSLESS_WEBP:
223 		      break;
224 		  default:
225 		      return 0;
226 		  };
227 	    }
228 	  break;
229       case RL2_PIXEL_MULTIBAND:
230 	  switch (sample_type)
231 	    {
232 	    case RL2_SAMPLE_UINT8:
233 	    case RL2_SAMPLE_UINT16:
234 		break;
235 	    default:
236 		return 0;
237 	    };
238 	  if (num_samples < 2)
239 	      return 0;
240 	  switch (compression)
241 	    {
242 	    case RL2_COMPRESSION_NONE:
243 	    case RL2_COMPRESSION_DEFLATE:
244 	    case RL2_COMPRESSION_LZMA:
245 		break;
246 	    default:
247 		return 0;
248 	    };
249 	  break;
250       case RL2_PIXEL_DATAGRID:
251 	  switch (sample_type)
252 	    {
253 	    case RL2_SAMPLE_INT8:
254 	    case RL2_SAMPLE_UINT8:
255 	    case RL2_SAMPLE_INT16:
256 	    case RL2_SAMPLE_UINT16:
257 	    case RL2_SAMPLE_INT32:
258 	    case RL2_SAMPLE_UINT32:
259 	    case RL2_SAMPLE_FLOAT:
260 	    case RL2_SAMPLE_DOUBLE:
261 		break;
262 	    default:
263 		return 0;
264 	    };
265 	  if (num_samples != 1)
266 	      return 0;
267 	  switch (compression)
268 	    {
269 	    case RL2_COMPRESSION_NONE:
270 	    case RL2_COMPRESSION_DEFLATE:
271 	    case RL2_COMPRESSION_LZMA:
272 		break;
273 	    default:
274 		return 0;
275 	    };
276 	  break;
277       };
278     return 1;
279 }
280 
281 static int
check_raster_self_consistency(unsigned char sample_type,unsigned char pixel_type,unsigned char num_samples)282 check_raster_self_consistency (unsigned char sample_type,
283 			       unsigned char pixel_type,
284 			       unsigned char num_samples)
285 {
286 /* checking overall self-consistency for raster params */
287     switch (pixel_type)
288       {
289       case RL2_PIXEL_MONOCHROME:
290 	  if (sample_type != RL2_SAMPLE_1_BIT || num_samples != 1)
291 	      return 0;
292 	  break;
293       case RL2_PIXEL_PALETTE:
294 	  switch (sample_type)
295 	    {
296 	    case RL2_SAMPLE_1_BIT:
297 	    case RL2_SAMPLE_2_BIT:
298 	    case RL2_SAMPLE_4_BIT:
299 	    case RL2_SAMPLE_UINT8:
300 		break;
301 	    default:
302 		return 0;
303 	    };
304 	  if (num_samples != 1)
305 	      return 0;
306 	  break;
307       case RL2_PIXEL_GRAYSCALE:
308 	  switch (sample_type)
309 	    {
310 	    case RL2_SAMPLE_2_BIT:
311 	    case RL2_SAMPLE_4_BIT:
312 	    case RL2_SAMPLE_UINT8:
313 	    case RL2_SAMPLE_UINT16:
314 		break;
315 	    default:
316 		return 0;
317 	    };
318 	  if (num_samples != 1)
319 	      return 0;
320 	  break;
321       case RL2_PIXEL_RGB:
322 	  switch (sample_type)
323 	    {
324 	    case RL2_SAMPLE_UINT8:
325 	    case RL2_SAMPLE_UINT16:
326 		break;
327 	    default:
328 		return 0;
329 	    };
330 	  if (num_samples != 3)
331 	      return 0;
332 	  break;
333       case RL2_PIXEL_MULTIBAND:
334 	  switch (sample_type)
335 	    {
336 	    case RL2_SAMPLE_UINT8:
337 	    case RL2_SAMPLE_UINT16:
338 		break;
339 	    default:
340 		return 0;
341 	    };
342 	  if (num_samples < 2)
343 	      return 0;
344 	  break;
345       case RL2_PIXEL_DATAGRID:
346 	  switch (sample_type)
347 	    {
348 	    case RL2_SAMPLE_INT8:
349 	    case RL2_SAMPLE_UINT8:
350 	    case RL2_SAMPLE_INT16:
351 	    case RL2_SAMPLE_UINT16:
352 	    case RL2_SAMPLE_INT32:
353 	    case RL2_SAMPLE_UINT32:
354 	    case RL2_SAMPLE_FLOAT:
355 	    case RL2_SAMPLE_DOUBLE:
356 		break;
357 	    default:
358 		return 0;
359 	    };
360 	  if (num_samples != 1)
361 	      return 0;
362 	  break;
363       };
364     return 1;
365 }
366 
367 RL2_DECLARE void
rl2_free(void * ptr)368 rl2_free (void *ptr)
369 {
370 /* memory cleanup - generic free */
371     if (ptr != NULL)
372 	free (ptr);
373 }
374 
375 static int
check_coverage_no_data(rl2PrivPixelPtr pxl_no_data,unsigned char sample_type,unsigned char pixel_type,unsigned char num_samples)376 check_coverage_no_data (rl2PrivPixelPtr pxl_no_data, unsigned char sample_type,
377 			unsigned char pixel_type, unsigned char num_samples)
378 {
379 /* checking if the NoData pixel is consistent with the Coverage */
380     if (pxl_no_data == NULL)
381 	return 1;
382     if (pxl_no_data->sampleType != sample_type)
383 	return 0;
384     if (pxl_no_data->pixelType != pixel_type)
385 	return 0;
386     if (pxl_no_data->nBands != num_samples)
387 	return 0;
388     return 1;
389 }
390 
391 RL2_DECLARE rl2CoveragePtr
rl2_create_coverage(const char * name,unsigned char sample_type,unsigned char pixel_type,unsigned char num_samples,unsigned char compression,int quality,unsigned int tile_width,unsigned int tile_height,rl2PixelPtr no_data)392 rl2_create_coverage (const char *name, unsigned char sample_type,
393 		     unsigned char pixel_type, unsigned char num_samples,
394 		     unsigned char compression, int quality,
395 		     unsigned int tile_width, unsigned int tile_height,
396 		     rl2PixelPtr no_data)
397 {
398 /* allocating and initializing a Coverage object */
399     int len;
400     rl2PrivPixelPtr pxl_no_data = (rl2PrivPixelPtr) no_data;
401     rl2PrivCoveragePtr cvg = NULL;
402     if (name == NULL)
403 	return NULL;
404     if (!is_valid_sample_type (sample_type))
405 	return NULL;
406     if (!is_valid_pixel_type (pixel_type))
407 	return NULL;
408     if (!is_valid_compression (compression))
409 	return NULL;
410     if (!check_coverage_self_consistency
411 	(sample_type, pixel_type, num_samples, compression))
412 	return NULL;
413     if (tile_width < 256 || tile_width > 1024)
414 	return NULL;
415     if (tile_height < 256 || tile_height > 1024)
416 	return NULL;
417     if ((tile_width % 16) != 0)
418 	return NULL;
419     if ((tile_height % 16) != 0)
420 	return NULL;
421     if (!check_coverage_no_data
422 	(pxl_no_data, sample_type, pixel_type, num_samples))
423 	return NULL;
424 
425     cvg = malloc (sizeof (rl2PrivCoverage));
426     if (cvg == NULL)
427 	return NULL;
428     len = strlen (name);
429     cvg->coverageName = malloc (len + 1);
430     strcpy (cvg->coverageName, name);
431     cvg->sampleType = sample_type;
432     cvg->pixelType = pixel_type;
433     cvg->nBands = num_samples;
434     cvg->Compression = compression;
435     if (quality < 0)
436 	cvg->Quality = 0;
437     else if (quality > 100)
438 	cvg->Quality = 100;
439     else
440 	cvg->Quality = quality;
441     cvg->tileWidth = tile_width;
442     cvg->tileHeight = tile_height;
443     cvg->Srid = RL2_GEOREFERENCING_NONE;
444     cvg->hResolution = 1.0;
445     cvg->vResolution = 1.0;
446     cvg->noData = pxl_no_data;
447     return (rl2CoveragePtr) cvg;
448 }
449 
450 RL2_DECLARE void
rl2_destroy_coverage(rl2CoveragePtr ptr)451 rl2_destroy_coverage (rl2CoveragePtr ptr)
452 {
453 /* memory cleanup - destroying a Coverage object */
454     rl2PrivCoveragePtr cvg = (rl2PrivCoveragePtr) ptr;
455     if (cvg == NULL)
456 	return;
457     if (cvg->coverageName != NULL)
458 	free (cvg->coverageName);
459     if (cvg->noData != NULL)
460 	rl2_destroy_pixel ((rl2PixelPtr) (cvg->noData));
461     free (cvg);
462 }
463 
464 RL2_DECLARE int
rl2_coverage_georeference(rl2CoveragePtr ptr,int srid,double horz_res,double vert_res)465 rl2_coverage_georeference (rl2CoveragePtr ptr, int srid, double horz_res,
466 			   double vert_res)
467 {
468 /* setting the Coverage's georeferencing infos */
469     rl2PrivCoveragePtr cvg = (rl2PrivCoveragePtr) ptr;
470     if (cvg == NULL)
471 	return RL2_ERROR;
472     cvg->Srid = srid;
473     cvg->hResolution = horz_res;
474     cvg->vResolution = vert_res;
475     return RL2_OK;
476 }
477 
478 RL2_DECLARE const char *
rl2_get_coverage_name(rl2CoveragePtr ptr)479 rl2_get_coverage_name (rl2CoveragePtr ptr)
480 {
481 /* return the Coverage name */
482     rl2PrivCoveragePtr cvg = (rl2PrivCoveragePtr) ptr;
483     if (cvg == NULL)
484 	return NULL;
485     return cvg->coverageName;
486 }
487 
488 RL2_DECLARE int
rl2_get_coverage_type(rl2CoveragePtr ptr,unsigned char * sample_type,unsigned char * pixel_type,unsigned char * num_bands)489 rl2_get_coverage_type (rl2CoveragePtr ptr, unsigned char *sample_type,
490 		       unsigned char *pixel_type, unsigned char *num_bands)
491 {
492 /* return the Coverage type */
493     rl2PrivCoveragePtr cvg = (rl2PrivCoveragePtr) ptr;
494     if (cvg == NULL)
495 	return RL2_ERROR;
496     *sample_type = cvg->sampleType;
497     *pixel_type = cvg->pixelType;
498     *num_bands = cvg->nBands;
499     return RL2_OK;
500 }
501 
502 RL2_DECLARE int
rl2_get_coverage_compression(rl2CoveragePtr ptr,unsigned char * compression,int * quality)503 rl2_get_coverage_compression (rl2CoveragePtr ptr, unsigned char *compression,
504 			      int *quality)
505 {
506 /* return the Coverage compression */
507     rl2PrivCoveragePtr cvg = (rl2PrivCoveragePtr) ptr;
508     if (cvg == NULL)
509 	return RL2_ERROR;
510     *compression = cvg->Compression;
511     *quality = cvg->Quality;
512     return RL2_OK;
513 }
514 
515 RL2_DECLARE int
rl2_is_coverage_uncompressed(rl2CoveragePtr ptr,int * is_uncompressed)516 rl2_is_coverage_uncompressed (rl2CoveragePtr ptr, int *is_uncompressed)
517 {
518 /* tests if Coverage is compressed */
519     rl2PrivCoveragePtr cvg = (rl2PrivCoveragePtr) ptr;
520     if (cvg == NULL)
521 	return RL2_ERROR;
522     if (cvg->Compression == RL2_COMPRESSION_NONE)
523 	*is_uncompressed = RL2_TRUE;
524     else
525 	*is_uncompressed = RL2_FALSE;
526     return RL2_OK;
527 }
528 
529 RL2_DECLARE int
rl2_is_coverage_compression_lossless(rl2CoveragePtr ptr,int * is_lossless)530 rl2_is_coverage_compression_lossless (rl2CoveragePtr ptr, int *is_lossless)
531 {
532 /* tests if Coverage is lossless compressed */
533     rl2PrivCoveragePtr cvg = (rl2PrivCoveragePtr) ptr;
534     if (cvg == NULL)
535 	return RL2_ERROR;
536     switch (cvg->Compression)
537       {
538       case RL2_COMPRESSION_DEFLATE:
539       case RL2_COMPRESSION_LZMA:
540       case RL2_COMPRESSION_GIF:
541       case RL2_COMPRESSION_PNG:
542 	  *is_lossless = RL2_TRUE;
543 	  break;
544       default:
545 	  *is_lossless = RL2_FALSE;
546 	  break;
547       };
548     return RL2_OK;
549 }
550 
551 RL2_DECLARE int
rl2_is_coverage_compression_lossy(rl2CoveragePtr ptr,int * is_lossy)552 rl2_is_coverage_compression_lossy (rl2CoveragePtr ptr, int *is_lossy)
553 {
554 /* tests if Coverage is lossy compressed */
555     rl2PrivCoveragePtr cvg = (rl2PrivCoveragePtr) ptr;
556     if (cvg == NULL)
557 	return RL2_ERROR;
558     switch (cvg->Compression)
559       {
560       case RL2_COMPRESSION_JPEG:
561       case RL2_COMPRESSION_LOSSY_WEBP:
562 	  *is_lossy = RL2_TRUE;
563 	  break;
564       default:
565 	  *is_lossy = RL2_FALSE;
566 	  break;
567       };
568     return RL2_OK;
569 }
570 
571 RL2_DECLARE int
rl2_get_coverage_tile_size(rl2CoveragePtr ptr,unsigned int * tile_width,unsigned int * tile_height)572 rl2_get_coverage_tile_size (rl2CoveragePtr ptr, unsigned int *tile_width,
573 			    unsigned int *tile_height)
574 {
575 /* return the Coverage tile width */
576     rl2PrivCoveragePtr cvg = (rl2PrivCoveragePtr) ptr;
577     if (cvg == NULL)
578 	return RL2_ERROR;
579     *tile_width = cvg->tileWidth;
580     *tile_height = cvg->tileHeight;
581     return RL2_OK;
582 }
583 
584 RL2_DECLARE rl2PixelPtr
rl2_get_coverage_no_data(rl2CoveragePtr ptr)585 rl2_get_coverage_no_data (rl2CoveragePtr ptr)
586 {
587 /* return the Coverage NoData pixel (if any) */
588     rl2PrivCoveragePtr cvg = (rl2PrivCoveragePtr) ptr;
589     if (cvg == NULL)
590 	return NULL;
591     return (rl2PixelPtr) (cvg->noData);
592 }
593 
594 RL2_DECLARE rl2PixelPtr
rl2_create_coverage_pixel(rl2CoveragePtr ptr)595 rl2_create_coverage_pixel (rl2CoveragePtr ptr)
596 {
597 /* creating a Pixel matching the given Coverage */
598     rl2PrivCoveragePtr cvg = (rl2PrivCoveragePtr) ptr;
599     if (cvg == NULL)
600 	return NULL;
601     return rl2_create_pixel (cvg->sampleType, cvg->pixelType, cvg->nBands);
602 }
603 
604 RL2_DECLARE int
rl2_get_coverage_srid(rl2CoveragePtr ptr,int * srid)605 rl2_get_coverage_srid (rl2CoveragePtr ptr, int *srid)
606 {
607 /* return the Coverage SRID */
608     rl2PrivCoveragePtr cvg = (rl2PrivCoveragePtr) ptr;
609     if (cvg == NULL)
610 	return RL2_ERROR;
611     *srid = cvg->Srid;
612     return RL2_OK;
613 }
614 
615 RL2_DECLARE int
rl2_get_coverage_resolution(rl2CoveragePtr ptr,double * hResolution,double * vResolution)616 rl2_get_coverage_resolution (rl2CoveragePtr ptr, double *hResolution,
617 			     double *vResolution)
618 {
619 /* return the Coverage SRID */
620     rl2PrivCoveragePtr cvg = (rl2PrivCoveragePtr) ptr;
621     if (cvg == NULL)
622 	return RL2_ERROR;
623     *hResolution = cvg->hResolution;
624     *vResolution = cvg->vResolution;
625     return RL2_OK;
626 }
627 
628 RL2_DECLARE rl2SectionPtr
rl2_create_section(const char * name,unsigned char compression,unsigned int tile_width,unsigned int tile_height,rl2RasterPtr rst)629 rl2_create_section (const char *name, unsigned char compression,
630 		    unsigned int tile_width, unsigned int tile_height,
631 		    rl2RasterPtr rst)
632 {
633 /* allocating and initializing a Section object */
634     int len;
635     rl2PrivRasterPtr raster = (rl2PrivRasterPtr) rst;
636     rl2PrivSectionPtr scn = NULL;
637     if (name == NULL)
638 	return NULL;
639     if (raster == NULL)
640 	return NULL;
641     if (!check_coverage_self_consistency
642 	(raster->sampleType, raster->pixelType, raster->nBands, compression))
643 	return NULL;
644     if (tile_width == RL2_TILESIZE_UNDEFINED
645 	&& tile_height == RL2_TILESIZE_UNDEFINED)
646 	;
647     else
648       {
649 	  if (tile_width < 256 || tile_width > 1024)
650 	      return NULL;
651 	  if (tile_height < 256 || tile_height > 1024)
652 	      return NULL;
653 	  if ((tile_width % 16) != 0)
654 	      return NULL;
655 	  if ((tile_height % 16) != 0)
656 	      return NULL;
657       }
658 
659     scn = malloc (sizeof (rl2PrivSection));
660     if (scn == NULL)
661 	return NULL;
662     len = strlen (name);
663     scn->sectionName = malloc (len + 1);
664     strcpy (scn->sectionName, name);
665     scn->Compression = compression;
666     scn->tileWidth = tile_width;
667     scn->tileHeight = tile_height;
668     scn->Raster = raster;
669     return (rl2SectionPtr) scn;
670 }
671 
672 RL2_DECLARE void
rl2_destroy_section(rl2SectionPtr ptr)673 rl2_destroy_section (rl2SectionPtr ptr)
674 {
675 /* memory cleanup - destroying a Section object */
676     rl2PrivSectionPtr scn = (rl2PrivSectionPtr) ptr;
677     if (scn == NULL)
678 	return;
679     if (scn->sectionName != NULL)
680 	free (scn->sectionName);
681     if (scn->Raster != NULL)
682 	rl2_destroy_raster ((rl2RasterPtr) (scn->Raster));
683     free (scn);
684 }
685 
686 RL2_DECLARE const char *
rl2_get_section_name(rl2SectionPtr ptr)687 rl2_get_section_name (rl2SectionPtr ptr)
688 {
689 /* return the Section name */
690     rl2PrivSectionPtr scn = (rl2PrivSectionPtr) ptr;
691     if (scn == NULL)
692 	return NULL;
693     return scn->sectionName;
694 }
695 
696 RL2_DECLARE int
rl2_get_section_compression(rl2SectionPtr ptr,unsigned char * compression)697 rl2_get_section_compression (rl2SectionPtr ptr, unsigned char *compression)
698 {
699 /* return the Section compression */
700     rl2PrivSectionPtr scn = (rl2PrivSectionPtr) ptr;
701     if (scn == NULL)
702 	return RL2_ERROR;
703     *compression = scn->Compression;
704     return RL2_OK;
705 }
706 
707 RL2_DECLARE int
rl2_is_section_uncompressed(rl2SectionPtr ptr,int * is_uncompressed)708 rl2_is_section_uncompressed (rl2SectionPtr ptr, int *is_uncompressed)
709 {
710 /* tests if Section is compressed */
711     rl2PrivSectionPtr scn = (rl2PrivSectionPtr) ptr;
712     if (scn == NULL)
713 	return RL2_ERROR;
714     if (scn->Compression == RL2_COMPRESSION_NONE)
715 	*is_uncompressed = RL2_TRUE;
716     else
717 	*is_uncompressed = RL2_FALSE;
718     return RL2_OK;
719 }
720 
721 RL2_DECLARE int
rl2_is_section_compression_lossless(rl2SectionPtr ptr,int * is_lossless)722 rl2_is_section_compression_lossless (rl2SectionPtr ptr, int *is_lossless)
723 {
724 /* tests if Section is lossless compressed */
725     rl2PrivSectionPtr scn = (rl2PrivSectionPtr) ptr;
726     if (scn == NULL)
727 	return RL2_ERROR;
728     switch (scn->Compression)
729       {
730       case RL2_COMPRESSION_DEFLATE:
731       case RL2_COMPRESSION_LZMA:
732       case RL2_COMPRESSION_GIF:
733       case RL2_COMPRESSION_PNG:
734       case RL2_COMPRESSION_LOSSLESS_WEBP:
735 	  *is_lossless = RL2_TRUE;
736 	  break;
737       default:
738 	  *is_lossless = RL2_FALSE;
739 	  break;
740       };
741     return RL2_OK;
742 }
743 
744 RL2_DECLARE int
rl2_is_section_compression_lossy(rl2SectionPtr ptr,int * is_lossy)745 rl2_is_section_compression_lossy (rl2SectionPtr ptr, int *is_lossy)
746 {
747 /* tests if Section is lossy compressed */
748     rl2PrivSectionPtr scn = (rl2PrivSectionPtr) ptr;
749     if (scn == NULL)
750 	return RL2_ERROR;
751     switch (scn->Compression)
752       {
753       case RL2_COMPRESSION_JPEG:
754       case RL2_COMPRESSION_LOSSY_WEBP:
755 	  *is_lossy = RL2_TRUE;
756 	  break;
757       default:
758 	  *is_lossy = RL2_FALSE;
759 	  break;
760       };
761     return RL2_OK;
762 }
763 
764 RL2_DECLARE int
rl2_get_section_tile_size(rl2SectionPtr ptr,unsigned int * tile_width,unsigned int * tile_height)765 rl2_get_section_tile_size (rl2SectionPtr ptr, unsigned int *tile_width,
766 			   unsigned int *tile_height)
767 {
768 /* return the Section tile width */
769     rl2PrivSectionPtr scn = (rl2PrivSectionPtr) ptr;
770     if (scn == NULL)
771 	return RL2_ERROR;
772     *tile_width = scn->tileWidth;
773     *tile_height = scn->tileHeight;
774     return RL2_OK;
775 }
776 
777 RL2_DECLARE rl2RasterPtr
rl2_get_section_raster(rl2SectionPtr ptr)778 rl2_get_section_raster (rl2SectionPtr ptr)
779 {
780 /* return the Section Raster */
781     rl2PrivSectionPtr scn = (rl2PrivSectionPtr) ptr;
782     if (scn == NULL)
783 	return NULL;
784     return (rl2RasterPtr) (scn->Raster);
785 }
786 
787 int
compute_raster_buffer_size(unsigned short width,unsigned short height,unsigned char sample_type,unsigned char num_samples)788 compute_raster_buffer_size (unsigned short width, unsigned short height,
789 			    unsigned char sample_type,
790 			    unsigned char num_samples)
791 {
792 /* determining the pixel buffer size */
793     int pixel_size = 1;
794     switch (sample_type)
795       {
796       case RL2_SAMPLE_INT16:
797       case RL2_SAMPLE_UINT16:
798 	  pixel_size = 2;
799 	  break;
800       case RL2_SAMPLE_INT32:
801       case RL2_SAMPLE_UINT32:
802       case RL2_SAMPLE_FLOAT:
803 	  pixel_size = 4;
804 	  break;
805       case RL2_SAMPLE_DOUBLE:
806 	  pixel_size = 8;
807 	  break;
808       };
809     return width * height * pixel_size * num_samples;
810 }
811 
812 static int
check_raster_no_data(rl2PrivPixelPtr pxl_no_data,unsigned char sample_type,unsigned char pixel_type,unsigned char num_samples)813 check_raster_no_data (rl2PrivPixelPtr pxl_no_data, unsigned char sample_type,
814 		      unsigned char pixel_type, unsigned char num_samples)
815 {
816 /* checking if the NoData pixel is consistent with the Raster */
817     if (pxl_no_data == NULL)
818 	return 1;
819     if (pxl_no_data->sampleType != sample_type)
820 	return 0;
821     if (pxl_no_data->pixelType != pixel_type)
822 	return 0;
823     if (pxl_no_data->nBands != num_samples)
824 	return 0;
825     return 1;
826 }
827 
828 RL2_DECLARE rl2RasterPtr
rl2_create_raster(unsigned int width,unsigned int height,unsigned char sample_type,unsigned char pixel_type,unsigned char num_samples,unsigned char * bufpix,int bufpix_size,rl2PalettePtr palette,unsigned char * mask,int mask_size,rl2PixelPtr no_data)829 rl2_create_raster (unsigned int width, unsigned int height,
830 		   unsigned char sample_type, unsigned char pixel_type,
831 		   unsigned char num_samples, unsigned char *bufpix,
832 		   int bufpix_size, rl2PalettePtr palette, unsigned char *mask,
833 		   int mask_size, rl2PixelPtr no_data)
834 {
835 /* allocating and initializing a Raster object */
836     rl2PrivPixelPtr pxl_no_data = (rl2PrivPixelPtr) no_data;
837     unsigned char *p;
838     unsigned int row;
839     unsigned int col;
840     int raster_size;
841     rl2PrivRasterPtr rst = NULL;
842 
843     if (!is_valid_sample_type (sample_type))
844 	return NULL;
845     if (!is_valid_pixel_type (pixel_type))
846 	return NULL;
847     if (!check_raster_self_consistency (sample_type, pixel_type, num_samples))
848 	return NULL;
849     if (width < 1 || height < 1)
850 	return NULL;
851     raster_size =
852 	compute_raster_buffer_size (width, height, sample_type, num_samples);
853     if (bufpix == NULL)
854 	return NULL;
855     if (raster_size != bufpix_size)
856 	return NULL;
857     if (pixel_type == RL2_PIXEL_PALETTE && palette == NULL)
858 	return NULL;
859     if (palette != NULL && pixel_type != RL2_PIXEL_PALETTE)
860 	return NULL;
861     if (!check_raster_no_data
862 	(pxl_no_data, sample_type, pixel_type, num_samples))
863 	return NULL;
864     if (mask != NULL)
865       {
866 	  /* checking the mask size */
867 	  if (width * height != (unsigned int) mask_size)
868 	      return NULL;
869 	  p = mask;
870 	  for (row = 0; row < height; row++)
871 	    {
872 		/* checking if sample doesn't exceed the max value */
873 		for (col = 0; col < width; col++)
874 		  {
875 		      if (*p++ > 1)
876 			  return NULL;
877 		  }
878 	    }
879       }
880     if (palette != NULL)
881       {
882 	  /* checking the Palette for validity */
883 	  unsigned short max_palette;
884 	  rl2_get_palette_entries (palette, &max_palette);
885 	  p = bufpix;
886 	  for (row = 0; row < height; row++)
887 	    {
888 		for (col = 0; col < width; col++)
889 		  {
890 		      if (*p++ >= max_palette)
891 			  return NULL;
892 		  }
893 	    }
894       }
895     switch (sample_type)
896       {
897 	  /* checking if sample doesn't exceed the max value for #bits */
898       case RL2_SAMPLE_1_BIT:
899 	  p = bufpix;
900 	  for (row = 0; row < height; row++)
901 	    {
902 		for (col = 0; col < width; col++)
903 		  {
904 		      if (*p++ > 1)
905 			  return NULL;
906 		  }
907 	    }
908 	  break;
909       case RL2_SAMPLE_2_BIT:
910 	  p = bufpix;
911 	  for (row = 0; row < height; row++)
912 	    {
913 		for (col = 0; col < width; col++)
914 		  {
915 		      if (*p++ > 3)
916 			  return NULL;
917 		  }
918 	    }
919 	  break;
920       case RL2_SAMPLE_4_BIT:
921 	  p = bufpix;
922 	  for (row = 0; row < height; row++)
923 	    {
924 		for (col = 0; col < width; col++)
925 		  {
926 		      if (*p++ > 15)
927 			  return NULL;
928 		  }
929 	    }
930 	  break;
931       };
932 
933     rst = malloc (sizeof (rl2PrivRaster));
934     if (rst == NULL)
935 	return NULL;
936     rst->sampleType = sample_type;
937     rst->pixelType = pixel_type;
938     rst->nBands = num_samples;
939     rst->width = width;
940     rst->height = height;
941     rst->Srid = RL2_GEOREFERENCING_NONE;
942     rst->minX = 0.0;
943     rst->minY = 0.0;
944     rst->maxX = width;
945     rst->maxY = height;
946     rst->rasterBuffer = bufpix;
947     rst->maskBuffer = mask;
948     rst->Palette = (rl2PrivPalettePtr) palette;
949     rst->noData = pxl_no_data;
950     return (rl2RasterPtr) rst;
951 }
952 
953 RL2_DECLARE void
rl2_destroy_raster(rl2RasterPtr ptr)954 rl2_destroy_raster (rl2RasterPtr ptr)
955 {
956 /* memory cleanup - destroying a Raster object */
957     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
958     if (rst == NULL)
959 	return;
960     if (rst->rasterBuffer != NULL)
961 	free (rst->rasterBuffer);
962     if (rst->maskBuffer != NULL)
963 	free (rst->maskBuffer);
964     if (rst->Palette != NULL)
965 	rl2_destroy_palette ((rl2PalettePtr) (rst->Palette));
966     if (rst->noData != NULL)
967 	rl2_destroy_pixel ((rl2PixelPtr) (rst->noData));
968     free (rst);
969 }
970 
971 RL2_DECLARE int
rl2_set_raster_no_data(rl2RasterPtr ptr,rl2PixelPtr no_data)972 rl2_set_raster_no_data (rl2RasterPtr ptr, rl2PixelPtr no_data)
973 {
974 /* explicitly sets the Raster NoData pixel */
975     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
976     rl2PrivPixelPtr pxl_no_data = (rl2PrivPixelPtr) no_data;
977     if (rst == NULL)
978 	return RL2_ERROR;
979     if (!check_raster_no_data
980 	(pxl_no_data, rst->sampleType, rst->pixelType, rst->nBands))
981 	return RL2_ERROR;
982     if (rst->noData != NULL)
983 	rl2_destroy_pixel ((rl2PixelPtr) (rst->noData));
984     rst->noData = pxl_no_data;
985     return RL2_OK;
986 }
987 
988 RL2_DECLARE rl2PixelPtr
rl2_get_raster_no_data(rl2RasterPtr ptr)989 rl2_get_raster_no_data (rl2RasterPtr ptr)
990 {
991 /* return the Raster NoData pixel (if any) */
992     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
993     if (rst == NULL)
994 	return NULL;
995     return (rl2PixelPtr) (rst->noData);
996 }
997 
998 RL2_DECLARE int
rl2_get_raster_type(rl2RasterPtr ptr,unsigned char * sample_type,unsigned char * pixel_type,unsigned char * num_bands)999 rl2_get_raster_type (rl2RasterPtr ptr, unsigned char *sample_type,
1000 		     unsigned char *pixel_type, unsigned char *num_bands)
1001 {
1002 /* return the Raster type */
1003     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
1004     if (rst == NULL)
1005 	return RL2_ERROR;
1006     *sample_type = rst->sampleType;
1007     *pixel_type = rst->pixelType;
1008     *num_bands = rst->nBands;
1009     return RL2_OK;
1010 }
1011 
1012 RL2_DECLARE int
rl2_get_raster_size(rl2RasterPtr ptr,unsigned int * width,unsigned int * height)1013 rl2_get_raster_size (rl2RasterPtr ptr, unsigned int *width,
1014 		     unsigned int *height)
1015 {
1016 /* return the Raster width and height */
1017     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
1018     if (rst == NULL)
1019 	return RL2_ERROR;
1020     *width = rst->width;
1021     *height = rst->height;
1022     return RL2_OK;
1023 }
1024 
1025 RL2_DECLARE int
rl2_get_raster_srid(rl2RasterPtr ptr,int * srid)1026 rl2_get_raster_srid (rl2RasterPtr ptr, int *srid)
1027 {
1028 /* return the Raster SRID */
1029     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
1030     if (rst == NULL)
1031 	return RL2_ERROR;
1032     *srid = rst->Srid;
1033     return RL2_OK;
1034 }
1035 
1036 RL2_DECLARE int
rl2_get_raster_extent(rl2RasterPtr ptr,double * minX,double * minY,double * maxX,double * maxY)1037 rl2_get_raster_extent (rl2RasterPtr ptr, double *minX, double *minY,
1038 		       double *maxX, double *maxY)
1039 {
1040 /* return the Raster Min X coord */
1041     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
1042     if (rst == NULL)
1043 	return RL2_ERROR;
1044     if (rst->Srid == RL2_GEOREFERENCING_NONE)
1045       {
1046 	  *minX = 0.0;
1047 	  *minY = 0.0;
1048 	  *maxX = rst->width;
1049 	  *maxY = rst->height;
1050 	  return RL2_OK;
1051       }
1052     *minX = rst->minX;
1053     *minY = rst->minY;
1054     *maxX = rst->maxX;
1055     *maxY = rst->maxY;
1056     return RL2_OK;
1057 }
1058 
1059 RL2_DECLARE gaiaGeomCollPtr
rl2_get_raster_bbox(rl2RasterPtr ptr)1060 rl2_get_raster_bbox (rl2RasterPtr ptr)
1061 {
1062 /* return the Raster BBox [envelope] */
1063     gaiaGeomCollPtr geom;
1064     gaiaPolygonPtr pg;
1065     gaiaRingPtr rng;
1066     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
1067     if (rst == NULL)
1068 	return NULL;
1069     if (rst->Srid == RL2_GEOREFERENCING_NONE)
1070 	return NULL;
1071     geom = gaiaAllocGeomColl ();
1072     geom->Srid = rst->Srid;
1073     pg = gaiaAddPolygonToGeomColl (geom, 5, 0);
1074     rng = pg->Exterior;
1075     gaiaSetPoint (rng->Coords, 0, rst->minX, rst->minY);
1076     gaiaSetPoint (rng->Coords, 1, rst->maxX, rst->minY);
1077     gaiaSetPoint (rng->Coords, 2, rst->maxX, rst->maxY);
1078     gaiaSetPoint (rng->Coords, 3, rst->minX, rst->maxY);
1079     gaiaSetPoint (rng->Coords, 4, rst->minX, rst->minY);
1080     return geom;
1081 }
1082 
1083 RL2_DECLARE int
rl2_get_raster_resolution(rl2RasterPtr ptr,double * hResolution,double * vResolution)1084 rl2_get_raster_resolution (rl2RasterPtr ptr, double *hResolution,
1085 			   double *vResolution)
1086 {
1087 /* return the Raster resolution */
1088     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
1089     if (rst == NULL)
1090 	return RL2_ERROR;
1091     if (rst->Srid == RL2_GEOREFERENCING_NONE)
1092 	return RL2_ERROR;
1093     *hResolution = rst->hResolution;
1094     *vResolution = rst->vResolution;
1095     return RL2_OK;
1096 }
1097 
1098 RL2_DECLARE rl2PalettePtr
rl2_get_raster_palette(rl2RasterPtr ptr)1099 rl2_get_raster_palette (rl2RasterPtr ptr)
1100 {
1101 /* return a pointer to the Raster palette */
1102     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
1103     if (rst == NULL)
1104 	return NULL;
1105     return (rl2PalettePtr) (rst->Palette);
1106 }
1107 
1108 RL2_DECLARE int
rl2_raster_georeference_center(rl2RasterPtr ptr,int srid,double horz_res,double vert_res,double cx,double cy)1109 rl2_raster_georeference_center (rl2RasterPtr ptr, int srid, double horz_res,
1110 				double vert_res, double cx, double cy)
1111 {
1112 /* setting the Raster's georeferencing infos - Center Point */
1113     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
1114     double hExt;
1115     double vExt;
1116     if (rst == NULL)
1117 	return RL2_ERROR;
1118     rst->Srid = srid;
1119     rst->hResolution = horz_res;
1120     rst->vResolution = vert_res;
1121     hExt = horz_res * (double) (rst->width) / 2.0;
1122     vExt = vert_res * (double) (rst->height) / 2.0;
1123     rst->minX = cx - hExt;
1124     rst->minY = cy - vExt;
1125     rst->maxX = cx + hExt;
1126     rst->maxY = cy + vExt;
1127     return RL2_OK;
1128 }
1129 
1130 RL2_DECLARE int
rl2_raster_georeference_upper_left(rl2RasterPtr ptr,int srid,double horz_res,double vert_res,double x,double y)1131 rl2_raster_georeference_upper_left (rl2RasterPtr ptr, int srid, double horz_res,
1132 				    double vert_res, double x, double y)
1133 {
1134 /* setting the Raster's georeferencing infos - UpperLeft corner */
1135     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
1136     double hExt;
1137     double vExt;
1138     if (rst == NULL)
1139 	return RL2_ERROR;
1140     rst->Srid = srid;
1141     rst->hResolution = horz_res;
1142     rst->vResolution = vert_res;
1143     hExt = horz_res * (double) (rst->width);
1144     vExt = vert_res * (double) (rst->height);
1145     rst->minX = x;
1146     rst->minY = y - vExt;
1147     rst->maxX = x + hExt;
1148     rst->maxY = y;
1149     return RL2_OK;
1150 }
1151 
1152 RL2_DECLARE int
rl2_raster_georeference_upper_right(rl2RasterPtr ptr,int srid,double horz_res,double vert_res,double x,double y)1153 rl2_raster_georeference_upper_right (rl2RasterPtr ptr, int srid,
1154 				     double horz_res, double vert_res, double x,
1155 				     double y)
1156 {
1157 /* setting the Raster's georeferencing infos - UpperRight corner */
1158     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
1159     double hExt;
1160     double vExt;
1161     if (rst == NULL)
1162 	return RL2_ERROR;
1163     rst->Srid = srid;
1164     rst->hResolution = horz_res;
1165     rst->vResolution = vert_res;
1166     hExt = horz_res * (double) (rst->width);
1167     vExt = vert_res * (double) (rst->height);
1168     rst->minX = x - hExt;
1169     rst->minY = y - vExt;
1170     rst->maxX = x;
1171     rst->maxY = y;
1172     return RL2_OK;
1173 }
1174 
1175 RL2_DECLARE int
rl2_raster_georeference_lower_left(rl2RasterPtr ptr,int srid,double horz_res,double vert_res,double x,double y)1176 rl2_raster_georeference_lower_left (rl2RasterPtr ptr, int srid, double horz_res,
1177 				    double vert_res, double x, double y)
1178 {
1179 /* setting the Raster's georeferencing infos - LowerLeft corner */
1180     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
1181     double hExt;
1182     double vExt;
1183     if (rst == NULL)
1184 	return RL2_ERROR;
1185     rst->Srid = srid;
1186     rst->hResolution = horz_res;
1187     rst->vResolution = vert_res;
1188     hExt = horz_res * (double) (rst->width);
1189     vExt = vert_res * (double) (rst->height);
1190     rst->minX = x;
1191     rst->minY = y;
1192     rst->maxX = x + hExt;
1193     rst->maxY = y + vExt;
1194     return RL2_OK;
1195 }
1196 
1197 RL2_DECLARE int
rl2_raster_georeference_lower_right(rl2RasterPtr ptr,int srid,double horz_res,double vert_res,double x,double y)1198 rl2_raster_georeference_lower_right (rl2RasterPtr ptr, int srid,
1199 				     double horz_res, double vert_res, double x,
1200 				     double y)
1201 {
1202 /* setting the Raster's georeferencing infos - LowerRight corner */
1203     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
1204     double hExt;
1205     double vExt;
1206     if (rst == NULL)
1207 	return RL2_ERROR;
1208     rst->Srid = srid;
1209     rst->hResolution = horz_res;
1210     rst->vResolution = vert_res;
1211     hExt = horz_res * (double) (rst->width);
1212     vExt = vert_res * (double) (rst->height);
1213     rst->minX = x - hExt;
1214     rst->minY = y;
1215     rst->maxX = x;
1216     rst->maxY = y + vExt;
1217     return RL2_OK;
1218 }
1219 
1220 RL2_DECLARE int
rl2_raster_georeference_frame(rl2RasterPtr ptr,int srid,double min_x,double min_y,double max_x,double max_y)1221 rl2_raster_georeference_frame (rl2RasterPtr ptr, int srid, double min_x,
1222 			       double min_y, double max_x, double max_y)
1223 {
1224 /* setting the Raster's georeferencing infos - LowerRight corner */
1225     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
1226     double hExt;
1227     double vExt;
1228     double horz_res;
1229     double vert_res;
1230     if (rst == NULL)
1231 	return RL2_ERROR;
1232     if (max_x <= min_x)
1233 	return RL2_ERROR;
1234     if (max_y <= min_y)
1235 	return RL2_ERROR;
1236 
1237     rst->Srid = srid;
1238     rst->minX = min_x;
1239     rst->minY = min_y;
1240     rst->maxX = max_x;
1241     rst->maxY = max_y;
1242     hExt = max_x - min_x;
1243     vExt = max_y - min_y;
1244     horz_res = hExt / (double) (rst->width);
1245     vert_res = vExt / (double) (rst->height);
1246     rst->hResolution = horz_res;
1247     rst->vResolution = vert_res;
1248     hExt = horz_res * (double) (rst->width);
1249     vExt = vert_res * (double) (rst->height);
1250     return RL2_OK;
1251 }
1252 
1253 RL2_DECLARE rl2PalettePtr
rl2_create_palette(int num_entries)1254 rl2_create_palette (int num_entries)
1255 {
1256 /* allocating and initializing a Palette object */
1257     int i;
1258     rl2PrivPalettePtr plt = NULL;
1259     if (num_entries < 0 || num_entries > 256)
1260 	return NULL;
1261 
1262     plt = malloc (sizeof (rl2PrivPalette));
1263     if (plt == NULL)
1264 	return NULL;
1265     plt->nEntries = num_entries;
1266     if (num_entries == 0)
1267       {
1268 	  plt->entries = NULL;
1269 	  return (rl2PalettePtr) plt;
1270       }
1271     plt->entries = malloc (sizeof (rl2PrivPaletteEntry) * num_entries);
1272     if (plt->entries == NULL)
1273       {
1274 	  free (plt);
1275 	  return NULL;
1276       }
1277     for (i = 0; i < num_entries; i++)
1278       {
1279 	  /* setting all entries as BLACK full opaque */
1280 	  rl2PrivPaletteEntryPtr entry = plt->entries + i;
1281 	  entry->red = 0;
1282 	  entry->green = 0;
1283 	  entry->blue = 0;
1284       }
1285     return (rl2PalettePtr) plt;
1286 }
1287 
1288 RL2_DECLARE void
rl2_destroy_palette(rl2PalettePtr ptr)1289 rl2_destroy_palette (rl2PalettePtr ptr)
1290 {
1291 /* memory cleanup - destroying a Palette object */
1292     rl2PrivPalettePtr plt = (rl2PrivPalettePtr) ptr;
1293     if (plt == NULL)
1294 	return;
1295     if (plt->entries != NULL)
1296 	free (plt->entries);
1297     free (plt);
1298 }
1299 
1300 RL2_DECLARE rl2PalettePtr
rl2_clone_palette(rl2PalettePtr in)1301 rl2_clone_palette (rl2PalettePtr in)
1302 {
1303 /* cloning a Palette object */
1304     rl2PrivPalettePtr plt_in = (rl2PrivPalettePtr) in;
1305     rl2PalettePtr out;
1306     rl2PrivPalettePtr plt_out;
1307     int i;
1308     if (in == NULL)
1309 	return NULL;
1310     out = rl2_create_palette (plt_in->nEntries);
1311     plt_out = (rl2PrivPalettePtr) out;
1312     for (i = 0; i < plt_out->nEntries; i++)
1313       {
1314 	  rl2PrivPaletteEntryPtr entry_in = plt_in->entries + i;
1315 	  rl2PrivPaletteEntryPtr entry_out = plt_out->entries + i;
1316 	  entry_out->red = entry_in->red;
1317 	  entry_out->green = entry_in->green;
1318 	  entry_out->blue = entry_in->blue;
1319       }
1320     return out;
1321 }
1322 
1323 RL2_DECLARE int
rl2_compare_palettes(rl2PalettePtr palette_1,rl2PalettePtr palette_2)1324 rl2_compare_palettes (rl2PalettePtr palette_1, rl2PalettePtr palette_2)
1325 {
1326 /* comparing two Palette objects */
1327     rl2PrivPalettePtr plt_1 = (rl2PrivPalettePtr) palette_1;
1328     rl2PrivPalettePtr plt_2 = (rl2PrivPalettePtr) palette_2;
1329     int i;
1330     if (plt_1 == NULL || plt_2 == NULL)
1331 	return 0;
1332     if (plt_1->nEntries != plt_2->nEntries)
1333 	return 0;
1334     for (i = 0; i < plt_2->nEntries; i++)
1335       {
1336 	  rl2PrivPaletteEntryPtr entry_1 = plt_1->entries + i;
1337 	  rl2PrivPaletteEntryPtr entry_2 = plt_2->entries + i;
1338 	  if (entry_1->red != entry_2->red)
1339 	      return 0;
1340 	  if (entry_1->green != entry_2->green)
1341 	      return 0;
1342 	  if (entry_1->blue != entry_2->blue)
1343 	      return 0;
1344       }
1345     return 1;
1346 }
1347 
1348 static int
check_monochrome(int max,unsigned char * red,unsigned char * green,unsigned char * blue)1349 check_monochrome (int max, unsigned char *red, unsigned char *green,
1350 		  unsigned char *blue)
1351 {
1352 /* testing for a MONOCHROME palette */
1353     if (max != 2)
1354 	return 0;
1355     if (*(red + 0) != 255 || *(green + 0) != 255 || *(blue + 0) != 255)
1356 	return 0;
1357     if (*(red + 1) != 0 || *(green + 1) != 0 || *(blue + 1) != 0)
1358 	return 0;
1359     return 1;
1360 }
1361 
1362 static int
check_gray(int max,unsigned char * red,unsigned char * green,unsigned char * blue)1363 check_gray (int max, unsigned char *red, unsigned char *green,
1364 	    unsigned char *blue)
1365 {
1366 /* testing for a GRAYSCALE palette */
1367     int i;
1368     if (max == 4)
1369       {
1370 	  /* Gray4 */
1371 	  if (*(red + 0) != 0 || *(green + 0) != 0 || *(blue + 0) != 0)
1372 	      return 0;
1373 	  if (*(red + 1) != 86 || *(green + 1) != 86 || *(blue + 1) != 86)
1374 	      return 0;
1375 	  if (*(red + 2) != 170 || *(green + 2) != 170 || *(blue + 2) != 170)
1376 	      return 0;
1377 	  if (*(red + 3) != 255 || *(green + 3) != 255 || *(blue + 3) != 255)
1378 	      return 0;
1379 	  return 1;
1380       }
1381     if (max == 16)
1382       {
1383 	  /* Gray16 */
1384 	  if (*(red + 0) != 0 || *(green + 0) != 0 || *(blue + 0) != 0)
1385 	      return 0;
1386 	  if (*(red + 1) != 17 || *(green + 1) != 17 || *(blue + 1) != 17)
1387 	      return 0;
1388 	  if (*(red + 2) != 34 || *(green + 2) != 34 || *(blue + 2) != 34)
1389 	      return 0;
1390 	  if (*(red + 3) != 51 || *(green + 3) != 51 || *(blue + 3) != 51)
1391 	      return 0;
1392 	  if (*(red + 4) != 68 || *(green + 4) != 68 || *(blue + 4) != 68)
1393 	      return 0;
1394 	  if (*(red + 5) != 85 || *(green + 5) != 85 || *(blue + 5) != 85)
1395 	      return 0;
1396 	  if (*(red + 6) != 102 || *(green + 6) != 102 || *(blue + 6) != 102)
1397 	      return 0;
1398 	  if (*(red + 7) != 119 || *(green + 7) != 119 || *(blue + 7) != 119)
1399 	      return 0;
1400 	  if (*(red + 8) != 137 || *(green + 8) != 137 || *(blue + 8) != 137)
1401 	      return 0;
1402 	  if (*(red + 9) != 154 || *(green + 9) != 154 || *(blue + 9) != 154)
1403 	      return 0;
1404 	  if (*(red + 10) != 171 || *(green + 10) != 171 || *(blue + 10) != 171)
1405 	      return 0;
1406 	  if (*(red + 11) != 188 || *(green + 11) != 188 || *(blue + 11) != 188)
1407 	      return 0;
1408 	  if (*(red + 12) != 205 || *(green + 12) != 205 || *(blue + 12) != 205)
1409 	      return 0;
1410 	  if (*(red + 13) != 222 || *(green + 13) != 222 || *(blue + 13) != 222)
1411 	      return 0;
1412 	  if (*(red + 14) != 239 || *(green + 14) != 239 || *(blue + 14) != 239)
1413 	      return 0;
1414 	  if (*(red + 15) != 255 || *(green + 15) != 255 || *(blue + 15) != 255)
1415 	      return 0;
1416 	  return 1;
1417       }
1418     if (max == 256)
1419       {
1420 	  /* Gray256 */
1421 	  for (i = 0; i < max; i++)
1422 	    {
1423 		if (*(red + i) != i || *(green + i) != i || *(blue + i) != i)
1424 		    return 0;
1425 	    }
1426 	  return 1;
1427       }
1428     return 0;
1429 }
1430 
1431 RL2_DECLARE int
rl2_get_palette_type(rl2PalettePtr ptr,unsigned char * sample_type,unsigned char * pixel_type)1432 rl2_get_palette_type (rl2PalettePtr ptr, unsigned char *sample_type,
1433 		      unsigned char *pixel_type)
1434 {
1435 /* retrieving the palette type */
1436     unsigned char red[256];
1437     unsigned char green[256];
1438     unsigned char blue[256];
1439     int max = 0;
1440     int index;
1441     int i;
1442     int already_defined;
1443     rl2PrivPaletteEntryPtr entry;
1444     rl2PrivPalettePtr palette = (rl2PrivPalettePtr) ptr;
1445     if (palette == NULL)
1446 	return RL2_ERROR;
1447 
1448     for (index = 0; index < palette->nEntries; index++)
1449       {
1450 	  /* normalizing the palette, so to avoid duplicate colors */
1451 	  already_defined = 0;
1452 	  entry = palette->entries + index;
1453 	  for (i = 0; i < max; i++)
1454 	    {
1455 		if (entry->red == red[i] && entry->green == green[i]
1456 		    && entry->blue == blue[i])
1457 		  {
1458 		      already_defined = 1;
1459 		      break;
1460 		  }
1461 	    }
1462 	  if (!already_defined)
1463 	    {
1464 		/* inserting a normalized color */
1465 		red[max] = entry->red;
1466 		green[max] = entry->green;
1467 		blue[max] = entry->blue;
1468 		max++;
1469 	    }
1470       }
1471     if (max <= 2)
1472 	*sample_type = RL2_SAMPLE_1_BIT;
1473     else if (max <= 4)
1474 	*sample_type = RL2_SAMPLE_2_BIT;
1475     else if (max <= 16)
1476 	*sample_type = RL2_SAMPLE_4_BIT;
1477     else
1478 	*sample_type = RL2_SAMPLE_UINT8;
1479     *pixel_type = RL2_PIXEL_PALETTE;
1480     if (check_monochrome (max, red, green, blue))
1481 	*pixel_type = RL2_PIXEL_MONOCHROME;
1482     else if (check_gray (max, red, green, blue))
1483 	*pixel_type = RL2_PIXEL_GRAYSCALE;
1484     return RL2_OK;
1485 }
1486 
1487 RL2_DECLARE int
rl2_set_palette_color(rl2PalettePtr ptr,int index,unsigned char r,unsigned char g,unsigned char b)1488 rl2_set_palette_color (rl2PalettePtr ptr, int index, unsigned char r,
1489 		       unsigned char g, unsigned char b)
1490 {
1491 /* setting a Palette entry */
1492     rl2PrivPaletteEntryPtr entry;
1493     rl2PrivPalettePtr plt = (rl2PrivPalettePtr) ptr;
1494     if (plt == NULL)
1495 	return RL2_ERROR;
1496     if (index < 0 || index >= plt->nEntries)
1497 	return RL2_ERROR;
1498     entry = plt->entries + index;
1499     entry->red = r;
1500     entry->green = g;
1501     entry->blue = b;
1502     return RL2_OK;
1503 }
1504 
1505 RL2_DECLARE int
rl2_get_palette_index(rl2PalettePtr ptr,unsigned char * index,unsigned char r,unsigned char g,unsigned char b)1506 rl2_get_palette_index (rl2PalettePtr ptr, unsigned char *index, unsigned char r,
1507 		       unsigned char g, unsigned char b)
1508 {
1509 /* finding the index corresponding to the given color (if any) */
1510     int i;
1511     rl2PrivPaletteEntryPtr entry;
1512     rl2PrivPalettePtr plt = (rl2PrivPalettePtr) ptr;
1513     if (plt == NULL)
1514 	return RL2_ERROR;
1515     for (i = 0; i < plt->nEntries; i++)
1516       {
1517 	  entry = plt->entries + i;
1518 	  if (entry->red == r && entry->green == g && entry->blue == b)
1519 	    {
1520 		*index = i;
1521 		return RL2_OK;
1522 	    }
1523       }
1524     return RL2_ERROR;
1525 }
1526 
1527 static int
parse_hex(unsigned char hi,unsigned char lo,unsigned char * x)1528 parse_hex (unsigned char hi, unsigned char lo, unsigned char *x)
1529 {
1530 /* parsing an Hex Byte */
1531     unsigned char res;
1532     switch (hi)
1533       {
1534       case '0':
1535 	  res = 0;
1536 	  break;
1537       case '1':
1538 	  res = 16;
1539 	  break;
1540       case '2':
1541 	  res = 2 * 16;
1542 	  break;
1543       case '3':
1544 	  res = 3 * 16;
1545 	  break;
1546       case '4':
1547 	  res = 4 * 16;
1548 	  break;
1549       case '5':
1550 	  res = 5 * 16;
1551 	  break;
1552       case '6':
1553 	  res = 6 * 16;
1554 	  break;
1555       case '7':
1556 	  res = 7 * 16;
1557 	  break;
1558       case '8':
1559 	  res = 8 * 16;
1560 	  break;
1561       case '9':
1562 	  res = 9 * 16;
1563 	  break;
1564       case 'a':
1565       case 'A':
1566 	  res = 10 * 16;
1567 	  break;
1568       case 'b':
1569       case 'B':
1570 	  res = 11 * 16;
1571 	  break;
1572       case 'c':
1573       case 'C':
1574 	  res = 12 * 16;
1575 	  break;
1576       case 'd':
1577       case 'D':
1578 	  res = 13 * 16;
1579 	  break;
1580       case 'e':
1581       case 'E':
1582 	  res = 14 * 16;
1583 	  break;
1584       case 'f':
1585       case 'F':
1586 	  res = 15 * 16;
1587 	  break;
1588       default:
1589 	  return RL2_ERROR;
1590       };
1591     switch (lo)
1592       {
1593       case '0':
1594 	  break;
1595       case '1':
1596 	  res += 1;
1597 	  break;
1598       case '2':
1599 	  res += 2;
1600 	  break;
1601       case '3':
1602 	  res += 3;
1603 	  break;
1604       case '4':
1605 	  res += 4;
1606 	  break;
1607       case '5':
1608 	  res += 5;
1609 	  break;
1610       case '6':
1611 	  res += 6;
1612 	  break;
1613       case '7':
1614 	  res += 7;
1615 	  break;
1616       case '8':
1617 	  res += 8;
1618 	  break;
1619       case '9':
1620 	  res += 9;
1621 	  break;
1622       case 'a':
1623       case 'A':
1624 	  res += 10;
1625 	  break;
1626       case 'b':
1627       case 'B':
1628 	  res += 11;
1629 	  break;
1630       case 'c':
1631       case 'C':
1632 	  res += 12;
1633 	  break;
1634       case 'd':
1635       case 'D':
1636 	  res += 13;
1637 	  break;
1638       case 'e':
1639       case 'E':
1640 	  res += 14;
1641 	  break;
1642       case 'f':
1643       case 'F':
1644 	  res += 15;
1645 	  break;
1646       default:
1647 	  return RL2_ERROR;
1648       };
1649     *x = res;
1650     return RL2_OK;
1651 }
1652 
1653 static int
parse_hex_rgb(const char * hex,unsigned char * r,unsigned char * g,unsigned char * b)1654 parse_hex_rgb (const char *hex, unsigned char *r, unsigned char *g,
1655 	       unsigned char *b)
1656 {
1657 /* parsing an Hex RGB */
1658     if (parse_hex (*(hex + 0), *(hex + 1), r) != RL2_OK)
1659 	goto error;
1660     if (parse_hex (*(hex + 2), *(hex + 3), g) != RL2_OK)
1661 	goto error;
1662     if (parse_hex (*(hex + 4), *(hex + 5), b) != RL2_OK)
1663 	goto error;
1664     return RL2_OK;
1665   error:
1666     *r = 0;
1667     *g = 0;
1668     *b = 0;
1669     return RL2_ERROR;
1670 }
1671 
1672 RL2_DECLARE int
rl2_parse_hexrgb(const char * hex,unsigned char * red,unsigned char * green,unsigned char * blue)1673 rl2_parse_hexrgb (const char *hex, unsigned char *red, unsigned char *green,
1674 		  unsigned char *blue)
1675 {
1676 /* setting a Palette entry */
1677     if (hex == NULL)
1678 	return RL2_ERROR;
1679     if (strlen (hex) != 7)
1680 	return RL2_ERROR;
1681     if (*hex != '#')
1682 	return RL2_ERROR;
1683     if (parse_hex_rgb (hex + 1, red, green, blue) != RL2_OK)
1684 	return RL2_ERROR;
1685     return RL2_OK;
1686 }
1687 
1688 RL2_DECLARE int
rl2_set_palette_hexrgb(rl2PalettePtr ptr,int index,const char * hex)1689 rl2_set_palette_hexrgb (rl2PalettePtr ptr, int index, const char *hex)
1690 {
1691 /* setting a Palette entry */
1692     unsigned char r;
1693     unsigned char g;
1694     unsigned char b;
1695     rl2PrivPaletteEntryPtr entry;
1696     rl2PrivPalettePtr plt = (rl2PrivPalettePtr) ptr;
1697     if (plt == NULL)
1698 	return RL2_ERROR;
1699     if (index < 0 || index >= plt->nEntries)
1700 	return RL2_ERROR;
1701     if (hex == NULL)
1702 	return RL2_ERROR;
1703     if (strlen (hex) != 7)
1704 	return RL2_ERROR;
1705     if (*hex != '#')
1706 	return RL2_ERROR;
1707     if (parse_hex_rgb (hex + 1, &r, &g, &b) != RL2_OK)
1708 	return RL2_ERROR;
1709     entry = plt->entries + index;
1710     entry->red = r;
1711     entry->green = g;
1712     entry->blue = b;
1713     return RL2_OK;
1714 }
1715 
1716 RL2_DECLARE int
rl2_get_palette_entries(rl2PalettePtr ptr,unsigned short * num_entries)1717 rl2_get_palette_entries (rl2PalettePtr ptr, unsigned short *num_entries)
1718 {
1719 /* return the Palette entries count */
1720     rl2PrivPalettePtr plt = (rl2PrivPalettePtr) ptr;
1721     if (plt == NULL)
1722 	return RL2_ERROR;
1723     *num_entries = plt->nEntries;
1724     return RL2_OK;
1725 }
1726 
1727 RL2_DECLARE int
rl2_get_palette_colors(rl2PalettePtr ptr,unsigned short * num_entries,unsigned char ** r,unsigned char ** g,unsigned char ** b)1728 rl2_get_palette_colors (rl2PalettePtr ptr, unsigned short *num_entries,
1729 			unsigned char **r, unsigned char **g, unsigned char **b)
1730 {
1731 /* return the Palette colors */
1732     rl2PrivPalettePtr plt = (rl2PrivPalettePtr) ptr;
1733     unsigned char *red = NULL;
1734     unsigned char *green = NULL;
1735     unsigned char *blue = NULL;
1736     int i;
1737     *num_entries = 0;
1738     *r = NULL;
1739     *g = NULL;
1740     *b = NULL;
1741     if (plt == NULL)
1742 	return RL2_ERROR;
1743     red = malloc (plt->nEntries);
1744     green = malloc (plt->nEntries);
1745     blue = malloc (plt->nEntries);
1746     if (red == NULL || green == NULL || blue == NULL)
1747       {
1748 	  if (red != NULL)
1749 	      free (red);
1750 	  if (green != NULL)
1751 	      free (green);
1752 	  if (blue != NULL)
1753 	      free (blue);
1754 	  return RL2_ERROR;
1755       }
1756     for (i = 0; i < plt->nEntries; i++)
1757       {
1758 	  rl2PrivPaletteEntryPtr entry = plt->entries + i;
1759 	  *(red + i) = entry->red;
1760 	  *(green + i) = entry->green;
1761 	  *(blue + i) = entry->blue;
1762       }
1763     *num_entries = plt->nEntries;
1764     *r = red;
1765     *g = green;
1766     *b = blue;
1767     return RL2_OK;
1768 }
1769 
1770 RL2_DECLARE rl2PixelPtr
rl2_create_pixel(unsigned char sample_type,unsigned char pixel_type,unsigned char num_samples)1771 rl2_create_pixel (unsigned char sample_type, unsigned char pixel_type,
1772 		  unsigned char num_samples)
1773 {
1774 /* allocating and initializing a Pixel object */
1775     int nBand;
1776     rl2PrivPixelPtr pxl = NULL;
1777     if (!is_valid_sample_type (sample_type))
1778 	return NULL;
1779     if (!is_valid_pixel_type (pixel_type))
1780 	return NULL;
1781     switch (pixel_type)
1782       {
1783       case RL2_PIXEL_MONOCHROME:
1784       case RL2_PIXEL_PALETTE:
1785       case RL2_PIXEL_GRAYSCALE:
1786       case RL2_PIXEL_DATAGRID:
1787 	  if (num_samples != 1)
1788 	      return NULL;
1789 	  break;
1790       case RL2_PIXEL_RGB:
1791 	  if (num_samples != 3)
1792 	      return NULL;
1793 	  break;
1794       case RL2_PIXEL_MULTIBAND:
1795 	  if (num_samples < 2)
1796 	      return NULL;
1797 	  break;
1798       };
1799 
1800     pxl = malloc (sizeof (rl2PrivPixel));
1801     if (pxl == NULL)
1802 	return NULL;
1803     pxl->sampleType = sample_type;
1804     pxl->pixelType = pixel_type;
1805     pxl->nBands = num_samples;
1806     pxl->isTransparent = 0;
1807     pxl->Samples = malloc (sizeof (rl2PrivSample) * num_samples);
1808     if (pxl->Samples == NULL)
1809       {
1810 	  free (pxl);
1811 	  return NULL;
1812       }
1813     for (nBand = 0; nBand < num_samples; nBand++)
1814       {
1815 	  /* initializing all samples as ZERO */
1816 	  rl2PrivSamplePtr sample = pxl->Samples + nBand;
1817 	  switch (sample_type)
1818 	    {
1819 	    case RL2_SAMPLE_1_BIT:
1820 	    case RL2_SAMPLE_2_BIT:
1821 	    case RL2_SAMPLE_4_BIT:
1822 	    case RL2_SAMPLE_UINT8:
1823 		sample->uint8 = 0;
1824 		break;
1825 	    case RL2_SAMPLE_INT8:
1826 		sample->int8 = 0;
1827 		break;
1828 	    case RL2_SAMPLE_INT16:
1829 		sample->int16 = 0;
1830 		break;
1831 	    case RL2_SAMPLE_UINT16:
1832 		sample->uint16 = 0;
1833 		break;
1834 	    case RL2_SAMPLE_INT32:
1835 		sample->int32 = 0;
1836 		break;
1837 	    case RL2_SAMPLE_UINT32:
1838 		sample->uint32 = 0;
1839 		break;
1840 	    case RL2_SAMPLE_FLOAT:
1841 		sample->float32 = 0.0;
1842 		break;
1843 	    case RL2_SAMPLE_DOUBLE:
1844 		sample->float64 = 0.0;
1845 		break;
1846 	    }
1847       }
1848     return (rl2PixelPtr) pxl;
1849 }
1850 
1851 RL2_DECLARE rl2PixelPtr
rl2_clone_pixel(rl2PixelPtr org)1852 rl2_clone_pixel (rl2PixelPtr org)
1853 {
1854 /* cloning a Pixel object */
1855     int b;
1856     rl2PixelPtr dst;
1857     rl2PrivPixelPtr px_out;
1858     rl2PrivPixelPtr px_in = (rl2PrivPixelPtr) org;
1859     if (px_in == NULL)
1860 	return NULL;
1861     dst = rl2_create_pixel (px_in->sampleType, px_in->pixelType, px_in->nBands);
1862     if (dst == NULL)
1863 	return NULL;
1864     px_out = (rl2PrivPixelPtr) dst;
1865     for (b = 0; b < px_in->nBands; b++)
1866       {
1867 	  /* copying all samples */
1868 	  rl2PrivSamplePtr sample_in = px_in->Samples + b;
1869 	  rl2PrivSamplePtr sample_out = px_out->Samples + b;
1870 	  switch (px_in->sampleType)
1871 	    {
1872 	    case RL2_SAMPLE_1_BIT:
1873 	    case RL2_SAMPLE_2_BIT:
1874 	    case RL2_SAMPLE_4_BIT:
1875 	    case RL2_SAMPLE_UINT8:
1876 		sample_out->uint8 = sample_in->uint8;
1877 		break;
1878 	    case RL2_SAMPLE_INT8:
1879 		sample_out->int8 = sample_in->int8;
1880 		break;
1881 	    case RL2_SAMPLE_INT16:
1882 		sample_out->int16 = sample_in->int16;
1883 		break;
1884 	    case RL2_SAMPLE_UINT16:
1885 		sample_out->uint16 = sample_in->uint16;
1886 		break;
1887 	    case RL2_SAMPLE_INT32:
1888 		sample_out->int32 = sample_in->int32;
1889 		break;
1890 	    case RL2_SAMPLE_UINT32:
1891 		sample_out->uint32 = sample_in->uint32;
1892 		break;
1893 	    case RL2_SAMPLE_FLOAT:
1894 		sample_out->float32 = sample_in->float32;
1895 		break;
1896 	    case RL2_SAMPLE_DOUBLE:
1897 		sample_out->float64 = sample_in->float64;
1898 		break;
1899 	    }
1900       }
1901     return dst;
1902 }
1903 
1904 RL2_DECLARE rl2PixelPtr
rl2_create_triple_band_pixel(rl2PixelPtr org,unsigned char red_band,unsigned char green_band,unsigned char blue_band)1905 rl2_create_triple_band_pixel (rl2PixelPtr org, unsigned char red_band,
1906 			      unsigned char green_band, unsigned char blue_band)
1907 {
1908 /* creating a new Pixel object by applying band composing */
1909     rl2PrivSamplePtr sample_in;
1910     rl2PrivSamplePtr sample_out;
1911     rl2PixelPtr dst;
1912     rl2PrivPixelPtr px_out;
1913     rl2PrivPixelPtr px_in = (rl2PrivPixelPtr) org;
1914     if (px_in == NULL)
1915 	return NULL;
1916     if (px_in->sampleType != RL2_SAMPLE_UINT8
1917 	&& px_in->sampleType != RL2_SAMPLE_UINT16)
1918 	return NULL;
1919     if (px_in->pixelType != RL2_PIXEL_RGB
1920 	&& px_in->pixelType != RL2_PIXEL_MULTIBAND)
1921 	return NULL;
1922     if (red_band >= px_in->nBands)
1923 	return NULL;
1924     if (green_band >= px_in->nBands)
1925 	return NULL;
1926     if (blue_band >= px_in->nBands)
1927 	return NULL;
1928     dst = rl2_create_pixel (px_in->sampleType, RL2_PIXEL_RGB, 3);
1929     if (dst == NULL)
1930 	return NULL;
1931     px_out = (rl2PrivPixelPtr) dst;
1932 /* red band */
1933     sample_in = px_in->Samples + red_band;
1934     sample_out = px_out->Samples + 0;
1935     if (px_in->sampleType == RL2_SAMPLE_UINT16)
1936 	sample_out->uint16 = sample_in->uint16;
1937     else
1938 	sample_out->uint8 = sample_in->uint8;
1939 /* green band */
1940     sample_in = px_in->Samples + green_band;
1941     sample_out = px_out->Samples + 1;
1942     if (px_in->sampleType == RL2_SAMPLE_UINT16)
1943 	sample_out->uint16 = sample_in->uint16;
1944     else
1945 	sample_out->uint8 = sample_in->uint8;
1946 /* blue band */
1947     sample_in = px_in->Samples + blue_band;
1948     sample_out = px_out->Samples + 2;
1949     if (px_in->sampleType == RL2_SAMPLE_UINT16)
1950 	sample_out->uint16 = sample_in->uint16;
1951     else
1952 	sample_out->uint8 = sample_in->uint8;
1953     return dst;
1954 }
1955 
1956 RL2_DECLARE rl2PixelPtr
rl2_create_mono_band_pixel(rl2PixelPtr org,unsigned char mono_band)1957 rl2_create_mono_band_pixel (rl2PixelPtr org, unsigned char mono_band)
1958 {
1959 /* creating a new Pixel object by applying band composing */
1960     rl2PrivSamplePtr sample_in;
1961     rl2PrivSamplePtr sample_out;
1962     rl2PixelPtr dst;
1963     rl2PrivPixelPtr px_out;
1964     rl2PrivPixelPtr px_in = (rl2PrivPixelPtr) org;
1965     if (px_in == NULL)
1966 	return NULL;
1967     if (px_in->sampleType != RL2_SAMPLE_UINT8
1968 	&& px_in->sampleType != RL2_SAMPLE_UINT16)
1969 	return NULL;
1970     if (px_in->pixelType != RL2_PIXEL_RGB
1971 	&& px_in->pixelType != RL2_PIXEL_MULTIBAND)
1972 	return NULL;
1973     if (mono_band >= px_in->nBands)
1974 	return NULL;
1975     if (px_in->sampleType == RL2_SAMPLE_UINT16)
1976 	dst = rl2_create_pixel (RL2_SAMPLE_UINT16, RL2_PIXEL_DATAGRID, 1);
1977     else
1978 	dst = rl2_create_pixel (RL2_SAMPLE_UINT8, RL2_PIXEL_RGB, 3);
1979     if (dst == NULL)
1980 	return NULL;
1981     px_out = (rl2PrivPixelPtr) dst;
1982 /* mono band */
1983     sample_in = px_in->Samples + mono_band;
1984     sample_out = px_out->Samples + 0;
1985     if (px_in->sampleType == RL2_SAMPLE_UINT16)
1986 	sample_out->uint16 = sample_in->uint16;
1987     else
1988 	sample_out->uint8 = sample_in->uint8;
1989     return dst;
1990 }
1991 
1992 RL2_DECLARE void
rl2_destroy_pixel(rl2PixelPtr ptr)1993 rl2_destroy_pixel (rl2PixelPtr ptr)
1994 {
1995 /* memory cleanup - destroying a Pixel object */
1996     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
1997     if (pxl == NULL)
1998 	return;
1999     if (pxl->Samples != NULL)
2000 	free (pxl->Samples);
2001     free (pxl);
2002 }
2003 
2004 RL2_DECLARE int
rl2_compare_pixels(rl2PixelPtr pixel1,rl2PixelPtr pixel2)2005 rl2_compare_pixels (rl2PixelPtr pixel1, rl2PixelPtr pixel2)
2006 {
2007 /* comparing if two pixels are the same */
2008     int band;
2009     rl2PrivPixelPtr pxl1 = (rl2PrivPixelPtr) pixel1;
2010     rl2PrivPixelPtr pxl2 = (rl2PrivPixelPtr) pixel2;
2011     if (pxl1 == NULL || pxl2 == NULL)
2012 	return RL2_ERROR;
2013     if (pxl1->sampleType != pxl2->sampleType)
2014 	return RL2_ERROR;
2015     if (pxl1->pixelType != pxl2->pixelType)
2016 	return RL2_ERROR;
2017     if (pxl1->nBands != pxl2->nBands)
2018 	return RL2_ERROR;
2019     for (band = 0; band < pxl1->nBands; band++)
2020       {
2021 	  rl2PrivSamplePtr sample1 = pxl1->Samples + band;
2022 	  rl2PrivSamplePtr sample2 = pxl2->Samples + band;
2023 	  switch (pxl1->sampleType)
2024 	    {
2025 	    case RL2_SAMPLE_INT8:
2026 		if (sample1->int8 != sample2->int8)
2027 		    return RL2_FALSE;
2028 		break;
2029 	    case RL2_SAMPLE_1_BIT:
2030 	    case RL2_SAMPLE_2_BIT:
2031 	    case RL2_SAMPLE_4_BIT:
2032 	    case RL2_SAMPLE_UINT8:
2033 		if (sample1->uint8 != sample2->uint8)
2034 		    return RL2_FALSE;
2035 		break;
2036 	    case RL2_SAMPLE_INT16:
2037 		if (sample1->int16 != sample2->int16)
2038 		    return RL2_FALSE;
2039 		break;
2040 	    case RL2_SAMPLE_UINT16:
2041 		if (sample1->uint16 != sample2->uint16)
2042 		    return RL2_FALSE;
2043 		break;
2044 	    case RL2_SAMPLE_INT32:
2045 		if (sample1->int32 != sample2->int32)
2046 		    return RL2_FALSE;
2047 		break;
2048 	    case RL2_SAMPLE_UINT32:
2049 		if (sample1->uint32 != sample2->uint32)
2050 		    return RL2_FALSE;
2051 		break;
2052 	    case RL2_SAMPLE_FLOAT:
2053 		if (sample1->float32 != sample2->float32)
2054 		    return RL2_FALSE;
2055 		break;
2056 	    case RL2_SAMPLE_DOUBLE:
2057 		if (sample1->float64 != sample2->float64)
2058 		    return RL2_FALSE;
2059 		break;
2060 	    };
2061       }
2062     if (pxl1->isTransparent != pxl2->isTransparent)
2063 	return RL2_FALSE;
2064     return RL2_TRUE;
2065 }
2066 
2067 
2068 RL2_DECLARE int
rl2_get_pixel_type(rl2PixelPtr ptr,unsigned char * sample_type,unsigned char * pixel_type,unsigned char * num_bands)2069 rl2_get_pixel_type (rl2PixelPtr ptr,
2070 		    unsigned char *sample_type,
2071 		    unsigned char *pixel_type, unsigned char *num_bands)
2072 {
2073 /* return the Pixel pixel type */
2074     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2075     if (pxl == NULL)
2076 	return RL2_ERROR;
2077     *sample_type = pxl->sampleType;
2078     *pixel_type = pxl->pixelType;
2079     *num_bands = pxl->nBands;
2080     return RL2_OK;
2081 }
2082 
2083 RL2_DECLARE int
rl2_get_pixel_sample_1bit(rl2PixelPtr ptr,unsigned char * sample)2084 rl2_get_pixel_sample_1bit (rl2PixelPtr ptr, unsigned char *sample)
2085 {
2086 /* get a Pixel/Sample value - 1-BIT */
2087     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2088     if (pxl == NULL)
2089 	return RL2_ERROR;
2090     if (pxl->sampleType != RL2_SAMPLE_1_BIT)
2091 	return RL2_ERROR;
2092     *sample = pxl->Samples->uint8;
2093     return RL2_OK;
2094 }
2095 
2096 RL2_DECLARE int
rl2_set_pixel_sample_1bit(rl2PixelPtr ptr,unsigned char sample)2097 rl2_set_pixel_sample_1bit (rl2PixelPtr ptr, unsigned char sample)
2098 {
2099 /* set a Pixel/Sample value - 1-BIT */
2100     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2101     if (pxl == NULL)
2102 	return RL2_ERROR;
2103     if (pxl->sampleType != RL2_SAMPLE_1_BIT)
2104 	return RL2_ERROR;
2105     if (sample > 1)
2106 	return RL2_ERROR;
2107     pxl->Samples->uint8 = sample;
2108     return RL2_OK;
2109 }
2110 
2111 RL2_DECLARE int
rl2_get_pixel_sample_2bit(rl2PixelPtr ptr,unsigned char * sample)2112 rl2_get_pixel_sample_2bit (rl2PixelPtr ptr, unsigned char *sample)
2113 {
2114 /* get a Pixel/Sample value - 2-BIT */
2115     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2116     if (pxl == NULL)
2117 	return RL2_ERROR;
2118     if (pxl->sampleType != RL2_SAMPLE_2_BIT)
2119 	return RL2_ERROR;
2120     *sample = pxl->Samples->uint8;
2121     return RL2_OK;
2122 }
2123 
2124 RL2_DECLARE int
rl2_set_pixel_sample_2bit(rl2PixelPtr ptr,unsigned char sample)2125 rl2_set_pixel_sample_2bit (rl2PixelPtr ptr, unsigned char sample)
2126 {
2127 /* set a Pixel/Sample value - 2-BIT */
2128     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2129     if (pxl == NULL)
2130 	return RL2_ERROR;
2131     if (pxl->sampleType != RL2_SAMPLE_2_BIT)
2132 	return RL2_ERROR;
2133     if (sample > 3)
2134 	return RL2_ERROR;
2135     pxl->Samples->uint8 = sample;
2136     return RL2_OK;
2137 }
2138 
2139 RL2_DECLARE int
rl2_get_pixel_sample_4bit(rl2PixelPtr ptr,unsigned char * sample)2140 rl2_get_pixel_sample_4bit (rl2PixelPtr ptr, unsigned char *sample)
2141 {
2142 /* get a Pixel/Sample value - 4-BIT */
2143     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2144     if (pxl == NULL)
2145 	return RL2_ERROR;
2146     if (pxl->sampleType != RL2_SAMPLE_4_BIT)
2147 	return RL2_ERROR;
2148     *sample = pxl->Samples->uint8;
2149     return RL2_OK;
2150 }
2151 
2152 RL2_DECLARE int
rl2_set_pixel_sample_4bit(rl2PixelPtr ptr,unsigned char sample)2153 rl2_set_pixel_sample_4bit (rl2PixelPtr ptr, unsigned char sample)
2154 {
2155 /* set a Pixel/Sample value - 4-BIT */
2156     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2157     if (pxl == NULL)
2158 	return RL2_ERROR;
2159     if (pxl->sampleType != RL2_SAMPLE_4_BIT)
2160 	return RL2_ERROR;
2161     if (sample > 15)
2162 	return RL2_ERROR;
2163     pxl->Samples->uint8 = sample;
2164     return RL2_OK;
2165 }
2166 
2167 RL2_DECLARE int
rl2_get_pixel_sample_int8(rl2PixelPtr ptr,char * sample)2168 rl2_get_pixel_sample_int8 (rl2PixelPtr ptr, char *sample)
2169 {
2170 /* get a Pixel/Sample value - INT8 */
2171     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2172     if (pxl == NULL)
2173 	return RL2_ERROR;
2174     if (pxl->sampleType != RL2_SAMPLE_INT8)
2175 	return RL2_ERROR;
2176     *sample = pxl->Samples->int8;
2177     return RL2_OK;
2178 }
2179 
2180 RL2_DECLARE int
rl2_set_pixel_sample_int8(rl2PixelPtr ptr,char sample)2181 rl2_set_pixel_sample_int8 (rl2PixelPtr ptr, char sample)
2182 {
2183 /* set a Pixel/Sample value - INT8 */
2184     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2185     if (pxl == NULL)
2186 	return RL2_ERROR;
2187     if (pxl->sampleType != RL2_SAMPLE_INT8)
2188 	return RL2_ERROR;
2189     pxl->Samples->int8 = sample;
2190     return RL2_OK;
2191 }
2192 
2193 RL2_DECLARE int
rl2_get_pixel_sample_uint8(rl2PixelPtr ptr,int band,unsigned char * sample)2194 rl2_get_pixel_sample_uint8 (rl2PixelPtr ptr, int band, unsigned char *sample)
2195 {
2196 /* get a Pixel/Sample value - UINT8 */
2197     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2198     if (pxl == NULL)
2199 	return RL2_ERROR;
2200     if (pxl->sampleType != RL2_SAMPLE_UINT8)
2201 	return RL2_ERROR;
2202     if (band >= 0 && band < pxl->nBands)
2203       {
2204 	  rl2PrivSamplePtr smp = pxl->Samples + band;
2205 	  *sample = smp->uint8;
2206 	  return RL2_OK;
2207       }
2208     return RL2_ERROR;
2209 }
2210 
2211 RL2_DECLARE int
rl2_set_pixel_sample_uint8(rl2PixelPtr ptr,int band,unsigned char sample)2212 rl2_set_pixel_sample_uint8 (rl2PixelPtr ptr, int band, unsigned char sample)
2213 {
2214 /* set a Pixel/Sample value - UINT8 */
2215     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2216     if (pxl == NULL)
2217 	return RL2_ERROR;
2218     if (pxl->sampleType != RL2_SAMPLE_UINT8)
2219 	return RL2_ERROR;
2220     if (band >= 0 && band < pxl->nBands)
2221       {
2222 	  rl2PrivSamplePtr smp = pxl->Samples + band;
2223 	  smp->uint8 = sample;
2224 	  return RL2_OK;
2225       }
2226     return RL2_ERROR;
2227 }
2228 
2229 RL2_DECLARE int
rl2_get_pixel_sample_int16(rl2PixelPtr ptr,short * sample)2230 rl2_get_pixel_sample_int16 (rl2PixelPtr ptr, short *sample)
2231 {
2232 /* get a Pixel/Sample value - INT16 */
2233     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2234     if (pxl == NULL)
2235 	return RL2_ERROR;
2236     if (pxl->sampleType != RL2_SAMPLE_INT16)
2237 	return RL2_ERROR;
2238     *sample = pxl->Samples->int16;
2239     return RL2_OK;
2240 }
2241 
2242 RL2_DECLARE int
rl2_set_pixel_sample_int16(rl2PixelPtr ptr,short sample)2243 rl2_set_pixel_sample_int16 (rl2PixelPtr ptr, short sample)
2244 {
2245 /* set a Pixel/Sample value - INT16 */
2246     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2247     if (pxl == NULL)
2248 	return RL2_ERROR;
2249     if (pxl->sampleType != RL2_SAMPLE_INT16)
2250 	return RL2_ERROR;
2251     pxl->Samples->int16 = sample;
2252     return RL2_OK;
2253 }
2254 
2255 RL2_DECLARE int
rl2_get_pixel_sample_uint16(rl2PixelPtr ptr,int band,unsigned short * sample)2256 rl2_get_pixel_sample_uint16 (rl2PixelPtr ptr, int band, unsigned short *sample)
2257 {
2258 /* get a Pixel/Sample value - UINT16 */
2259     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2260     if (pxl == NULL)
2261 	return RL2_ERROR;
2262     if (pxl->sampleType != RL2_SAMPLE_UINT16)
2263 	return RL2_ERROR;
2264     if (band >= 0 && band < pxl->nBands)
2265       {
2266 	  rl2PrivSamplePtr smp = pxl->Samples + band;
2267 	  *sample = smp->uint16;
2268 	  return RL2_OK;
2269       }
2270     return RL2_ERROR;
2271 }
2272 
2273 RL2_DECLARE int
rl2_set_pixel_sample_uint16(rl2PixelPtr ptr,int band,unsigned short sample)2274 rl2_set_pixel_sample_uint16 (rl2PixelPtr ptr, int band, unsigned short sample)
2275 {
2276 /* set a Pixel/Sample value - UINT16 */
2277     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2278     if (pxl == NULL)
2279 	return RL2_ERROR;
2280     if (pxl->sampleType != RL2_SAMPLE_UINT16)
2281 	return RL2_ERROR;
2282     if (band >= 0 && band < pxl->nBands)
2283       {
2284 	  rl2PrivSamplePtr smp = pxl->Samples + band;
2285 	  smp->uint16 = sample;
2286 	  return RL2_OK;
2287       }
2288     return RL2_ERROR;
2289 }
2290 
2291 RL2_DECLARE int
rl2_get_pixel_sample_int32(rl2PixelPtr ptr,int * sample)2292 rl2_get_pixel_sample_int32 (rl2PixelPtr ptr, int *sample)
2293 {
2294 /* get a Pixel/Sample value - INT32 */
2295     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2296     if (pxl == NULL)
2297 	return RL2_ERROR;
2298     if (pxl->sampleType != RL2_SAMPLE_INT32)
2299 	return RL2_ERROR;
2300     *sample = pxl->Samples->int32;
2301     return RL2_OK;
2302 }
2303 
2304 RL2_DECLARE int
rl2_set_pixel_sample_int32(rl2PixelPtr ptr,int sample)2305 rl2_set_pixel_sample_int32 (rl2PixelPtr ptr, int sample)
2306 {
2307 /* set a Pixel/Sample value - INT32 */
2308     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2309     if (pxl == NULL)
2310 	return RL2_ERROR;
2311     if (pxl->sampleType != RL2_SAMPLE_INT32)
2312 	return RL2_ERROR;
2313     pxl->Samples->int32 = sample;
2314     return RL2_OK;
2315 }
2316 
2317 RL2_DECLARE int
rl2_get_pixel_sample_uint32(rl2PixelPtr ptr,unsigned int * sample)2318 rl2_get_pixel_sample_uint32 (rl2PixelPtr ptr, unsigned int *sample)
2319 {
2320 /* get a Pixel/Sample value - UINT32 */
2321     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2322     if (pxl == NULL)
2323 	return RL2_ERROR;
2324     if (pxl->sampleType != RL2_SAMPLE_UINT32)
2325 	return RL2_ERROR;
2326     *sample = pxl->Samples->uint32;
2327     return RL2_OK;
2328 }
2329 
2330 RL2_DECLARE int
rl2_set_pixel_sample_uint32(rl2PixelPtr ptr,unsigned int sample)2331 rl2_set_pixel_sample_uint32 (rl2PixelPtr ptr, unsigned int sample)
2332 {
2333 /* set a Pixel/Sample value - UINT32 */
2334     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2335     if (pxl == NULL)
2336 	return RL2_ERROR;
2337     if (pxl->sampleType != RL2_SAMPLE_UINT32)
2338 	return RL2_ERROR;
2339     pxl->Samples->uint32 = sample;
2340     return RL2_OK;
2341 }
2342 
2343 RL2_DECLARE int
rl2_get_pixel_sample_float(rl2PixelPtr ptr,float * sample)2344 rl2_get_pixel_sample_float (rl2PixelPtr ptr, float *sample)
2345 {
2346 /* get a Pixel/Sample value - FLOAT */
2347     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2348     if (pxl == NULL)
2349 	return RL2_ERROR;
2350     if (pxl->sampleType != RL2_SAMPLE_FLOAT)
2351 	return RL2_ERROR;
2352     *sample = pxl->Samples->float32;
2353     return RL2_OK;
2354 }
2355 
2356 RL2_DECLARE int
rl2_set_pixel_sample_float(rl2PixelPtr ptr,float sample)2357 rl2_set_pixel_sample_float (rl2PixelPtr ptr, float sample)
2358 {
2359 /* set a Pixel/Sample value - FLOAT */
2360     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2361     if (pxl == NULL)
2362 	return RL2_ERROR;
2363     if (pxl->sampleType != RL2_SAMPLE_FLOAT)
2364 	return RL2_ERROR;
2365     pxl->Samples->float32 = sample;
2366     return RL2_OK;
2367 }
2368 
2369 RL2_DECLARE int
rl2_get_pixel_sample_double(rl2PixelPtr ptr,double * sample)2370 rl2_get_pixel_sample_double (rl2PixelPtr ptr, double *sample)
2371 {
2372 /* get a Pixel/Sample value - DOUBLE */
2373     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2374     if (pxl == NULL)
2375 	return RL2_ERROR;
2376     if (pxl->sampleType != RL2_SAMPLE_DOUBLE)
2377 	return RL2_ERROR;
2378     *sample = pxl->Samples->float64;
2379     return RL2_OK;
2380 }
2381 
2382 RL2_DECLARE int
rl2_set_pixel_sample_double(rl2PixelPtr ptr,double sample)2383 rl2_set_pixel_sample_double (rl2PixelPtr ptr, double sample)
2384 {
2385 /* set a Pixel/Sample value - DOUBLE */
2386     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2387     if (pxl == NULL)
2388 	return RL2_ERROR;
2389     if (pxl->sampleType != RL2_SAMPLE_DOUBLE)
2390 	return RL2_ERROR;
2391     pxl->Samples->float64 = sample;
2392     return RL2_OK;
2393 }
2394 
2395 RL2_DECLARE int
rl2_is_pixel_transparent(rl2PixelPtr ptr,int * is_transparent)2396 rl2_is_pixel_transparent (rl2PixelPtr ptr, int *is_transparent)
2397 {
2398 /* tests for a transparent pixel */
2399     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2400     if (pxl == NULL)
2401 	return RL2_ERROR;
2402     if (pxl->isTransparent)
2403 	*is_transparent = RL2_TRUE;
2404     else
2405 	*is_transparent = RL2_FALSE;
2406     return RL2_OK;
2407 }
2408 
2409 RL2_DECLARE int
rl2_is_pixel_opaque(rl2PixelPtr ptr,int * is_opaque)2410 rl2_is_pixel_opaque (rl2PixelPtr ptr, int *is_opaque)
2411 {
2412 /* tests for an opaque pixel */
2413     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2414     if (pxl == NULL)
2415 	return RL2_ERROR;
2416     if (pxl->isTransparent)
2417 	*is_opaque = RL2_FALSE;
2418     else
2419 	*is_opaque = RL2_TRUE;
2420     return RL2_OK;
2421 }
2422 
2423 RL2_DECLARE int
rl2_set_pixel_transparent(rl2PixelPtr ptr)2424 rl2_set_pixel_transparent (rl2PixelPtr ptr)
2425 {
2426 /* marks a pixel as transparent */
2427     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2428     if (pxl == NULL)
2429 	return RL2_ERROR;
2430     pxl->isTransparent = 1;
2431     return RL2_OK;
2432 }
2433 
2434 RL2_DECLARE int
rl2_set_pixel_opaque(rl2PixelPtr ptr)2435 rl2_set_pixel_opaque (rl2PixelPtr ptr)
2436 {
2437 /* marks a pixel as opaque */
2438     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) ptr;
2439     if (pxl == NULL)
2440 	return RL2_ERROR;
2441     pxl->isTransparent = 0;
2442     return RL2_OK;
2443 }
2444 
2445 RL2_DECLARE rl2PixelPtr
rl2_create_raster_pixel(rl2RasterPtr ptr)2446 rl2_create_raster_pixel (rl2RasterPtr ptr)
2447 {
2448 /* creating a Pixel matching the given Raster */
2449     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
2450     if (rst == NULL)
2451 	return NULL;
2452     return rl2_create_pixel (rst->sampleType, rst->pixelType, rst->nBands);
2453 }
2454 
2455 RL2_DECLARE int
rl2_get_raster_pixel(rl2RasterPtr ptr,rl2PixelPtr pixel,unsigned int row,unsigned int col)2456 rl2_get_raster_pixel (rl2RasterPtr ptr, rl2PixelPtr pixel, unsigned int row,
2457 		      unsigned int col)
2458 {
2459 /* fetching a Pixel from a Raster */
2460     int nBand;
2461     rl2PrivSamplePtr sample;
2462     char *p_int8;
2463     unsigned char *p_uint8;
2464     short *p_int16;
2465     unsigned short *p_uint16;
2466     int *p_int32;
2467     unsigned int *p_uint32;
2468     float *p_float32;
2469     double *p_float64;
2470     unsigned char *mask;
2471     unsigned char *p_mask;
2472     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
2473     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) pixel;
2474     if (rst == NULL)
2475 	return RL2_ERROR;
2476     if (pxl == NULL)
2477 	return RL2_ERROR;
2478 
2479     if (pxl->sampleType != rst->sampleType || pxl->pixelType != rst->pixelType
2480 	|| pxl->nBands != rst->nBands)
2481 	return RL2_ERROR;
2482     if (row >= rst->height || col >= rst->width)
2483 	return RL2_ERROR;
2484 
2485     for (nBand = 0; nBand < pxl->nBands; nBand++)
2486       {
2487 	  sample = pxl->Samples + nBand;
2488 	  switch (pxl->sampleType)
2489 	    {
2490 	    case RL2_SAMPLE_1_BIT:
2491 	    case RL2_SAMPLE_2_BIT:
2492 	    case RL2_SAMPLE_4_BIT:
2493 	    case RL2_SAMPLE_UINT8:
2494 		p_uint8 = rst->rasterBuffer;
2495 		p_uint8 +=
2496 		    (row * rst->width * pxl->nBands) + (col * pxl->nBands) +
2497 		    nBand;
2498 		sample->uint8 = *p_uint8;
2499 		break;
2500 	    case RL2_SAMPLE_INT8:
2501 		p_int8 = (char *) (rst->rasterBuffer);
2502 		p_int8 +=
2503 		    (row * rst->width * pxl->nBands) + (col * pxl->nBands) +
2504 		    nBand;
2505 		sample->int8 = *p_int8;
2506 		break;
2507 	    case RL2_SAMPLE_INT16:
2508 		p_int16 = (short *) (rst->rasterBuffer);
2509 		p_int16 +=
2510 		    (row * rst->width * pxl->nBands) + (col * pxl->nBands) +
2511 		    nBand;
2512 		sample->int16 = *p_int16;
2513 		break;
2514 	    case RL2_SAMPLE_UINT16:
2515 		p_uint16 = (unsigned short *) (rst->rasterBuffer);
2516 		p_uint16 +=
2517 		    (row * rst->width * pxl->nBands) + (col * pxl->nBands) +
2518 		    nBand;
2519 		sample->uint16 = *p_uint16;
2520 		break;
2521 	    case RL2_SAMPLE_INT32:
2522 		p_int32 = (int *) (rst->rasterBuffer);
2523 		p_int32 +=
2524 		    (row * rst->width * pxl->nBands) + (col * pxl->nBands) +
2525 		    nBand;
2526 		sample->int32 = *p_int32;
2527 		break;
2528 	    case RL2_SAMPLE_UINT32:
2529 		p_uint32 = (unsigned int *) (rst->rasterBuffer);
2530 		p_uint32 +=
2531 		    (row * rst->width * pxl->nBands) + (col * pxl->nBands) +
2532 		    nBand;
2533 		sample->uint32 = *p_uint32;
2534 		break;
2535 	    case RL2_SAMPLE_FLOAT:
2536 		p_float32 = (float *) (rst->rasterBuffer);
2537 		p_float32 +=
2538 		    (row * rst->width * pxl->nBands) + (col * pxl->nBands) +
2539 		    nBand;
2540 		sample->float32 = *p_float32;
2541 		break;
2542 	    case RL2_SAMPLE_DOUBLE:
2543 		p_float64 = (double *) (rst->rasterBuffer);
2544 		p_float64 +=
2545 		    (row * rst->width * pxl->nBands) + (col * pxl->nBands) +
2546 		    nBand;
2547 		sample->float64 = *p_float64;
2548 		break;
2549 	    };
2550       }
2551 
2552 /* transparency */
2553     pxl->isTransparent = 0;
2554     mask = rst->maskBuffer;
2555     if (mask != NULL)
2556       {
2557 	  /* evaluating transparency mask */
2558 	  p_mask = mask + (row * rst->width) + col;
2559 	  if (*p_mask == 0)
2560 	      pxl->isTransparent = 1;
2561       }
2562     if (rst->noData != NULL)
2563       {
2564 	  /* evaluating transparent color */
2565 	  if (rl2_compare_pixels (pixel, (rl2PixelPtr) (rst->noData)) ==
2566 	      RL2_TRUE)
2567 	      pxl->isTransparent = 1;
2568       }
2569     return RL2_OK;
2570 }
2571 
2572 RL2_DECLARE int
rl2_set_raster_pixel(rl2RasterPtr ptr,rl2PixelPtr pixel,unsigned int row,unsigned int col)2573 rl2_set_raster_pixel (rl2RasterPtr ptr, rl2PixelPtr pixel, unsigned int row,
2574 		      unsigned int col)
2575 {
2576 /* changing a Pixel into a Raster */
2577     int nBand;
2578     rl2PrivSamplePtr sample;
2579     char *p_int8;
2580     unsigned char *p_uint8;
2581     short *p_int16;
2582     unsigned short *p_uint16;
2583     int *p_int32;
2584     unsigned int *p_uint32;
2585     float *p_float32;
2586     double *p_float64;
2587     unsigned char *mask;
2588     unsigned char *p_mask;
2589     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) ptr;
2590     rl2PrivPixelPtr pxl = (rl2PrivPixelPtr) pixel;
2591     if (rst == NULL)
2592 	return RL2_ERROR;
2593     if (pxl == NULL)
2594 	return RL2_ERROR;
2595 
2596     if (pxl->sampleType != rst->sampleType || pxl->pixelType != rst->pixelType
2597 	|| pxl->nBands != rst->nBands)
2598 	return RL2_ERROR;
2599     if (row >= rst->height || col >= rst->width)
2600 	return RL2_ERROR;
2601     if (pxl->pixelType == RL2_PIXEL_PALETTE)
2602       {
2603 	  /* blocking any attempt to insert out-palette values */
2604 	  rl2PrivPalettePtr plt = (rl2PrivPalettePtr) rst->Palette;
2605 	  if (pxl->Samples->uint8 >= plt->nEntries)
2606 	      return RL2_ERROR;
2607       }
2608 
2609     for (nBand = 0; nBand < pxl->nBands; nBand++)
2610       {
2611 	  sample = pxl->Samples + nBand;
2612 	  switch (pxl->sampleType)
2613 	    {
2614 	    case RL2_SAMPLE_1_BIT:
2615 	    case RL2_SAMPLE_2_BIT:
2616 	    case RL2_SAMPLE_4_BIT:
2617 	    case RL2_SAMPLE_UINT8:
2618 		p_uint8 = rst->rasterBuffer;
2619 		p_uint8 +=
2620 		    (row * rst->width * pxl->nBands) + (col * pxl->nBands) +
2621 		    nBand;
2622 		*p_uint8 = sample->uint8;
2623 		break;
2624 	    case RL2_SAMPLE_INT8:
2625 		p_int8 = (char *) (rst->rasterBuffer);
2626 		p_int8 +=
2627 		    (row * rst->width * pxl->nBands) + (col * pxl->nBands) +
2628 		    nBand;
2629 		*p_int8 = sample->int8;
2630 		break;
2631 	    case RL2_SAMPLE_INT16:
2632 		p_int16 = (short *) (rst->rasterBuffer);
2633 		p_int16 +=
2634 		    (row * rst->width * pxl->nBands) + (col * pxl->nBands) +
2635 		    nBand;
2636 		*p_int16 = sample->int16;
2637 		break;
2638 	    case RL2_SAMPLE_UINT16:
2639 		p_uint16 = (unsigned short *) (rst->rasterBuffer);
2640 		p_uint16 +=
2641 		    (row * rst->width * pxl->nBands) + (col * pxl->nBands) +
2642 		    nBand;
2643 		*p_uint16 = sample->uint16;
2644 		break;
2645 	    case RL2_SAMPLE_INT32:
2646 		p_int32 = (int *) (rst->rasterBuffer);
2647 		p_int32 +=
2648 		    (row * rst->width * pxl->nBands) + (col * pxl->nBands) +
2649 		    nBand;
2650 		*p_int32 = sample->int32;
2651 		break;
2652 	    case RL2_SAMPLE_UINT32:
2653 		p_uint32 = (unsigned int *) (rst->rasterBuffer);
2654 		p_uint32 +=
2655 		    (row * rst->width * pxl->nBands) + (col * pxl->nBands) +
2656 		    nBand;
2657 		*p_uint32 = sample->uint32;
2658 		break;
2659 	    case RL2_SAMPLE_FLOAT:
2660 		p_float32 = (float *) (rst->rasterBuffer);
2661 		p_float32 +=
2662 		    (row * rst->width * pxl->nBands) + (col * pxl->nBands) +
2663 		    nBand;
2664 		*p_float32 = sample->float32;
2665 		break;
2666 	    case RL2_SAMPLE_DOUBLE:
2667 		p_float64 = (double *) (rst->rasterBuffer);
2668 		p_float64 +=
2669 		    (row * rst->width * pxl->nBands) + (col * pxl->nBands) +
2670 		    nBand;
2671 		*p_float64 = sample->float64;
2672 		break;
2673 	    };
2674       }
2675 
2676     mask = rst->maskBuffer;
2677     if (mask != NULL)
2678       {
2679 	  /* updating the transparency mask */
2680 	  p_mask = mask + (row * rst->width) + col;
2681 	  if (pxl->isTransparent)
2682 	      *p_mask = 0;
2683 	  else
2684 	      *p_mask = 1;
2685       }
2686     return RL2_OK;
2687 }
2688 
2689 RL2_DECLARE rl2RasterStatisticsPtr
rl2_create_raster_statistics(unsigned char sample_type,unsigned char num_bands)2690 rl2_create_raster_statistics (unsigned char sample_type,
2691 			      unsigned char num_bands)
2692 {
2693 /* allocating and initializing a Raster Statistics object */
2694     int i;
2695     int j;
2696     int nHistogram;
2697     rl2PrivRasterStatisticsPtr stats = NULL;
2698     if (num_bands == 0)
2699 	return NULL;
2700     switch (sample_type)
2701       {
2702       case RL2_SAMPLE_1_BIT:
2703 	  nHistogram = 2;
2704 	  break;
2705       case RL2_SAMPLE_2_BIT:
2706 	  nHistogram = 4;
2707 	  break;
2708       case RL2_SAMPLE_4_BIT:
2709 	  nHistogram = 16;
2710 	  break;
2711       default:
2712 	  nHistogram = 256;
2713 	  break;
2714       };
2715 
2716     stats = malloc (sizeof (rl2PrivRasterStatistics));
2717     if (stats == NULL)
2718 	return NULL;
2719     stats->no_data = 0.0;
2720     stats->count = 0.0;
2721     stats->sampleType = sample_type;
2722     stats->nBands = num_bands;
2723     stats->band_stats = malloc (sizeof (rl2PrivBandStatistics) * num_bands);
2724     if (stats->band_stats == NULL)
2725       {
2726 	  free (stats);
2727 	  return NULL;
2728       }
2729     for (i = 0; i < num_bands; i++)
2730       {
2731 	  /* initializing the Bands Statistics */
2732 	  rl2PrivBandStatisticsPtr band = stats->band_stats + i;
2733 	  band->min = DBL_MAX;
2734 	  band->max = 0.0 - DBL_MAX;
2735 	  band->mean = 0.0;
2736 	  band->sum_sq_diff = 0.0;
2737 	  band->nHistogram = nHistogram;
2738 	  band->histogram = malloc (sizeof (double) * nHistogram);
2739 	  for (j = 0; j < nHistogram; j++)
2740 	      *(band->histogram + j) = 0.0;
2741 	  band->first = NULL;
2742 	  band->last = NULL;
2743       }
2744     return (rl2RasterStatisticsPtr) stats;
2745 }
2746 
2747 static void
free_band_stats(rl2PrivBandStatisticsPtr band)2748 free_band_stats (rl2PrivBandStatisticsPtr band)
2749 {
2750 /* memory cleanup - destroying a Raster Band Statistics object */
2751     rl2PoolVariancePtr pV;
2752     rl2PoolVariancePtr pVn;
2753     if (band == NULL)
2754 	return;
2755     if (band->histogram != NULL)
2756 	free (band->histogram);
2757     pV = band->first;
2758     while (pV != NULL)
2759       {
2760 	  pVn = pV->next;
2761 	  free (pV);
2762 	  pV = pVn;
2763       }
2764 }
2765 
2766 RL2_DECLARE void
rl2_destroy_raster_statistics(rl2RasterStatisticsPtr stats)2767 rl2_destroy_raster_statistics (rl2RasterStatisticsPtr stats)
2768 {
2769 /* memory cleanup - destroying a Raster Statistics object */
2770     int nb;
2771     rl2PrivRasterStatisticsPtr st = (rl2PrivRasterStatisticsPtr) stats;
2772     if (st == NULL)
2773 	return;
2774     for (nb = 0; nb < st->nBands; nb++)
2775       {
2776 	  rl2PrivBandStatisticsPtr band = st->band_stats + nb;
2777 	  free_band_stats (band);
2778       }
2779     if (st->band_stats != NULL)
2780 	free (st->band_stats);
2781     free (st);
2782 }
2783 
2784 RL2_DECLARE int
rl2_get_raster_statistics_summary(rl2RasterStatisticsPtr stats,double * no_data,double * count,unsigned char * sample_type,unsigned char * num_bands)2785 rl2_get_raster_statistics_summary (rl2RasterStatisticsPtr stats,
2786 				   double *no_data, double *count,
2787 				   unsigned char *sample_type,
2788 				   unsigned char *num_bands)
2789 {
2790 /* returning overall statistics values */
2791     rl2PrivRasterStatisticsPtr st = (rl2PrivRasterStatisticsPtr) stats;
2792     if (st == NULL)
2793 	return RL2_ERROR;
2794     *no_data = st->no_data;
2795     *count = st->count;
2796     *sample_type = st->sampleType;
2797     *num_bands = st->nBands;
2798     return RL2_OK;
2799 }
2800 
2801 RL2_DECLARE int
rl2_get_band_statistics(rl2RasterStatisticsPtr stats,unsigned char band,double * min,double * max,double * mean,double * variance,double * standard_deviation)2802 rl2_get_band_statistics (rl2RasterStatisticsPtr stats, unsigned char band,
2803 			 double *min, double *max, double *mean,
2804 			 double *variance, double *standard_deviation)
2805 {
2806 /* returning Band statistics values */
2807     rl2PrivBandStatisticsPtr st_band;
2808     rl2PrivRasterStatisticsPtr st = (rl2PrivRasterStatisticsPtr) stats;
2809     if (st == NULL)
2810 	return RL2_ERROR;
2811     if (band >= st->nBands)
2812 	return RL2_ERROR;
2813 
2814     st_band = st->band_stats + band;
2815     *min = st_band->min;
2816     *max = st_band->max;
2817     *mean = st_band->mean;
2818     if (st_band->first != NULL)
2819       {
2820 	  double count = 0.0;
2821 	  double sum_var = 0.0;
2822 	  double sum_count = 0.0;
2823 	  rl2PoolVariancePtr pV = st_band->first;
2824 	  while (pV != NULL)
2825 	    {
2826 		count += 1.0;
2827 		sum_var += (pV->count - 1.0) * pV->variance;
2828 		sum_count += pV->count;
2829 		pV = pV->next;
2830 	    }
2831 	  *variance = sum_var / (sum_count - count);
2832       }
2833     else
2834 	*variance = st_band->sum_sq_diff / (st->count - 1.0);
2835     *standard_deviation = sqrt (*variance);
2836     return RL2_OK;
2837 }
2838