1 /*
2 
3  rl2tiff -- TIFF / GeoTIFF related functions
4 
5  version 0.1, 2013 April 5
6 
7  Author: Sandro Furieri a.furieri@lqt.it
8 
9  -----------------------------------------------------------------------------
10 
11  Version: MPL 1.1/GPL 2.0/LGPL 2.1
12 
13  The contents of this file are subject to the Mozilla Public License Version
14  1.1 (the "License"); you may not use this file except in compliance with
15  the License. You may obtain a copy of the License at
16  http://www.mozilla.org/MPL/
17 
18 Software distributed under the License is distributed on an "AS IS" basis,
19 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
20 for the specific language governing rights and limitations under the
21 License.
22 
23 The Original Code is the SpatiaLite library
24 
25 The Initial Developer of the Original Code is Alessandro Furieri
26 
27 Portions created by the Initial Developer are Copyright (C) 2008-2013
28 the Initial Developer. All Rights Reserved.
29 
30 Alternatively, the contents of this file may be used under the terms of
31 either the GNU General Public License Version 2 or later (the "GPL"), or
32 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 in which case the provisions of the GPL or the LGPL are applicable instead
34 of those above. If you wish to allow use of your version of this file only
35 under the terms of either the GPL or the LGPL, and not to allow others to
36 use your version of this file under the terms of the MPL, indicate your
37 decision by deleting the provisions above and replace them with the notice
38 and other provisions required by the GPL or the LGPL. If you do not delete
39 the provisions above, a recipient may use your version of this file under
40 the terms of any one of the MPL, the GPL or the LGPL.
41 
42 */
43 
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <float.h>
48 #include <inttypes.h>
49 
50 #include "rasterlite2/sqlite.h"
51 
52 #include "config.h"
53 
54 #include "rasterlite2/rasterlite2.h"
55 #include "rasterlite2_private.h"
56 #include "rasterlite2/rl2tiff.h"
57 
58 struct memfile
59 {
60 /* a struct emulating a file [memory mapped] */
61     unsigned char *buffer;
62     int malloc_block;
63     tsize_t size;
64     tsize_t eof;
65     toff_t current;
66 };
67 
68 static void
memory_realloc(struct memfile * mem,tsize_t req_size)69 memory_realloc (struct memfile *mem, tsize_t req_size)
70 {
71 /* expanding the allocated memory */
72     unsigned char *new_buffer;
73     tsize_t new_size = mem->size;
74     while (new_size <= req_size)
75 	new_size += mem->malloc_block;
76     new_buffer = realloc (mem->buffer, new_size);
77     if (!new_buffer)
78 	return;
79     mem->buffer = new_buffer;
80     memset (mem->buffer + mem->size, '\0', new_size - mem->size);
81     mem->size = new_size;
82 }
83 
84 static tsize_t
memory_readproc(thandle_t clientdata,tdata_t data,tsize_t size)85 memory_readproc (thandle_t clientdata, tdata_t data, tsize_t size)
86 {
87 /* emulating the read()  function */
88     struct memfile *mem = clientdata;
89     tsize_t len;
90     if (mem->current >= (toff_t) mem->eof)
91 	return 0;
92     len = size;
93     if ((mem->current + size) >= (toff_t) mem->eof)
94 	len = (tsize_t) (mem->eof - mem->current);
95     memcpy (data, mem->buffer + mem->current, len);
96     mem->current += len;
97     return len;
98 }
99 
100 static tsize_t
memory_writeproc(thandle_t clientdata,tdata_t data,tsize_t size)101 memory_writeproc (thandle_t clientdata, tdata_t data, tsize_t size)
102 {
103 /* emulating the write()  function */
104     struct memfile *mem = clientdata;
105     if ((mem->current + size) >= (toff_t) mem->size)
106 	memory_realloc (mem, mem->current + size);
107     if ((mem->current + size) >= (toff_t) mem->size)
108 	return -1;
109     memcpy (mem->buffer + mem->current, (unsigned char *) data, size);
110     mem->current += size;
111     if (mem->current > (toff_t) mem->eof)
112 	mem->eof = (tsize_t) (mem->current);
113     return size;
114 }
115 
116 static toff_t
memory_seekproc(thandle_t clientdata,toff_t offset,int whence)117 memory_seekproc (thandle_t clientdata, toff_t offset, int whence)
118 {
119 /* emulating the lseek()  function */
120     struct memfile *mem = clientdata;
121     switch (whence)
122       {
123       case SEEK_CUR:
124 	  if ((int) (mem->current + offset) < 0)
125 	      return (toff_t) - 1;
126 	  mem->current += offset;
127 	  if ((toff_t) mem->eof < mem->current)
128 	      mem->eof = (tsize_t) (mem->current);
129 	  break;
130       case SEEK_END:
131 	  if ((int) (mem->eof + offset) < 0)
132 	      return (toff_t) - 1;
133 	  mem->current = mem->eof + offset;
134 	  if ((toff_t) mem->eof < mem->current)
135 	      mem->eof = (tsize_t) (mem->current);
136 	  break;
137       case SEEK_SET:
138       default:
139 	  if ((int) offset < 0)
140 	      return (toff_t) - 1;
141 	  mem->current = offset;
142 	  if ((toff_t) mem->eof < mem->current)
143 	      mem->eof = (tsize_t) (mem->current);
144 	  break;
145       };
146     return mem->current;
147 }
148 
149 static int
closeproc(thandle_t clientdata)150 closeproc (thandle_t clientdata)
151 {
152 /* emulating the close()  function */
153     if (clientdata)
154 	return 0;		/* does absolutely nothing - required in order to suppress warnings */
155     return 0;
156 }
157 
158 static toff_t
memory_sizeproc(thandle_t clientdata)159 memory_sizeproc (thandle_t clientdata)
160 {
161 /* returning the pseudo-file current size */
162     struct memfile *mem = clientdata;
163     return mem->eof;
164 }
165 
166 static int
mapproc(thandle_t clientdata,tdata_t * data,toff_t * offset)167 mapproc (thandle_t clientdata, tdata_t * data, toff_t * offset)
168 {
169     if (clientdata || data || offset)
170 	return 0;		/* does absolutely nothing - required in order to suppress warnings */
171     return 0;
172 }
173 
174 static void
unmapproc(thandle_t clientdata,tdata_t data,toff_t offset)175 unmapproc (thandle_t clientdata, tdata_t data, toff_t offset)
176 {
177     if (clientdata || data || offset)
178 	return;			/* does absolutely nothing - required in order to suppress warnings */
179     return;
180 }
181 
182 static int
183 read_from_tiff (rl2PrivTiffOriginPtr origin, unsigned short width,
184 		unsigned short height, unsigned char sample_type,
185 		unsigned char pixel_type, unsigned char num_bands,
186 		unsigned int startRow, unsigned int startCol,
187 		unsigned char **pixels, int *pixels_sz, rl2PalettePtr palette);
188 
189 static rl2PrivTiffOriginPtr
create_tiff_origin(const char * path,unsigned char force_sample_type,unsigned char force_pixel_type,unsigned char force_num_bands)190 create_tiff_origin (const char *path, unsigned char force_sample_type,
191 		    unsigned char force_pixel_type,
192 		    unsigned char force_num_bands)
193 {
194 /* creating an uninitialized TIFF origin */
195     int len;
196     rl2PrivTiffOriginPtr origin;
197     if (path == NULL)
198 	return NULL;
199     origin = malloc (sizeof (rl2PrivTiffOrigin));
200     if (origin == NULL)
201 	return NULL;
202 
203     len = strlen (path);
204     origin->path = malloc (len + 1);
205     strcpy (origin->path, path);
206     origin->tfw_path = NULL;
207     origin->isGeoTiff = 0;
208     origin->in = (TIFF *) 0;
209     origin->tileWidth = 0;
210     origin->tileHeight = 0;
211     origin->rowsPerStrip = 0;
212     origin->maxPalette = 0;
213     origin->red = NULL;
214     origin->green = NULL;
215     origin->blue = NULL;
216     origin->remapMaxPalette = 0;
217     origin->remapRed = NULL;
218     origin->remapGreen = NULL;
219     origin->remapBlue = NULL;
220     origin->isGeoReferenced = 0;
221     origin->Srid = -1;
222     origin->srsName = NULL;
223     origin->proj4text = NULL;
224     origin->forced_sample_type = force_sample_type;
225     origin->forced_pixel_type = force_pixel_type;
226     origin->forced_num_bands = force_num_bands;
227     origin->forced_conversion = RL2_CONVERT_NO;
228     return origin;
229 }
230 
231 static int
alloc_palette(rl2PrivTiffOriginPtr tiff,int max_palette)232 alloc_palette (rl2PrivTiffOriginPtr tiff, int max_palette)
233 {
234 /* allocating an empty Palette */
235     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
236     int i;
237 
238     if (origin == NULL)
239 	return 0;
240     if (max_palette < 1 || max_palette > 256)
241 	return 0;
242     origin->maxPalette = max_palette;
243     origin->red = malloc (max_palette);
244     if (origin->red == NULL)
245 	return 0;
246     origin->green = malloc (max_palette);
247     if (origin->green == NULL)
248       {
249 	  free (origin->red);
250 	  return 0;
251       }
252     origin->blue = malloc (max_palette);
253     if (origin->blue == NULL)
254       {
255 	  free (origin->red);
256 	  free (origin->green);
257 	  return 0;
258       }
259     for (i = 0; i < max_palette; i++)
260       {
261 	  origin->red[i] = 0;
262 	  origin->green[i] = 0;
263 	  origin->blue[i] = 0;
264       }
265     return 1;
266 }
267 
268 RL2_DECLARE void
rl2_destroy_tiff_origin(rl2TiffOriginPtr tiff)269 rl2_destroy_tiff_origin (rl2TiffOriginPtr tiff)
270 {
271 /* memory cleanup - destroying a TIFF origin */
272     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
273     if (origin == NULL)
274 	return;
275     if (origin->in != (TIFF *) 0)
276 	TIFFClose (origin->in);
277     if (origin->path != NULL)
278 	free (origin->path);
279     if (origin->tfw_path != NULL)
280 	free (origin->tfw_path);
281     if (origin->red != NULL)
282 	free (origin->red);
283     if (origin->green != NULL)
284 	free (origin->green);
285     if (origin->blue != NULL)
286 	free (origin->blue);
287     if (origin->remapRed != NULL)
288 	free (origin->remapRed);
289     if (origin->remapGreen != NULL)
290 	free (origin->remapGreen);
291     if (origin->remapBlue != NULL)
292 	free (origin->remapBlue);
293     if (origin->srsName != NULL)
294 	free (origin->srsName);
295     if (origin->proj4text != NULL)
296 	free (origin->proj4text);
297     free (origin);
298 }
299 
300 static void
origin_set_tfw_path(const char * path,rl2PrivTiffOriginPtr origin)301 origin_set_tfw_path (const char *path, rl2PrivTiffOriginPtr origin)
302 {
303 /* building the TFW path (WorldFile) */
304     char *tfw;
305     const char *x = NULL;
306     const char *p = path;
307     int len = strlen (path);
308     len -= 1;
309     while (*p != '\0')
310       {
311 	  if (*p == '.')
312 	      x = p;
313 	  p++;
314       }
315     if (x > path)
316 	len = x - path;
317     tfw = malloc (len + 5);
318     memcpy (tfw, path, len);
319     memcpy (tfw + len, ".tfw", 4);
320     *(tfw + len + 4) = '\0';
321     origin->tfw_path = tfw;
322 }
323 
324 static int
is_valid_float(char * str)325 is_valid_float (char *str)
326 {
327 /* testing for a valid worlodfile float value */
328     char *p = str;
329     int point = 0;
330     int sign = 0;
331     int digit = 0;
332     int len = strlen (str);
333     int i;
334 
335     for (i = len - 1; i >= 0; i--)
336       {
337 	  /* suppressing any trailing blank */
338 	  if (str[i] == ' ' || str[i] == '\t' || str[i] == '\r')
339 	      str[i] = '\0';
340 	  else
341 	      break;
342       }
343 
344     while (1)
345       {
346 	  /* skipping leading blanks */
347 	  if (*p != ' ' && *p != '\t')
348 	      break;
349 	  p++;
350       }
351 
352 /* testing for a well formatted float */
353     while (1)
354       {
355 	  if (*p == '\0')
356 	      break;
357 	  if (*p >= '0' && *p <= '9')
358 	      digit++;
359 	  else if (*p == '.')
360 	      point++;
361 	  else if (*p == ',')
362 	    {
363 		*p = '.';
364 		point++;
365 	    }
366 	  else if (*p == '+' || *p == '-')
367 	    {
368 		if (digit == 0 && point == 0 && sign == 0)
369 		    ;
370 		else
371 		    return 0;
372 	    }
373 	  else
374 	      return 0;
375 	  p++;
376       }
377     if (digit > 0 && sign <= 1 && point <= 1)
378 	return 1;
379     return 0;
380 }
381 
382 RL2_PRIVATE int
parse_worldfile(FILE * in,double * px,double * py,double * pres_x,double * pres_y)383 parse_worldfile (FILE * in, double *px, double *py, double *pres_x,
384 		 double *pres_y)
385 {
386 /* attemtping to parse a WorldFile */
387     int line_no = 0;
388     int ok_res_x = 0;
389     int ok_res_y = 0;
390     int ok_x = 0;
391     int ok_y = 0;
392     char buf[1024];
393     char *p = buf;
394     double x;
395     double y;
396     double res_x;
397     double res_y;
398 
399     if (in == NULL)
400 	return 0;
401 
402     while (1)
403       {
404 	  int c = getc (in);
405 	  if (c == '\n' || c == EOF)
406 	    {
407 		*p = '\0';
408 		if (line_no == 0)
409 		  {
410 		      if (is_valid_float (buf))
411 			{
412 			    res_x = atof (buf);
413 			    ok_res_x = 1;
414 			}
415 		  }
416 		if (line_no == 3)
417 		  {
418 		      if (is_valid_float (buf))
419 			{
420 			    res_y = atof (buf) * -1.0;
421 			    ok_res_y = 1;
422 			}
423 		  }
424 		if (line_no == 4)
425 		  {
426 		      if (is_valid_float (buf))
427 			{
428 			    x = atof (buf);
429 			    ok_x = 1;
430 			}
431 		  }
432 		if (line_no == 5)
433 		  {
434 		      if (is_valid_float (buf))
435 			{
436 			    y = atof (buf);
437 			    ok_y = 1;
438 			}
439 		  }
440 		if (c == EOF)
441 		    break;
442 		p = buf;
443 		line_no++;
444 		continue;
445 	    }
446 	  *p++ = c;
447       }
448 
449     if (ok_x && ok_y && ok_res_x && ok_res_y)
450       {
451 	  *px = x;
452 	  *py = y;
453 	  *pres_x = res_x;
454 	  *pres_y = res_y;
455 	  return 1;
456       }
457     return 0;
458 }
459 
460 static void
worldfile_tiff_origin(const char * path,rl2PrivTiffOriginPtr origin,int srid)461 worldfile_tiff_origin (const char *path, rl2PrivTiffOriginPtr origin, int srid)
462 {
463 /* attempting to retrieve georeferencing from a TIFF+TFW origin */
464     FILE *tfw = NULL;
465     double res_x;
466     double res_y;
467     double x;
468     double y;
469 
470     origin_set_tfw_path (path, origin);
471     tfw = fopen (origin->tfw_path, "r");
472     if (tfw == NULL)
473 	goto error;
474     if (!parse_worldfile (tfw, &x, &y, &res_x, &res_y))
475 	goto error;
476     fclose (tfw);
477     origin->Srid = srid;
478     origin->hResolution = res_x;
479     origin->vResolution = res_y;
480     origin->minX = x;
481     origin->maxY = y;
482     origin->isGeoReferenced = 1;
483     return;
484 
485   error:
486     if (tfw != NULL)
487 	fclose (tfw);
488     if (origin->tfw_path != NULL)
489 	free (origin->tfw_path);
490     origin->tfw_path = NULL;
491 }
492 
493 static void
geo_tiff_origin(const char * path,rl2PrivTiffOriginPtr origin,int force_srid)494 geo_tiff_origin (const char *path, rl2PrivTiffOriginPtr origin, int force_srid)
495 {
496 /* attempting to retrieve georeferencing from a GeoTIFF origin */
497     uint32 width = 0;
498     uint32 height = 0;
499     double cx;
500     double cy;
501     GTIFDefn definition;
502     char *pString;
503     int len;
504     TIFF *in = (TIFF *) 0;
505     GTIF *gtif = (GTIF *) 0;
506 
507 /* suppressing TIFF messages */
508     TIFFSetErrorHandler (NULL);
509     TIFFSetWarningHandler (NULL);
510 
511 /* reading from file */
512     in = XTIFFOpen (path, "r");
513     if (in == NULL)
514 	goto error;
515     gtif = GTIFNew (in);
516     if (gtif == NULL)
517 	goto error;
518 
519     if (!GTIFGetDefn (gtif, &definition))
520 	goto error;
521 /* retrieving the EPSG code */
522     if (definition.PCS == 32767)
523       {
524 	  if (definition.GCS != 32767)
525 	      origin->Srid = definition.GCS;
526       }
527     else
528 	origin->Srid = definition.PCS;
529     if (origin->Srid <= 0)
530       {
531 	  origin->Srid = force_srid;
532 	  if (origin->Srid <= 0)
533 	      goto error;
534       }
535     if (definition.PCS == 32767)
536       {
537 	  /* Get the GCS name if possible */
538 	  pString = NULL;
539 	  GTIFGetGCSInfo (definition.GCS, &pString, NULL, NULL, NULL);
540 	  if (pString != NULL)
541 	    {
542 		len = strlen (pString);
543 		origin->srsName = malloc (len + 1);
544 		strcpy (origin->srsName, pString);
545 		CPLFree (pString);
546 	    }
547       }
548     else
549       {
550 	  /* Get the PCS name if possible */
551 	  pString = NULL;
552 	  GTIFGetPCSInfo (definition.PCS, &pString, NULL, NULL, NULL);
553 	  if (pString != NULL)
554 	    {
555 		len = strlen (pString);
556 		origin->srsName = malloc (len + 1);
557 		strcpy (origin->srsName, pString);
558 		CPLFree (pString);
559 	    }
560       }
561 /* retrieving the PROJ.4 params */
562     pString = GTIFGetProj4Defn (&definition);
563     if (pString != NULL)
564       {
565 	  len = strlen (pString);
566 	  origin->proj4text = malloc (len + 1);
567 	  strcpy (origin->proj4text, pString);
568 	  CPLFree (pString);
569       }
570 
571 /* retrieving the TIFF dimensions */
572     TIFFGetField (in, TIFFTAG_IMAGELENGTH, &height);
573     TIFFGetField (in, TIFFTAG_IMAGEWIDTH, &width);
574 
575 /* computing the corners coords */
576     cx = 0.0;
577     cy = 0.0;
578     GTIFImageToPCS (gtif, &cx, &cy);
579     origin->minX = cx;
580     origin->maxY = cy;
581     cx = 0.0;
582     cy = height;
583     GTIFImageToPCS (gtif, &cx, &cy);
584     origin->minY = cy;
585     cx = width;
586     cy = 0.0;
587     GTIFImageToPCS (gtif, &cx, &cy);
588     origin->maxX = cx;
589 
590 /* computing the pixel resolution */
591     origin->hResolution = (origin->maxX - origin->minX) / (double) width;
592     origin->vResolution = (origin->maxY - origin->minY) / (double) height;
593     origin->isGeoReferenced = 1;
594     origin->isGeoTiff = 1;
595 
596   error:
597     if (in != (TIFF *) 0)
598 	XTIFFClose (in);
599     if (gtif != (GTIF *) 0)
600 	GTIFFree (gtif);
601 }
602 
603 static int
check_grayscale_palette(rl2PrivTiffOriginPtr origin)604 check_grayscale_palette (rl2PrivTiffOriginPtr origin)
605 {
606 /* checking if a Palette actually is a Grayscale Palette */
607     int i;
608     if (origin->maxPalette == 0 || origin->maxPalette > 256)
609 	return 0;
610     for (i = 0; i < origin->maxPalette; i++)
611       {
612 	  if (origin->red[i] == origin->green[i]
613 	      && origin->red[i] == origin->blue[i])
614 	      ;
615 	  else
616 	      return 0;
617       }
618     return 1;
619 }
620 
621 static int
check_tiff_origin_pixel_conversion(rl2PrivTiffOriginPtr origin)622 check_tiff_origin_pixel_conversion (rl2PrivTiffOriginPtr origin)
623 {
624 /* check if the Color-Space conversion could be accepted */
625     if (origin->forced_sample_type == RL2_SAMPLE_UNKNOWN)
626       {
627 	  if (origin->sampleFormat == SAMPLEFORMAT_INT)
628 	    {
629 		if (origin->bitsPerSample == 8)
630 		    origin->forced_sample_type = RL2_SAMPLE_INT8;
631 		if (origin->bitsPerSample == 16)
632 		    origin->forced_sample_type = RL2_SAMPLE_INT16;
633 		if (origin->bitsPerSample == 32)
634 		    origin->forced_sample_type = RL2_SAMPLE_INT32;
635 	    }
636 	  else if (origin->sampleFormat == SAMPLEFORMAT_UINT)
637 	    {
638 		if (origin->bitsPerSample == 1)
639 		    origin->forced_sample_type = RL2_SAMPLE_1_BIT;
640 		if (origin->bitsPerSample == 2)
641 		    origin->forced_sample_type = RL2_SAMPLE_2_BIT;
642 		if (origin->bitsPerSample == 4)
643 		    origin->forced_sample_type = RL2_SAMPLE_4_BIT;
644 		if (origin->bitsPerSample == 8)
645 		    origin->forced_sample_type = RL2_SAMPLE_UINT8;
646 		if (origin->bitsPerSample == 16)
647 		    origin->forced_sample_type = RL2_SAMPLE_UINT16;
648 		if (origin->bitsPerSample == 32)
649 		    origin->forced_sample_type = RL2_SAMPLE_UINT32;
650 	    }
651 	  else if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP)
652 	    {
653 		if (origin->bitsPerSample == 32)
654 		    origin->forced_sample_type = RL2_SAMPLE_FLOAT;
655 		if (origin->bitsPerSample == 64)
656 		    origin->forced_sample_type = RL2_SAMPLE_DOUBLE;
657 	    }
658       }
659     if (origin->forced_pixel_type == RL2_PIXEL_UNKNOWN)
660       {
661 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
662 	      && origin->photometric == PHOTOMETRIC_RGB)
663 	    {
664 		if (origin->samplesPerPixel == 3)
665 		    origin->forced_pixel_type = RL2_PIXEL_RGB;
666 		else
667 		    origin->forced_pixel_type = RL2_PIXEL_MULTIBAND;
668 	    }
669 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
670 	      && origin->samplesPerPixel == 1
671 	      && origin->photometric < PHOTOMETRIC_RGB
672 	      && origin->bitsPerSample > 1)
673 	      origin->forced_pixel_type = RL2_PIXEL_GRAYSCALE;
674 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
675 	      && origin->samplesPerPixel == 1
676 	      && origin->photometric == PHOTOMETRIC_PALETTE
677 	      && origin->bitsPerSample <= 8)
678 	      origin->forced_pixel_type = RL2_PIXEL_PALETTE;
679 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
680 	      && origin->samplesPerPixel == 1
681 	      && origin->photometric <= PHOTOMETRIC_RGB
682 	      && origin->bitsPerSample == 1)
683 	      origin->forced_pixel_type = RL2_PIXEL_MONOCHROME;
684 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
685 	      && origin->samplesPerPixel == 1
686 	      && origin->photometric < PHOTOMETRIC_RGB
687 	      && origin->bitsPerSample == 8)
688 	      origin->forced_pixel_type = RL2_PIXEL_DATAGRID;
689 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
690 	      && origin->samplesPerPixel == 1
691 	      && origin->photometric < PHOTOMETRIC_RGB
692 	      && origin->bitsPerSample == 16)
693 	      origin->forced_pixel_type = RL2_PIXEL_DATAGRID;
694 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
695 	      && origin->samplesPerPixel == 1
696 	      && origin->photometric < PHOTOMETRIC_RGB
697 	      && origin->bitsPerSample == 32)
698 	      origin->forced_pixel_type = RL2_PIXEL_DATAGRID;
699 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
700 	      && origin->samplesPerPixel == 1
701 	      && origin->photometric < PHOTOMETRIC_RGB
702 	      && origin->bitsPerSample == 32)
703 	      origin->forced_pixel_type = RL2_PIXEL_DATAGRID;
704 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
705 	      && origin->samplesPerPixel == 1
706 	      && origin->photometric < PHOTOMETRIC_RGB
707 	      && origin->bitsPerSample == 32)
708 	      origin->forced_pixel_type = RL2_PIXEL_DATAGRID;
709 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
710 	      && origin->samplesPerPixel == 1
711 	      && origin->photometric < PHOTOMETRIC_RGB
712 	      && origin->bitsPerSample == 64)
713 	      origin->forced_pixel_type = RL2_PIXEL_DATAGRID;
714       }
715     if (origin->forced_num_bands == RL2_BANDS_UNKNOWN)
716 	origin->forced_num_bands = origin->samplesPerPixel;
717 
718     if (origin->forced_sample_type == RL2_SAMPLE_UINT8
719 	&& origin->forced_pixel_type == RL2_PIXEL_RGB
720 	&& origin->forced_num_bands == 3)
721       {
722 	  /* RGB color-space */
723 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
724 	      && origin->samplesPerPixel == 3
725 	      && origin->photometric == PHOTOMETRIC_RGB)
726 	      return 1;
727 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
728 	      && origin->samplesPerPixel == 1
729 	      && origin->photometric < PHOTOMETRIC_RGB)
730 	    {
731 		origin->forced_conversion = RL2_CONVERT_GRAYSCALE_TO_RGB;
732 		return 1;
733 	    }
734 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
735 	      && origin->samplesPerPixel == 1
736 	      && origin->photometric == PHOTOMETRIC_PALETTE
737 	      && origin->bitsPerSample <= 8)
738 	    {
739 		origin->forced_conversion = RL2_CONVERT_PALETTE_TO_RGB;
740 		return 1;
741 	    }
742       }
743     if (origin->forced_sample_type == RL2_SAMPLE_UINT16
744 	&& origin->forced_pixel_type == RL2_PIXEL_RGB
745 	&& origin->forced_num_bands == 3)
746       {
747 	  /* RGB color-space */
748 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
749 	      && origin->samplesPerPixel == 3
750 	      && origin->photometric == PHOTOMETRIC_RGB)
751 	      return 1;
752       }
753     if (origin->forced_sample_type == RL2_SAMPLE_UINT8
754 	&& origin->forced_pixel_type == RL2_PIXEL_MULTIBAND)
755       {
756 	  /* MULTIBAND color-space */
757 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
758 	      && origin->samplesPerPixel == origin->forced_num_bands
759 	      && origin->photometric == PHOTOMETRIC_RGB)
760 	      return 1;
761       }
762     if (origin->forced_sample_type == RL2_SAMPLE_UINT16
763 	&& origin->forced_pixel_type == RL2_PIXEL_MULTIBAND)
764       {
765 	  /* MULTIBAND color-space */
766 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
767 	      && origin->samplesPerPixel == origin->forced_num_bands
768 	      && origin->photometric == PHOTOMETRIC_RGB)
769 	      return 1;
770       }
771     if (origin->forced_sample_type == RL2_SAMPLE_UINT8
772 	&& origin->forced_pixel_type == RL2_PIXEL_GRAYSCALE
773 	&& origin->forced_num_bands == 1)
774       {
775 	  /* GRAYSCALE color-space */
776 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
777 	      && origin->samplesPerPixel == 1
778 	      && origin->photometric < PHOTOMETRIC_RGB
779 	      && origin->bitsPerSample > 1)
780 	      return 1;
781 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
782 	      && origin->samplesPerPixel == 3
783 	      && origin->photometric == PHOTOMETRIC_RGB)
784 	    {
785 		origin->forced_conversion = RL2_CONVERT_RGB_TO_GRAYSCALE;
786 		return 1;
787 	    }
788 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
789 	      && origin->samplesPerPixel == 1
790 	      && origin->photometric == PHOTOMETRIC_PALETTE
791 	      && origin->bitsPerSample <= 8 && check_grayscale_palette (origin))
792 	    {
793 		origin->forced_conversion = RL2_CONVERT_PALETTE_TO_GRAYSCALE;
794 		return 1;
795 	    }
796       }
797     if (origin->forced_sample_type == RL2_SAMPLE_UINT16
798 	&& origin->forced_pixel_type == RL2_PIXEL_GRAYSCALE
799 	&& origin->forced_num_bands == 1)
800       {
801 	  /* GRAYSCALE color-space */
802 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
803 	      && origin->samplesPerPixel == 1
804 	      && origin->photometric < PHOTOMETRIC_RGB
805 	      && origin->bitsPerSample > 1)
806 	      return 1;
807       }
808     if (origin->forced_sample_type == RL2_SAMPLE_UINT8
809 	&& origin->forced_pixel_type == RL2_PIXEL_PALETTE
810 	&& origin->forced_num_bands == 1)
811       {
812 	  /* PALETTE-256 color-space */
813 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
814 	      && origin->samplesPerPixel == 1
815 	      && origin->photometric == PHOTOMETRIC_PALETTE
816 	      && origin->bitsPerSample <= 8)
817 	      return 1;
818 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
819 	      && origin->samplesPerPixel == 1
820 	      && origin->photometric < PHOTOMETRIC_RGB)
821 	    {
822 		origin->forced_conversion = RL2_CONVERT_GRAYSCALE_TO_PALETTE;
823 		return 1;
824 	    }
825       }
826     if (origin->forced_sample_type == RL2_SAMPLE_4_BIT
827 	&& origin->forced_pixel_type == RL2_PIXEL_PALETTE
828 	&& origin->forced_num_bands == 1)
829       {
830 	  /* PALETTE-16 color-space */
831 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
832 	      && origin->samplesPerPixel == 1
833 	      && origin->photometric == PHOTOMETRIC_PALETTE
834 	      && origin->bitsPerSample <= 8)
835 	      return 1;
836       }
837     if (origin->forced_sample_type == RL2_SAMPLE_2_BIT
838 	&& origin->forced_pixel_type == RL2_PIXEL_PALETTE
839 	&& origin->forced_num_bands == 1)
840       {
841 	  /* PALETTE-4 color-space */
842 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
843 	      && origin->samplesPerPixel == 1
844 	      && origin->photometric == PHOTOMETRIC_PALETTE
845 	      && origin->bitsPerSample <= 8)
846 	      return 1;
847       }
848     if (origin->forced_sample_type == RL2_SAMPLE_1_BIT
849 	&& origin->forced_pixel_type == RL2_PIXEL_PALETTE
850 	&& origin->forced_num_bands == 1)
851       {
852 	  /* PALETTE-2 color-space */
853 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
854 	      && origin->samplesPerPixel == 1
855 	      && origin->photometric == PHOTOMETRIC_PALETTE
856 	      && origin->bitsPerSample <= 8)
857 	      return 1;
858 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
859 	      && origin->samplesPerPixel == 1
860 	      && origin->photometric <= PHOTOMETRIC_RGB
861 	      && origin->bitsPerSample == 1)
862 	    {
863 		origin->forced_conversion = RL2_CONVERT_MONOCHROME_TO_PALETTE;
864 		return 1;
865 	    }
866       }
867     if (origin->forced_sample_type == RL2_SAMPLE_1_BIT
868 	&& origin->forced_pixel_type == RL2_PIXEL_MONOCHROME
869 	&& origin->forced_num_bands == 1)
870       {
871 	  /* MONOCHROME color-space */
872 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
873 	      && origin->samplesPerPixel == 1
874 	      && origin->photometric <= PHOTOMETRIC_RGB
875 	      && origin->bitsPerSample == 1)
876 	      return 1;
877 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
878 	      && origin->samplesPerPixel == 1
879 	      && origin->photometric == PHOTOMETRIC_PALETTE
880 	      && origin->bitsPerSample <= 8)
881 	    {
882 		origin->forced_conversion = RL2_CONVERT_PALETTE_TO_MONOCHROME;
883 		return 1;
884 	    }
885       }
886     if (origin->forced_sample_type == RL2_SAMPLE_INT8
887 	&& origin->forced_pixel_type == RL2_PIXEL_DATAGRID
888 	&& origin->forced_num_bands == 1)
889       {
890 	  /* INT8 datagrid */
891 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
892 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 8)
893 	      return 1;
894 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
895 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 8)
896 	    {
897 		origin->forced_conversion = RL2_CONVERT_GRID_UINT8_TO_INT8;
898 		return 1;
899 	    }
900 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
901 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 16)
902 	    {
903 		origin->forced_conversion = RL2_CONVERT_GRID_INT16_TO_INT8;
904 		return 1;
905 	    }
906 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
907 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 16)
908 	    {
909 		origin->forced_conversion = RL2_CONVERT_GRID_UINT16_TO_INT8;
910 		return 1;
911 	    }
912 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
913 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
914 	    {
915 		origin->forced_conversion = RL2_CONVERT_GRID_INT32_TO_INT8;
916 		return 1;
917 	    }
918 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
919 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
920 	    {
921 		origin->forced_conversion = RL2_CONVERT_GRID_UINT32_TO_INT8;
922 		return 1;
923 	    }
924 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
925 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
926 	    {
927 		origin->forced_conversion = RL2_CONVERT_GRID_FLOAT_TO_INT8;
928 		return 1;
929 	    }
930 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
931 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 64)
932 	    {
933 		origin->forced_conversion = RL2_CONVERT_GRID_DOUBLE_TO_INT8;
934 		return 1;
935 	    }
936       }
937     if (origin->forced_sample_type == RL2_SAMPLE_UINT8
938 	&& origin->forced_pixel_type == RL2_PIXEL_DATAGRID
939 	&& origin->forced_num_bands == 1)
940       {
941 	  /* UINT8 datagrid */
942 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
943 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 8)
944 	      return 1;
945 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
946 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 8)
947 	    {
948 		origin->forced_conversion = RL2_CONVERT_GRID_INT8_TO_UINT8;
949 		return 1;
950 	    }
951 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
952 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 16)
953 	    {
954 		origin->forced_conversion = RL2_CONVERT_GRID_INT16_TO_UINT8;
955 		return 1;
956 	    }
957 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
958 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 16)
959 	    {
960 		origin->forced_conversion = RL2_CONVERT_GRID_UINT16_TO_UINT8;
961 		return 1;
962 	    }
963 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
964 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
965 	    {
966 		origin->forced_conversion = RL2_CONVERT_GRID_INT32_TO_UINT8;
967 		return 1;
968 	    }
969 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
970 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
971 	    {
972 		origin->forced_conversion = RL2_CONVERT_GRID_UINT32_TO_UINT8;
973 		return 1;
974 	    }
975 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
976 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
977 	    {
978 		origin->forced_conversion = RL2_CONVERT_GRID_FLOAT_TO_UINT8;
979 		return 1;
980 	    }
981 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
982 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 64)
983 	    {
984 		origin->forced_conversion = RL2_CONVERT_GRID_DOUBLE_TO_UINT8;
985 		return 1;
986 	    }
987       }
988     if (origin->forced_sample_type == RL2_SAMPLE_INT16
989 	&& origin->forced_pixel_type == RL2_PIXEL_DATAGRID
990 	&& origin->forced_num_bands == 1)
991       {
992 	  /* INT16 datagrid */
993 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
994 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 16)
995 	      return 1;
996 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
997 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 16)
998 	    {
999 		origin->forced_conversion = RL2_CONVERT_GRID_UINT16_TO_INT16;
1000 		return 1;
1001 	    }
1002 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
1003 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 8)
1004 	    {
1005 		origin->forced_conversion = RL2_CONVERT_GRID_INT8_TO_INT16;
1006 		return 1;
1007 	    }
1008 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
1009 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 8)
1010 	    {
1011 		origin->forced_conversion = RL2_CONVERT_GRID_UINT8_TO_INT16;
1012 		return 1;
1013 	    }
1014 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
1015 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1016 	    {
1017 		origin->forced_conversion = RL2_CONVERT_GRID_INT32_TO_INT16;
1018 		return 1;
1019 	    }
1020 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
1021 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1022 	    {
1023 		origin->forced_conversion = RL2_CONVERT_GRID_UINT32_TO_INT16;
1024 		return 1;
1025 	    }
1026 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
1027 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1028 	    {
1029 		origin->forced_conversion = RL2_CONVERT_GRID_FLOAT_TO_INT16;
1030 		return 1;
1031 	    }
1032 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
1033 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 64)
1034 	    {
1035 		origin->forced_conversion = RL2_CONVERT_GRID_DOUBLE_TO_INT16;
1036 		return 1;
1037 	    }
1038       }
1039     if (origin->forced_sample_type == RL2_SAMPLE_UINT16
1040 	&& origin->forced_pixel_type == RL2_PIXEL_DATAGRID
1041 	&& origin->forced_num_bands == 1)
1042       {
1043 	  /* UINT16 datagrid */
1044 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
1045 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 16)
1046 	      return 1;
1047 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
1048 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 16)
1049 	    {
1050 		origin->forced_conversion = RL2_CONVERT_GRID_INT16_TO_UINT16;
1051 		return 1;
1052 	    }
1053 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
1054 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 8)
1055 	    {
1056 		origin->forced_conversion = RL2_CONVERT_GRID_UINT8_TO_UINT16;
1057 		return 1;
1058 	    }
1059 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
1060 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 8)
1061 	    {
1062 		origin->forced_conversion = RL2_CONVERT_GRID_INT8_TO_UINT16;
1063 		return 1;
1064 	    }
1065 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
1066 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1067 	    {
1068 		origin->forced_conversion = RL2_CONVERT_GRID_INT32_TO_UINT16;
1069 		return 1;
1070 	    }
1071 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
1072 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1073 	    {
1074 		origin->forced_conversion = RL2_CONVERT_GRID_UINT32_TO_UINT16;
1075 		return 1;
1076 	    }
1077 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
1078 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1079 	    {
1080 		origin->forced_conversion = RL2_CONVERT_GRID_FLOAT_TO_UINT16;
1081 		return 1;
1082 	    }
1083 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
1084 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 64)
1085 	    {
1086 		origin->forced_conversion = RL2_CONVERT_GRID_DOUBLE_TO_UINT16;
1087 		return 1;
1088 	    }
1089       }
1090     if (origin->forced_sample_type == RL2_SAMPLE_INT32
1091 	&& origin->forced_pixel_type == RL2_PIXEL_DATAGRID
1092 	&& origin->forced_num_bands == 1)
1093       {
1094 	  /* INT32 datagrid */
1095 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
1096 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1097 	      return 1;
1098 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
1099 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1100 	    {
1101 		origin->forced_conversion = RL2_CONVERT_GRID_UINT32_TO_INT32;
1102 		return 1;
1103 	    }
1104 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
1105 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 8)
1106 	    {
1107 		origin->forced_conversion = RL2_CONVERT_GRID_INT8_TO_INT32;
1108 		return 1;
1109 	    }
1110 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
1111 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 8)
1112 	    {
1113 		origin->forced_conversion = RL2_CONVERT_GRID_UINT8_TO_INT32;
1114 		return 1;
1115 	    }
1116 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
1117 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 16)
1118 	    {
1119 		origin->forced_conversion = RL2_CONVERT_GRID_INT16_TO_INT32;
1120 		return 1;
1121 	    }
1122 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
1123 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 16)
1124 	    {
1125 		origin->forced_conversion = RL2_CONVERT_GRID_UINT16_TO_INT32;
1126 		return 1;
1127 	    }
1128 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
1129 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1130 	    {
1131 		origin->forced_conversion = RL2_CONVERT_GRID_FLOAT_TO_INT32;
1132 		return 1;
1133 	    }
1134 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
1135 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 64)
1136 	    {
1137 		origin->forced_conversion = RL2_CONVERT_GRID_DOUBLE_TO_INT32;
1138 		return 1;
1139 	    }
1140       }
1141     if (origin->forced_sample_type == RL2_SAMPLE_UINT32
1142 	&& origin->forced_pixel_type == RL2_PIXEL_DATAGRID
1143 	&& origin->forced_num_bands == 1)
1144       {
1145 	  /* UINT32 datagrid */
1146 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
1147 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1148 	      return 1;
1149 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
1150 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1151 	    {
1152 		origin->forced_conversion = RL2_CONVERT_GRID_INT32_TO_UINT32;
1153 		return 1;
1154 	    }
1155 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
1156 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 8)
1157 	    {
1158 		origin->forced_conversion = RL2_CONVERT_GRID_UINT8_TO_UINT32;
1159 		return 1;
1160 	    }
1161 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
1162 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 8)
1163 	    {
1164 		origin->forced_conversion = RL2_CONVERT_GRID_INT8_TO_UINT32;
1165 		return 1;
1166 	    }
1167 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
1168 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 16)
1169 	    {
1170 		origin->forced_conversion = RL2_CONVERT_GRID_UINT16_TO_UINT32;
1171 		return 1;
1172 	    }
1173 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
1174 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 16)
1175 	    {
1176 		origin->forced_conversion = RL2_CONVERT_GRID_INT16_TO_UINT32;
1177 		return 1;
1178 	    }
1179 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
1180 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1181 	    {
1182 		origin->forced_conversion = RL2_CONVERT_GRID_FLOAT_TO_UINT32;
1183 		return 1;
1184 	    }
1185 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
1186 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 64)
1187 	    {
1188 		origin->forced_conversion = RL2_CONVERT_GRID_DOUBLE_TO_UINT32;
1189 		return 1;
1190 	    }
1191       }
1192     if (origin->forced_sample_type == RL2_SAMPLE_FLOAT
1193 	&& origin->forced_pixel_type == RL2_PIXEL_DATAGRID
1194 	&& origin->forced_num_bands == 1)
1195       {
1196 	  /* FLOAT datagrid */
1197 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
1198 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1199 	      return 1;
1200 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
1201 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 8)
1202 	    {
1203 		origin->forced_conversion = RL2_CONVERT_GRID_INT8_TO_FLOAT;
1204 		return 1;
1205 	    }
1206 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
1207 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 16)
1208 	    {
1209 		origin->forced_conversion = RL2_CONVERT_GRID_INT16_TO_FLOAT;
1210 		return 1;
1211 	    }
1212 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
1213 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1214 	    {
1215 		origin->forced_conversion = RL2_CONVERT_GRID_INT32_TO_FLOAT;
1216 		return 1;
1217 	    }
1218 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
1219 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 8)
1220 	    {
1221 		origin->forced_conversion = RL2_CONVERT_GRID_UINT8_TO_FLOAT;
1222 		return 1;
1223 	    }
1224 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
1225 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 16)
1226 	    {
1227 		origin->forced_conversion = RL2_CONVERT_GRID_UINT16_TO_FLOAT;
1228 		return 1;
1229 	    }
1230 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
1231 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1232 	    {
1233 		origin->forced_conversion = RL2_CONVERT_GRID_UINT32_TO_FLOAT;
1234 		return 1;
1235 	    }
1236 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
1237 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 64)
1238 	    {
1239 		origin->forced_conversion = RL2_CONVERT_GRID_DOUBLE_TO_FLOAT;
1240 		return 1;
1241 	    }
1242       }
1243     if (origin->forced_sample_type == RL2_SAMPLE_DOUBLE
1244 	&& origin->forced_pixel_type == RL2_PIXEL_DATAGRID
1245 	&& origin->forced_num_bands == 1)
1246       {
1247 	  /* DOUBLE datagrid */
1248 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
1249 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 64)
1250 	      return 1;
1251 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
1252 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 8)
1253 	    {
1254 		origin->forced_conversion = RL2_CONVERT_GRID_INT8_TO_DOUBLE;
1255 		return 1;
1256 	    }
1257 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
1258 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 16)
1259 	    {
1260 		origin->forced_conversion = RL2_CONVERT_GRID_INT16_TO_DOUBLE;
1261 		return 1;
1262 	    }
1263 	  if (origin->sampleFormat == SAMPLEFORMAT_INT
1264 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1265 	    {
1266 		origin->forced_conversion = RL2_CONVERT_GRID_INT32_TO_DOUBLE;
1267 		return 1;
1268 	    }
1269 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
1270 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 8)
1271 	    {
1272 		origin->forced_conversion = RL2_CONVERT_GRID_UINT8_TO_DOUBLE;
1273 		return 1;
1274 	    }
1275 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
1276 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 16)
1277 	    {
1278 		origin->forced_conversion = RL2_CONVERT_GRID_UINT16_TO_DOUBLE;
1279 		return 1;
1280 	    }
1281 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT
1282 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1283 	    {
1284 		origin->forced_conversion = RL2_CONVERT_GRID_UINT32_TO_DOUBLE;
1285 		return 1;
1286 	    }
1287 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP
1288 	      && origin->samplesPerPixel == 1 && origin->bitsPerSample == 32)
1289 	    {
1290 		origin->forced_conversion = RL2_CONVERT_GRID_FLOAT_TO_DOUBLE;
1291 		return 1;
1292 	    }
1293       }
1294     return 0;
1295 }
1296 
1297 static int
init_tiff_origin(const char * path,rl2PrivTiffOriginPtr origin)1298 init_tiff_origin (const char *path, rl2PrivTiffOriginPtr origin)
1299 {
1300 /* attempting to initialize a file-based TIFF origin */
1301     uint32 value32;
1302     uint16 value16;
1303 
1304 /* suppressing TIFF messages */
1305     TIFFSetErrorHandler (NULL);
1306     TIFFSetWarningHandler (NULL);
1307 
1308 /* reading from file */
1309     origin->in = TIFFOpen (path, "r");
1310     if (origin->in == NULL)
1311 	goto error;
1312 /* tiled/striped layout */
1313     origin->isTiled = TIFFIsTiled (origin->in);
1314 
1315 /* retrieving TIFF dimensions */
1316     TIFFGetField (origin->in, TIFFTAG_IMAGELENGTH, &value32);
1317     origin->height = value32;
1318     TIFFGetField (origin->in, TIFFTAG_IMAGEWIDTH, &value32);
1319     origin->width = value32;
1320     if (origin->isTiled)
1321       {
1322 	  TIFFGetField (origin->in, TIFFTAG_TILEWIDTH, &value32);
1323 	  origin->tileWidth = value32;
1324 	  TIFFGetField (origin->in, TIFFTAG_TILELENGTH, &value32);
1325 	  origin->tileHeight = value32;
1326       }
1327     else
1328       {
1329 	  TIFFGetField (origin->in, TIFFTAG_ROWSPERSTRIP, &value32);
1330 	  origin->rowsPerStrip = value32;
1331       }
1332 
1333     if (origin->isGeoReferenced && origin->isGeoTiff == 0)
1334       {
1335 	  /* completing Worldfile georeferencing */
1336 	  origin->maxX =
1337 	      origin->minX + (origin->hResolution * (double) (origin->width));
1338 	  origin->minY =
1339 	      origin->maxY - (origin->vResolution * (double) (origin->height));
1340       }
1341 
1342 /* retrieving pixel configuration */
1343     TIFFGetField (origin->in, TIFFTAG_BITSPERSAMPLE, &value16);
1344     origin->bitsPerSample = value16;
1345     if (TIFFGetField (origin->in, TIFFTAG_SAMPLESPERPIXEL, &value16) == 0)
1346       {
1347 	  /* attempting to recover badly formatted TIFFs */
1348 	  origin->samplesPerPixel = 1;
1349       }
1350     else
1351 	origin->samplesPerPixel = value16;
1352     TIFFGetField (origin->in, TIFFTAG_PHOTOMETRIC, &value16);
1353     origin->photometric = value16;
1354     TIFFGetField (origin->in, TIFFTAG_COMPRESSION, &value16);
1355     origin->compression = value16;
1356     if (TIFFGetField (origin->in, TIFFTAG_SAMPLEFORMAT, &value16) == 0)
1357 	origin->sampleFormat = SAMPLEFORMAT_UINT;
1358     else
1359 	origin->sampleFormat = value16;
1360     if (TIFFGetField (origin->in, TIFFTAG_PLANARCONFIG, &value16) == 0)
1361       {
1362 	  /* attempting to recover badly formatted TIFFs */
1363 	  origin->planarConfig = PLANARCONFIG_CONTIG;
1364       }
1365     else
1366 	origin->planarConfig = value16;
1367 
1368     if (origin->bitsPerSample == 16 && origin->sampleFormat == SAMPLEFORMAT_UINT
1369 	&& origin->planarConfig == PLANARCONFIG_SEPARATE)
1370 	;
1371     else if (origin->bitsPerSample == 8
1372 	     && origin->sampleFormat == SAMPLEFORMAT_UINT
1373 	     && origin->planarConfig == PLANARCONFIG_SEPARATE)
1374 	;
1375     else if (origin->planarConfig != PLANARCONFIG_CONTIG)
1376 	goto error;
1377 
1378     if (origin->photometric == PHOTOMETRIC_PALETTE
1379 	&& origin->sampleFormat == SAMPLEFORMAT_UINT)
1380       {
1381 	  /* attempting to retrieve a Palette */
1382 	  uint16 *red;
1383 	  uint16 *green;
1384 	  uint16 *blue;
1385 	  int max_palette = 0;
1386 	  int i;
1387 	  switch (origin->bitsPerSample)
1388 	    {
1389 	    case 1:
1390 		max_palette = 2;
1391 		break;
1392 	    case 2:
1393 		max_palette = 4;
1394 		break;
1395 	    case 3:
1396 		max_palette = 8;
1397 		break;
1398 	    case 4:
1399 		max_palette = 16;
1400 		break;
1401 	    case 5:
1402 		max_palette = 32;
1403 		break;
1404 	    case 6:
1405 		max_palette = 64;
1406 		break;
1407 	    case 7:
1408 		max_palette = 128;
1409 		break;
1410 	    case 8:
1411 		max_palette = 256;
1412 		break;
1413 	    };
1414 	  if (origin->forced_conversion == RL2_CONVERT_GRAYSCALE_TO_PALETTE)
1415 	    {
1416 		/* forced conversion: creating a GRAYSCALE palette */
1417 		max_palette = 256;
1418 		for (i = 0; i < max_palette; i++)
1419 		  {
1420 		      red[i] = i;
1421 		      green[i] = i;
1422 		      blue[i] = i;
1423 		  }
1424 	    }
1425 	  if (max_palette == 0)
1426 	      goto error;
1427 	  if (!alloc_palette (origin, max_palette))
1428 	      goto error;
1429 	  if (TIFFGetField (origin->in, TIFFTAG_COLORMAP, &red, &green, &blue)
1430 	      == 0)
1431 	      goto error;
1432 	  for (i = 0; i < max_palette; i++)
1433 	    {
1434 		if (red[i] < 256)
1435 		    origin->red[i] = red[i];
1436 		else
1437 		    origin->red[i] = red[i] / 256;
1438 		if (green[i] < 256)
1439 		    origin->green[i] = green[i];
1440 		else
1441 		    origin->green[i] = green[i] / 256;
1442 		if (blue[i] < 256)
1443 		    origin->blue[i] = blue[i];
1444 		else
1445 		    origin->blue[i] = blue[i] / 256;
1446 	    }
1447 	  if ((origin->forced_sample_type == RL2_SAMPLE_1_BIT
1448 	       || origin->forced_sample_type == RL2_SAMPLE_2_BIT
1449 	       || origin->forced_sample_type == RL2_SAMPLE_4_BIT)
1450 	      && origin->forced_pixel_type == RL2_PIXEL_PALETTE)
1451 	    {
1452 		int max = 0;
1453 		unsigned char plt[256];
1454 		int j;
1455 		unsigned char *p;
1456 		unsigned short x;
1457 		unsigned short y;
1458 		unsigned short row;
1459 		unsigned short height = 256;
1460 		if (origin->isTiled)
1461 		    height = origin->tileHeight;
1462 		for (row = 0; row < origin->height; row += height)
1463 		  {
1464 		      unsigned char *pixels = NULL;
1465 		      int pixels_sz = 0;
1466 		      rl2PalettePtr pltx = rl2_create_palette (max_palette);
1467 		      for (j = 0; j < max_palette; j++)
1468 			  rl2_set_palette_color (pltx, j, origin->red[j],
1469 						 origin->green[j],
1470 						 origin->blue[j]);
1471 		      if (read_from_tiff
1472 			  (origin, origin->width, height, RL2_SAMPLE_UINT8,
1473 			   RL2_PIXEL_PALETTE, 1, row, 0, &pixels, &pixels_sz,
1474 			   pltx) != RL2_OK)
1475 			  goto error;
1476 		      rl2_destroy_palette (pltx);
1477 		      p = pixels;
1478 		      for (y = 0; y < height; y++)
1479 			{
1480 			    if ((y + row) >= origin->height)
1481 				break;
1482 			    for (x = 0; x < origin->width; x++)
1483 			      {
1484 				  int ok = 0;
1485 				  int index = *p++;
1486 				  for (j = 0; j < max; j++)
1487 				    {
1488 					if (plt[j] == index)
1489 					  {
1490 					      ok = 1;
1491 					      break;
1492 					  }
1493 				    }
1494 				  if (!ok)
1495 				      plt[max++] = index;
1496 			      }
1497 			}
1498 		      free (pixels);
1499 		  }
1500 		if (origin->red != NULL)
1501 		    free (origin->red);
1502 		if (origin->green != NULL)
1503 		    free (origin->green);
1504 		if (origin->blue != NULL)
1505 		    free (origin->blue);
1506 		if (!alloc_palette (origin, max))
1507 		    goto error;
1508 		for (j = 0; j < max; j++)
1509 		  {
1510 		      /* normalized palette */
1511 		      if (red[plt[j]] < 256)
1512 			  origin->red[j] = red[plt[j]];
1513 		      else
1514 			  origin->red[j] = red[plt[j]] / 256;
1515 		      if (green[plt[j]] < 256)
1516 			  origin->green[j] = green[plt[j]];
1517 		      else
1518 			  origin->green[j] = green[plt[j]] / 256;
1519 		      if (blue[plt[j]] < 256)
1520 			  origin->blue[j] = blue[plt[j]];
1521 		      else
1522 			  origin->blue[j] = blue[plt[j]] / 256;
1523 		  }
1524 	    }
1525       }
1526     if (!check_tiff_origin_pixel_conversion (origin))
1527 	goto error;
1528 
1529     if (origin->forced_conversion == RL2_CONVERT_GRAYSCALE_TO_PALETTE)
1530       {
1531 	  /* forced conversion: creating a GRAYSCALE palette */
1532 	  int i;
1533 	  if (!alloc_palette (origin, 256))
1534 	      goto error;
1535 	  for (i = 0; i < 256; i++)
1536 	    {
1537 		origin->red[i] = i;
1538 		origin->green[i] = i;
1539 		origin->blue[i] = i;
1540 	    }
1541       }
1542     if (origin->forced_conversion == RL2_CONVERT_MONOCHROME_TO_PALETTE)
1543       {
1544 	  /* forced conversion: creating a BILEVEL palette */
1545 	  if (!alloc_palette (origin, 2))
1546 	      goto error;
1547 	  origin->red[0] = 255;
1548 	  origin->green[0] = 255;
1549 	  origin->blue[0] = 255;
1550 	  origin->red[1] = 0;
1551 	  origin->green[1] = 0;
1552 	  origin->blue[1] = 0;
1553       }
1554 
1555     return 1;
1556   error:
1557     return 0;
1558 }
1559 
1560 RL2_DECLARE rl2TiffOriginPtr
rl2_create_tiff_origin(const char * path,int georef_priority,int srid,unsigned char force_sample_type,unsigned char force_pixel_type,unsigned char force_num_bands)1561 rl2_create_tiff_origin (const char *path, int georef_priority, int srid,
1562 			unsigned char force_sample_type,
1563 			unsigned char force_pixel_type,
1564 			unsigned char force_num_bands)
1565 {
1566 /* attempting to create a file-based TIFF / GeoTIFF origin */
1567     rl2PrivTiffOriginPtr origin = NULL;
1568 
1569     if (georef_priority == RL2_TIFF_NO_GEOREF
1570 	|| georef_priority == RL2_TIFF_GEOTIFF
1571 	|| georef_priority == RL2_TIFF_WORLDFILE)
1572 	;
1573     else
1574 	return NULL;
1575     origin =
1576 	create_tiff_origin (path, force_sample_type, force_pixel_type,
1577 			    force_num_bands);
1578     if (origin == NULL)
1579 	return NULL;
1580     if (georef_priority == RL2_TIFF_GEOTIFF)
1581       {
1582 	  /* attempting first to retrieve GeoTIFF georeferencing */
1583 	  geo_tiff_origin (path, origin, srid);
1584 	  if (origin->isGeoReferenced == 0)
1585 	    {
1586 		/* then attempting to retrieve WorldFile georeferencing */
1587 		worldfile_tiff_origin (path, origin, srid);
1588 	    }
1589       }
1590     else if (georef_priority == RL2_TIFF_WORLDFILE)
1591       {
1592 	  /* attempting first to retrieve Worldfile georeferencing */
1593 	  worldfile_tiff_origin (path, origin, srid);
1594 	  if (origin->isGeoReferenced == 0)
1595 	    {
1596 		/* then attempting to retrieve GeoTIFF georeferencing */
1597 		geo_tiff_origin (path, origin, srid);
1598 	    }
1599       }
1600     if (!init_tiff_origin (path, origin))
1601 	goto error;
1602 
1603     return (rl2TiffOriginPtr) origin;
1604   error:
1605     if (origin != NULL)
1606 	rl2_destroy_tiff_origin ((rl2TiffOriginPtr) origin);
1607     return NULL;
1608 }
1609 
1610 RL2_DECLARE rl2TiffOriginPtr
rl2_create_geotiff_origin(const char * path,int force_srid,unsigned char force_sample_type,unsigned char force_pixel_type,unsigned char force_num_bands)1611 rl2_create_geotiff_origin (const char *path, int force_srid,
1612 			   unsigned char force_sample_type,
1613 			   unsigned char force_pixel_type,
1614 			   unsigned char force_num_bands)
1615 {
1616 /* attempting to create a file-based GeoTIFF origin */
1617     rl2PrivTiffOriginPtr origin = NULL;
1618 
1619     origin =
1620 	create_tiff_origin (path, force_sample_type, force_pixel_type,
1621 			    force_num_bands);
1622     if (origin == NULL)
1623 	return NULL;
1624 
1625     /* attempting to retrieve GeoTIFF georeferencing */
1626     geo_tiff_origin (path, origin, force_srid);
1627     if (origin->isGeoReferenced == 0)
1628 	goto error;
1629     if (!init_tiff_origin (path, origin))
1630 	goto error;
1631 
1632     return (rl2TiffOriginPtr) origin;
1633   error:
1634     if (origin != NULL)
1635 	rl2_destroy_tiff_origin ((rl2TiffOriginPtr) origin);
1636     return NULL;
1637 }
1638 
1639 RL2_DECLARE rl2TiffOriginPtr
rl2_create_tiff_worldfile_origin(const char * path,int srid,unsigned char force_sample_type,unsigned char force_pixel_type,unsigned char force_num_bands)1640 rl2_create_tiff_worldfile_origin (const char *path, int srid,
1641 				  unsigned char force_sample_type,
1642 				  unsigned char force_pixel_type,
1643 				  unsigned char force_num_bands)
1644 {
1645 /* attempting to create a file-based TIFF+TFW origin */
1646     rl2PrivTiffOriginPtr origin = NULL;
1647 
1648     origin =
1649 	create_tiff_origin (path, force_sample_type, force_pixel_type,
1650 			    force_num_bands);
1651     if (origin == NULL)
1652 	return NULL;
1653 
1654 /* attempting to retrieve Worldfile georeferencing */
1655     worldfile_tiff_origin (path, origin, srid);
1656     if (origin->isGeoReferenced == 0)
1657 	goto error;
1658     if (!init_tiff_origin (path, origin))
1659 	goto error;
1660 
1661     return (rl2TiffOriginPtr) origin;
1662   error:
1663     if (origin != NULL)
1664 	rl2_destroy_tiff_origin ((rl2TiffOriginPtr) origin);
1665     return NULL;
1666 }
1667 
1668 RL2_DECLARE int
rl2_set_tiff_origin_not_referenced(rl2TiffOriginPtr tiff)1669 rl2_set_tiff_origin_not_referenced (rl2TiffOriginPtr tiff)
1670 {
1671 /* setting up a false GeoReferncing */
1672     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
1673     if (origin == NULL)
1674 	return RL2_ERROR;
1675     origin->hResolution = 1.0;
1676     origin->vResolution = 1.0;
1677     origin->minX = 0.0;
1678     origin->minY = 0.0;
1679     origin->maxX = origin->width - 1;
1680     origin->maxY = origin->height - 1;
1681     origin->Srid = -1;
1682     origin->isGeoReferenced = 1;
1683     origin->isGeoTiff = 0;
1684     return RL2_OK;
1685 }
1686 
1687 RL2_DECLARE const char *
rl2_get_tiff_origin_path(rl2TiffOriginPtr tiff)1688 rl2_get_tiff_origin_path (rl2TiffOriginPtr tiff)
1689 {
1690 /* retrieving the input path from a TIFF origin */
1691     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
1692     if (origin == NULL)
1693 	return NULL;
1694 
1695     return origin->path;
1696 }
1697 
1698 RL2_DECLARE const char *
rl2_get_tiff_origin_worldfile_path(rl2TiffOriginPtr tiff)1699 rl2_get_tiff_origin_worldfile_path (rl2TiffOriginPtr tiff)
1700 {
1701 /* retrieving the Worldfile path from a TIFF origin */
1702     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
1703     if (origin == NULL)
1704 	return NULL;
1705 
1706     return origin->tfw_path;
1707 }
1708 
1709 RL2_DECLARE int
rl2_is_geotiff_origin(rl2TiffOriginPtr tiff,int * geotiff)1710 rl2_is_geotiff_origin (rl2TiffOriginPtr tiff, int *geotiff)
1711 {
1712 /* detecting if a TIFF origin actually is a GeoTIFF */
1713     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
1714     if (origin == NULL)
1715 	return RL2_ERROR;
1716     *geotiff = origin->isGeoTiff;
1717     return RL2_OK;
1718 }
1719 
1720 RL2_DECLARE int
rl2_is_tiff_worldfile_origin(rl2TiffOriginPtr tiff,int * tiff_worldfile)1721 rl2_is_tiff_worldfile_origin (rl2TiffOriginPtr tiff, int *tiff_worldfile)
1722 {
1723 /* detecting if a TIFF origin actually supports a TFW */
1724     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
1725     if (origin == NULL)
1726 	return RL2_ERROR;
1727     *tiff_worldfile = 0;
1728     if (origin->tfw_path != NULL)
1729 	*tiff_worldfile = 1;
1730     return RL2_OK;
1731 }
1732 
1733 RL2_DECLARE int
rl2_get_tiff_origin_size(rl2TiffOriginPtr tiff,unsigned int * width,unsigned int * height)1734 rl2_get_tiff_origin_size (rl2TiffOriginPtr tiff, unsigned int *width,
1735 			  unsigned int *height)
1736 {
1737 /* retrieving Width and Height from a TIFF origin */
1738     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
1739     if (origin == NULL)
1740 	return RL2_ERROR;
1741 
1742     *width = origin->width;
1743     *height = origin->height;
1744     return RL2_OK;
1745 }
1746 
1747 RL2_DECLARE int
rl2_get_tiff_origin_srid(rl2TiffOriginPtr tiff,int * srid)1748 rl2_get_tiff_origin_srid (rl2TiffOriginPtr tiff, int *srid)
1749 {
1750 /* retrieving the SRID from a TIFF origin */
1751     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
1752     if (origin == NULL)
1753 	return RL2_ERROR;
1754     if (origin->isGeoReferenced == 0)
1755 	return RL2_ERROR;
1756 
1757     *srid = origin->Srid;
1758     return RL2_OK;
1759 }
1760 
1761 RL2_DECLARE int
rl2_get_tiff_origin_extent(rl2TiffOriginPtr tiff,double * minX,double * minY,double * maxX,double * maxY)1762 rl2_get_tiff_origin_extent (rl2TiffOriginPtr tiff, double *minX, double *minY,
1763 			    double *maxX, double *maxY)
1764 {
1765 /* retrieving the Extent from a TIFF origin */
1766     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
1767     if (origin == NULL)
1768 	return RL2_ERROR;
1769     if (origin->isGeoReferenced == 0)
1770 	return RL2_ERROR;
1771 
1772     *minX = origin->minX;
1773     *minY = origin->minY;
1774     *maxX = origin->maxX;
1775     *maxY = origin->maxY;
1776     return RL2_OK;
1777 }
1778 
1779 RL2_DECLARE int
rl2_get_tiff_origin_resolution(rl2TiffOriginPtr tiff,double * hResolution,double * vResolution)1780 rl2_get_tiff_origin_resolution (rl2TiffOriginPtr tiff, double *hResolution,
1781 				double *vResolution)
1782 {
1783 /* retrieving the Pixel Resolution from a TIFF origin */
1784     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
1785     if (origin == NULL)
1786 	return RL2_ERROR;
1787     if (origin->isGeoReferenced == 0)
1788 	return RL2_ERROR;
1789 
1790     *hResolution = origin->hResolution;
1791     *vResolution = origin->vResolution;
1792     return RL2_OK;
1793 }
1794 
1795 RL2_DECLARE int
rl2_get_tiff_origin_type(rl2TiffOriginPtr tiff,unsigned char * sample_type,unsigned char * pixel_type,unsigned char * alias_pixel_type,unsigned char * num_bands)1796 rl2_get_tiff_origin_type (rl2TiffOriginPtr tiff, unsigned char *sample_type,
1797 			  unsigned char *pixel_type,
1798 			  unsigned char *alias_pixel_type,
1799 			  unsigned char *num_bands)
1800 {
1801 /* retrieving the sample/pixel type from a TIFF origin */
1802     int ok = 0;
1803     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
1804     if (origin == NULL)
1805 	return RL2_ERROR;
1806 
1807     if (origin->sampleFormat == SAMPLEFORMAT_UINT
1808 	&& origin->samplesPerPixel == 1
1809 	&& origin->photometric < PHOTOMETRIC_RGB)
1810       {
1811 	  /* could be some kind of MONOCHROME */
1812 	  if (origin->bitsPerSample == 1)
1813 	    {
1814 		*sample_type = RL2_SAMPLE_1_BIT;
1815 		ok = 1;
1816 	    }
1817 	  if (ok)
1818 	    {
1819 		*pixel_type = RL2_PIXEL_MONOCHROME;
1820 		*alias_pixel_type = RL2_PIXEL_MONOCHROME;
1821 		*num_bands = 1;
1822 		return RL2_OK;
1823 	    }
1824       }
1825     if (origin->sampleFormat == SAMPLEFORMAT_UINT
1826 	&& origin->samplesPerPixel == 1
1827 	&& origin->photometric < PHOTOMETRIC_RGB)
1828       {
1829 	  /* could be some kind of GRAYSCALE */
1830 	  if (origin->bitsPerSample == 2)
1831 	    {
1832 		*sample_type = RL2_SAMPLE_2_BIT;
1833 		ok = 1;
1834 	    }
1835 	  else if (origin->bitsPerSample == 4)
1836 	    {
1837 		*sample_type = RL2_SAMPLE_4_BIT;
1838 		ok = 1;
1839 	    }
1840 	  else if (origin->bitsPerSample == 8)
1841 	    {
1842 		*sample_type = RL2_SAMPLE_UINT8;
1843 		ok = 1;
1844 	    }
1845 	  else if (origin->bitsPerSample == 16)
1846 	    {
1847 		*sample_type = RL2_SAMPLE_UINT16;
1848 		ok = 1;
1849 	    }
1850 	  if (ok)
1851 	    {
1852 		*pixel_type = RL2_PIXEL_GRAYSCALE;
1853 		*alias_pixel_type = RL2_PIXEL_GRAYSCALE;
1854 		if (origin->bitsPerSample == 8 || origin->bitsPerSample == 16)
1855 		    *alias_pixel_type = RL2_PIXEL_DATAGRID;
1856 		*num_bands = 1;
1857 		return RL2_OK;
1858 	    }
1859       }
1860     if (origin->sampleFormat == SAMPLEFORMAT_UINT
1861 	&& origin->samplesPerPixel == 1
1862 	&& origin->photometric == PHOTOMETRIC_PALETTE)
1863       {
1864 	  /* could be some kind of PALETTE */
1865 	  if (origin->bitsPerSample == 1)
1866 	    {
1867 		*sample_type = RL2_SAMPLE_1_BIT;
1868 		ok = 1;
1869 	    }
1870 	  else if (origin->bitsPerSample == 2)
1871 	    {
1872 		*sample_type = RL2_SAMPLE_2_BIT;
1873 		ok = 1;
1874 	    }
1875 	  else if (origin->bitsPerSample == 4)
1876 	    {
1877 		*sample_type = RL2_SAMPLE_4_BIT;
1878 		ok = 1;
1879 	    }
1880 	  else if (origin->bitsPerSample == 8)
1881 	    {
1882 		*sample_type = RL2_SAMPLE_UINT8;
1883 		ok = 1;
1884 	    }
1885 	  if (ok)
1886 	    {
1887 		*pixel_type = RL2_PIXEL_PALETTE;
1888 		*alias_pixel_type = RL2_PIXEL_PALETTE;
1889 		*num_bands = 1;
1890 		return RL2_OK;
1891 	    }
1892       }
1893     if (origin->sampleFormat == SAMPLEFORMAT_UINT
1894 	&& origin->samplesPerPixel == 3
1895 	&& origin->photometric == PHOTOMETRIC_RGB)
1896       {
1897 	  /* could be some kind of RGB */
1898 	  if (origin->bitsPerSample == 8)
1899 	    {
1900 		*sample_type = RL2_SAMPLE_UINT8;
1901 		ok = 1;
1902 	    }
1903 	  else if (origin->bitsPerSample == 16)
1904 	    {
1905 		*sample_type = RL2_SAMPLE_UINT16;
1906 		ok = 1;
1907 	    }
1908 	  if (ok)
1909 	    {
1910 		*pixel_type = RL2_PIXEL_RGB;
1911 		*alias_pixel_type = RL2_PIXEL_RGB;
1912 		*num_bands = 3;
1913 		return RL2_OK;
1914 	    }
1915       }
1916     if (origin->samplesPerPixel == 1 && origin->photometric < PHOTOMETRIC_RGB)
1917       {
1918 	  /* could be some kind of DATA-GRID */
1919 	  if (origin->sampleFormat == SAMPLEFORMAT_INT)
1920 	    {
1921 		/* Signed Integer */
1922 		if (origin->bitsPerSample == 8)
1923 		  {
1924 		      *sample_type = RL2_SAMPLE_INT8;
1925 		      ok = 1;
1926 		  }
1927 		else if (origin->bitsPerSample == 16)
1928 		  {
1929 		      *sample_type = RL2_SAMPLE_INT16;
1930 		      ok = 1;
1931 		  }
1932 		else if (origin->bitsPerSample == 32)
1933 		  {
1934 		      *sample_type = RL2_SAMPLE_INT32;
1935 		      ok = 1;
1936 		  }
1937 	    }
1938 	  if (origin->sampleFormat == SAMPLEFORMAT_UINT)
1939 	    {
1940 		/* Unsigned Integer */
1941 		if (origin->bitsPerSample == 8)
1942 		  {
1943 		      *sample_type = RL2_SAMPLE_UINT8;
1944 		      ok = 1;
1945 		  }
1946 		else if (origin->bitsPerSample == 16)
1947 		  {
1948 		      *sample_type = RL2_SAMPLE_UINT16;
1949 		      ok = 1;
1950 		  }
1951 		else if (origin->bitsPerSample == 32)
1952 		  {
1953 		      *sample_type = RL2_SAMPLE_UINT32;
1954 		      ok = 1;
1955 		  }
1956 	    }
1957 	  if (origin->sampleFormat == SAMPLEFORMAT_IEEEFP)
1958 	    {
1959 		/* Floating-Point */
1960 		if (origin->bitsPerSample == 32)
1961 		  {
1962 		      *sample_type = RL2_SAMPLE_FLOAT;
1963 		      ok = 1;
1964 		  }
1965 		else if (origin->bitsPerSample == 64)
1966 		  {
1967 		      *sample_type = RL2_SAMPLE_DOUBLE;
1968 		      ok = 1;
1969 		  }
1970 	    }
1971 	  if (ok)
1972 	    {
1973 		*pixel_type = RL2_PIXEL_DATAGRID;
1974 		*alias_pixel_type = RL2_PIXEL_DATAGRID;
1975 		*num_bands = 1;
1976 		return RL2_OK;
1977 	    }
1978       }
1979     return RL2_ERROR;
1980 }
1981 
1982 RL2_DECLARE int
rl2_get_tiff_origin_forced_type(rl2TiffOriginPtr tiff,unsigned char * sample_type,unsigned char * pixel_type,unsigned char * num_bands)1983 rl2_get_tiff_origin_forced_type (rl2TiffOriginPtr tiff,
1984 				 unsigned char *sample_type,
1985 				 unsigned char *pixel_type,
1986 				 unsigned char *num_bands)
1987 {
1988 /* retrieving the sample/pixel type (FORCED) from a TIFF origin */
1989     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
1990     if (origin == NULL)
1991 	return RL2_ERROR;
1992 
1993     *sample_type = origin->forced_sample_type;
1994     *pixel_type = origin->forced_pixel_type;
1995     *num_bands = origin->forced_num_bands;
1996     return RL2_OK;
1997 }
1998 
1999 RL2_DECLARE int
rl2_get_tiff_origin_compression(rl2TiffOriginPtr tiff,unsigned char * compression)2000 rl2_get_tiff_origin_compression (rl2TiffOriginPtr tiff,
2001 				 unsigned char *compression)
2002 {
2003 /* retrieving the sample/pixel type from a TIFF origin */
2004     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
2005     if (origin == NULL)
2006 	return RL2_ERROR;
2007 
2008     switch (origin->compression)
2009       {
2010       case COMPRESSION_NONE:
2011 	  *compression = RL2_COMPRESSION_NONE;
2012 	  break;
2013       case COMPRESSION_LZW:
2014 	  *compression = RL2_COMPRESSION_LZW;
2015 	  break;
2016       case COMPRESSION_DEFLATE:
2017 	  *compression = RL2_COMPRESSION_DEFLATE;
2018 	  break;
2019       case COMPRESSION_LZMA:
2020 	  *compression = RL2_COMPRESSION_LZMA;
2021 	  break;
2022       case COMPRESSION_JPEG:
2023 	  *compression = RL2_COMPRESSION_JPEG;
2024 	  break;
2025       case COMPRESSION_CCITTFAX3:
2026 	  *compression = RL2_COMPRESSION_CCITTFAX3;
2027 	  break;
2028       case COMPRESSION_CCITTFAX4:
2029 	  *compression = RL2_COMPRESSION_CCITTFAX4;
2030 	  break;
2031       default:
2032 	  *compression = RL2_COMPRESSION_UNKNOWN;
2033 	  break;
2034       }
2035     return RL2_OK;
2036 }
2037 
2038 RL2_DECLARE int
rl2_eval_tiff_origin_compatibility(rl2CoveragePtr cvg,rl2TiffOriginPtr tiff,int force_srid)2039 rl2_eval_tiff_origin_compatibility (rl2CoveragePtr cvg, rl2TiffOriginPtr tiff,
2040 				    int force_srid)
2041 {
2042 /* testing if a Coverage and a TIFF origin are mutually compatible */
2043     unsigned char sample_type;
2044     unsigned char pixel_type;
2045     unsigned char num_bands;
2046     int srid;
2047     double hResolution;
2048     double vResolution;
2049     double confidence;
2050     rl2PrivCoveragePtr coverage = (rl2PrivCoveragePtr) cvg;
2051 
2052     if (coverage == NULL || tiff == NULL)
2053 	return RL2_ERROR;
2054     if (rl2_get_tiff_origin_forced_type
2055 	(tiff, &sample_type, &pixel_type, &num_bands) != RL2_OK)
2056 	return RL2_ERROR;
2057 
2058 /* aliasing GRAYSCALE and DATAGRID for UINT8 */
2059     if (coverage->sampleType == RL2_SAMPLE_UINT8
2060 	&& coverage->pixelType == RL2_PIXEL_DATAGRID
2061 	&& pixel_type == RL2_PIXEL_GRAYSCALE)
2062 	pixel_type = RL2_PIXEL_DATAGRID;
2063 /* aliasing GRAYSCALE and DATAGRID for UINT16 */
2064     if (coverage->sampleType == RL2_SAMPLE_UINT16
2065 	&& coverage->pixelType == RL2_PIXEL_DATAGRID
2066 	&& pixel_type == RL2_PIXEL_GRAYSCALE)
2067 	pixel_type = RL2_PIXEL_DATAGRID;
2068 
2069     if (coverage->sampleType != sample_type)
2070 	return RL2_FALSE;
2071     if (coverage->pixelType != pixel_type)
2072 	return RL2_FALSE;
2073     if (coverage->nBands != num_bands)
2074 	return RL2_FALSE;
2075 
2076     if (coverage->Srid == RL2_GEOREFERENCING_NONE)
2077 	return RL2_TRUE;
2078 
2079 /* checking for resolution compatibility */
2080     if (rl2_get_tiff_origin_srid (tiff, &srid) != RL2_OK)
2081 	return RL2_FALSE;
2082     if (coverage->Srid != srid)
2083       {
2084 	  if (force_srid > 0)
2085 	    {
2086 		if (coverage->Srid != force_srid)
2087 		    return RL2_FALSE;
2088 	    }
2089 	  else
2090 	      return RL2_FALSE;
2091       }
2092     if (rl2_get_tiff_origin_resolution (tiff, &hResolution, &vResolution) !=
2093 	RL2_OK)
2094 	return RL2_FALSE;
2095     confidence = coverage->hResolution / 100.0;
2096     if (hResolution < (coverage->hResolution - confidence)
2097 	|| hResolution > (coverage->hResolution + confidence))
2098 	return RL2_FALSE;
2099     confidence = coverage->vResolution / 100.0;
2100     if (vResolution < (coverage->vResolution - confidence)
2101 	|| vResolution > (coverage->vResolution + confidence))
2102 	return RL2_FALSE;
2103     return RL2_TRUE;
2104 }
2105 
2106 RL2_PRIVATE char
truncate_8(double val)2107 truncate_8 (double val)
2108 {
2109 /* truncating to signed 8 bit integer */
2110     if (val <= INT8_MIN)
2111 	return INT8_MIN;
2112     if (val >= INT8_MAX)
2113 	return INT8_MAX;
2114     return (char) val;
2115 }
2116 
2117 RL2_PRIVATE unsigned char
truncate_u8(double val)2118 truncate_u8 (double val)
2119 {
2120 /* truncating to unsigned 8 bit integer */
2121     if (val <= 0.0)
2122 	return 0;
2123     if (val >= UINT8_MAX)
2124 	return UINT8_MAX;
2125     return (unsigned char) val;
2126 }
2127 
2128 RL2_PRIVATE short
truncate_16(double val)2129 truncate_16 (double val)
2130 {
2131 /* truncating to signed 16 bit integer */
2132     if (val <= INT16_MIN)
2133 	return INT16_MIN;
2134     if (val >= INT16_MAX)
2135 	return INT16_MAX;
2136     return (short) val;
2137 }
2138 
2139 RL2_PRIVATE unsigned short
truncate_u16(double val)2140 truncate_u16 (double val)
2141 {
2142 /* truncating to unsigned 16 bit integer */
2143     if (val <= 0.0)
2144 	return 0;
2145     if (val >= UINT16_MAX)
2146 	return UINT16_MAX;
2147     return (unsigned short) val;
2148 }
2149 
2150 RL2_PRIVATE int
truncate_32(double val)2151 truncate_32 (double val)
2152 {
2153 /* truncating to signed 32 bit integer */
2154     if (val <= INT32_MIN)
2155 	return INT32_MIN;
2156     if (val >= INT32_MAX)
2157 	return INT32_MAX;
2158     return (int) val;
2159 }
2160 
2161 RL2_PRIVATE unsigned int
truncate_u32(double val)2162 truncate_u32 (double val)
2163 {
2164 /* truncating to unsigned 32 bit integer */
2165     if (val <= 0.0)
2166 	return 0;
2167     if (val >= UINT32_MAX)
2168 	return UINT32_MAX;
2169     return (unsigned int) val;
2170 }
2171 
2172 static void
copy_convert_tile(rl2PrivTiffOriginPtr origin,void * in,void * out,unsigned int startRow,unsigned int startCol,unsigned short width,unsigned short height,uint32 tile_y,uint32 tile_x,unsigned char convert)2173 copy_convert_tile (rl2PrivTiffOriginPtr origin, void *in, void *out,
2174 		   unsigned int startRow, unsigned int startCol,
2175 		   unsigned short width, unsigned short height, uint32 tile_y,
2176 		   uint32 tile_x, unsigned char convert)
2177 {
2178 /* copying pixels by applying a format conversion */
2179     char *p_in_8;
2180     char *p_out_8;
2181     unsigned char *p_in_u8;
2182     unsigned char *p_out_u8;
2183     short *p_in_16;
2184     short *p_out_16;
2185     unsigned short *p_in_u16;
2186     unsigned short *p_out_u16;
2187     int *p_in_32;
2188     int *p_out_32;
2189     unsigned int *p_in_u32;
2190     unsigned int *p_out_u32;
2191     float *p_in_flt;
2192     float *p_out_flt;
2193     double *p_in_dbl;
2194     double *p_out_dbl;
2195     uint32 x;
2196     uint32 y;
2197     unsigned int dest_x;
2198     unsigned int dest_y;
2199 
2200     for (y = 0; y < origin->tileHeight; y++)
2201       {
2202 	  dest_y = tile_y + y;
2203 	  if (dest_y < startRow || dest_y >= (startRow + height))
2204 	      continue;
2205 
2206 	  switch (convert)
2207 	    {
2208 	    case RL2_CONVERT_GRID_INT8_TO_UINT8:
2209 	    case RL2_CONVERT_GRID_INT8_TO_INT16:
2210 	    case RL2_CONVERT_GRID_INT8_TO_UINT16:
2211 	    case RL2_CONVERT_GRID_INT8_TO_INT32:
2212 	    case RL2_CONVERT_GRID_INT8_TO_UINT32:
2213 	    case RL2_CONVERT_GRID_INT8_TO_FLOAT:
2214 	    case RL2_CONVERT_GRID_INT8_TO_DOUBLE:
2215 		p_in_8 = (char *) in;
2216 		p_in_8 += y * origin->tileWidth;
2217 		break;
2218 	    case RL2_CONVERT_GRID_UINT8_TO_INT8:
2219 	    case RL2_CONVERT_GRID_UINT8_TO_UINT16:
2220 	    case RL2_CONVERT_GRID_UINT8_TO_INT16:
2221 	    case RL2_CONVERT_GRID_UINT8_TO_UINT32:
2222 	    case RL2_CONVERT_GRID_UINT8_TO_INT32:
2223 	    case RL2_CONVERT_GRID_UINT8_TO_FLOAT:
2224 	    case RL2_CONVERT_GRID_UINT8_TO_DOUBLE:
2225 		p_in_u8 = (unsigned char *) in;
2226 		p_in_u8 += y * origin->tileWidth;
2227 		break;
2228 	    case RL2_CONVERT_GRID_INT16_TO_INT8:
2229 	    case RL2_CONVERT_GRID_INT16_TO_UINT8:
2230 	    case RL2_CONVERT_GRID_INT16_TO_UINT16:
2231 	    case RL2_CONVERT_GRID_INT16_TO_INT32:
2232 	    case RL2_CONVERT_GRID_INT16_TO_UINT32:
2233 	    case RL2_CONVERT_GRID_INT16_TO_FLOAT:
2234 	    case RL2_CONVERT_GRID_INT16_TO_DOUBLE:
2235 		p_in_16 = (short *) in;
2236 		p_in_16 += y * origin->tileWidth;
2237 		break;
2238 	    case RL2_CONVERT_GRID_UINT16_TO_INT8:
2239 	    case RL2_CONVERT_GRID_UINT16_TO_UINT8:
2240 	    case RL2_CONVERT_GRID_UINT16_TO_INT16:
2241 	    case RL2_CONVERT_GRID_UINT16_TO_UINT32:
2242 	    case RL2_CONVERT_GRID_UINT16_TO_INT32:
2243 	    case RL2_CONVERT_GRID_UINT16_TO_FLOAT:
2244 	    case RL2_CONVERT_GRID_UINT16_TO_DOUBLE:
2245 		p_in_u16 = (unsigned short *) in;
2246 		p_in_u16 += y * origin->tileWidth;
2247 		break;
2248 	    case RL2_CONVERT_GRID_INT32_TO_INT8:
2249 	    case RL2_CONVERT_GRID_INT32_TO_UINT8:
2250 	    case RL2_CONVERT_GRID_INT32_TO_INT16:
2251 	    case RL2_CONVERT_GRID_INT32_TO_UINT16:
2252 	    case RL2_CONVERT_GRID_INT32_TO_UINT32:
2253 	    case RL2_CONVERT_GRID_INT32_TO_FLOAT:
2254 	    case RL2_CONVERT_GRID_INT32_TO_DOUBLE:
2255 		p_in_32 = (int *) in;
2256 		p_in_32 += y * origin->tileWidth;
2257 		break;
2258 	    case RL2_CONVERT_GRID_UINT32_TO_INT8:
2259 	    case RL2_CONVERT_GRID_UINT32_TO_UINT8:
2260 	    case RL2_CONVERT_GRID_UINT32_TO_INT16:
2261 	    case RL2_CONVERT_GRID_UINT32_TO_UINT16:
2262 	    case RL2_CONVERT_GRID_UINT32_TO_INT32:
2263 	    case RL2_CONVERT_GRID_UINT32_TO_FLOAT:
2264 	    case RL2_CONVERT_GRID_UINT32_TO_DOUBLE:
2265 		p_in_u32 = (unsigned int *) in;
2266 		p_in_u32 += y * origin->tileWidth;
2267 		break;
2268 	    case RL2_CONVERT_GRID_FLOAT_TO_INT8:
2269 	    case RL2_CONVERT_GRID_FLOAT_TO_UINT8:
2270 	    case RL2_CONVERT_GRID_FLOAT_TO_INT16:
2271 	    case RL2_CONVERT_GRID_FLOAT_TO_UINT16:
2272 	    case RL2_CONVERT_GRID_FLOAT_TO_INT32:
2273 	    case RL2_CONVERT_GRID_FLOAT_TO_UINT32:
2274 	    case RL2_CONVERT_GRID_FLOAT_TO_DOUBLE:
2275 		p_in_flt = (float *) in;
2276 		p_in_flt += y * origin->tileWidth;
2277 		break;
2278 	    case RL2_CONVERT_GRID_DOUBLE_TO_INT8:
2279 	    case RL2_CONVERT_GRID_DOUBLE_TO_UINT8:
2280 	    case RL2_CONVERT_GRID_DOUBLE_TO_INT16:
2281 	    case RL2_CONVERT_GRID_DOUBLE_TO_UINT16:
2282 	    case RL2_CONVERT_GRID_DOUBLE_TO_INT32:
2283 	    case RL2_CONVERT_GRID_DOUBLE_TO_UINT32:
2284 	    case RL2_CONVERT_GRID_DOUBLE_TO_FLOAT:
2285 		p_in_dbl = (double *) in;
2286 		p_in_dbl += y * origin->tileWidth;
2287 		break;
2288 	    };
2289 
2290 	  for (x = 0; x < origin->tileWidth; x++)
2291 	    {
2292 		dest_x = tile_x + x;
2293 		if (dest_x < startCol || dest_x >= (startCol + width))
2294 		    continue;
2295 
2296 		switch (convert)
2297 		  {
2298 		  case RL2_CONVERT_GRID_UINT8_TO_INT8:
2299 		  case RL2_CONVERT_GRID_INT16_TO_INT8:
2300 		  case RL2_CONVERT_GRID_UINT16_TO_INT8:
2301 		  case RL2_CONVERT_GRID_INT32_TO_INT8:
2302 		  case RL2_CONVERT_GRID_UINT32_TO_INT8:
2303 		  case RL2_CONVERT_GRID_FLOAT_TO_INT8:
2304 		  case RL2_CONVERT_GRID_DOUBLE_TO_INT8:
2305 		      p_out_8 = (char *) out;
2306 		      p_out_8 +=
2307 			  ((dest_y - startRow) * width) + (dest_x - startCol);
2308 		      break;
2309 		  case RL2_CONVERT_GRID_INT8_TO_UINT8:
2310 		  case RL2_CONVERT_GRID_INT16_TO_UINT8:
2311 		  case RL2_CONVERT_GRID_UINT16_TO_UINT8:
2312 		  case RL2_CONVERT_GRID_INT32_TO_UINT8:
2313 		  case RL2_CONVERT_GRID_UINT32_TO_UINT8:
2314 		  case RL2_CONVERT_GRID_FLOAT_TO_UINT8:
2315 		  case RL2_CONVERT_GRID_DOUBLE_TO_UINT8:
2316 		      p_out_u8 = (unsigned char *) out;
2317 		      p_out_u8 +=
2318 			  ((dest_y - startRow) * width) + (dest_x - startCol);
2319 		      break;
2320 		  case RL2_CONVERT_GRID_INT8_TO_INT16:
2321 		  case RL2_CONVERT_GRID_UINT8_TO_INT16:
2322 		  case RL2_CONVERT_GRID_UINT16_TO_INT16:
2323 		  case RL2_CONVERT_GRID_INT32_TO_INT16:
2324 		  case RL2_CONVERT_GRID_UINT32_TO_INT16:
2325 		  case RL2_CONVERT_GRID_FLOAT_TO_INT16:
2326 		  case RL2_CONVERT_GRID_DOUBLE_TO_INT16:
2327 		      p_out_16 = (short *) out;
2328 		      p_out_16 +=
2329 			  ((dest_y - startRow) * width) + (dest_x - startCol);
2330 		      break;
2331 		  case RL2_CONVERT_GRID_INT8_TO_UINT16:
2332 		  case RL2_CONVERT_GRID_UINT8_TO_UINT16:
2333 		  case RL2_CONVERT_GRID_INT16_TO_UINT16:
2334 		  case RL2_CONVERT_GRID_INT32_TO_UINT16:
2335 		  case RL2_CONVERT_GRID_UINT32_TO_UINT16:
2336 		  case RL2_CONVERT_GRID_FLOAT_TO_UINT16:
2337 		  case RL2_CONVERT_GRID_DOUBLE_TO_UINT16:
2338 		      p_out_u16 = (unsigned short *) out;
2339 		      p_out_u16 +=
2340 			  ((dest_y - startRow) * width) + (dest_x - startCol);
2341 		      break;
2342 		  case RL2_CONVERT_GRID_INT8_TO_INT32:
2343 		  case RL2_CONVERT_GRID_UINT8_TO_INT32:
2344 		  case RL2_CONVERT_GRID_INT16_TO_INT32:
2345 		  case RL2_CONVERT_GRID_UINT16_TO_INT32:
2346 		  case RL2_CONVERT_GRID_UINT32_TO_INT32:
2347 		  case RL2_CONVERT_GRID_FLOAT_TO_INT32:
2348 		  case RL2_CONVERT_GRID_DOUBLE_TO_INT32:
2349 		      p_out_32 = (int *) out;
2350 		      p_out_32 +=
2351 			  ((dest_y - startRow) * width) + (dest_x - startCol);
2352 		      break;
2353 		  case RL2_CONVERT_GRID_INT8_TO_UINT32:
2354 		  case RL2_CONVERT_GRID_UINT8_TO_UINT32:
2355 		  case RL2_CONVERT_GRID_INT16_TO_UINT32:
2356 		  case RL2_CONVERT_GRID_UINT16_TO_UINT32:
2357 		  case RL2_CONVERT_GRID_INT32_TO_UINT32:
2358 		  case RL2_CONVERT_GRID_FLOAT_TO_UINT32:
2359 		  case RL2_CONVERT_GRID_DOUBLE_TO_UINT32:
2360 		      p_out_u32 = (unsigned int *) out;
2361 		      p_out_u32 +=
2362 			  ((dest_y - startRow) * width) + (dest_x - startCol);
2363 		      break;
2364 		  case RL2_CONVERT_GRID_INT8_TO_FLOAT:
2365 		  case RL2_CONVERT_GRID_UINT8_TO_FLOAT:
2366 		  case RL2_CONVERT_GRID_INT16_TO_FLOAT:
2367 		  case RL2_CONVERT_GRID_UINT16_TO_FLOAT:
2368 		  case RL2_CONVERT_GRID_INT32_TO_FLOAT:
2369 		  case RL2_CONVERT_GRID_UINT32_TO_FLOAT:
2370 		  case RL2_CONVERT_GRID_DOUBLE_TO_FLOAT:
2371 		      p_out_flt = (float *) out;
2372 		      p_out_flt +=
2373 			  ((dest_y - startRow) * width) + (dest_x - startCol);
2374 		      break;
2375 		  case RL2_CONVERT_GRID_INT8_TO_DOUBLE:
2376 		  case RL2_CONVERT_GRID_UINT8_TO_DOUBLE:
2377 		  case RL2_CONVERT_GRID_INT16_TO_DOUBLE:
2378 		  case RL2_CONVERT_GRID_UINT16_TO_DOUBLE:
2379 		  case RL2_CONVERT_GRID_INT32_TO_DOUBLE:
2380 		  case RL2_CONVERT_GRID_UINT32_TO_DOUBLE:
2381 		  case RL2_CONVERT_GRID_FLOAT_TO_DOUBLE:
2382 		      p_out_dbl = (double *) out;
2383 		      p_out_dbl +=
2384 			  ((dest_y - startRow) * width) + (dest_x - startCol);
2385 		      break;
2386 		  };
2387 
2388 		switch (convert)
2389 		  {
2390 		  case RL2_CONVERT_GRID_INT8_TO_UINT8:
2391 		      *p_out_u8++ = truncate_u8 (*p_in_8++);
2392 		      break;
2393 		  case RL2_CONVERT_GRID_INT8_TO_INT16:
2394 		      *p_out_16++ = *p_in_8++;
2395 		      break;
2396 		  case RL2_CONVERT_GRID_INT8_TO_UINT16:
2397 		      *p_out_u16++ = truncate_u16 (*p_in_8++);
2398 		      break;
2399 		  case RL2_CONVERT_GRID_INT8_TO_INT32:
2400 		      *p_out_32++ = *p_in_8++;
2401 		      break;
2402 		  case RL2_CONVERT_GRID_INT8_TO_UINT32:
2403 		      *p_out_u32++ = truncate_u32 (*p_in_8++);
2404 		      break;
2405 		  case RL2_CONVERT_GRID_INT8_TO_FLOAT:
2406 		      *p_out_flt++ = *p_in_8++;
2407 		      break;
2408 		  case RL2_CONVERT_GRID_INT8_TO_DOUBLE:
2409 		      *p_out_dbl++ = *p_in_8++;
2410 		      break;
2411 		  case RL2_CONVERT_GRID_UINT8_TO_INT8:
2412 		      *p_out_8++ = truncate_8 (*p_in_u8++);
2413 		      break;
2414 		  case RL2_CONVERT_GRID_UINT8_TO_INT16:
2415 		      *p_out_16++ = truncate_16 (*p_in_u8++);
2416 		      break;
2417 		  case RL2_CONVERT_GRID_UINT8_TO_UINT16:
2418 		      *p_out_u16++ = *p_in_u8++;
2419 		      break;
2420 		  case RL2_CONVERT_GRID_UINT8_TO_UINT32:
2421 		      *p_out_u32++ = *p_in_u8++;
2422 		      break;
2423 		  case RL2_CONVERT_GRID_UINT8_TO_INT32:
2424 		      *p_out_32++ = truncate_32 (*p_in_u8++);
2425 		      break;
2426 		  case RL2_CONVERT_GRID_UINT8_TO_FLOAT:
2427 		      *p_out_flt++ = *p_in_u8++;
2428 		      break;
2429 		  case RL2_CONVERT_GRID_UINT8_TO_DOUBLE:
2430 		      *p_out_dbl++ = *p_in_u8++;
2431 		      break;
2432 		  case RL2_CONVERT_GRID_INT16_TO_INT8:
2433 		      *p_out_8++ = truncate_8 (*p_in_16++);
2434 		      break;
2435 		  case RL2_CONVERT_GRID_INT16_TO_UINT8:
2436 		      *p_out_u8++ = truncate_u8 (*p_in_16++);
2437 		      break;
2438 		  case RL2_CONVERT_GRID_INT16_TO_UINT16:
2439 		      *p_out_u16++ = truncate_u16 (*p_in_16++);
2440 		      break;
2441 		  case RL2_CONVERT_GRID_INT16_TO_INT32:
2442 		      *p_out_32++ = *p_in_16++;
2443 		      break;
2444 		  case RL2_CONVERT_GRID_INT16_TO_UINT32:
2445 		      *p_out_u32++ = truncate_u32 (*p_in_16++);
2446 		      break;
2447 		  case RL2_CONVERT_GRID_INT16_TO_FLOAT:
2448 		      *p_out_flt++ = *p_in_16++;
2449 		      break;
2450 		  case RL2_CONVERT_GRID_INT16_TO_DOUBLE:
2451 		      *p_out_dbl++ = *p_in_16++;
2452 		      break;
2453 		  case RL2_CONVERT_GRID_UINT16_TO_INT8:
2454 		      *p_out_8++ = truncate_8 (*p_in_u16++);
2455 		      break;
2456 		  case RL2_CONVERT_GRID_UINT16_TO_UINT8:
2457 		      *p_out_u8++ = truncate_u8 (*p_in_u16++);
2458 		      break;
2459 		  case RL2_CONVERT_GRID_UINT16_TO_INT16:
2460 		      *p_out_16++ = truncate_16 (*p_in_u16++);
2461 		      break;
2462 		  case RL2_CONVERT_GRID_UINT16_TO_UINT32:
2463 		      *p_out_u32++ = *p_in_u16++;
2464 		      break;
2465 		  case RL2_CONVERT_GRID_UINT16_TO_INT32:
2466 		      *p_out_32++ = truncate_32 (*p_in_u16++);
2467 		      break;
2468 		  case RL2_CONVERT_GRID_UINT16_TO_FLOAT:
2469 		      *p_out_flt++ = *p_in_u16++;
2470 		      break;
2471 		  case RL2_CONVERT_GRID_UINT16_TO_DOUBLE:
2472 		      *p_out_dbl++ = *p_in_u16++;
2473 		      break;
2474 		  case RL2_CONVERT_GRID_INT32_TO_INT8:
2475 		      *p_out_8++ = truncate_8 (*p_in_32++);
2476 		      break;
2477 		  case RL2_CONVERT_GRID_INT32_TO_UINT8:
2478 		      *p_out_u8++ = truncate_u8 (*p_in_32++);
2479 		      break;
2480 		  case RL2_CONVERT_GRID_INT32_TO_INT16:
2481 		      *p_out_16++ = truncate_16 (*p_in_32++);
2482 		      break;
2483 		  case RL2_CONVERT_GRID_INT32_TO_UINT16:
2484 		      *p_out_u16++ = truncate_u16 (*p_in_32++);
2485 		      break;
2486 		  case RL2_CONVERT_GRID_INT32_TO_UINT32:
2487 		      *p_out_u32++ = truncate_u32 (*p_in_32++);
2488 		      break;
2489 		  case RL2_CONVERT_GRID_INT32_TO_FLOAT:
2490 		      *p_out_flt++ = *p_in_32++;
2491 		      break;
2492 		  case RL2_CONVERT_GRID_INT32_TO_DOUBLE:
2493 		      *p_out_dbl++ = *p_in_32++;
2494 		      break;
2495 		  case RL2_CONVERT_GRID_UINT32_TO_INT8:
2496 		      *p_out_8++ = truncate_8 (*p_in_u32++);
2497 		      break;
2498 		  case RL2_CONVERT_GRID_UINT32_TO_UINT8:
2499 		      *p_out_u8++ = truncate_u8 (*p_in_u32++);
2500 		      break;
2501 		  case RL2_CONVERT_GRID_UINT32_TO_INT16:
2502 		      *p_out_16++ = truncate_16 (*p_in_u32++);
2503 		      break;
2504 		  case RL2_CONVERT_GRID_UINT32_TO_UINT16:
2505 		      *p_out_u16++ = truncate_u16 (*p_in_u32++);
2506 		      break;
2507 		  case RL2_CONVERT_GRID_UINT32_TO_INT32:
2508 		      *p_out_32++ = truncate_32 (*p_in_u32++);
2509 		      break;
2510 		  case RL2_CONVERT_GRID_UINT32_TO_FLOAT:
2511 		      *p_out_flt++ = *p_in_u32++;
2512 		      break;
2513 		  case RL2_CONVERT_GRID_UINT32_TO_DOUBLE:
2514 		      *p_out_dbl++ = *p_in_u32++;
2515 		      break;
2516 		  case RL2_CONVERT_GRID_FLOAT_TO_INT8:
2517 		      *p_out_8++ = truncate_8 (*p_in_flt++);
2518 		      break;
2519 		  case RL2_CONVERT_GRID_FLOAT_TO_UINT8:
2520 		      *p_out_u8++ = truncate_u8 (*p_in_flt++);
2521 		      break;
2522 		  case RL2_CONVERT_GRID_FLOAT_TO_INT16:
2523 		      *p_out_16++ = truncate_16 (*p_in_flt++);
2524 		      break;
2525 		  case RL2_CONVERT_GRID_FLOAT_TO_UINT16:
2526 		      *p_out_u16++ = truncate_u16 (*p_in_flt++);
2527 		      break;
2528 		  case RL2_CONVERT_GRID_FLOAT_TO_INT32:
2529 		      *p_out_32++ = truncate_32 (*p_in_flt++);
2530 		      break;
2531 		  case RL2_CONVERT_GRID_FLOAT_TO_UINT32:
2532 		      *p_out_u32++ = truncate_u32 (*p_in_flt++);
2533 		      break;
2534 		  case RL2_CONVERT_GRID_FLOAT_TO_DOUBLE:
2535 		      *p_out_dbl++ = *p_in_flt++;
2536 		      break;
2537 		  case RL2_CONVERT_GRID_DOUBLE_TO_INT8:
2538 		      *p_out_8++ = truncate_8 (*p_in_dbl++);
2539 		      break;
2540 		  case RL2_CONVERT_GRID_DOUBLE_TO_UINT8:
2541 		      *p_out_u8++ = truncate_u8 (*p_in_dbl++);
2542 		      break;
2543 		  case RL2_CONVERT_GRID_DOUBLE_TO_INT16:
2544 		      *p_out_16++ = truncate_16 (*p_in_dbl++);
2545 		      break;
2546 		  case RL2_CONVERT_GRID_DOUBLE_TO_UINT16:
2547 		      *p_out_u16++ = truncate_u16 (*p_in_dbl++);
2548 		      break;
2549 		  case RL2_CONVERT_GRID_DOUBLE_TO_INT32:
2550 		      *p_out_32++ = truncate_32 (*p_in_dbl++);
2551 		      break;
2552 		  case RL2_CONVERT_GRID_DOUBLE_TO_UINT32:
2553 		      *p_out_u32++ = truncate_u32 (*p_in_dbl++);
2554 		      break;
2555 		  case RL2_CONVERT_GRID_DOUBLE_TO_FLOAT:
2556 		      *p_out_flt++ = *p_in_dbl++;
2557 		      break;
2558 		  };
2559 	    }
2560       }
2561 }
2562 
2563 static int
read_raw_tiles(rl2PrivTiffOriginPtr origin,unsigned short width,unsigned short height,unsigned char sample_type,unsigned char num_bands,unsigned int startRow,unsigned int startCol,unsigned char * pixels)2564 read_raw_tiles (rl2PrivTiffOriginPtr origin, unsigned short width,
2565 		unsigned short height, unsigned char sample_type,
2566 		unsigned char num_bands, unsigned int startRow,
2567 		unsigned int startCol, unsigned char *pixels)
2568 {
2569 /* reading TIFF raw tiles */
2570     uint32 tile_x;
2571     uint32 tile_y;
2572     uint32 x;
2573     uint32 y;
2574     uint32 *tiff_tile = NULL;
2575     char *p_in_8;
2576     char *p_out_8;
2577     unsigned char *p_in_u8;
2578     unsigned char *p_out_u8;
2579     short *p_in_16;
2580     short *p_out_16;
2581     unsigned short *p_in_u16;
2582     unsigned short *p_out_u16;
2583     int *p_in_32;
2584     int *p_out_32;
2585     unsigned int *p_in_u32;
2586     unsigned int *p_out_u32;
2587     float *p_in_flt;
2588     float *p_out_flt;
2589     double *p_in_dbl;
2590     double *p_out_dbl;
2591     unsigned int dest_x;
2592     unsigned int dest_y;
2593     int skip;
2594     unsigned char bnd;
2595     unsigned char convert = origin->forced_conversion;
2596 
2597     tiff_tile = malloc (TIFFTileSize (origin->in));
2598     if (tiff_tile == NULL)
2599 	goto error;
2600 
2601     for (tile_y = 0; tile_y < origin->height; tile_y += origin->tileHeight)
2602       {
2603 	  /* scanning tiles by row */
2604 	  unsigned int tiff_min_y = tile_y;
2605 	  unsigned int tiff_max_y = tile_y + origin->tileHeight - 1;
2606 	  skip = 0;
2607 	  if (tiff_min_y > (startRow + height))
2608 	      skip = 1;
2609 	  if (tiff_max_y < startRow)
2610 	      skip = 1;
2611 	  if (skip)
2612 	    {
2613 		/* skipping any not required tile */
2614 		continue;
2615 	    }
2616 	  for (tile_x = 0; tile_x < origin->width; tile_x += origin->tileWidth)
2617 	    {
2618 		/* reading a TIFF tile */
2619 		unsigned int tiff_min_x = tile_x;
2620 		unsigned int tiff_max_x = tile_x + origin->tileWidth - 1;
2621 		skip = 0;
2622 		if (tiff_min_x > (startCol + width))
2623 		    skip = 1;
2624 		if (tiff_max_x < startCol)
2625 		    skip = 1;
2626 		if (skip)
2627 		  {
2628 		      /* skipping any not required tile */
2629 		      continue;
2630 		  }
2631 		if (TIFFReadTile (origin->in, tiff_tile, tile_x, tile_y, 0, 0) <
2632 		    0)
2633 		    goto error;
2634 		if (convert != RL2_CONVERT_NO)
2635 		  {
2636 		      /* applying some format conversion */
2637 		      copy_convert_tile (origin, tiff_tile, pixels, startRow,
2638 					 startCol, width, height, tile_y,
2639 					 tile_x, convert);
2640 		      continue;
2641 		  }
2642 		for (y = 0; y < origin->tileHeight; y++)
2643 		  {
2644 		      dest_y = tile_y + y;
2645 		      if (dest_y < startRow || dest_y >= (startRow + height))
2646 			  continue;
2647 		      for (x = 0; x < origin->tileWidth; x++)
2648 			{
2649 			    dest_x = tile_x + x;
2650 			    if (dest_x < startCol
2651 				|| dest_x >= (startCol + width))
2652 				continue;
2653 			    switch (sample_type)
2654 			      {
2655 			      case RL2_SAMPLE_INT8:
2656 				  p_in_8 = (char *) tiff_tile;
2657 				  p_in_8 += y * origin->tileWidth;
2658 				  p_in_8 += x;
2659 				  p_out_8 = (char *) pixels;
2660 				  p_out_8 +=
2661 				      ((dest_y - startRow) * width) + (dest_x -
2662 								       startCol);
2663 				  break;
2664 			      case RL2_SAMPLE_UINT8:
2665 				  p_in_u8 = (unsigned char *) tiff_tile;
2666 				  p_in_u8 += y * origin->tileWidth * num_bands;
2667 				  p_in_u8 += x * num_bands;
2668 				  p_out_u8 = (unsigned char *) pixels;
2669 				  p_out_u8 +=
2670 				      ((dest_y -
2671 					startRow) * width * num_bands) +
2672 				      ((dest_x - startCol) * num_bands);
2673 				  break;
2674 			      case RL2_SAMPLE_INT16:
2675 				  p_in_16 = (short *) tiff_tile;
2676 				  p_in_16 += y * origin->tileWidth;
2677 				  p_in_16 += x;
2678 				  p_out_16 = (short *) pixels;
2679 				  p_out_16 +=
2680 				      ((dest_y - startRow) * width) + (dest_x -
2681 								       startCol);
2682 				  break;
2683 			      case RL2_SAMPLE_UINT16:
2684 				  p_in_u16 = (unsigned short *) tiff_tile;
2685 				  p_in_u16 += y * origin->tileWidth * num_bands;
2686 				  p_in_u16 += x * num_bands;
2687 				  p_out_u16 = (unsigned short *) pixels;
2688 				  p_out_u16 +=
2689 				      ((dest_y -
2690 					startRow) * width * num_bands) +
2691 				      ((dest_x - startCol) * num_bands);
2692 				  break;
2693 			      case RL2_SAMPLE_INT32:
2694 				  p_in_32 = (int *) tiff_tile;
2695 				  p_in_32 += y * origin->tileWidth;
2696 				  p_in_32 += x;
2697 				  p_out_32 = (int *) pixels;
2698 				  p_out_32 +=
2699 				      ((dest_y - startRow) * width) + (dest_x -
2700 								       startCol);
2701 				  break;
2702 			      case RL2_SAMPLE_UINT32:
2703 				  p_in_u32 = (unsigned int *) tiff_tile;
2704 				  p_in_u32 += y * origin->tileWidth;
2705 				  p_in_u32 += x;
2706 				  p_out_u32 = (unsigned int *) pixels;
2707 				  p_out_u32 +=
2708 				      ((dest_y - startRow) * width) + (dest_x -
2709 								       startCol);
2710 				  break;
2711 			      case RL2_SAMPLE_FLOAT:
2712 				  p_in_flt = (float *) tiff_tile;
2713 				  p_in_flt += y * origin->tileWidth;
2714 				  p_in_flt += x;
2715 				  p_out_flt = (float *) pixels;
2716 				  p_out_flt +=
2717 				      ((dest_y - startRow) * width) + (dest_x -
2718 								       startCol);
2719 				  break;
2720 			      case RL2_SAMPLE_DOUBLE:
2721 				  p_in_dbl = (double *) tiff_tile;
2722 				  p_in_dbl += y * origin->tileWidth;
2723 				  p_in_dbl += x;
2724 				  p_out_dbl = (double *) pixels;
2725 				  p_out_dbl +=
2726 				      ((dest_y - startRow) * width) + (dest_x -
2727 								       startCol);
2728 				  break;
2729 			      };
2730 			    for (bnd = 0; bnd < num_bands; bnd++)
2731 			      {
2732 				  switch (sample_type)
2733 				    {
2734 				    case RL2_SAMPLE_INT8:
2735 					*p_out_8 = *p_in_8++;
2736 					break;
2737 				    case RL2_SAMPLE_UINT8:
2738 					*p_out_u8 = *p_in_u8++;
2739 					break;
2740 				    case RL2_SAMPLE_INT16:
2741 					*p_out_16 = *p_in_16++;
2742 					break;
2743 				    case RL2_SAMPLE_UINT16:
2744 					*p_out_u16 = *p_in_u16++;
2745 					break;
2746 				    case RL2_SAMPLE_INT32:
2747 					*p_out_32 = *p_in_32++;
2748 					break;
2749 				    case RL2_SAMPLE_UINT32:
2750 					*p_out_u32 = *p_in_u32++;
2751 					break;
2752 				    case RL2_SAMPLE_FLOAT:
2753 					*p_out_flt = *p_in_flt++;
2754 					break;
2755 				    case RL2_SAMPLE_DOUBLE:
2756 					*p_out_dbl = *p_in_dbl++;
2757 					break;
2758 				    };
2759 			      }
2760 			}
2761 		  }
2762 	    }
2763       }
2764 
2765     free (tiff_tile);
2766     return RL2_OK;
2767   error:
2768     if (tiff_tile != NULL)
2769 	free (tiff_tile);
2770     return RL2_ERROR;
2771 }
2772 
2773 static void
copy_convert_scanline(rl2PrivTiffOriginPtr origin,void * in,void * out,unsigned int lineNo,unsigned int startCol,unsigned int width,unsigned char convert)2774 copy_convert_scanline (rl2PrivTiffOriginPtr origin, void *in, void *out,
2775 		       unsigned int lineNo, unsigned int startCol,
2776 		       unsigned int width, unsigned char convert)
2777 {
2778 /* copying pixels by applying a format conversion */
2779     char *p_in_8;
2780     char *p_out_8;
2781     unsigned char *p_in_u8;
2782     unsigned char *p_out_u8;
2783     short *p_in_16;
2784     short *p_out_16;
2785     unsigned short *p_in_u16;
2786     unsigned short *p_out_u16;
2787     int *p_in_32;
2788     int *p_out_32;
2789     unsigned int *p_in_u32;
2790     unsigned int *p_out_u32;
2791     float *p_in_flt;
2792     float *p_out_flt;
2793     double *p_in_dbl;
2794     double *p_out_dbl;
2795     uint32 x;
2796 
2797     switch (convert)
2798       {
2799       case RL2_CONVERT_GRID_INT8_TO_UINT8:
2800       case RL2_CONVERT_GRID_INT8_TO_INT16:
2801       case RL2_CONVERT_GRID_INT8_TO_UINT16:
2802       case RL2_CONVERT_GRID_INT8_TO_INT32:
2803       case RL2_CONVERT_GRID_INT8_TO_UINT32:
2804       case RL2_CONVERT_GRID_INT8_TO_FLOAT:
2805       case RL2_CONVERT_GRID_INT8_TO_DOUBLE:
2806 	  p_in_8 = (char *) in;
2807 	  break;
2808       case RL2_CONVERT_GRID_UINT8_TO_INT8:
2809       case RL2_CONVERT_GRID_UINT8_TO_UINT16:
2810       case RL2_CONVERT_GRID_UINT8_TO_INT16:
2811       case RL2_CONVERT_GRID_UINT8_TO_UINT32:
2812       case RL2_CONVERT_GRID_UINT8_TO_INT32:
2813       case RL2_CONVERT_GRID_UINT8_TO_FLOAT:
2814       case RL2_CONVERT_GRID_UINT8_TO_DOUBLE:
2815 	  p_in_u8 = (unsigned char *) in;
2816 	  break;
2817       case RL2_CONVERT_GRID_INT16_TO_INT8:
2818       case RL2_CONVERT_GRID_INT16_TO_UINT8:
2819       case RL2_CONVERT_GRID_INT16_TO_UINT16:
2820       case RL2_CONVERT_GRID_INT16_TO_INT32:
2821       case RL2_CONVERT_GRID_INT16_TO_UINT32:
2822       case RL2_CONVERT_GRID_INT16_TO_FLOAT:
2823       case RL2_CONVERT_GRID_INT16_TO_DOUBLE:
2824 	  p_in_16 = (short *) in;
2825 	  break;
2826       case RL2_CONVERT_GRID_UINT16_TO_INT8:
2827       case RL2_CONVERT_GRID_UINT16_TO_UINT8:
2828       case RL2_CONVERT_GRID_UINT16_TO_INT16:
2829       case RL2_CONVERT_GRID_UINT16_TO_UINT32:
2830       case RL2_CONVERT_GRID_UINT16_TO_INT32:
2831       case RL2_CONVERT_GRID_UINT16_TO_FLOAT:
2832       case RL2_CONVERT_GRID_UINT16_TO_DOUBLE:
2833 	  p_in_u16 = (unsigned short *) in;
2834 	  break;
2835       case RL2_CONVERT_GRID_INT32_TO_INT8:
2836       case RL2_CONVERT_GRID_INT32_TO_UINT8:
2837       case RL2_CONVERT_GRID_INT32_TO_INT16:
2838       case RL2_CONVERT_GRID_INT32_TO_UINT16:
2839       case RL2_CONVERT_GRID_INT32_TO_UINT32:
2840       case RL2_CONVERT_GRID_INT32_TO_FLOAT:
2841       case RL2_CONVERT_GRID_INT32_TO_DOUBLE:
2842 	  p_in_32 = (int *) in;
2843 	  break;
2844       case RL2_CONVERT_GRID_UINT32_TO_INT8:
2845       case RL2_CONVERT_GRID_UINT32_TO_UINT8:
2846       case RL2_CONVERT_GRID_UINT32_TO_INT16:
2847       case RL2_CONVERT_GRID_UINT32_TO_UINT16:
2848       case RL2_CONVERT_GRID_UINT32_TO_INT32:
2849       case RL2_CONVERT_GRID_UINT32_TO_FLOAT:
2850       case RL2_CONVERT_GRID_UINT32_TO_DOUBLE:
2851 	  p_in_u32 = (unsigned int *) in;
2852 	  break;
2853       case RL2_CONVERT_GRID_FLOAT_TO_INT8:
2854       case RL2_CONVERT_GRID_FLOAT_TO_UINT8:
2855       case RL2_CONVERT_GRID_FLOAT_TO_INT16:
2856       case RL2_CONVERT_GRID_FLOAT_TO_UINT16:
2857       case RL2_CONVERT_GRID_FLOAT_TO_INT32:
2858       case RL2_CONVERT_GRID_FLOAT_TO_UINT32:
2859       case RL2_CONVERT_GRID_FLOAT_TO_DOUBLE:
2860 	  p_in_flt = (float *) in;
2861 	  break;
2862       case RL2_CONVERT_GRID_DOUBLE_TO_INT8:
2863       case RL2_CONVERT_GRID_DOUBLE_TO_UINT8:
2864       case RL2_CONVERT_GRID_DOUBLE_TO_INT16:
2865       case RL2_CONVERT_GRID_DOUBLE_TO_UINT16:
2866       case RL2_CONVERT_GRID_DOUBLE_TO_INT32:
2867       case RL2_CONVERT_GRID_DOUBLE_TO_UINT32:
2868       case RL2_CONVERT_GRID_DOUBLE_TO_FLOAT:
2869 	  p_in_dbl = (double *) in;
2870 	  break;
2871       };
2872 
2873     switch (convert)
2874       {
2875       case RL2_CONVERT_GRID_UINT8_TO_INT8:
2876       case RL2_CONVERT_GRID_INT16_TO_INT8:
2877       case RL2_CONVERT_GRID_UINT16_TO_INT8:
2878       case RL2_CONVERT_GRID_INT32_TO_INT8:
2879       case RL2_CONVERT_GRID_UINT32_TO_INT8:
2880       case RL2_CONVERT_GRID_FLOAT_TO_INT8:
2881       case RL2_CONVERT_GRID_DOUBLE_TO_INT8:
2882 	  p_out_8 = (char *) out;
2883 	  p_out_8 += lineNo * width;
2884 	  break;
2885       case RL2_CONVERT_GRID_INT8_TO_UINT8:
2886       case RL2_CONVERT_GRID_INT16_TO_UINT8:
2887       case RL2_CONVERT_GRID_UINT16_TO_UINT8:
2888       case RL2_CONVERT_GRID_INT32_TO_UINT8:
2889       case RL2_CONVERT_GRID_UINT32_TO_UINT8:
2890       case RL2_CONVERT_GRID_FLOAT_TO_UINT8:
2891       case RL2_CONVERT_GRID_DOUBLE_TO_UINT8:
2892 	  p_out_u8 = (unsigned char *) out;
2893 	  p_out_u8 += lineNo * width;
2894 	  break;
2895       case RL2_CONVERT_GRID_INT8_TO_INT16:
2896       case RL2_CONVERT_GRID_UINT8_TO_INT16:
2897       case RL2_CONVERT_GRID_UINT16_TO_INT16:
2898       case RL2_CONVERT_GRID_INT32_TO_INT16:
2899       case RL2_CONVERT_GRID_UINT32_TO_INT16:
2900       case RL2_CONVERT_GRID_FLOAT_TO_INT16:
2901       case RL2_CONVERT_GRID_DOUBLE_TO_INT16:
2902 	  p_out_16 = (short *) out;
2903 	  p_out_16 += lineNo * width;
2904 	  break;
2905       case RL2_CONVERT_GRID_INT8_TO_UINT16:
2906       case RL2_CONVERT_GRID_UINT8_TO_UINT16:
2907       case RL2_CONVERT_GRID_INT16_TO_UINT16:
2908       case RL2_CONVERT_GRID_INT32_TO_UINT16:
2909       case RL2_CONVERT_GRID_UINT32_TO_UINT16:
2910       case RL2_CONVERT_GRID_FLOAT_TO_UINT16:
2911       case RL2_CONVERT_GRID_DOUBLE_TO_UINT16:
2912 	  p_out_u16 = (unsigned short *) out;
2913 	  p_out_u16 += lineNo * width;
2914 	  break;
2915       case RL2_CONVERT_GRID_INT8_TO_INT32:
2916       case RL2_CONVERT_GRID_UINT8_TO_INT32:
2917       case RL2_CONVERT_GRID_INT16_TO_INT32:
2918       case RL2_CONVERT_GRID_UINT16_TO_INT32:
2919       case RL2_CONVERT_GRID_UINT32_TO_INT32:
2920       case RL2_CONVERT_GRID_FLOAT_TO_INT32:
2921       case RL2_CONVERT_GRID_DOUBLE_TO_INT32:
2922 	  p_out_32 = (int *) out;
2923 	  p_out_32 += lineNo * width;
2924 	  break;
2925       case RL2_CONVERT_GRID_INT8_TO_UINT32:
2926       case RL2_CONVERT_GRID_UINT8_TO_UINT32:
2927       case RL2_CONVERT_GRID_INT16_TO_UINT32:
2928       case RL2_CONVERT_GRID_UINT16_TO_UINT32:
2929       case RL2_CONVERT_GRID_INT32_TO_UINT32:
2930       case RL2_CONVERT_GRID_FLOAT_TO_UINT32:
2931       case RL2_CONVERT_GRID_DOUBLE_TO_UINT32:
2932 	  p_out_u32 = (unsigned int *) out;
2933 	  p_out_u32 += lineNo * width;
2934 	  break;
2935       case RL2_CONVERT_GRID_INT8_TO_FLOAT:
2936       case RL2_CONVERT_GRID_UINT8_TO_FLOAT:
2937       case RL2_CONVERT_GRID_INT16_TO_FLOAT:
2938       case RL2_CONVERT_GRID_UINT16_TO_FLOAT:
2939       case RL2_CONVERT_GRID_INT32_TO_FLOAT:
2940       case RL2_CONVERT_GRID_UINT32_TO_FLOAT:
2941       case RL2_CONVERT_GRID_DOUBLE_TO_FLOAT:
2942 	  p_out_flt = (float *) out;
2943 	  p_out_flt += lineNo * width;
2944 	  break;
2945       case RL2_CONVERT_GRID_INT8_TO_DOUBLE:
2946       case RL2_CONVERT_GRID_UINT8_TO_DOUBLE:
2947       case RL2_CONVERT_GRID_INT16_TO_DOUBLE:
2948       case RL2_CONVERT_GRID_UINT16_TO_DOUBLE:
2949       case RL2_CONVERT_GRID_INT32_TO_DOUBLE:
2950       case RL2_CONVERT_GRID_UINT32_TO_DOUBLE:
2951       case RL2_CONVERT_GRID_FLOAT_TO_DOUBLE:
2952 	  p_out_dbl = (double *) out;
2953 	  p_out_dbl += lineNo * width;
2954 	  break;
2955       };
2956 
2957     for (x = 0; x < origin->width; x++)
2958       {
2959 	  if (x >= (startCol + width))
2960 	      break;
2961 	  if (x < startCol)
2962 	    {
2963 		switch (convert)
2964 		  {
2965 		  case RL2_CONVERT_GRID_INT8_TO_UINT8:
2966 		  case RL2_CONVERT_GRID_INT8_TO_INT16:
2967 		  case RL2_CONVERT_GRID_INT8_TO_UINT16:
2968 		  case RL2_CONVERT_GRID_INT8_TO_INT32:
2969 		  case RL2_CONVERT_GRID_INT8_TO_UINT32:
2970 		  case RL2_CONVERT_GRID_INT8_TO_FLOAT:
2971 		  case RL2_CONVERT_GRID_INT8_TO_DOUBLE:
2972 		      p_in_8++;
2973 		      break;
2974 		  case RL2_CONVERT_GRID_UINT8_TO_INT8:
2975 		  case RL2_CONVERT_GRID_UINT8_TO_INT16:
2976 		  case RL2_CONVERT_GRID_UINT8_TO_UINT16:
2977 		  case RL2_CONVERT_GRID_UINT8_TO_INT32:
2978 		  case RL2_CONVERT_GRID_UINT8_TO_UINT32:
2979 		  case RL2_CONVERT_GRID_UINT8_TO_FLOAT:
2980 		  case RL2_CONVERT_GRID_UINT8_TO_DOUBLE:
2981 		      p_in_u8++;
2982 		      break;
2983 		  case RL2_CONVERT_GRID_INT16_TO_INT8:
2984 		  case RL2_CONVERT_GRID_INT16_TO_UINT8:
2985 		  case RL2_CONVERT_GRID_INT16_TO_UINT16:
2986 		  case RL2_CONVERT_GRID_INT16_TO_INT32:
2987 		  case RL2_CONVERT_GRID_INT16_TO_UINT32:
2988 		  case RL2_CONVERT_GRID_INT16_TO_FLOAT:
2989 		  case RL2_CONVERT_GRID_INT16_TO_DOUBLE:
2990 		      p_in_16++;
2991 		      break;
2992 		  case RL2_CONVERT_GRID_UINT16_TO_INT8:
2993 		  case RL2_CONVERT_GRID_UINT16_TO_UINT8:
2994 		  case RL2_CONVERT_GRID_UINT16_TO_INT16:
2995 		  case RL2_CONVERT_GRID_UINT16_TO_INT32:
2996 		  case RL2_CONVERT_GRID_UINT16_TO_UINT32:
2997 		  case RL2_CONVERT_GRID_UINT16_TO_FLOAT:
2998 		  case RL2_CONVERT_GRID_UINT16_TO_DOUBLE:
2999 		      p_in_u16++;
3000 		      break;
3001 		  case RL2_CONVERT_GRID_INT32_TO_INT8:
3002 		  case RL2_CONVERT_GRID_INT32_TO_UINT8:
3003 		  case RL2_CONVERT_GRID_INT32_TO_INT16:
3004 		  case RL2_CONVERT_GRID_INT32_TO_UINT16:
3005 		  case RL2_CONVERT_GRID_INT32_TO_UINT32:
3006 		  case RL2_CONVERT_GRID_INT32_TO_FLOAT:
3007 		  case RL2_CONVERT_GRID_INT32_TO_DOUBLE:
3008 		      p_in_32++;
3009 		      break;
3010 		  case RL2_CONVERT_GRID_UINT32_TO_INT8:
3011 		  case RL2_CONVERT_GRID_UINT32_TO_UINT8:
3012 		  case RL2_CONVERT_GRID_UINT32_TO_INT16:
3013 		  case RL2_CONVERT_GRID_UINT32_TO_UINT16:
3014 		  case RL2_CONVERT_GRID_UINT32_TO_INT32:
3015 		  case RL2_CONVERT_GRID_UINT32_TO_FLOAT:
3016 		  case RL2_CONVERT_GRID_UINT32_TO_DOUBLE:
3017 		      p_in_u32++;
3018 		      break;
3019 		  case RL2_CONVERT_GRID_FLOAT_TO_INT8:
3020 		  case RL2_CONVERT_GRID_FLOAT_TO_UINT8:
3021 		  case RL2_CONVERT_GRID_FLOAT_TO_INT16:
3022 		  case RL2_CONVERT_GRID_FLOAT_TO_UINT16:
3023 		  case RL2_CONVERT_GRID_FLOAT_TO_INT32:
3024 		  case RL2_CONVERT_GRID_FLOAT_TO_UINT32:
3025 		  case RL2_CONVERT_GRID_FLOAT_TO_DOUBLE:
3026 		      p_in_flt++;
3027 		      break;
3028 		  case RL2_CONVERT_GRID_DOUBLE_TO_INT8:
3029 		  case RL2_CONVERT_GRID_DOUBLE_TO_UINT8:
3030 		  case RL2_CONVERT_GRID_DOUBLE_TO_INT16:
3031 		  case RL2_CONVERT_GRID_DOUBLE_TO_UINT16:
3032 		  case RL2_CONVERT_GRID_DOUBLE_TO_INT32:
3033 		  case RL2_CONVERT_GRID_DOUBLE_TO_UINT32:
3034 		  case RL2_CONVERT_GRID_DOUBLE_TO_FLOAT:
3035 		      p_in_dbl++;
3036 		      break;
3037 		  };
3038 		continue;
3039 	    }
3040 
3041 	  switch (convert)
3042 	    {
3043 	    case RL2_CONVERT_GRID_INT8_TO_UINT8:
3044 		*p_out_u8++ = truncate_u8 (*p_in_8++);
3045 		break;
3046 	    case RL2_CONVERT_GRID_INT8_TO_INT16:
3047 		*p_out_16++ = *p_in_8++;
3048 		break;
3049 	    case RL2_CONVERT_GRID_INT8_TO_UINT16:
3050 		*p_out_u16++ = truncate_u16 (*p_in_8++);
3051 		break;
3052 	    case RL2_CONVERT_GRID_INT8_TO_INT32:
3053 		*p_out_32++ = *p_in_8++;
3054 		break;
3055 	    case RL2_CONVERT_GRID_INT8_TO_UINT32:
3056 		*p_out_u32++ = truncate_u32 (*p_in_8++);
3057 		break;
3058 	    case RL2_CONVERT_GRID_INT8_TO_FLOAT:
3059 		*p_out_flt++ = *p_in_8++;
3060 		break;
3061 	    case RL2_CONVERT_GRID_INT8_TO_DOUBLE:
3062 		*p_out_dbl++ = *p_in_8++;
3063 		break;
3064 	    case RL2_CONVERT_GRID_UINT8_TO_INT8:
3065 		*p_out_8++ = truncate_8 (*p_in_u8++);
3066 		break;
3067 	    case RL2_CONVERT_GRID_UINT8_TO_INT16:
3068 		*p_out_16++ = truncate_16 (*p_in_u8++);
3069 		break;
3070 	    case RL2_CONVERT_GRID_UINT8_TO_UINT16:
3071 		*p_out_u16++ = *p_in_u8++;
3072 		break;
3073 	    case RL2_CONVERT_GRID_UINT8_TO_UINT32:
3074 		*p_out_u32++ = *p_in_u8++;
3075 		break;
3076 	    case RL2_CONVERT_GRID_UINT8_TO_INT32:
3077 		*p_out_32++ = truncate_32 (*p_in_u8++);
3078 		break;
3079 	    case RL2_CONVERT_GRID_UINT8_TO_FLOAT:
3080 		*p_out_flt++ = *p_in_u8++;
3081 		break;
3082 	    case RL2_CONVERT_GRID_UINT8_TO_DOUBLE:
3083 		*p_out_dbl++ = *p_in_u8++;
3084 		break;
3085 	    case RL2_CONVERT_GRID_INT16_TO_INT8:
3086 		*p_out_8++ = truncate_8 (*p_in_16++);
3087 		break;
3088 	    case RL2_CONVERT_GRID_INT16_TO_UINT8:
3089 		*p_out_u8++ = truncate_u8 (*p_in_16++);
3090 		break;
3091 	    case RL2_CONVERT_GRID_INT16_TO_UINT16:
3092 		*p_out_u16++ = truncate_u16 (*p_in_16++);
3093 		break;
3094 	    case RL2_CONVERT_GRID_INT16_TO_INT32:
3095 		*p_out_32++ = *p_in_16++;
3096 		break;
3097 	    case RL2_CONVERT_GRID_INT16_TO_UINT32:
3098 		*p_out_u32++ = truncate_u32 (*p_in_16++);
3099 		break;
3100 	    case RL2_CONVERT_GRID_INT16_TO_FLOAT:
3101 		*p_out_flt++ = *p_in_16++;
3102 		break;
3103 	    case RL2_CONVERT_GRID_INT16_TO_DOUBLE:
3104 		*p_out_dbl++ = *p_in_16++;
3105 		break;
3106 	    case RL2_CONVERT_GRID_UINT16_TO_INT8:
3107 		*p_out_8++ = truncate_8 (*p_in_u16++);
3108 		break;
3109 	    case RL2_CONVERT_GRID_UINT16_TO_UINT8:
3110 		*p_out_u8++ = truncate_u8 (*p_in_u16++);
3111 		break;
3112 	    case RL2_CONVERT_GRID_UINT16_TO_INT16:
3113 		*p_out_16++ = truncate_16 (*p_in_u16++);
3114 		break;
3115 	    case RL2_CONVERT_GRID_UINT16_TO_UINT32:
3116 		*p_out_u32++ = *p_in_u16++;
3117 		break;
3118 	    case RL2_CONVERT_GRID_UINT16_TO_INT32:
3119 		*p_out_32++ = truncate_32 (*p_in_u16++);
3120 		break;
3121 	    case RL2_CONVERT_GRID_UINT16_TO_FLOAT:
3122 		*p_out_flt++ = *p_in_u16++;
3123 		break;
3124 	    case RL2_CONVERT_GRID_UINT16_TO_DOUBLE:
3125 		*p_out_dbl++ = *p_in_u16++;
3126 		break;
3127 	    case RL2_CONVERT_GRID_INT32_TO_INT8:
3128 		*p_out_8++ = truncate_8 (*p_in_32++);
3129 		break;
3130 	    case RL2_CONVERT_GRID_INT32_TO_UINT8:
3131 		*p_out_u8++ = truncate_u8 (*p_in_32++);
3132 		break;
3133 	    case RL2_CONVERT_GRID_INT32_TO_INT16:
3134 		*p_out_16++ = truncate_16 (*p_in_32++);
3135 		break;
3136 	    case RL2_CONVERT_GRID_INT32_TO_UINT16:
3137 		*p_out_u16++ = truncate_u16 (*p_in_32++);
3138 		break;
3139 	    case RL2_CONVERT_GRID_INT32_TO_UINT32:
3140 		*p_out_u32++ = truncate_u32 (*p_in_32++);
3141 		break;
3142 	    case RL2_CONVERT_GRID_INT32_TO_FLOAT:
3143 		*p_out_flt++ = *p_in_32++;
3144 		break;
3145 	    case RL2_CONVERT_GRID_INT32_TO_DOUBLE:
3146 		*p_out_dbl++ = *p_in_32++;
3147 		break;
3148 	    case RL2_CONVERT_GRID_UINT32_TO_INT8:
3149 		*p_out_8++ = truncate_8 (*p_in_u32++);
3150 		break;
3151 	    case RL2_CONVERT_GRID_UINT32_TO_UINT8:
3152 		*p_out_u8++ = truncate_u8 (*p_in_u32++);
3153 		break;
3154 	    case RL2_CONVERT_GRID_UINT32_TO_INT16:
3155 		*p_out_16++ = truncate_16 (*p_in_u32++);
3156 		break;
3157 	    case RL2_CONVERT_GRID_UINT32_TO_UINT16:
3158 		*p_out_u16++ = truncate_u16 (*p_in_u32++);
3159 		break;
3160 	    case RL2_CONVERT_GRID_UINT32_TO_INT32:
3161 		*p_out_32++ = truncate_32 (*p_in_u32++);
3162 		break;
3163 	    case RL2_CONVERT_GRID_UINT32_TO_FLOAT:
3164 		*p_out_flt++ = *p_in_u32++;
3165 		break;
3166 	    case RL2_CONVERT_GRID_UINT32_TO_DOUBLE:
3167 		*p_out_dbl++ = *p_in_u32++;
3168 		break;
3169 	    case RL2_CONVERT_GRID_FLOAT_TO_INT8:
3170 		*p_out_8++ = truncate_8 (*p_in_flt++);
3171 		break;
3172 	    case RL2_CONVERT_GRID_FLOAT_TO_UINT8:
3173 		*p_out_u8++ = truncate_u8 (*p_in_flt++);
3174 		break;
3175 	    case RL2_CONVERT_GRID_FLOAT_TO_INT16:
3176 		*p_out_16++ = truncate_16 (*p_in_flt++);
3177 		break;
3178 	    case RL2_CONVERT_GRID_FLOAT_TO_UINT16:
3179 		*p_out_u16++ = truncate_u16 (*p_in_flt++);
3180 		break;
3181 	    case RL2_CONVERT_GRID_FLOAT_TO_INT32:
3182 		*p_out_32++ = truncate_32 (*p_in_flt++);
3183 		break;
3184 	    case RL2_CONVERT_GRID_FLOAT_TO_UINT32:
3185 		*p_out_u32++ = truncate_u32 (*p_in_flt++);
3186 		break;
3187 	    case RL2_CONVERT_GRID_FLOAT_TO_DOUBLE:
3188 		*p_out_dbl++ = *p_in_flt++;
3189 		break;
3190 	    case RL2_CONVERT_GRID_DOUBLE_TO_INT8:
3191 		*p_out_8++ = truncate_8 (*p_in_dbl++);
3192 		break;
3193 	    case RL2_CONVERT_GRID_DOUBLE_TO_UINT8:
3194 		*p_out_u8++ = truncate_u8 (*p_in_dbl++);
3195 		break;
3196 	    case RL2_CONVERT_GRID_DOUBLE_TO_INT16:
3197 		*p_out_16++ = truncate_16 (*p_in_dbl++);
3198 		break;
3199 	    case RL2_CONVERT_GRID_DOUBLE_TO_UINT16:
3200 		*p_out_u16++ = truncate_u16 (*p_in_dbl++);
3201 		break;
3202 	    case RL2_CONVERT_GRID_DOUBLE_TO_INT32:
3203 		*p_out_32++ = truncate_32 (*p_in_dbl++);
3204 		break;
3205 	    case RL2_CONVERT_GRID_DOUBLE_TO_UINT32:
3206 		*p_out_u32++ = truncate_u32 (*p_in_dbl++);
3207 		break;
3208 	    case RL2_CONVERT_GRID_DOUBLE_TO_FLOAT:
3209 		*p_out_flt++ = *p_in_dbl++;
3210 		break;
3211 	    };
3212       }
3213 }
3214 
3215 static int
read_raw_scanlines(rl2PrivTiffOriginPtr origin,unsigned short width,unsigned short height,unsigned char sample_type,unsigned char num_bands,unsigned int startRow,unsigned int startCol,unsigned char * pixels)3216 read_raw_scanlines (rl2PrivTiffOriginPtr origin, unsigned short width,
3217 		    unsigned short height, unsigned char sample_type,
3218 		    unsigned char num_bands, unsigned int startRow,
3219 		    unsigned int startCol, unsigned char *pixels)
3220 {
3221 /* reading TIFF raw strips */
3222     uint32 line_no;
3223     uint32 x;
3224     uint32 y;
3225     uint32 *tiff_scanline = NULL;
3226     char *p_in_8;
3227     char *p_out_8;
3228     unsigned char *p_in_u8;
3229     unsigned char *p_out_u8;
3230     short *p_in_16;
3231     short *p_out_16;
3232     unsigned short *p_in_u16;
3233     unsigned short *p_out_u16;
3234     int *p_in_32;
3235     int *p_out_32;
3236     unsigned int *p_in_u32;
3237     unsigned int *p_out_u32;
3238     float *p_in_flt;
3239     float *p_out_flt;
3240     double *p_in_dbl;
3241     double *p_out_dbl;
3242     unsigned char bnd;
3243     unsigned char convert = origin->forced_conversion;
3244     TIFF *in = (TIFF *) 0;
3245 
3246     tiff_scanline = malloc (TIFFScanlineSize (origin->in));
3247     if (tiff_scanline == NULL)
3248 	goto error;
3249 
3250 /*
3251 / random access doesn't work on compressed scanlines
3252 / so we'll open an auxiliary TIFF handle, thus ensuring
3253 / an always clean reading context
3254 */
3255     in = TIFFOpen (origin->path, "r");
3256     if (in == NULL)
3257 	goto error;
3258 
3259     for (y = 0; y < startRow; y++)
3260       {
3261 	  /* skipping trailing scanlines */
3262 	  if (TIFFReadScanline (in, tiff_scanline, y, 0) < 0)
3263 	      goto error;
3264       }
3265 
3266     for (y = 0; y < height; y++)
3267       {
3268 	  /* scanning scanlines by row */
3269 	  line_no = y + startRow;
3270 	  if (line_no >= origin->height)
3271 	    {
3272 		switch (sample_type)
3273 		  {
3274 		  case RL2_SAMPLE_INT8:
3275 		      p_out_8 = (char *) pixels;
3276 		      for (x = 0; x < width; x++)
3277 			  *p_out_8++ = 0;
3278 		      break;
3279 		  case RL2_SAMPLE_UINT8:
3280 		      p_out_u8 = (unsigned char *) pixels;
3281 		      for (x = 0; x < width * num_bands; x++)
3282 			  *p_out_u8++ = 0;
3283 		      break;
3284 		  case RL2_SAMPLE_INT16:
3285 		      p_out_16 = (short *) pixels;
3286 		      for (x = 0; x < width; x++)
3287 			  *p_out_16++ = 0;
3288 		      break;
3289 		  case RL2_SAMPLE_UINT16:
3290 		      p_out_u16 = (unsigned short *) pixels;
3291 		      for (x = 0; x < width * num_bands; x++)
3292 			  *p_out_u16++ = 0;
3293 		      break;
3294 		  case RL2_SAMPLE_INT32:
3295 		      p_out_32 = (int *) pixels;
3296 		      for (x = 0; x < width; x++)
3297 			  *p_out_32++ = 0;
3298 		      break;
3299 		  case RL2_SAMPLE_UINT32:
3300 		      p_out_u32 = (unsigned int *) pixels;
3301 		      for (x = 0; x < width; x++)
3302 			  *p_out_u32++ = 0;
3303 		      break;
3304 		  case RL2_SAMPLE_FLOAT:
3305 		      p_out_flt = (float *) pixels;
3306 		      for (x = 0; x < width; x++)
3307 			  *p_out_flt++ = 0;
3308 		      break;
3309 		  case RL2_SAMPLE_DOUBLE:
3310 		      p_out_dbl = (double *) pixels;
3311 		      for (x = 0; x < width; x++)
3312 			  *p_out_dbl++ = 0;
3313 		      break;
3314 		  default:
3315 		      goto error;
3316 		  };
3317 		continue;
3318 	    }
3319 	  if (TIFFReadScanline (in, tiff_scanline, line_no, 0) < 0)
3320 	      goto error;
3321 	  if (convert != RL2_CONVERT_NO)
3322 	    {
3323 		/* applying some format conversion */
3324 		copy_convert_scanline (origin, tiff_scanline, pixels, y,
3325 				       startCol, width, convert);
3326 		continue;
3327 	    }
3328 	  switch (sample_type)
3329 	    {
3330 	    case RL2_SAMPLE_INT8:
3331 		p_in_8 = (char *) tiff_scanline;
3332 		p_out_8 = (char *) pixels;
3333 		p_out_8 += y * width;
3334 		break;
3335 	    case RL2_SAMPLE_UINT8:
3336 		p_in_u8 = (unsigned char *) tiff_scanline;
3337 		p_out_u8 = (unsigned char *) pixels;
3338 		p_out_u8 += y * width * num_bands;
3339 		break;
3340 	    case RL2_SAMPLE_INT16:
3341 		p_in_16 = (short *) tiff_scanline;
3342 		p_out_16 = (short *) pixels;
3343 		p_out_16 += y * width;
3344 		break;
3345 	    case RL2_SAMPLE_UINT16:
3346 		p_in_u16 = (unsigned short *) tiff_scanline;
3347 		p_out_u16 = (unsigned short *) pixels;
3348 		p_out_u16 += y * width * num_bands;
3349 		break;
3350 	    case RL2_SAMPLE_INT32:
3351 		p_in_32 = (int *) tiff_scanline;
3352 		p_out_32 = (int *) pixels;
3353 		p_out_32 += y * width;
3354 		break;
3355 	    case RL2_SAMPLE_UINT32:
3356 		p_in_u32 = (unsigned int *) tiff_scanline;
3357 		p_out_u32 = (unsigned int *) pixels;
3358 		p_out_u32 += y * width;
3359 		break;
3360 	    case RL2_SAMPLE_FLOAT:
3361 		p_in_flt = (float *) tiff_scanline;
3362 		p_out_flt = (float *) pixels;
3363 		p_out_flt += y * width;
3364 		break;
3365 	    case RL2_SAMPLE_DOUBLE:
3366 		p_in_dbl = (double *) tiff_scanline;
3367 		p_out_dbl = (double *) pixels;
3368 		p_out_dbl += y * width;
3369 		break;
3370 	    default:
3371 		goto error;
3372 	    };
3373 	  for (x = 0; x < origin->width; x++)
3374 	    {
3375 		if (x >= (startCol + width))
3376 		    break;
3377 		if (x < startCol)
3378 		  {
3379 		      for (bnd = 0; bnd < num_bands; bnd++)
3380 			{
3381 			    switch (sample_type)
3382 			      {
3383 			      case RL2_SAMPLE_INT8:
3384 				  p_in_8++;
3385 				  break;
3386 			      case RL2_SAMPLE_UINT8:
3387 				  p_in_u8++;
3388 				  break;
3389 			      case RL2_SAMPLE_INT16:
3390 				  p_in_16++;
3391 				  break;
3392 			      case RL2_SAMPLE_UINT16:
3393 				  p_in_u16++;
3394 				  break;
3395 			      case RL2_SAMPLE_INT32:
3396 				  p_in_32++;
3397 				  break;
3398 			      case RL2_SAMPLE_UINT32:
3399 				  p_in_u32++;
3400 				  break;
3401 			      case RL2_SAMPLE_FLOAT:
3402 				  p_in_flt++;
3403 				  break;
3404 			      case RL2_SAMPLE_DOUBLE:
3405 				  p_in_dbl++;
3406 				  break;
3407 			      };
3408 			}
3409 		      continue;
3410 		  }
3411 		for (bnd = 0; bnd < num_bands; bnd++)
3412 		  {
3413 		      switch (sample_type)
3414 			{
3415 			case RL2_SAMPLE_INT8:
3416 			    *p_out_8++ = *p_in_8++;
3417 			    break;
3418 			case RL2_SAMPLE_UINT8:
3419 			    *p_out_u8++ = *p_in_u8++;
3420 			    break;
3421 			case RL2_SAMPLE_INT16:
3422 			    *p_out_16++ = *p_in_16++;
3423 			    break;
3424 			case RL2_SAMPLE_UINT16:
3425 			    *p_out_u16++ = *p_in_u16++;
3426 			    break;
3427 			case RL2_SAMPLE_INT32:
3428 			    *p_out_32++ = *p_in_32++;
3429 			    break;
3430 			case RL2_SAMPLE_UINT32:
3431 			    *p_out_u32++ = *p_in_u32++;
3432 			    break;
3433 			case RL2_SAMPLE_FLOAT:
3434 			    *p_out_flt++ = *p_in_flt++;
3435 			    break;
3436 			case RL2_SAMPLE_DOUBLE:
3437 			    *p_out_dbl++ = *p_in_dbl++;
3438 			    break;
3439 			};
3440 		  }
3441 	    }
3442       }
3443 
3444     free (tiff_scanline);
3445     TIFFClose (in);
3446     return RL2_OK;
3447   error:
3448     if (tiff_scanline != NULL)
3449 	free (tiff_scanline);
3450     if (in != (TIFF *) 0)
3451 	TIFFClose (in);
3452     return RL2_ERROR;
3453 }
3454 
3455 static int
read_raw_separate_tiles(rl2PrivTiffOriginPtr origin,unsigned short width,unsigned short height,unsigned char sample_type,unsigned char num_bands,unsigned int startRow,unsigned int startCol,void * pixels)3456 read_raw_separate_tiles (rl2PrivTiffOriginPtr origin, unsigned short width,
3457 			 unsigned short height, unsigned char sample_type,
3458 			 unsigned char num_bands, unsigned int startRow,
3459 			 unsigned int startCol, void *pixels)
3460 {
3461 /* reading TIFF raw tiles - separate planes */
3462     uint32 tile_x;
3463     uint32 tile_y;
3464     uint32 x;
3465     uint32 y;
3466     uint32 *tiff_tile = NULL;
3467     unsigned char *p_in_u8;
3468     unsigned char *p_out_u8;
3469     unsigned short *p_in_u16;
3470     unsigned short *p_out_u16;
3471     unsigned int dest_x;
3472     unsigned int dest_y;
3473     int skip;
3474     unsigned char band;
3475 
3476     if (sample_type != RL2_SAMPLE_UINT16 && sample_type != RL2_SAMPLE_UINT8)
3477 	goto error;
3478 
3479     tiff_tile = malloc (TIFFTileSize (origin->in));
3480     if (tiff_tile == NULL)
3481 	goto error;
3482 
3483     for (tile_y = 0; tile_y < origin->height; tile_y += origin->tileHeight)
3484       {
3485 	  /* scanning tiles by row */
3486 	  unsigned int tiff_min_y = tile_y;
3487 	  unsigned int tiff_max_y = tile_y + origin->tileHeight - 1;
3488 	  skip = 0;
3489 	  if (tiff_min_y > (startRow + height))
3490 	      skip = 1;
3491 	  if (tiff_max_y < startRow)
3492 	      skip = 1;
3493 	  if (skip)
3494 	    {
3495 		/* skipping any not required tile */
3496 		continue;
3497 	    }
3498 	  for (tile_x = 0; tile_x < origin->width; tile_x += origin->tileWidth)
3499 	    {
3500 		/* reading a TIFF tile */
3501 		unsigned int tiff_min_x = tile_x;
3502 		unsigned int tiff_max_x = tile_x + origin->tileWidth - 1;
3503 		skip = 0;
3504 		if (tiff_min_x > (startCol + width))
3505 		    skip = 1;
3506 		if (tiff_max_x < startCol)
3507 		    skip = 1;
3508 		if (skip)
3509 		  {
3510 		      /* skipping any not required tile */
3511 		      continue;
3512 		  }
3513 		for (band = 0; band < num_bands; band++)
3514 		  {
3515 		      /* one component for each separate plane */
3516 		      if (TIFFReadTile
3517 			  (origin->in, tiff_tile, tile_x, tile_y, 0, band) < 0)
3518 			  goto error;
3519 		      for (y = 0; y < origin->tileHeight; y++)
3520 			{
3521 			    dest_y = tile_y + y;
3522 			    if (dest_y < startRow
3523 				|| dest_y >= (startRow + height))
3524 				continue;
3525 			    for (x = 0; x < origin->tileWidth; x++)
3526 			      {
3527 				  dest_x = tile_x + x;
3528 				  if (dest_x < startCol
3529 				      || dest_x >= (startCol + width))
3530 				      continue;
3531 				  if (sample_type == RL2_SAMPLE_UINT16)
3532 				    {
3533 					p_in_u16 = (unsigned short *) tiff_tile;
3534 					p_in_u16 += y * origin->tileWidth;
3535 					p_in_u16 += x;
3536 					p_out_u16 = (unsigned short *) pixels;
3537 					p_out_u16 +=
3538 					    ((dest_y -
3539 					      startRow) * width * num_bands) +
3540 					    ((dest_x - startCol) * num_bands) +
3541 					    band;
3542 					*p_out_u16 = *p_in_u16;
3543 				    }
3544 				  if (sample_type == RL2_SAMPLE_UINT8)
3545 				    {
3546 					p_in_u8 = (unsigned char *) tiff_tile;
3547 					p_in_u8 += y * origin->tileWidth;
3548 					p_in_u8 += x;
3549 					p_out_u8 = (unsigned char *) pixels;
3550 					p_out_u8 +=
3551 					    ((dest_y -
3552 					      startRow) * width * num_bands) +
3553 					    ((dest_x - startCol) * num_bands) +
3554 					    band;
3555 					*p_out_u8 = *p_in_u8;
3556 				    }
3557 			      }
3558 			}
3559 		  }
3560 	    }
3561       }
3562 
3563     free (tiff_tile);
3564     return RL2_OK;
3565   error:
3566     if (tiff_tile != NULL)
3567 	free (tiff_tile);
3568     return RL2_ERROR;
3569 }
3570 
3571 static int
read_raw_separate_scanlines(rl2PrivTiffOriginPtr origin,unsigned short width,unsigned short height,unsigned char sample_type,unsigned char num_bands,unsigned int startRow,unsigned int startCol,void * pixels)3572 read_raw_separate_scanlines (rl2PrivTiffOriginPtr origin, unsigned short width,
3573 			     unsigned short height, unsigned char sample_type,
3574 			     unsigned char num_bands, unsigned int startRow,
3575 			     unsigned int startCol, void *pixels)
3576 {
3577 /* reading TIFF raw strips - separate planes */
3578     uint32 line_no;
3579     uint32 x;
3580     uint32 y;
3581     uint32 *tiff_scanline = NULL;
3582     unsigned char *p_in_u8;
3583     unsigned char *p_out_u8;
3584     unsigned char *p_out_u8_base;
3585     unsigned short *p_in_u16;
3586     unsigned short *p_out_u16;
3587     unsigned short *p_out_u16_base;
3588     unsigned char band;
3589     TIFF *in = (TIFF *) 0;
3590 
3591     if (sample_type != RL2_SAMPLE_UINT8 && sample_type != RL2_SAMPLE_UINT16)
3592 	goto error;
3593 
3594     tiff_scanline = malloc (TIFFScanlineSize (origin->in));
3595     if (tiff_scanline == NULL)
3596 	goto error;
3597 
3598     for (band = 0; band < num_bands; band++)
3599       {
3600 	  /* one component for each separate plane */
3601 
3602 /*
3603 / random access doesn't work on compressed scanlines
3604 / so we'll open an auxiliary TIFF handle, thus ensuring
3605 / an always clean reading context
3606 */
3607 	  in = TIFFOpen (origin->path, "r");
3608 	  if (in == NULL)
3609 	      goto error;
3610 
3611 	  for (y = 0; y < startRow; y++)
3612 	    {
3613 		/* skipping trailing scanlines */
3614 		if (TIFFReadScanline (in, tiff_scanline, y, band) < 0)
3615 		    goto error;
3616 	    }
3617 	  for (y = 0; y < height; y++)
3618 	    {
3619 		/* scanning scanlines by row */
3620 		line_no = y + startRow;
3621 		if (line_no >= origin->height)
3622 		    continue;
3623 		if (TIFFReadScanline (in, tiff_scanline, line_no, band) < 0)
3624 		    goto error;
3625 		if (sample_type == RL2_SAMPLE_UINT16)
3626 		  {
3627 		      p_in_u16 = (unsigned short *) tiff_scanline;
3628 		      p_in_u16 += startCol;
3629 		      p_out_u16_base = (unsigned short *) pixels;
3630 		      p_out_u16_base += y * width * num_bands;
3631 		  }
3632 		else
3633 		  {
3634 		      p_in_u8 = (unsigned char *) tiff_scanline;
3635 		      p_in_u8 += startCol;
3636 		      p_out_u8_base = (unsigned char *) pixels;
3637 		      p_out_u8_base += y * width * num_bands;
3638 		  }
3639 		for (x = startCol; x < origin->width; x++)
3640 		  {
3641 		      if (x >= (startCol + width))
3642 			  break;
3643 		      if (sample_type == RL2_SAMPLE_UINT16)
3644 			  p_out_u16 =
3645 			      p_out_u16_base + ((x - startCol) * num_bands) +
3646 			      band;
3647 		      else
3648 			  p_out_u8 =
3649 			      p_out_u8_base + ((x - startCol) * num_bands) +
3650 			      band;
3651 		      if (sample_type == RL2_SAMPLE_UINT16)
3652 			  *p_out_u16 = *p_in_u16++;
3653 		      else
3654 			  *p_out_u8 = *p_in_u8++;
3655 		  }
3656 	    }
3657 	  TIFFClose (in);
3658 	  in = (TIFF *) 0;
3659       }
3660 
3661     free (tiff_scanline);
3662     return RL2_OK;
3663   error:
3664     if (tiff_scanline != NULL)
3665 	free (tiff_scanline);
3666     if (in != (TIFF *) 0)
3667 	TIFFClose (in);
3668     return RL2_ERROR;
3669 }
3670 
3671 static int
read_RGBA_tiles(rl2PrivTiffOriginPtr origin,unsigned short width,unsigned short height,unsigned char pixel_type,unsigned char num_bands,unsigned int startRow,unsigned int startCol,unsigned char * pixels,rl2PalettePtr palette)3672 read_RGBA_tiles (rl2PrivTiffOriginPtr origin, unsigned short width,
3673 		 unsigned short height, unsigned char pixel_type,
3674 		 unsigned char num_bands, unsigned int startRow,
3675 		 unsigned int startCol, unsigned char *pixels,
3676 		 rl2PalettePtr palette)
3677 {
3678 /* reading TIFF RGBA tiles */
3679     uint32 tile_x;
3680     uint32 tile_y;
3681     uint32 x;
3682     uint32 y;
3683     uint32 pix;
3684     uint32 *tiff_tile = NULL;
3685     uint32 *p_in;
3686     unsigned char *p_out;
3687     unsigned int dest_x;
3688     unsigned int dest_y;
3689     int skip;
3690     unsigned char index;
3691     unsigned char red;
3692     unsigned char green;
3693     unsigned char blue;
3694 
3695     tiff_tile =
3696 	malloc (sizeof (uint32) * origin->tileWidth * origin->tileHeight);
3697     if (tiff_tile == NULL)
3698 	goto error;
3699 
3700     for (tile_y = 0; tile_y < origin->height; tile_y += origin->tileHeight)
3701       {
3702 	  /* scanning tiles by row */
3703 	  unsigned int tiff_min_y = tile_y;
3704 	  unsigned int tiff_max_y = tile_y + origin->tileHeight - 1;
3705 	  skip = 0;
3706 	  if (tiff_min_y > (startRow + height))
3707 	      skip = 1;
3708 	  if (tiff_max_y < startRow)
3709 	      skip = 1;
3710 	  if (skip)
3711 	    {
3712 		/* skipping any not required tile */
3713 		continue;
3714 	    }
3715 	  for (tile_x = 0; tile_x < origin->width; tile_x += origin->tileWidth)
3716 	    {
3717 		/* reading a TIFF tile */
3718 		unsigned int tiff_min_x = tile_x;
3719 		unsigned int tiff_max_x = tile_x + origin->tileWidth - 1;
3720 		skip = 0;
3721 		if (tiff_min_x > (startCol + width))
3722 		    skip = 1;
3723 		if (tiff_max_x < startCol)
3724 		    skip = 1;
3725 		if (skip)
3726 		  {
3727 		      /* skipping any not required tile */
3728 		      continue;
3729 		  }
3730 		if (!TIFFReadRGBATile (origin->in, tile_x, tile_y, tiff_tile))
3731 		    goto error;
3732 		for (y = 0; y < origin->tileHeight; y++)
3733 		  {
3734 		      dest_y = tile_y + (origin->tileHeight - y) - 1;
3735 		      if (dest_y < startRow || dest_y >= (startRow + height))
3736 			  continue;
3737 		      p_in = tiff_tile + (origin->tileWidth * y);
3738 		      for (x = 0; x < origin->tileWidth; x++)
3739 			{
3740 			    dest_x = tile_x + x;
3741 			    if (dest_x < startCol
3742 				|| dest_x >= (startCol + width))
3743 			      {
3744 				  p_in++;
3745 				  continue;
3746 			      }
3747 			    p_out =
3748 				pixels +
3749 				((dest_y - startRow) * width * num_bands) +
3750 				((dest_x - startCol) * num_bands);
3751 			    pix = *p_in++;
3752 			    red = TIFFGetR (pix);
3753 			    green = TIFFGetG (pix);
3754 			    blue = TIFFGetB (pix);
3755 			    if (origin->forced_conversion ==
3756 				RL2_CONVERT_RGB_TO_GRAYSCALE)
3757 			      {
3758 				  /* forced conversion: RGB -> GRAYSCALE */
3759 				  double gray =
3760 				      ((double) red * 0.2126) +
3761 				      ((double) green * 0.7152) +
3762 				      ((double) blue * 0.0722);
3763 				  *p_out++ = (unsigned char) gray;
3764 			      }
3765 			    else if (origin->forced_conversion ==
3766 				     RL2_CONVERT_GRAYSCALE_TO_RGB
3767 				     || origin->forced_conversion ==
3768 				     RL2_CONVERT_PALETTE_TO_RGB)
3769 			      {
3770 				  /* forced conversion: GRAYSCALE or PALETTE -> RGB */
3771 				  *p_out++ = red;
3772 				  *p_out++ = green;
3773 				  *p_out++ = blue;
3774 			      }
3775 			    else if (origin->forced_conversion ==
3776 				     RL2_CONVERT_GRAYSCALE_TO_PALETTE)
3777 			      {
3778 				  /* forced conversion: GRAYSCALE -> PALETTE */
3779 				  *p_out++ = red;
3780 			      }
3781 			    else if (origin->forced_conversion ==
3782 				     RL2_CONVERT_PALETTE_TO_GRAYSCALE)
3783 			      {
3784 				  /* forced conversion: PALETTE -> GRAYSCALE */
3785 				  *p_out++ = red;
3786 			      }
3787 			    else if (origin->forced_conversion ==
3788 				     RL2_CONVERT_PALETTE_TO_MONOCHROME)
3789 			      {
3790 				  /* forced conversion: PALETTE -> MONOCHROME */
3791 				  if (red == 255 && green == 255 && blue == 255)
3792 				      *p_out++ = 0;
3793 				  else
3794 				      *p_out++ = 1;
3795 			      }
3796 			    else if (origin->forced_conversion ==
3797 				     RL2_CONVERT_MONOCHROME_TO_PALETTE)
3798 			      {
3799 				  /* forced conversion: MONOCHROME -> PALETTE */
3800 				  if (red == 0)
3801 				      *p_out++ = 1;
3802 				  else
3803 				      *p_out++ = 0;
3804 			      }
3805 			    else if (pixel_type == RL2_PIXEL_PALETTE)
3806 			      {
3807 				  /* PALETTE image */
3808 				  if (rl2_get_palette_index
3809 				      (palette, &index, red, green,
3810 				       blue) != RL2_OK)
3811 				      index = 0;
3812 				  *p_out++ = index;
3813 			      }
3814 			    else if (pixel_type == RL2_PIXEL_MONOCHROME)
3815 			      {
3816 				  /* MONOCHROME  image */
3817 				  if (red == 0)
3818 				      *p_out++ = 1;
3819 				  else
3820 				      *p_out++ = 0;
3821 			      }
3822 			    else if (pixel_type == RL2_PIXEL_GRAYSCALE)
3823 			      {
3824 				  /* GRAYSCALE  image */
3825 				  *p_out++ = red;
3826 			      }
3827 			    else
3828 			      {
3829 				  /* should be an RGB image */
3830 				  *p_out++ = red;
3831 				  *p_out++ = green;
3832 				  *p_out++ = blue;
3833 			      }
3834 			}
3835 		  }
3836 	    }
3837       }
3838 
3839     free (tiff_tile);
3840     return RL2_OK;
3841   error:
3842     if (tiff_tile != NULL)
3843 	free (tiff_tile);
3844     return RL2_ERROR;
3845 }
3846 
3847 static int
read_RGBA_strips(rl2PrivTiffOriginPtr origin,unsigned short width,unsigned short height,unsigned char pixel_type,unsigned char num_bands,unsigned int startRow,unsigned int startCol,unsigned char * pixels,rl2PalettePtr palette)3848 read_RGBA_strips (rl2PrivTiffOriginPtr origin, unsigned short width,
3849 		  unsigned short height, unsigned char pixel_type,
3850 		  unsigned char num_bands, unsigned int startRow,
3851 		  unsigned int startCol, unsigned char *pixels,
3852 		  rl2PalettePtr palette)
3853 {
3854 /* reading TIFF RGBA strips */
3855     uint32 strip;
3856     uint32 x;
3857     uint32 y;
3858     uint32 pix;
3859     uint32 *tiff_strip = NULL;
3860     uint32 *p_in;
3861     unsigned char *p_out;
3862     unsigned int dest_x;
3863     unsigned int dest_y;
3864     int skip;
3865     unsigned char index;
3866     unsigned char red;
3867     unsigned char green;
3868     unsigned char blue;
3869 
3870     tiff_strip =
3871 	malloc (sizeof (uint32) * origin->width * origin->rowsPerStrip);
3872     if (tiff_strip == NULL)
3873 	goto error;
3874 
3875     for (strip = 0; strip < origin->height; strip += origin->rowsPerStrip)
3876       {
3877 	  /* scanning strips by row */
3878 	  unsigned int tiff_min_y = strip;
3879 	  unsigned int tiff_max_y = strip + origin->rowsPerStrip - 1;
3880 	  skip = 0;
3881 	  if (tiff_min_y > (startRow + height))
3882 	      skip = 1;
3883 	  if (tiff_max_y < startRow)
3884 	      skip = 1;
3885 	  if (skip)
3886 	    {
3887 		/* skipping any not required strip */
3888 		continue;
3889 	    }
3890 	  if (!TIFFReadRGBAStrip (origin->in, strip, tiff_strip))
3891 	      goto error;
3892 	  for (y = 0; y < origin->rowsPerStrip; y++)
3893 	    {
3894 		dest_y = strip + (origin->rowsPerStrip - y) - 1;
3895 		if (dest_y < startRow || dest_y >= (startRow + height))
3896 		    continue;
3897 		p_in = tiff_strip + (origin->width * y);
3898 		for (x = 0; x < origin->width; x++)
3899 		  {
3900 		      dest_x = x;
3901 		      if (dest_x < startCol || dest_x >= (startCol + width))
3902 			{
3903 			    p_in++;
3904 			    continue;
3905 			}
3906 		      p_out =
3907 			  pixels + ((dest_y - startRow) * width * num_bands) +
3908 			  ((dest_x - startCol) * num_bands);
3909 		      pix = *p_in++;
3910 		      red = TIFFGetR (pix);
3911 		      green = TIFFGetG (pix);
3912 		      blue = TIFFGetB (pix);
3913 		      if (origin->forced_conversion ==
3914 			  RL2_CONVERT_RGB_TO_GRAYSCALE)
3915 			{
3916 			    /* forced conversion: RGB -> GRAYSCALE */
3917 			    double gray =
3918 				((double) red * 0.2126) +
3919 				((double) green * 0.7152) +
3920 				((double) blue * 0.0722);
3921 			    *p_out++ = (unsigned char) gray;
3922 			}
3923 		      else if (origin->forced_conversion ==
3924 			       RL2_CONVERT_GRAYSCALE_TO_RGB
3925 			       || origin->forced_conversion ==
3926 			       RL2_CONVERT_PALETTE_TO_RGB)
3927 			{
3928 			    /* forced conversion: GRAYSCALE or PALETTE -> RGB */
3929 			    *p_out++ = red;
3930 			    *p_out++ = green;
3931 			    *p_out++ = blue;
3932 			}
3933 		      else if (origin->forced_conversion ==
3934 			       RL2_CONVERT_GRAYSCALE_TO_PALETTE)
3935 			{
3936 			    /* forced conversion: GRAYSCALE -> PALETTE */
3937 			    *p_out++ = red;
3938 			}
3939 		      else if (origin->forced_conversion ==
3940 			       RL2_CONVERT_PALETTE_TO_GRAYSCALE)
3941 			{
3942 			    /* forced conversion: PALETTE -> GRAYSCALE */
3943 			    *p_out++ = red;
3944 			}
3945 		      else if (origin->forced_conversion ==
3946 			       RL2_CONVERT_PALETTE_TO_MONOCHROME)
3947 			{
3948 			    /* forced conversion: PALETTE -> MONOCHROME */
3949 			    if (red == 255 && green == 255 && blue == 255)
3950 				*p_out++ = 0;
3951 			    else
3952 				*p_out++ = 1;
3953 			}
3954 		      else if (origin->forced_conversion ==
3955 			       RL2_CONVERT_MONOCHROME_TO_PALETTE)
3956 			{
3957 			    /* forced conversion: MONOCHROME -> PALETTE */
3958 			    if (red == 0)
3959 				*p_out++ = 1;
3960 			    else
3961 				*p_out++ = 0;
3962 			}
3963 		      else if (pixel_type == RL2_PIXEL_PALETTE)
3964 			{
3965 			    /* PALETTE image */
3966 			    if (rl2_get_palette_index
3967 				(palette, &index, red, green, blue) != RL2_OK)
3968 				index = 0;
3969 			    *p_out++ = index;
3970 			}
3971 		      else if (pixel_type == RL2_PIXEL_MONOCHROME)
3972 			{
3973 			    /* MONOCHROME  image */
3974 			    if (red == 0)
3975 				*p_out++ = 1;
3976 			    else
3977 				*p_out++ = 0;
3978 			}
3979 		      else if (pixel_type == RL2_PIXEL_GRAYSCALE)
3980 			{
3981 			    /* GRAYSCALE  image */
3982 			    *p_out++ = red;
3983 			}
3984 		      else
3985 			{
3986 			    /* should be an RGB image */
3987 			    *p_out++ = red;
3988 			    *p_out++ = green;
3989 			    *p_out++ = blue;
3990 			}
3991 		  }
3992 	    }
3993       }
3994 
3995     free (tiff_strip);
3996     return RL2_OK;
3997   error:
3998     if (tiff_strip != NULL)
3999 	free (tiff_strip);
4000     return RL2_ERROR;
4001 }
4002 
4003 static int
read_from_tiff(rl2PrivTiffOriginPtr origin,unsigned short width,unsigned short height,unsigned char sample_type,unsigned char pixel_type,unsigned char num_bands,unsigned int startRow,unsigned int startCol,unsigned char ** pixels,int * pixels_sz,rl2PalettePtr palette)4004 read_from_tiff (rl2PrivTiffOriginPtr origin, unsigned short width,
4005 		unsigned short height, unsigned char sample_type,
4006 		unsigned char pixel_type, unsigned char num_bands,
4007 		unsigned int startRow, unsigned int startCol,
4008 		unsigned char **pixels, int *pixels_sz, rl2PalettePtr palette)
4009 {
4010 /* creating a tile from the Tiff origin */
4011     int ret;
4012     unsigned char *bufPixels = NULL;
4013     int bufPixelsSz = 0;
4014     int pix_sz = 1;
4015 
4016 /* allocating the pixels buffer */
4017     switch (sample_type)
4018       {
4019       case RL2_SAMPLE_INT16:
4020       case RL2_SAMPLE_UINT16:
4021 	  pix_sz = 2;
4022 	  break;
4023       case RL2_SAMPLE_INT32:
4024       case RL2_SAMPLE_UINT32:
4025       case RL2_SAMPLE_FLOAT:
4026 	  pix_sz = 4;
4027 	  break;
4028       case RL2_SAMPLE_DOUBLE:
4029 	  pix_sz = 8;
4030 	  break;
4031       };
4032     bufPixelsSz = width * height * pix_sz * num_bands;
4033     bufPixels = malloc (bufPixelsSz);
4034     if (bufPixels == NULL)
4035 	goto error;
4036     if ((startRow + height) > origin->height
4037 	|| (startCol + width) > origin->width)
4038 	rl2_prime_void_tile (bufPixels, width, height, sample_type, num_bands,
4039 			     NULL);
4040 
4041     if (origin->planarConfig == PLANARCONFIG_SEPARATE)
4042       {
4043 	  /* separate planes configuration */
4044 	  if ((origin->bitsPerSample == 16 || origin->bitsPerSample == 8)
4045 	      && origin->sampleFormat == SAMPLEFORMAT_UINT)
4046 	    {
4047 		/* using raw TIFF methods - separate planes */
4048 		if (origin->isTiled)
4049 		    ret =
4050 			read_raw_separate_tiles (origin, width, height,
4051 						 sample_type, num_bands,
4052 						 startRow, startCol,
4053 						 (void *) bufPixels);
4054 		else
4055 		    ret =
4056 			read_raw_separate_scanlines (origin, width, height,
4057 						     sample_type, num_bands,
4058 						     startRow, startCol,
4059 						     (void *) bufPixels);
4060 		if (ret != RL2_OK)
4061 		    goto error;
4062 	    }
4063 	  else
4064 	      goto error;
4065       }
4066     else
4067       {
4068 	  /* contiguous planar configuration */
4069 	  if (origin->bitsPerSample <= 8
4070 	      && origin->sampleFormat == SAMPLEFORMAT_UINT
4071 	      && (origin->samplesPerPixel == 1 || origin->samplesPerPixel == 3)
4072 	      && (pixel_type == RL2_PIXEL_MONOCHROME
4073 		  || pixel_type == RL2_PIXEL_PALETTE
4074 		  || pixel_type == RL2_PIXEL_GRAYSCALE
4075 		  || pixel_type == RL2_PIXEL_RGB))
4076 	    {
4077 		/* using the TIFF RGBA methods */
4078 		if (origin->isTiled)
4079 		    ret =
4080 			read_RGBA_tiles (origin, width, height, pixel_type,
4081 					 num_bands, startRow, startCol,
4082 					 bufPixels, palette);
4083 		else
4084 		    ret =
4085 			read_RGBA_strips (origin, width, height, pixel_type,
4086 					  num_bands, startRow, startCol,
4087 					  bufPixels, palette);
4088 		if (ret != RL2_OK)
4089 		    goto error;
4090 	    }
4091 	  else
4092 	    {
4093 		/* using raw TIFF methods */
4094 		if (origin->isTiled)
4095 		    ret =
4096 			read_raw_tiles (origin, width, height, sample_type,
4097 					num_bands, startRow, startCol,
4098 					bufPixels);
4099 		else
4100 		    ret =
4101 			read_raw_scanlines (origin, width, height, sample_type,
4102 					    num_bands, startRow, startCol,
4103 					    bufPixels);
4104 		if (ret != RL2_OK)
4105 		    goto error;
4106 	    }
4107       }
4108 
4109     *pixels = bufPixels;
4110     *pixels_sz = bufPixelsSz;
4111     return RL2_OK;
4112   error:
4113     if (bufPixels != NULL)
4114 	free (bufPixels);
4115     return RL2_ERROR;
4116 }
4117 
4118 RL2_DECLARE int
rl2_is_tiled_tiff_origin(rl2TiffOriginPtr tiff,int * is_tiled)4119 rl2_is_tiled_tiff_origin (rl2TiffOriginPtr tiff, int *is_tiled)
4120 {
4121 /* testing if the TIFF Origin is tiled or not */
4122     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
4123     if (origin == NULL)
4124 	return RL2_ERROR;
4125     *is_tiled = origin->isTiled;
4126     return RL2_OK;
4127 }
4128 
4129 RL2_DECLARE int
rl2_get_tiff_origin_tile_size(rl2TiffOriginPtr tiff,unsigned int * tile_width,unsigned int * tile_height)4130 rl2_get_tiff_origin_tile_size (rl2TiffOriginPtr tiff,
4131 			       unsigned int *tile_width,
4132 			       unsigned int *tile_height)
4133 {
4134 /* attempting to return the Tile dimensions */
4135     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
4136     if (origin == NULL)
4137 	return RL2_ERROR;
4138     if (origin->isTiled == 0)
4139 	return RL2_ERROR;
4140     *tile_width = origin->tileWidth;
4141     *tile_height = origin->tileHeight;
4142     return RL2_OK;
4143 }
4144 
4145 RL2_DECLARE int
rl2_get_tiff_origin_strip_size(rl2TiffOriginPtr tiff,unsigned int * strip_size)4146 rl2_get_tiff_origin_strip_size (rl2TiffOriginPtr tiff, unsigned int *strip_size)
4147 {
4148 /* attempting to return the Strip dimension */
4149     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
4150     if (origin == NULL)
4151 	return RL2_ERROR;
4152     if (origin->isTiled != 0)
4153 	return RL2_ERROR;
4154     *strip_size = origin->rowsPerStrip;
4155     return RL2_OK;
4156 }
4157 
4158 static void
build_remap(rl2PrivTiffOriginPtr origin)4159 build_remap (rl2PrivTiffOriginPtr origin)
4160 {
4161 /* building a remapped palette identical to the natural one */
4162     int j;
4163     if (origin->remapRed != NULL)
4164 	free (origin->remapRed);
4165     if (origin->remapGreen != NULL)
4166 	free (origin->remapGreen);
4167     if (origin->remapBlue != NULL)
4168 	free (origin->remapBlue);
4169     origin->remapMaxPalette = origin->maxPalette;
4170     origin->remapRed = malloc (origin->remapMaxPalette);
4171     origin->remapGreen = malloc (origin->remapMaxPalette);
4172     origin->remapBlue = malloc (origin->remapMaxPalette);
4173     for (j = 0; j < origin->maxPalette; j++)
4174       {
4175 	  origin->remapRed[j] = origin->red[j];
4176 	  origin->remapGreen[j] = origin->green[j];
4177 	  origin->remapBlue[j] = origin->blue[j];
4178       }
4179 }
4180 
4181 RL2_DECLARE rl2RasterPtr
rl2_get_tile_from_tiff_origin(rl2CoveragePtr cvg,rl2TiffOriginPtr tiff,unsigned int startRow,unsigned int startCol,int force_srid)4182 rl2_get_tile_from_tiff_origin (rl2CoveragePtr cvg, rl2TiffOriginPtr tiff,
4183 			       unsigned int startRow, unsigned int startCol,
4184 			       int force_srid)
4185 {
4186 /* attempting to create a Coverage-tile from a Tiff origin */
4187     unsigned int x;
4188     rl2PrivCoveragePtr coverage = (rl2PrivCoveragePtr) cvg;
4189     rl2PrivTiffOriginPtr origin = (rl2PrivTiffOriginPtr) tiff;
4190     rl2RasterPtr raster = NULL;
4191     rl2PalettePtr palette = NULL;
4192     unsigned char *pixels = NULL;
4193     int pixels_sz = 0;
4194     unsigned char *mask = NULL;
4195     int mask_size = 0;
4196     unsigned int unused_width = 0;
4197     unsigned int unused_height = 0;
4198 
4199     if (coverage == NULL || tiff == NULL)
4200 	return NULL;
4201     if (rl2_eval_tiff_origin_compatibility (cvg, tiff, force_srid) != RL2_TRUE)
4202 	return NULL;
4203 
4204 /* testing for tile's boundary validity */
4205     if (startCol > origin->width)
4206 	return NULL;
4207     if (startRow > origin->height)
4208 	return NULL;
4209     x = startCol / coverage->tileWidth;
4210     if ((x * coverage->tileWidth) != startCol)
4211 	return NULL;
4212     x = startRow / coverage->tileHeight;
4213     if ((x * coverage->tileHeight) != startRow)
4214 	return NULL;
4215 
4216     if ((origin->photometric == PHOTOMETRIC_RGB
4217 	 && origin->forced_pixel_type == RL2_PIXEL_PALETTE)
4218 	|| origin->forced_conversion == RL2_CONVERT_GRAYSCALE_TO_PALETTE)
4219       {
4220 	  /* creating a remapped Palette */
4221 	  if (origin->remapMaxPalette == 0 && origin->maxPalette > 0
4222 	      && origin->maxPalette <= 256)
4223 	      build_remap (origin);
4224 	  palette = rl2_create_palette (origin->remapMaxPalette);
4225 	  for (x = 0; x < origin->remapMaxPalette; x++)
4226 	    {
4227 		rl2_set_palette_color (palette, x, origin->remapRed[x],
4228 				       origin->remapGreen[x],
4229 				       origin->remapBlue[x]);
4230 	    }
4231       }
4232     else if ((origin->photometric < PHOTOMETRIC_RGB
4233 	      && origin->forced_pixel_type == RL2_PIXEL_PALETTE)
4234 	     || origin->forced_conversion == RL2_CONVERT_MONOCHROME_TO_PALETTE)
4235       {
4236 	  /* creating a remapped Palette */
4237 	  if (origin->remapMaxPalette == 0 && origin->maxPalette > 0
4238 	      && origin->maxPalette <= 2)
4239 	      build_remap (origin);
4240 	  palette = rl2_create_palette (origin->remapMaxPalette);
4241 	  for (x = 0; x < origin->remapMaxPalette; x++)
4242 	    {
4243 		rl2_set_palette_color (palette, x, origin->remapRed[x],
4244 				       origin->remapGreen[x],
4245 				       origin->remapBlue[x]);
4246 	    }
4247       }
4248     if (origin->photometric == PHOTOMETRIC_PALETTE)
4249       {
4250 	  /* creating an ordinary Palette */
4251 	  if (origin->remapMaxPalette > 0)
4252 	    {
4253 		palette = rl2_create_palette (origin->remapMaxPalette);
4254 		for (x = 0; x < origin->maxPalette; x++)
4255 		  {
4256 		      rl2_set_palette_color (palette, x,
4257 					     origin->remapRed[x],
4258 					     origin->remapGreen[x],
4259 					     origin->remapBlue[x]);
4260 		  }
4261 	    }
4262 	  else
4263 	    {
4264 		if (origin->maxPalette > 0)
4265 		  {
4266 		      palette = rl2_create_palette (origin->maxPalette);
4267 		      for (x = 0; x < origin->maxPalette; x++)
4268 			{
4269 			    rl2_set_palette_color (palette, x, origin->red[x],
4270 						   origin->green[x],
4271 						   origin->blue[x]);
4272 			}
4273 		  }
4274 	    }
4275       }
4276 
4277 /* attempting to create the tile */
4278     if (read_from_tiff
4279 	(origin, coverage->tileWidth, coverage->tileHeight,
4280 	 coverage->sampleType, coverage->pixelType, coverage->nBands, startRow,
4281 	 startCol, &pixels, &pixels_sz, palette) != RL2_OK)
4282 	goto error;
4283     if (startCol + coverage->tileWidth > origin->width)
4284 	unused_width = (startCol + coverage->tileWidth) - origin->width;
4285     if (startRow + coverage->tileHeight > origin->height)
4286 	unused_height = (startRow + coverage->tileHeight) - origin->height;
4287     if (unused_width || unused_height)
4288       {
4289 	  /*
4290 	   * creating a Transparency Mask so to shadow any
4291 	   * unused portion of the current tile
4292 	   */
4293 	  unsigned int shadow_x = coverage->tileWidth - unused_width;
4294 	  unsigned int shadow_y = coverage->tileHeight - unused_height;
4295 	  unsigned int row;
4296 	  mask_size = coverage->tileWidth * coverage->tileHeight;
4297 	  mask = malloc (mask_size);
4298 	  if (mask == NULL)
4299 	      goto error;
4300 	  /* full Transparent mask */
4301 	  memset (mask, 0, coverage->tileWidth * coverage->tileHeight);
4302 	  for (row = 0; row < coverage->tileHeight; row++)
4303 	    {
4304 		unsigned char *p = mask + (row * coverage->tileWidth);
4305 		if (row < shadow_y)
4306 		  {
4307 		      /* setting opaque pixels */
4308 		      memset (p, 1, shadow_x);
4309 		  }
4310 	    }
4311       }
4312 
4313     if (origin->forced_conversion == RL2_CONVERT_PALETTE_TO_MONOCHROME ||
4314 	origin->forced_conversion == RL2_CONVERT_PALETTE_TO_GRAYSCALE ||
4315 	origin->forced_conversion == RL2_CONVERT_PALETTE_TO_RGB)
4316       {
4317 	  rl2_destroy_palette (palette);
4318 	  palette = NULL;
4319       }
4320     raster =
4321 	rl2_create_raster (coverage->tileWidth, coverage->tileHeight,
4322 			   coverage->sampleType, coverage->pixelType,
4323 			   coverage->nBands, pixels, pixels_sz, palette, mask,
4324 			   mask_size, NULL);
4325     if (raster == NULL)
4326 	goto error;
4327     return raster;
4328   error:
4329     if (palette != NULL)
4330 	rl2_destroy_palette (palette);
4331     if (pixels != NULL)
4332 	free (pixels);
4333     if (mask != NULL)
4334 	free (mask);
4335     return NULL;
4336 }
4337 
4338 static rl2PrivTiffDestinationPtr
create_tiff_destination(const char * path,int is_geo_tiff)4339 create_tiff_destination (const char *path, int is_geo_tiff)
4340 {
4341 /* creating an uninitialized TIFF destination */
4342     int len;
4343     rl2PrivTiffDestinationPtr destination;
4344     if (path == NULL)
4345 	return NULL;
4346     destination = malloc (sizeof (rl2PrivTiffDestination));
4347     if (destination == NULL)
4348 	return NULL;
4349 
4350     len = strlen (path);
4351     destination->path = malloc (len + 1);
4352     strcpy (destination->path, path);
4353     destination->isGeoTiff = is_geo_tiff;
4354     destination->out = (TIFF *) 0;
4355     destination->gtif = (GTIF *) 0;
4356     destination->tiffBuffer = NULL;
4357     destination->tileWidth = 256;
4358     destination->tileHeight = 256;
4359     destination->maxPalette = 0;
4360     destination->red = NULL;
4361     destination->green = NULL;
4362     destination->blue = NULL;
4363     destination->isGeoReferenced = 0;
4364     destination->Srid = -1;
4365     destination->srsName = NULL;
4366     destination->proj4text = NULL;
4367     return destination;
4368 }
4369 
4370 RL2_DECLARE void
rl2_destroy_tiff_destination(rl2TiffDestinationPtr tiff)4371 rl2_destroy_tiff_destination (rl2TiffDestinationPtr tiff)
4372 {
4373 /* memory cleanup - destroying a TIFF destination */
4374     rl2PrivTiffDestinationPtr destination = (rl2PrivTiffDestinationPtr) tiff;
4375     if (destination == NULL)
4376 	return;
4377     if (destination->isGeoTiff)
4378       {
4379 	  /* it's a GeoTiff */
4380 	  if (destination->gtif != (GTIF *) 0)
4381 	      GTIFFree (destination->gtif);
4382 	  if (destination->out != (TIFF *) 0)
4383 	      XTIFFClose (destination->out);
4384       }
4385     else
4386       {
4387 	  /* it's a plain ordinary Tiff */
4388 	  if (destination->out != (TIFF *) 0)
4389 	      TIFFClose (destination->out);
4390       }
4391     if (destination->path != NULL)
4392 	free (destination->path);
4393     if (destination->tfw_path != NULL)
4394 	free (destination->tfw_path);
4395     if (destination->tiffBuffer != NULL)
4396 	free (destination->tiffBuffer);
4397     if (destination->red != NULL)
4398 	free (destination->red);
4399     if (destination->green != NULL)
4400 	free (destination->green);
4401     if (destination->blue != NULL)
4402 	free (destination->blue);
4403     if (destination->srsName != NULL)
4404 	free (destination->srsName);
4405     if (destination->proj4text != NULL)
4406 	free (destination->proj4text);
4407     free (destination);
4408 }
4409 
4410 static int
check_color_model(unsigned char sample_type,unsigned char pixel_type,unsigned char num_bands,rl2PalettePtr plt,unsigned char compression)4411 check_color_model (unsigned char sample_type, unsigned char pixel_type,
4412 		   unsigned char num_bands, rl2PalettePtr plt,
4413 		   unsigned char compression)
4414 {
4415 /* checking TIFF arguments for self consistency */
4416     switch (pixel_type)
4417       {
4418       case RL2_PIXEL_MONOCHROME:
4419 	  if (sample_type != RL2_SAMPLE_1_BIT || num_bands != 1)
4420 	      return 0;
4421 	  switch (compression)
4422 	    {
4423 	    case RL2_COMPRESSION_NONE:
4424 	    case RL2_COMPRESSION_CCITTFAX3:
4425 	    case RL2_COMPRESSION_CCITTFAX4:
4426 		break;
4427 	    default:
4428 		return 0;
4429 	    };
4430 	  break;
4431       case RL2_PIXEL_PALETTE:
4432 	  switch (sample_type)
4433 	    {
4434 	    case RL2_SAMPLE_1_BIT:
4435 	    case RL2_SAMPLE_2_BIT:
4436 	    case RL2_SAMPLE_4_BIT:
4437 	    case RL2_SAMPLE_UINT8:
4438 		break;
4439 	    default:
4440 		return 0;
4441 	    };
4442 	  if (num_bands != 1)
4443 	      return 0;
4444 	  if (plt == NULL)
4445 	      return 0;
4446 	  switch (compression)
4447 	    {
4448 	    case RL2_COMPRESSION_NONE:
4449 	    case RL2_COMPRESSION_DEFLATE:
4450 	    case RL2_COMPRESSION_LZMA:
4451 	    case RL2_COMPRESSION_LZW:
4452 		break;
4453 	    default:
4454 		return 0;
4455 	    };
4456 	  break;
4457       case RL2_PIXEL_GRAYSCALE:
4458 	  switch (sample_type)
4459 	    {
4460 	    case RL2_SAMPLE_1_BIT:
4461 	    case RL2_SAMPLE_2_BIT:
4462 	    case RL2_SAMPLE_4_BIT:
4463 	    case RL2_SAMPLE_UINT8:
4464 		break;
4465 	    default:
4466 		return 0;
4467 	    };
4468 	  if (num_bands != 1)
4469 	      return 0;
4470 	  switch (compression)
4471 	    {
4472 	    case RL2_COMPRESSION_NONE:
4473 	    case RL2_COMPRESSION_DEFLATE:
4474 	    case RL2_COMPRESSION_LZMA:
4475 	    case RL2_COMPRESSION_LZW:
4476 	    case RL2_COMPRESSION_JPEG:
4477 		break;
4478 	    default:
4479 		return 0;
4480 	    };
4481 	  break;
4482       case RL2_PIXEL_RGB:
4483 	  switch (sample_type)
4484 	    {
4485 	    case RL2_SAMPLE_UINT8:
4486 	    case RL2_SAMPLE_UINT16:
4487 		break;
4488 	    default:
4489 		return 0;
4490 	    };
4491 	  if (num_bands != 3)
4492 	      return 0;
4493 	  if (sample_type == RL2_SAMPLE_UINT16)
4494 	    {
4495 		switch (compression)
4496 		  {
4497 		  case RL2_COMPRESSION_NONE:
4498 		  case RL2_COMPRESSION_DEFLATE:
4499 		  case RL2_COMPRESSION_LZMA:
4500 		  case RL2_COMPRESSION_LZW:
4501 		      break;
4502 		  default:
4503 		      return 0;
4504 		  };
4505 	    }
4506 	  else
4507 	    {
4508 		switch (compression)
4509 		  {
4510 		  case RL2_COMPRESSION_NONE:
4511 		  case RL2_COMPRESSION_DEFLATE:
4512 		  case RL2_COMPRESSION_LZMA:
4513 		  case RL2_COMPRESSION_LZW:
4514 		  case RL2_COMPRESSION_JPEG:
4515 		      break;
4516 		  default:
4517 		      return 0;
4518 		  };
4519 	    }
4520 	  break;
4521       case RL2_PIXEL_DATAGRID:
4522 	  switch (sample_type)
4523 	    {
4524 	    case RL2_SAMPLE_INT8:
4525 	    case RL2_SAMPLE_UINT8:
4526 	    case RL2_SAMPLE_INT16:
4527 	    case RL2_SAMPLE_UINT16:
4528 	    case RL2_SAMPLE_INT32:
4529 	    case RL2_SAMPLE_UINT32:
4530 	    case RL2_SAMPLE_FLOAT:
4531 	    case RL2_SAMPLE_DOUBLE:
4532 		break;
4533 	    default:
4534 		return 0;
4535 	    };
4536 	  if (num_bands != 1)
4537 	      return 0;
4538 	  switch (compression)
4539 	    {
4540 	    case RL2_COMPRESSION_NONE:
4541 	    case RL2_COMPRESSION_DEFLATE:
4542 	    case RL2_COMPRESSION_LZMA:
4543 	    case RL2_COMPRESSION_LZW:
4544 		break;
4545 	    default:
4546 		return 0;
4547 	    };
4548 	  break;
4549       };
4550     return 1;
4551 }
4552 
4553 static int
set_tiff_destination(rl2PrivTiffDestinationPtr destination,unsigned short width,unsigned short height,unsigned char sample_type,unsigned char pixel_type,unsigned char num_bands,rl2PalettePtr plt,unsigned char tiff_compression)4554 set_tiff_destination (rl2PrivTiffDestinationPtr destination,
4555 		      unsigned short width, unsigned short height,
4556 		      unsigned char sample_type, unsigned char pixel_type,
4557 		      unsigned char num_bands, rl2PalettePtr plt,
4558 		      unsigned char tiff_compression)
4559 {
4560 /* setting up the TIFF headers */
4561     int i;
4562     uint16 r_plt[256];
4563     uint16 g_plt[256];
4564     uint16 b_plt[256];
4565     tsize_t buf_size;
4566     void *tiff_buffer = NULL;
4567 
4568     TIFFSetField (destination->out, TIFFTAG_SUBFILETYPE, 0);
4569     TIFFSetField (destination->out, TIFFTAG_IMAGEWIDTH, width);
4570     TIFFSetField (destination->out, TIFFTAG_IMAGELENGTH, height);
4571     TIFFSetField (destination->out, TIFFTAG_XRESOLUTION, 300.0);
4572     TIFFSetField (destination->out, TIFFTAG_YRESOLUTION, 300.0);
4573     TIFFSetField (destination->out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
4574     if (pixel_type == RL2_PIXEL_MULTIBAND)
4575 	TIFFSetField (destination->out, TIFFTAG_PLANARCONFIG,
4576 		      PLANARCONFIG_SEPARATE);
4577     else if (pixel_type == RL2_PIXEL_RGB && sample_type == RL2_SAMPLE_UINT16)
4578 	TIFFSetField (destination->out, TIFFTAG_PLANARCONFIG,
4579 		      PLANARCONFIG_SEPARATE);
4580     else
4581 	TIFFSetField (destination->out, TIFFTAG_PLANARCONFIG,
4582 		      PLANARCONFIG_CONTIG);
4583     TIFFSetField (destination->out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
4584     if (pixel_type == RL2_PIXEL_MONOCHROME)
4585       {
4586 	  /* MONOCHROME */
4587 	  destination->sampleFormat = SAMPLEFORMAT_UINT;
4588 	  destination->bitsPerSample = 1;
4589 	  destination->samplesPerPixel = 1;
4590 	  destination->photometric = PHOTOMETRIC_MINISWHITE;
4591 	  TIFFSetField (destination->out, TIFFTAG_SAMPLEFORMAT,
4592 			SAMPLEFORMAT_UINT);
4593 	  TIFFSetField (destination->out, TIFFTAG_SAMPLESPERPIXEL, 1);
4594 	  TIFFSetField (destination->out, TIFFTAG_BITSPERSAMPLE, 1);
4595 	  TIFFSetField (destination->out, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
4596 	  TIFFSetField (destination->out, TIFFTAG_PHOTOMETRIC,
4597 			PHOTOMETRIC_MINISWHITE);
4598 	  if (tiff_compression == RL2_COMPRESSION_CCITTFAX3)
4599 	    {
4600 		destination->compression = COMPRESSION_CCITTFAX3;
4601 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4602 			      COMPRESSION_CCITTFAX3);
4603 	    }
4604 	  else if (tiff_compression == RL2_COMPRESSION_CCITTFAX4)
4605 	    {
4606 		destination->compression = COMPRESSION_CCITTFAX4;
4607 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4608 			      COMPRESSION_CCITTFAX4);
4609 	    }
4610 	  else
4611 	    {
4612 		destination->compression = COMPRESSION_NONE;
4613 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4614 			      COMPRESSION_NONE);
4615 	    }
4616 	  goto header_done;
4617       }
4618     else if (pixel_type == RL2_PIXEL_PALETTE)
4619       {
4620 	  /* PALETTE */
4621 	  unsigned short max_palette;
4622 	  unsigned char *red;
4623 	  unsigned char *green;
4624 	  unsigned char *blue;
4625 	  if (rl2_get_palette_colors
4626 	      (plt, &max_palette, &red, &green, &blue) == RL2_ERROR)
4627 	    {
4628 		fprintf (stderr, "RL2-TIFF writer: invalid Palette\n");
4629 		goto error;
4630 	    }
4631 	  for (i = 0; i < 256; i++)
4632 	    {
4633 		r_plt[i] = 0;
4634 		g_plt[i] = 0;
4635 		b_plt[i] = 0;
4636 	    }
4637 	  for (i = 0; i < max_palette; i++)
4638 	    {
4639 		r_plt[i] = red[i] * 256;
4640 		g_plt[i] = green[i] * 256;
4641 		b_plt[i] = blue[i] * 256;
4642 	    }
4643 	  rl2_free (red);
4644 	  rl2_free (green);
4645 	  rl2_free (blue);
4646 	  destination->sampleFormat = SAMPLEFORMAT_UINT;
4647 	  destination->bitsPerSample = 8;
4648 	  destination->samplesPerPixel = 1;
4649 	  destination->photometric = PHOTOMETRIC_PALETTE;
4650 	  TIFFSetField (destination->out, TIFFTAG_SAMPLEFORMAT,
4651 			SAMPLEFORMAT_UINT);
4652 	  TIFFSetField (destination->out, TIFFTAG_SAMPLESPERPIXEL, 1);
4653 	  TIFFSetField (destination->out, TIFFTAG_BITSPERSAMPLE, 8);
4654 	  TIFFSetField (destination->out, TIFFTAG_PHOTOMETRIC,
4655 			PHOTOMETRIC_PALETTE);
4656 	  TIFFSetField (destination->out, TIFFTAG_COLORMAP, r_plt, g_plt,
4657 			b_plt);
4658 	  if (tiff_compression == RL2_COMPRESSION_LZW)
4659 	    {
4660 		destination->compression = COMPRESSION_LZW;
4661 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4662 			      COMPRESSION_LZW);
4663 	    }
4664 	  else if (tiff_compression == RL2_COMPRESSION_DEFLATE)
4665 	    {
4666 		destination->compression = COMPRESSION_DEFLATE;
4667 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4668 			      COMPRESSION_DEFLATE);
4669 	    }
4670 	  else if (tiff_compression == RL2_COMPRESSION_LZMA)
4671 	    {
4672 		destination->compression = COMPRESSION_LZMA;
4673 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4674 			      COMPRESSION_LZMA);
4675 	    }
4676 	  else
4677 	    {
4678 		destination->compression = COMPRESSION_NONE;
4679 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4680 			      COMPRESSION_NONE);
4681 	    }
4682 	  goto header_done;
4683       }
4684     else if (pixel_type == RL2_PIXEL_GRAYSCALE)
4685       {
4686 	  /* GRAYSCALE */
4687 	  destination->sampleFormat = SAMPLEFORMAT_UINT;
4688 	  destination->bitsPerSample = 8;
4689 	  destination->samplesPerPixel = 1;
4690 	  destination->photometric = PHOTOMETRIC_MINISBLACK;
4691 	  TIFFSetField (destination->out, TIFFTAG_SAMPLEFORMAT,
4692 			SAMPLEFORMAT_UINT);
4693 	  TIFFSetField (destination->out, TIFFTAG_SAMPLESPERPIXEL, 1);
4694 	  TIFFSetField (destination->out, TIFFTAG_BITSPERSAMPLE, 8);
4695 	  TIFFSetField (destination->out, TIFFTAG_PHOTOMETRIC,
4696 			PHOTOMETRIC_MINISBLACK);
4697 	  if (tiff_compression == RL2_COMPRESSION_LZW)
4698 	    {
4699 		destination->compression = COMPRESSION_LZW;
4700 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4701 			      COMPRESSION_LZW);
4702 	    }
4703 	  else if (tiff_compression == RL2_COMPRESSION_DEFLATE)
4704 	    {
4705 		destination->compression = COMPRESSION_DEFLATE;
4706 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4707 			      COMPRESSION_DEFLATE);
4708 	    }
4709 	  else if (tiff_compression == RL2_COMPRESSION_LZMA)
4710 	    {
4711 		destination->compression = COMPRESSION_LZMA;
4712 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4713 			      COMPRESSION_LZMA);
4714 	    }
4715 	  else if (tiff_compression == RL2_COMPRESSION_JPEG)
4716 	    {
4717 		destination->compression = COMPRESSION_JPEG;
4718 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4719 			      COMPRESSION_JPEG);
4720 	    }
4721 	  else
4722 	    {
4723 		destination->compression = COMPRESSION_NONE;
4724 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4725 			      COMPRESSION_NONE);
4726 	    }
4727 	  goto header_done;
4728       }
4729     else if (pixel_type == RL2_PIXEL_RGB)
4730       {
4731 	  /* RGB */
4732 	  destination->sampleFormat = SAMPLEFORMAT_UINT;
4733 	  if (sample_type == RL2_SAMPLE_UINT16)
4734 	      destination->bitsPerSample = 16;
4735 	  else
4736 	      destination->bitsPerSample = 8;
4737 	  destination->samplesPerPixel = 3;
4738 	  destination->photometric = PHOTOMETRIC_RGB;
4739 	  TIFFSetField (destination->out, TIFFTAG_SAMPLEFORMAT,
4740 			SAMPLEFORMAT_UINT);
4741 	  TIFFSetField (destination->out, TIFFTAG_SAMPLESPERPIXEL, 3);
4742 	  TIFFSetField (destination->out, TIFFTAG_BITSPERSAMPLE,
4743 			destination->bitsPerSample);
4744 	  TIFFSetField (destination->out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
4745 	  if (tiff_compression == RL2_COMPRESSION_LZW)
4746 	    {
4747 		destination->compression = COMPRESSION_LZW;
4748 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4749 			      COMPRESSION_LZW);
4750 	    }
4751 	  else if (tiff_compression == RL2_COMPRESSION_DEFLATE)
4752 	    {
4753 		destination->compression = COMPRESSION_DEFLATE;
4754 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4755 			      COMPRESSION_DEFLATE);
4756 	    }
4757 	  else if (tiff_compression == RL2_COMPRESSION_LZMA)
4758 	    {
4759 		destination->compression = COMPRESSION_LZMA;
4760 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4761 			      COMPRESSION_LZMA);
4762 	    }
4763 	  else if (tiff_compression == RL2_COMPRESSION_JPEG)
4764 	    {
4765 		destination->compression = COMPRESSION_JPEG;
4766 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4767 			      COMPRESSION_JPEG);
4768 	    }
4769 	  else
4770 	    {
4771 		destination->compression = COMPRESSION_NONE;
4772 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4773 			      COMPRESSION_NONE);
4774 	    }
4775 	  goto header_done;
4776       }
4777     else if (pixel_type == RL2_PIXEL_DATAGRID)
4778       {
4779 	  /* GRID data */
4780 	  switch (sample_type)
4781 	    {
4782 	    case RL2_SAMPLE_INT8:
4783 	    case RL2_SAMPLE_INT16:
4784 	    case RL2_SAMPLE_INT32:
4785 		destination->sampleFormat = SAMPLEFORMAT_INT;
4786 		TIFFSetField (destination->out, TIFFTAG_SAMPLEFORMAT,
4787 			      SAMPLEFORMAT_INT);
4788 		break;
4789 	    case RL2_SAMPLE_UINT8:
4790 	    case RL2_SAMPLE_UINT16:
4791 	    case RL2_SAMPLE_UINT32:
4792 		destination->sampleFormat = SAMPLEFORMAT_UINT;
4793 		TIFFSetField (destination->out, TIFFTAG_SAMPLEFORMAT,
4794 			      SAMPLEFORMAT_UINT);
4795 		break;
4796 	    case RL2_SAMPLE_FLOAT:
4797 	    case RL2_SAMPLE_DOUBLE:
4798 		destination->sampleFormat = SAMPLEFORMAT_IEEEFP;
4799 		TIFFSetField (destination->out, TIFFTAG_SAMPLEFORMAT,
4800 			      SAMPLEFORMAT_IEEEFP);
4801 		break;
4802 	    };
4803 	  destination->samplesPerPixel = 1;
4804 	  TIFFSetField (destination->out, TIFFTAG_SAMPLESPERPIXEL, 1);
4805 	  switch (sample_type)
4806 	    {
4807 	    case RL2_SAMPLE_INT8:
4808 	    case RL2_SAMPLE_UINT8:
4809 		destination->bitsPerSample = 8;
4810 		TIFFSetField (destination->out, TIFFTAG_BITSPERSAMPLE, 8);
4811 		break;
4812 	    case RL2_SAMPLE_INT16:
4813 	    case RL2_SAMPLE_UINT16:
4814 		destination->bitsPerSample = 16;
4815 		TIFFSetField (destination->out, TIFFTAG_BITSPERSAMPLE, 16);
4816 		break;
4817 	    case RL2_SAMPLE_INT32:
4818 	    case RL2_SAMPLE_UINT32:
4819 		destination->bitsPerSample = 32;
4820 		TIFFSetField (destination->out, TIFFTAG_BITSPERSAMPLE, 32);
4821 		break;
4822 	    case RL2_SAMPLE_FLOAT:
4823 		destination->bitsPerSample = 32;
4824 		TIFFSetField (destination->out, TIFFTAG_BITSPERSAMPLE, 32);
4825 		break;
4826 		break;
4827 	    case RL2_SAMPLE_DOUBLE:
4828 		destination->bitsPerSample = 64;
4829 		TIFFSetField (destination->out, TIFFTAG_BITSPERSAMPLE, 64);
4830 		break;
4831 	    }
4832 	  destination->photometric = PHOTOMETRIC_MINISBLACK;
4833 	  TIFFSetField (destination->out, TIFFTAG_PHOTOMETRIC,
4834 			PHOTOMETRIC_MINISBLACK);
4835 	  if (tiff_compression == RL2_COMPRESSION_LZW)
4836 	    {
4837 		destination->compression = COMPRESSION_LZW;
4838 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4839 			      COMPRESSION_LZW);
4840 	    }
4841 	  else if (tiff_compression == RL2_COMPRESSION_DEFLATE)
4842 	    {
4843 		destination->compression = COMPRESSION_DEFLATE;
4844 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4845 			      COMPRESSION_DEFLATE);
4846 	    }
4847 	  else if (tiff_compression == RL2_COMPRESSION_LZMA)
4848 	    {
4849 		destination->compression = COMPRESSION_LZMA;
4850 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4851 			      COMPRESSION_LZMA);
4852 	    }
4853 	  else
4854 	    {
4855 		destination->compression = COMPRESSION_NONE;
4856 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4857 			      COMPRESSION_NONE);
4858 	    }
4859       }
4860     else if (pixel_type == RL2_PIXEL_MULTIBAND)
4861       {
4862 	  /* MULTIBAND */
4863 	  destination->sampleFormat = SAMPLEFORMAT_UINT;
4864 	  if (sample_type == RL2_SAMPLE_UINT8)
4865 	      destination->bitsPerSample = 8;
4866 	  else if (sample_type == RL2_SAMPLE_UINT16)
4867 	      destination->bitsPerSample = 16;
4868 	  else
4869 	      goto error;
4870 	  destination->samplesPerPixel = num_bands;
4871 	  if (num_bands == 2)
4872 	      destination->photometric = PHOTOMETRIC_MINISBLACK;
4873 	  else
4874 	      destination->photometric = PHOTOMETRIC_RGB;
4875 	  TIFFSetField (destination->out, TIFFTAG_SAMPLEFORMAT,
4876 			SAMPLEFORMAT_UINT);
4877 	  TIFFSetField (destination->out, TIFFTAG_SAMPLESPERPIXEL,
4878 			destination->samplesPerPixel);
4879 	  if (num_bands == 2)
4880 	    {
4881 		uint16 extra[1];
4882 		extra[0] = EXTRASAMPLE_UNSPECIFIED;
4883 		TIFFSetField (destination->out, TIFFTAG_EXTRASAMPLES, 1,
4884 			      &extra);
4885 	    }
4886 	  if (num_bands > 3)
4887 	    {
4888 		int n_extra = num_bands - 3;
4889 		int i_extra;
4890 		uint16 extra[256];
4891 		for (i_extra = 0; i_extra < n_extra; i_extra++)
4892 		    extra[i_extra] = EXTRASAMPLE_UNSPECIFIED;
4893 		TIFFSetField (destination->out, TIFFTAG_EXTRASAMPLES, n_extra,
4894 			      &extra);
4895 	    }
4896 	  TIFFSetField (destination->out, TIFFTAG_BITSPERSAMPLE,
4897 			destination->bitsPerSample);
4898 	  TIFFSetField (destination->out, TIFFTAG_PHOTOMETRIC,
4899 			destination->photometric);
4900 	  if (tiff_compression == RL2_COMPRESSION_LZW)
4901 	    {
4902 		destination->compression = COMPRESSION_LZW;
4903 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4904 			      COMPRESSION_LZW);
4905 	    }
4906 	  else if (tiff_compression == RL2_COMPRESSION_DEFLATE)
4907 	    {
4908 		destination->compression = COMPRESSION_DEFLATE;
4909 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4910 			      COMPRESSION_DEFLATE);
4911 	    }
4912 	  else if (tiff_compression == RL2_COMPRESSION_LZMA)
4913 	    {
4914 		destination->compression = COMPRESSION_LZMA;
4915 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4916 			      COMPRESSION_LZMA);
4917 	    }
4918 	  else
4919 	    {
4920 		destination->compression = COMPRESSION_NONE;
4921 		TIFFSetField (destination->out, TIFFTAG_COMPRESSION,
4922 			      COMPRESSION_NONE);
4923 	    }
4924 	  goto header_done;
4925       }
4926     else
4927 	goto error;
4928 
4929   header_done:
4930     TIFFSetField (destination->out, TIFFTAG_SOFTWARE, "RasterLite-2");
4931     if (destination->isTiled)
4932       {
4933 	  TIFFSetField (destination->out, TIFFTAG_TILEWIDTH,
4934 			destination->tileWidth);
4935 	  TIFFSetField (destination->out, TIFFTAG_TILELENGTH,
4936 			destination->tileHeight);
4937       }
4938     else
4939       {
4940 	  if (tiff_compression == RL2_COMPRESSION_JPEG)
4941 	      TIFFSetField (destination->out, TIFFTAG_ROWSPERSTRIP, 8);
4942 	  else
4943 	      TIFFSetField (destination->out, TIFFTAG_ROWSPERSTRIP, 1);
4944       }
4945 
4946 /* allocating the TIFF write buffer */
4947     if (destination->isTiled)
4948 	buf_size = TIFFTileSize (destination->out);
4949     else
4950 	buf_size = TIFFScanlineSize (destination->out);
4951     tiff_buffer = malloc (buf_size);
4952     if (!tiff_buffer)
4953 	goto error;
4954     destination->tiffBuffer = tiff_buffer;
4955 
4956 /* NULL georeferencing */
4957     destination->Srid = -1;
4958     destination->hResolution = DBL_MAX;
4959     destination->vResolution = DBL_MAX;
4960     destination->srsName = NULL;
4961     destination->proj4text = NULL;
4962     destination->minX = DBL_MAX;
4963     destination->minY = DBL_MAX;
4964     destination->maxX = DBL_MAX;
4965     destination->maxY = DBL_MAX;
4966     destination->tfw_path = NULL;
4967 
4968     return 1;
4969   error:
4970     return 0;
4971 }
4972 
4973 RL2_DECLARE rl2TiffDestinationPtr
rl2_create_tiff_destination(const char * path,unsigned int width,unsigned int height,unsigned char sample_type,unsigned char pixel_type,unsigned char num_bands,rl2PalettePtr plt,unsigned char tiff_compression,int tiled,unsigned int tile_size)4974 rl2_create_tiff_destination (const char *path, unsigned int width,
4975 			     unsigned int height, unsigned char sample_type,
4976 			     unsigned char pixel_type, unsigned char num_bands,
4977 			     rl2PalettePtr plt, unsigned char tiff_compression,
4978 			     int tiled, unsigned int tile_size)
4979 {
4980 /* attempting to create a file-based TIFF destination (no georeferencing) */
4981     rl2PrivTiffDestinationPtr destination = NULL;
4982     if (!check_color_model
4983 	(sample_type, pixel_type, num_bands, plt, tiff_compression))
4984       {
4985 	  fprintf (stderr, "RL2-TIFF writer: unsupported pixel format\n");
4986 	  return NULL;
4987       }
4988 
4989     destination = create_tiff_destination (path, 0);
4990     if (destination == NULL)
4991 	return NULL;
4992 
4993     destination->width = width;
4994     destination->height = height;
4995     if (tiled)
4996       {
4997 	  destination->isTiled = 1;
4998 	  destination->tileWidth = tile_size;
4999 	  destination->tileHeight = tile_size;
5000       }
5001     else
5002       {
5003 	  destination->isTiled = 0;
5004 	  destination->rowsPerStrip = 1;
5005       }
5006 
5007 /* suppressing TIFF messages */
5008     TIFFSetErrorHandler (NULL);
5009     TIFFSetWarningHandler (NULL);
5010 
5011 /* creating a TIFF file */
5012     destination->out = TIFFOpen (destination->path, "w");
5013     if (destination->out == NULL)
5014 	goto error;
5015 
5016     if (!set_tiff_destination
5017 	(destination, width, height, sample_type, pixel_type, num_bands, plt,
5018 	 tiff_compression))
5019 	goto error;
5020 
5021     return (rl2TiffDestinationPtr) destination;
5022   error:
5023     if (destination != NULL)
5024 	rl2_destroy_tiff_destination ((rl2TiffDestinationPtr) destination);
5025     return NULL;
5026 }
5027 
5028 static int
is_projected_srs(const char * proj4text)5029 is_projected_srs (const char *proj4text)
5030 {
5031 /* checks if this one is a PCS SRS */
5032     if (proj4text == NULL)
5033 	return 0;
5034     if (strstr (proj4text, "+proj=longlat ") != NULL)
5035 	return 0;
5036     return 1;
5037 }
5038 
5039 static void
fetch_crs_params(sqlite3 * handle,int srid,char ** srs_name,char ** proj4text)5040 fetch_crs_params (sqlite3 * handle, int srid, char **srs_name, char **proj4text)
5041 {
5042     int ret;
5043     char **results;
5044     int rows;
5045     int columns;
5046     int i;
5047     char *sql = sqlite3_mprintf ("SELECT ref_sys_name, proj4text "
5048 				 "FROM spatial_ref_sys WHERE srid = %d\n",
5049 				 srid);
5050     *srs_name = NULL;
5051     *proj4text = NULL;
5052     ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
5053     sqlite3_free (sql);
5054     if (ret != SQLITE_OK)
5055 	return;
5056     for (i = 1; i <= rows; i++)
5057       {
5058 	  int len;
5059 	  const char *name = results[(i * columns) + 0];
5060 	  const char *proj4 = results[(i * columns) + 1];
5061 	  if (name != NULL)
5062 	    {
5063 		len = strlen (name);
5064 		*srs_name = malloc (len + 1);
5065 		strcpy (*srs_name, name);
5066 	    }
5067 	  if (proj4 != NULL)
5068 	    {
5069 		len = strlen (proj4);
5070 		*proj4text = malloc (len + 1);
5071 		strcpy (*proj4text, proj4);
5072 	    }
5073       }
5074     sqlite3_free_table (results);
5075 }
5076 
5077 static void
destination_set_tfw_path(const char * path,rl2PrivTiffDestinationPtr destination)5078 destination_set_tfw_path (const char *path,
5079 			  rl2PrivTiffDestinationPtr destination)
5080 {
5081 /* building the TFW path (WorldFile) */
5082     char *tfw;
5083     const char *x = NULL;
5084     const char *p = path;
5085     int len = strlen (path);
5086     len -= 1;
5087     while (*p != '\0')
5088       {
5089 	  if (*p == '.')
5090 	      x = p;
5091 	  p++;
5092       }
5093     if (x > path)
5094 	len = x - path;
5095     tfw = malloc (len + 5);
5096     memcpy (tfw, path, len);
5097     memcpy (tfw + len, ".tfw", 4);
5098     *(tfw + len + 4) = '\0';
5099     destination->tfw_path = tfw;
5100 }
5101 
5102 RL2_DECLARE rl2TiffDestinationPtr
rl2_create_geotiff_destination(const char * path,sqlite3 * handle,unsigned int width,unsigned int height,unsigned char sample_type,unsigned char pixel_type,unsigned char num_bands,rl2PalettePtr plt,unsigned char tiff_compression,int tiled,unsigned int tile_size,int srid,double minX,double minY,double maxX,double maxY,double hResolution,double vResolution,int with_worldfile)5103 rl2_create_geotiff_destination (const char *path, sqlite3 * handle,
5104 				unsigned int width, unsigned int height,
5105 				unsigned char sample_type,
5106 				unsigned char pixel_type,
5107 				unsigned char num_bands, rl2PalettePtr plt,
5108 				unsigned char tiff_compression, int tiled,
5109 				unsigned int tile_size, int srid, double minX,
5110 				double minY, double maxX, double maxY,
5111 				double hResolution, double vResolution,
5112 				int with_worldfile)
5113 {
5114 /* attempting to create a file-based GeoTIFF destination */
5115     rl2PrivTiffDestinationPtr destination = NULL;
5116     double tiepoint[6];
5117     double pixsize[3];
5118     char *srs_name = NULL;
5119     char *proj4text = NULL;
5120     if (!check_color_model
5121 	(sample_type, pixel_type, num_bands, plt, tiff_compression))
5122       {
5123 	  fprintf (stderr, "RL2-GeoTIFF writer: unsupported pixel format\n");
5124 	  return NULL;
5125       }
5126     if (handle == NULL)
5127 	return NULL;
5128 
5129     destination = create_tiff_destination (path, 1);
5130     if (destination == NULL)
5131 	return NULL;
5132 
5133     destination->width = width;
5134     destination->height = height;
5135     if (tiled)
5136       {
5137 	  destination->isTiled = 1;
5138 	  destination->tileWidth = tile_size;
5139 	  destination->tileHeight = tile_size;
5140       }
5141     else
5142       {
5143 	  destination->isTiled = 0;
5144 	  destination->rowsPerStrip = 1;
5145       }
5146 
5147 /* suppressing TIFF messages */
5148     TIFFSetErrorHandler (NULL);
5149     TIFFSetWarningHandler (NULL);
5150 
5151 /* creating a GeoTIFF file */
5152     destination->out = XTIFFOpen (destination->path, "w");
5153     if (destination->out == NULL)
5154 	goto error;
5155     destination->gtif = GTIFNew (destination->out);
5156     if (destination->gtif == NULL)
5157 	goto error;
5158 
5159     if (!set_tiff_destination
5160 	(destination, width, height, sample_type, pixel_type, num_bands, plt,
5161 	 tiff_compression))
5162 	goto error;
5163 
5164 /* attempting to retrieve the CRS params */
5165     fetch_crs_params (handle, srid, &srs_name, &proj4text);
5166     if (srs_name == NULL || proj4text == NULL)
5167 	goto error;
5168 
5169 /* setting georeferencing infos */
5170     destination->Srid = srid;
5171     destination->hResolution = hResolution;
5172     destination->vResolution = vResolution;
5173     destination->srsName = srs_name;
5174     destination->proj4text = proj4text;
5175     destination->minX = minX;
5176     destination->minY = minY;
5177     destination->maxX = maxX;
5178     destination->maxY = maxY;
5179     destination->tfw_path = NULL;
5180     if (with_worldfile)
5181 	destination_set_tfw_path (path, destination);
5182 
5183 /* setting up the GeoTIFF Tags */
5184     pixsize[0] = hResolution;
5185     pixsize[1] = vResolution;
5186     pixsize[2] = 0.0;
5187     TIFFSetField (destination->out, GTIFF_PIXELSCALE, 3, pixsize);
5188     tiepoint[0] = 0.0;
5189     tiepoint[1] = 0.0;
5190     tiepoint[2] = 0.0;
5191     tiepoint[3] = minX;
5192     tiepoint[4] = maxY;
5193     tiepoint[5] = 0.0;
5194     TIFFSetField (destination->out, GTIFF_TIEPOINTS, 6, tiepoint);
5195     if (srs_name != NULL)
5196 	TIFFSetField (destination->out, GTIFF_ASCIIPARAMS, srs_name);
5197     if (proj4text != NULL)
5198 	GTIFSetFromProj4 (destination->gtif, proj4text);
5199     if (srs_name != NULL)
5200 	GTIFKeySet (destination->gtif, GTCitationGeoKey, TYPE_ASCII, 0,
5201 		    srs_name);
5202     if (is_projected_srs (proj4text))
5203 	GTIFKeySet (destination->gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
5204 		    srid);
5205     GTIFWriteKeys (destination->gtif);
5206     destination->isGeoReferenced = 1;
5207 
5208     return (rl2TiffDestinationPtr) destination;
5209   error:
5210     if (destination != NULL)
5211 	rl2_destroy_tiff_destination ((rl2TiffDestinationPtr) destination);
5212     if (srs_name != NULL)
5213 	free (srs_name);
5214     if (proj4text != NULL)
5215 	free (proj4text);
5216     return NULL;
5217 }
5218 
5219 RL2_DECLARE rl2TiffDestinationPtr
rl2_create_tiff_worldfile_destination(const char * path,unsigned int width,unsigned int height,unsigned char sample_type,unsigned char pixel_type,unsigned char num_bands,rl2PalettePtr plt,unsigned char tiff_compression,int tiled,unsigned int tile_size,int srid,double minX,double minY,double maxX,double maxY,double hResolution,double vResolution)5220 rl2_create_tiff_worldfile_destination (const char *path, unsigned int width,
5221 				       unsigned int height,
5222 				       unsigned char sample_type,
5223 				       unsigned char pixel_type,
5224 				       unsigned char num_bands,
5225 				       rl2PalettePtr plt,
5226 				       unsigned char tiff_compression,
5227 				       int tiled, unsigned int tile_size,
5228 				       int srid, double minX, double minY,
5229 				       double maxX, double maxY,
5230 				       double hResolution, double vResolution)
5231 {
5232 /* attempting to create a file-based TIFF destination (with worldfile) */
5233     rl2TiffDestinationPtr destination =
5234 	rl2_create_tiff_destination (path, width, height, sample_type,
5235 				     pixel_type, num_bands,
5236 				     plt, tiff_compression, tiled, tile_size);
5237     rl2PrivTiffDestinationPtr tiff = (rl2PrivTiffDestinationPtr) destination;
5238     if (tiff == NULL)
5239 	return NULL;
5240 /* setting georeferencing infos */
5241     tiff->Srid = srid;
5242     tiff->hResolution = hResolution;
5243     tiff->vResolution = vResolution;
5244     tiff->srsName = NULL;
5245     tiff->proj4text = NULL;
5246     tiff->minX = minX;
5247     tiff->minY = minY;
5248     tiff->maxX = maxX;
5249     tiff->maxY = maxY;
5250     tiff->tfw_path = NULL;
5251     destination_set_tfw_path (path, tiff);
5252     tiff->isGeoReferenced = 1;
5253     return destination;
5254 }
5255 
5256 RL2_DECLARE const char *
rl2_get_tiff_destination_path(rl2TiffDestinationPtr tiff)5257 rl2_get_tiff_destination_path (rl2TiffDestinationPtr tiff)
5258 {
5259 /* retrieving the output path from a TIFF destination */
5260     rl2PrivTiffDestinationPtr destination = (rl2PrivTiffDestinationPtr) tiff;
5261     if (destination == NULL)
5262 	return NULL;
5263 
5264     return destination->path;
5265 }
5266 
5267 RL2_DECLARE const char *
rl2_get_tiff_destination_worldfile_path(rl2TiffDestinationPtr tiff)5268 rl2_get_tiff_destination_worldfile_path (rl2TiffDestinationPtr tiff)
5269 {
5270 /* retrieving the Worldfile path from a TIFF destination */
5271     rl2PrivTiffDestinationPtr destination = (rl2PrivTiffDestinationPtr) tiff;
5272     if (destination == NULL)
5273 	return NULL;
5274 
5275     return destination->tfw_path;
5276 }
5277 
5278 RL2_DECLARE int
rl2_is_geotiff_destination(rl2TiffDestinationPtr tiff,int * geotiff)5279 rl2_is_geotiff_destination (rl2TiffDestinationPtr tiff, int *geotiff)
5280 {
5281 /* detecting if a TIFF destination actually is a GeoTIFF */
5282     rl2PrivTiffDestinationPtr destination = (rl2PrivTiffDestinationPtr) tiff;
5283     if (destination == NULL)
5284 	return RL2_ERROR;
5285     *geotiff = destination->isGeoTiff;
5286     return RL2_OK;
5287 }
5288 
5289 RL2_DECLARE int
rl2_is_tiff_worldfile_destination(rl2TiffDestinationPtr tiff,int * tiff_worldfile)5290 rl2_is_tiff_worldfile_destination (rl2TiffDestinationPtr tiff,
5291 				   int *tiff_worldfile)
5292 {
5293 /* detecting if a TIFF destination actually supports a TFW */
5294     rl2PrivTiffDestinationPtr destination = (rl2PrivTiffDestinationPtr) tiff;
5295     if (destination == NULL)
5296 	return RL2_ERROR;
5297     *tiff_worldfile = 0;
5298     if (destination->tfw_path != NULL)
5299 	*tiff_worldfile = 1;
5300     return RL2_OK;
5301 }
5302 
5303 RL2_DECLARE int
rl2_get_tiff_destination_size(rl2TiffDestinationPtr tiff,unsigned int * width,unsigned int * height)5304 rl2_get_tiff_destination_size (rl2TiffDestinationPtr tiff,
5305 			       unsigned int *width, unsigned int *height)
5306 {
5307 /* retrieving Width and Height from a TIFF destination */
5308     rl2PrivTiffDestinationPtr destination = (rl2PrivTiffDestinationPtr) tiff;
5309     if (destination == NULL)
5310 	return RL2_ERROR;
5311 
5312     *width = destination->width;
5313     *height = destination->height;
5314     return RL2_OK;
5315 }
5316 
5317 RL2_DECLARE int
rl2_get_tiff_destination_srid(rl2TiffDestinationPtr tiff,int * srid)5318 rl2_get_tiff_destination_srid (rl2TiffDestinationPtr tiff, int *srid)
5319 {
5320 /* retrieving the SRID from a TIFF destination */
5321     rl2PrivTiffDestinationPtr destination = (rl2PrivTiffDestinationPtr) tiff;
5322     if (destination == NULL)
5323 	return RL2_ERROR;
5324     if (destination->isGeoReferenced == 0)
5325 	return RL2_ERROR;
5326 
5327     *srid = destination->Srid;
5328     return RL2_OK;
5329 }
5330 
5331 RL2_DECLARE int
rl2_get_tiff_destination_extent(rl2TiffDestinationPtr tiff,double * minX,double * minY,double * maxX,double * maxY)5332 rl2_get_tiff_destination_extent (rl2TiffDestinationPtr tiff, double *minX,
5333 				 double *minY, double *maxX, double *maxY)
5334 {
5335 /* retrieving the Extent from a TIFF destination */
5336     rl2PrivTiffDestinationPtr destination = (rl2PrivTiffDestinationPtr) tiff;
5337     if (destination == NULL)
5338 	return RL2_ERROR;
5339     if (destination->isGeoReferenced == 0)
5340 	return RL2_ERROR;
5341 
5342     *minX = destination->minX;
5343     *minY = destination->minY;
5344     *maxX = destination->maxX;
5345     *maxY = destination->maxY;
5346     return RL2_OK;
5347 }
5348 
5349 RL2_DECLARE int
rl2_get_tiff_destination_resolution(rl2TiffDestinationPtr tiff,double * hResolution,double * vResolution)5350 rl2_get_tiff_destination_resolution (rl2TiffDestinationPtr tiff,
5351 				     double *hResolution, double *vResolution)
5352 {
5353 /* retrieving the Pixel Resolution from a TIFF destination */
5354     rl2PrivTiffDestinationPtr destination = (rl2PrivTiffDestinationPtr) tiff;
5355     if (destination == NULL)
5356 	return RL2_ERROR;
5357     if (destination->isGeoReferenced == 0)
5358 	return RL2_ERROR;
5359 
5360     *hResolution = destination->hResolution;
5361     *vResolution = destination->vResolution;
5362     return RL2_OK;
5363 }
5364 
5365 RL2_DECLARE int
rl2_get_tiff_destination_type(rl2TiffDestinationPtr tiff,unsigned char * sample_type,unsigned char * pixel_type,unsigned char * alias_pixel_type,unsigned char * num_bands)5366 rl2_get_tiff_destination_type (rl2TiffDestinationPtr tiff,
5367 			       unsigned char *sample_type,
5368 			       unsigned char *pixel_type,
5369 			       unsigned char *alias_pixel_type,
5370 			       unsigned char *num_bands)
5371 {
5372 /* retrieving the sample/pixel type from a TIFF destination */
5373     int ok = 0;
5374     rl2PrivTiffDestinationPtr destination = (rl2PrivTiffDestinationPtr) tiff;
5375     if (destination == NULL)
5376 	return RL2_ERROR;
5377 
5378     if (destination->sampleFormat == SAMPLEFORMAT_UINT
5379 	&& destination->samplesPerPixel == 1
5380 	&& destination->photometric < PHOTOMETRIC_RGB)
5381       {
5382 	  /* could be some kind of MONOCHROME */
5383 	  if (destination->bitsPerSample == 1)
5384 	    {
5385 		*sample_type = RL2_SAMPLE_1_BIT;
5386 		ok = 1;
5387 	    }
5388 	  if (ok)
5389 	    {
5390 		*pixel_type = RL2_PIXEL_MONOCHROME;
5391 		*alias_pixel_type = RL2_PIXEL_MONOCHROME;
5392 		*num_bands = 1;
5393 		return RL2_OK;
5394 	    }
5395       }
5396     if (destination->sampleFormat == SAMPLEFORMAT_UINT
5397 	&& destination->samplesPerPixel == 1
5398 	&& destination->photometric < PHOTOMETRIC_RGB)
5399       {
5400 	  /* could be some kind of GRAYSCALE */
5401 	  if (destination->bitsPerSample == 2)
5402 	    {
5403 		*sample_type = RL2_SAMPLE_2_BIT;
5404 		ok = 1;
5405 	    }
5406 	  else if (destination->bitsPerSample == 4)
5407 	    {
5408 		*sample_type = RL2_SAMPLE_4_BIT;
5409 		ok = 1;
5410 	    }
5411 	  else if (destination->bitsPerSample == 8)
5412 	    {
5413 		*sample_type = RL2_SAMPLE_UINT8;
5414 		ok = 1;
5415 	    }
5416 	  else if (destination->bitsPerSample == 16)
5417 	    {
5418 		*sample_type = RL2_SAMPLE_UINT16;
5419 		ok = 1;
5420 	    }
5421 	  if (ok)
5422 	    {
5423 		*pixel_type = RL2_PIXEL_GRAYSCALE;
5424 		*alias_pixel_type = RL2_PIXEL_GRAYSCALE;
5425 		if (destination->bitsPerSample == 8
5426 		    || destination->bitsPerSample == 16)
5427 		    *alias_pixel_type = RL2_PIXEL_DATAGRID;
5428 		*num_bands = 1;
5429 		return RL2_OK;
5430 	    }
5431       }
5432     if (destination->sampleFormat == SAMPLEFORMAT_UINT
5433 	&& destination->samplesPerPixel == 1
5434 	&& destination->photometric == PHOTOMETRIC_PALETTE)
5435       {
5436 	  /* could be some kind of PALETTE */
5437 	  if (destination->bitsPerSample == 1)
5438 	    {
5439 		*sample_type = RL2_SAMPLE_1_BIT;
5440 		ok = 1;
5441 	    }
5442 	  else if (destination->bitsPerSample == 2)
5443 	    {
5444 		*sample_type = RL2_SAMPLE_2_BIT;
5445 		ok = 1;
5446 	    }
5447 	  else if (destination->bitsPerSample == 4)
5448 	    {
5449 		*sample_type = RL2_SAMPLE_4_BIT;
5450 		ok = 1;
5451 	    }
5452 	  else if (destination->bitsPerSample == 8)
5453 	    {
5454 		*sample_type = RL2_SAMPLE_UINT8;
5455 		ok = 1;
5456 	    }
5457 	  if (ok)
5458 	    {
5459 		*pixel_type = RL2_PIXEL_PALETTE;
5460 		*alias_pixel_type = RL2_PIXEL_PALETTE;
5461 		*num_bands = 1;
5462 		return RL2_OK;
5463 	    }
5464       }
5465     if (destination->sampleFormat == SAMPLEFORMAT_UINT
5466 	&& destination->samplesPerPixel == 3
5467 	&& destination->photometric == PHOTOMETRIC_RGB)
5468       {
5469 	  /* could be some kind of RGB */
5470 	  if (destination->bitsPerSample == 8)
5471 	    {
5472 		*sample_type = RL2_SAMPLE_UINT8;
5473 		ok = 1;
5474 	    }
5475 	  else if (destination->bitsPerSample == 16)
5476 	    {
5477 		*sample_type = RL2_SAMPLE_UINT16;
5478 		ok = 1;
5479 	    }
5480 	  if (ok)
5481 	    {
5482 		*pixel_type = RL2_PIXEL_RGB;
5483 		*alias_pixel_type = RL2_PIXEL_RGB;
5484 		*num_bands = 3;
5485 		return RL2_OK;
5486 	    }
5487       }
5488     if (destination->samplesPerPixel == 1
5489 	&& destination->photometric < PHOTOMETRIC_RGB)
5490       {
5491 	  /* could be some kind of DATA-GRID */
5492 	  if (destination->sampleFormat == SAMPLEFORMAT_INT)
5493 	    {
5494 		/* Signed Integer */
5495 		if (destination->bitsPerSample == 8)
5496 		  {
5497 		      *sample_type = RL2_SAMPLE_INT8;
5498 		      ok = 1;
5499 		  }
5500 		else if (destination->bitsPerSample == 16)
5501 		  {
5502 		      *sample_type = RL2_SAMPLE_INT16;
5503 		      ok = 1;
5504 		  }
5505 		else if (destination->bitsPerSample == 32)
5506 		  {
5507 		      *sample_type = RL2_SAMPLE_INT32;
5508 		      ok = 1;
5509 		  }
5510 	    }
5511 	  if (destination->sampleFormat == SAMPLEFORMAT_UINT)
5512 	    {
5513 		/* Unsigned Integer */
5514 		if (destination->bitsPerSample == 8)
5515 		  {
5516 		      *sample_type = RL2_SAMPLE_UINT8;
5517 		      ok = 1;
5518 		  }
5519 		else if (destination->bitsPerSample == 16)
5520 		  {
5521 		      *sample_type = RL2_SAMPLE_UINT16;
5522 		      ok = 1;
5523 		  }
5524 		else if (destination->bitsPerSample == 32)
5525 		  {
5526 		      *sample_type = RL2_SAMPLE_UINT32;
5527 		      ok = 1;
5528 		  }
5529 	    }
5530 	  if (destination->sampleFormat == SAMPLEFORMAT_IEEEFP)
5531 	    {
5532 		/* Floating-Point */
5533 		if (destination->bitsPerSample == 32)
5534 		  {
5535 		      *sample_type = RL2_SAMPLE_FLOAT;
5536 		      ok = 1;
5537 		  }
5538 		else if (destination->bitsPerSample == 64)
5539 		  {
5540 		      *sample_type = RL2_SAMPLE_DOUBLE;
5541 		      ok = 1;
5542 		  }
5543 	    }
5544 	  if (ok)
5545 	    {
5546 		*pixel_type = RL2_PIXEL_DATAGRID;
5547 		*alias_pixel_type = RL2_PIXEL_DATAGRID;
5548 		*num_bands = 1;
5549 		return RL2_OK;
5550 	    }
5551       }
5552     return RL2_ERROR;
5553 }
5554 
5555 RL2_DECLARE int
rl2_get_tiff_destination_compression(rl2TiffDestinationPtr tiff,unsigned char * compression)5556 rl2_get_tiff_destination_compression (rl2TiffDestinationPtr tiff,
5557 				      unsigned char *compression)
5558 {
5559 /* retrieving the sample/pixel type from a TIFF destination */
5560     rl2PrivTiffDestinationPtr destination = (rl2PrivTiffDestinationPtr) tiff;
5561     if (destination == NULL)
5562 	return RL2_ERROR;
5563 
5564     switch (destination->compression)
5565       {
5566       case COMPRESSION_NONE:
5567 	  *compression = RL2_COMPRESSION_NONE;
5568 	  break;
5569       case COMPRESSION_LZW:
5570 	  *compression = RL2_COMPRESSION_LZW;
5571 	  break;
5572       case COMPRESSION_DEFLATE:
5573 	  *compression = RL2_COMPRESSION_DEFLATE;
5574 	  break;
5575       case COMPRESSION_LZMA:
5576 	  *compression = RL2_COMPRESSION_LZMA;
5577 	  break;
5578       case COMPRESSION_JPEG:
5579 	  *compression = RL2_COMPRESSION_JPEG;
5580 	  break;
5581       case COMPRESSION_CCITTFAX3:
5582 	  *compression = RL2_COMPRESSION_CCITTFAX3;
5583 	  break;
5584       case COMPRESSION_CCITTFAX4:
5585 	  *compression = RL2_COMPRESSION_CCITTFAX4;
5586 	  break;
5587       default:
5588 	  *compression = RL2_COMPRESSION_UNKNOWN;
5589 	  break;
5590       }
5591     return RL2_OK;
5592 }
5593 
5594 RL2_DECLARE int
rl2_is_tiled_tiff_destination(rl2TiffDestinationPtr tiff,int * is_tiled)5595 rl2_is_tiled_tiff_destination (rl2TiffDestinationPtr tiff, int *is_tiled)
5596 {
5597 /* testing if the TIFF Destination is tiled or not */
5598     rl2PrivTiffDestinationPtr destination = (rl2PrivTiffDestinationPtr) tiff;
5599     if (destination == NULL)
5600 	return RL2_ERROR;
5601     *is_tiled = destination->isTiled;
5602     return RL2_OK;
5603 }
5604 
5605 RL2_DECLARE int
rl2_get_tiff_destination_tile_size(rl2TiffDestinationPtr tiff,unsigned int * tile_width,unsigned int * tile_height)5606 rl2_get_tiff_destination_tile_size (rl2TiffDestinationPtr tiff,
5607 				    unsigned int *tile_width,
5608 				    unsigned int *tile_height)
5609 {
5610 /* attempting to return the Tile dimensions */
5611     rl2PrivTiffDestinationPtr destination = (rl2PrivTiffDestinationPtr) tiff;
5612     if (destination == NULL)
5613 	return RL2_ERROR;
5614     if (destination->isTiled == 0)
5615 	return RL2_ERROR;
5616     *tile_width = destination->tileWidth;
5617     *tile_height = destination->tileHeight;
5618     return RL2_OK;
5619 }
5620 
5621 RL2_DECLARE int
rl2_get_tiff_destination_strip_size(rl2TiffDestinationPtr tiff,unsigned int * strip_size)5622 rl2_get_tiff_destination_strip_size (rl2TiffDestinationPtr tiff,
5623 				     unsigned int *strip_size)
5624 {
5625 /* attempting to return the Strip dimension */
5626     rl2PrivTiffDestinationPtr destination = (rl2PrivTiffDestinationPtr) tiff;
5627     if (destination == NULL)
5628 	return RL2_ERROR;
5629     if (destination->isTiled != 0)
5630 	return RL2_ERROR;
5631     *strip_size = destination->rowsPerStrip;
5632     return RL2_OK;
5633 }
5634 
5635 static int
tiff_write_strip_rgb(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row)5636 tiff_write_strip_rgb (rl2PrivTiffDestinationPtr tiff, rl2PrivRasterPtr raster,
5637 		      unsigned int row)
5638 {
5639 /* writing a TIFF RGB scanline */
5640     unsigned int x;
5641     unsigned char *p_in = raster->rasterBuffer;
5642     unsigned char *p_out = tiff->tiffBuffer;
5643 
5644     for (x = 0; x < raster->width; x++)
5645       {
5646 	  *p_out++ = *p_in++;
5647 	  *p_out++ = *p_in++;
5648 	  *p_out++ = *p_in++;
5649 	  if (raster->nBands == 4)
5650 	      p_in++;
5651       }
5652     if (TIFFWriteScanline (tiff->out, tiff->tiffBuffer, row, 0) < 0)
5653 	return 0;
5654     return 1;
5655 }
5656 
5657 static int
tiff_write_strip_gray(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row)5658 tiff_write_strip_gray (rl2PrivTiffDestinationPtr tiff, rl2PrivRasterPtr raster,
5659 		       unsigned int row)
5660 {
5661 /* writing a TIFF Grayscale scanline */
5662     unsigned int x;
5663     unsigned char *p_in = raster->rasterBuffer;
5664     unsigned char *p_out = tiff->tiffBuffer;
5665 
5666     for (x = 0; x < raster->width; x++)
5667 	*p_out++ = *p_in++;
5668     if (TIFFWriteScanline (tiff->out, tiff->tiffBuffer, row, 0) < 0)
5669 	return 0;
5670     return 1;
5671 }
5672 
5673 static int
tiff_write_strip_palette(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row)5674 tiff_write_strip_palette (rl2PrivTiffDestinationPtr tiff,
5675 			  rl2PrivRasterPtr raster, unsigned int row)
5676 {
5677 /* writing a TIFF Palette scanline */
5678     unsigned int x;
5679     unsigned char *p_in = raster->rasterBuffer;
5680     unsigned char *p_out = tiff->tiffBuffer;
5681 
5682     for (x = 0; x < raster->width; x++)
5683 	*p_out++ = *p_in++;
5684     if (TIFFWriteScanline (tiff->out, tiff->tiffBuffer, row, 0) < 0)
5685 	return 0;
5686     return 1;
5687 }
5688 
5689 static int
tiff_write_strip_monochrome(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row)5690 tiff_write_strip_monochrome (rl2PrivTiffDestinationPtr tiff,
5691 			     rl2PrivRasterPtr raster, unsigned int row)
5692 {
5693 /* writing a TIFF Monochrome */
5694     unsigned int x;
5695     unsigned char byte;
5696     unsigned char pixel;
5697     int pos;
5698     unsigned char *p_in = raster->rasterBuffer;
5699     unsigned char *p_out = tiff->tiffBuffer;
5700 
5701 /* priming a White scanline */
5702     for (x = 0; x < TIFFScanlineSize (tiff->out); x++)
5703 	*p_out++ = 0x00;
5704 
5705 /* inserting pixels */
5706     pos = 0;
5707     byte = 0x00;
5708     p_out = tiff->tiffBuffer;
5709     for (x = 0; x < raster->width; x++)
5710       {
5711 	  pixel = *p_in++;
5712 	  if (pixel == 1)
5713 	    {
5714 		/* handling a black pixel */
5715 		switch (pos)
5716 		  {
5717 		  case 0:
5718 		      byte |= 0x80;
5719 		      break;
5720 		  case 1:
5721 		      byte |= 0x40;
5722 		      break;
5723 		  case 2:
5724 		      byte |= 0x20;
5725 		      break;
5726 		  case 3:
5727 		      byte |= 0x10;
5728 		      break;
5729 		  case 4:
5730 		      byte |= 0x08;
5731 		      break;
5732 		  case 5:
5733 		      byte |= 0x04;
5734 		      break;
5735 		  case 6:
5736 		      byte |= 0x02;
5737 		      break;
5738 		  case 7:
5739 		      byte |= 0x01;
5740 		      break;
5741 		  };
5742 	    }
5743 	  pos++;
5744 	  if (pos > 7)
5745 	    {
5746 		/* exporting an octet */
5747 		*p_out++ = byte;
5748 		byte = 0x00;
5749 		pos = 0;
5750 	    }
5751       }
5752     if (TIFFWriteScanline (tiff->out, tiff->tiffBuffer, row, 0) < 0)
5753 	return 0;
5754     return 1;
5755 }
5756 
5757 static int
tiff_write_strip_int8(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row)5758 tiff_write_strip_int8 (rl2PrivTiffDestinationPtr tiff,
5759 		       rl2PrivRasterPtr raster, unsigned int row)
5760 {
5761 /* writing a TIFF Grid Int8 scanline */
5762     unsigned int x;
5763     char *p_in = (char *) (raster->rasterBuffer);
5764     char *p_out = (char *) (tiff->tiffBuffer);
5765 
5766     for (x = 0; x < raster->width; x++)
5767 	*p_out++ = *p_in++;
5768     if (TIFFWriteScanline (tiff->out, tiff->tiffBuffer, row, 0) < 0)
5769 	return 0;
5770     return 1;
5771 }
5772 
5773 static int
tiff_write_strip_uint8(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row)5774 tiff_write_strip_uint8 (rl2PrivTiffDestinationPtr tiff,
5775 			rl2PrivRasterPtr raster, unsigned int row)
5776 {
5777 /* writing a TIFF Grid UInt8 scanline */
5778     unsigned int x;
5779     unsigned char *p_in = raster->rasterBuffer;
5780     unsigned char *p_out = tiff->tiffBuffer;
5781 
5782     for (x = 0; x < raster->width; x++)
5783 	*p_out++ = *p_in++;
5784     if (TIFFWriteScanline (tiff->out, tiff->tiffBuffer, row, 0) < 0)
5785 	return 0;
5786     return 1;
5787 }
5788 
5789 static int
tiff_write_strip_int16(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row)5790 tiff_write_strip_int16 (rl2PrivTiffDestinationPtr tiff,
5791 			rl2PrivRasterPtr raster, unsigned int row)
5792 {
5793 /* writing a TIFF Grid Int16 scanline */
5794     unsigned int x;
5795     short *p_in = (short *) (raster->rasterBuffer);
5796     short *p_out = (short *) (tiff->tiffBuffer);
5797 
5798     for (x = 0; x < raster->width; x++)
5799 	*p_out++ = *p_in++;
5800     if (TIFFWriteScanline (tiff->out, tiff->tiffBuffer, row, 0) < 0)
5801 	return 0;
5802     return 1;
5803 }
5804 
5805 static int
tiff_write_strip_uint16(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row)5806 tiff_write_strip_uint16 (rl2PrivTiffDestinationPtr tiff,
5807 			 rl2PrivRasterPtr raster, unsigned int row)
5808 {
5809 /* writing a TIFF Grid UInt16 scanline */
5810     unsigned int x;
5811     unsigned short *p_in = (unsigned short *) (raster->rasterBuffer);
5812     unsigned short *p_out = (unsigned short *) (tiff->tiffBuffer);
5813 
5814     for (x = 0; x < raster->width; x++)
5815 	*p_out++ = *p_in++;
5816     if (TIFFWriteScanline (tiff->out, tiff->tiffBuffer, row, 0) < 0)
5817 	return 0;
5818     return 1;
5819 }
5820 
5821 static int
tiff_write_strip_int32(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row)5822 tiff_write_strip_int32 (rl2PrivTiffDestinationPtr tiff,
5823 			rl2PrivRasterPtr raster, unsigned int row)
5824 {
5825 /* writing a TIFF Grid Int32 scanline */
5826     unsigned int x;
5827     int *p_in = (int *) (raster->rasterBuffer);
5828     int *p_out = (int *) (tiff->tiffBuffer);
5829 
5830     for (x = 0; x < raster->width; x++)
5831 	*p_out++ = *p_in++;
5832     if (TIFFWriteScanline (tiff->out, tiff->tiffBuffer, row, 0) < 0)
5833 	return 0;
5834     return 1;
5835 }
5836 
5837 static int
tiff_write_strip_uint32(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row)5838 tiff_write_strip_uint32 (rl2PrivTiffDestinationPtr tiff,
5839 			 rl2PrivRasterPtr raster, unsigned int row)
5840 {
5841 /* writing a TIFF Grid UInt32 scanline */
5842     unsigned int x;
5843     unsigned int *p_in = (unsigned int *) (raster->rasterBuffer);
5844     unsigned int *p_out = (unsigned int *) (tiff->tiffBuffer);
5845 
5846     for (x = 0; x < raster->width; x++)
5847 	*p_out++ = *p_in++;
5848     if (TIFFWriteScanline (tiff->out, tiff->tiffBuffer, row, 0) < 0)
5849 	return 0;
5850     return 1;
5851 }
5852 
5853 static int
tiff_write_strip_float(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row)5854 tiff_write_strip_float (rl2PrivTiffDestinationPtr tiff,
5855 			rl2PrivRasterPtr raster, unsigned int row)
5856 {
5857 /* writing a TIFF Grid Float scanline */
5858     unsigned int x;
5859     float *p_in = (float *) (raster->rasterBuffer);
5860     float *p_out = (float *) (tiff->tiffBuffer);
5861 
5862     for (x = 0; x < raster->width; x++)
5863 	*p_out++ = *p_in++;
5864     if (TIFFWriteScanline (tiff->out, tiff->tiffBuffer, row, 0) < 0)
5865 	return 0;
5866     return 1;
5867 }
5868 
5869 static int
tiff_write_strip_double(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row)5870 tiff_write_strip_double (rl2PrivTiffDestinationPtr tiff,
5871 			 rl2PrivRasterPtr raster, unsigned int row)
5872 {
5873 /* writing a TIFF Grid Double scanline */
5874     unsigned int x;
5875     double *p_in = (double *) (raster->rasterBuffer);
5876     double *p_out = (double *) (tiff->tiffBuffer);
5877 
5878     for (x = 0; x < raster->width; x++)
5879 	*p_out++ = *p_in++;
5880     if (TIFFWriteScanline (tiff->out, tiff->tiffBuffer, row, 0) < 0)
5881 	return 0;
5882     return 1;
5883 }
5884 
5885 RL2_DECLARE int
rl2_write_tiff_scanline(rl2TiffDestinationPtr tiff,rl2RasterPtr raster,unsigned int row)5886 rl2_write_tiff_scanline (rl2TiffDestinationPtr tiff, rl2RasterPtr raster,
5887 			 unsigned int row)
5888 {
5889 /* writing a TIFF scanline */
5890     int ret = 0;
5891     rl2PrivTiffDestinationPtr destination = (rl2PrivTiffDestinationPtr) tiff;
5892     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) raster;
5893     if (tiff == NULL)
5894 	return RL2_ERROR;
5895     if (rst == NULL)
5896 	return RL2_ERROR;
5897 
5898     if (destination->sampleFormat == SAMPLEFORMAT_UINT
5899 	&& destination->samplesPerPixel == 3 && destination->photometric == 2
5900 	&& destination->bitsPerSample == 8
5901 	&& rst->sampleType == RL2_SAMPLE_UINT8
5902 	&& rst->pixelType == RL2_PIXEL_RGB && (rst->nBands == 3
5903 					       || rst->nBands == 4)
5904 	&& destination->width == rst->width)
5905 	ret = tiff_write_strip_rgb (destination, rst, row);
5906     else if (destination->sampleFormat == SAMPLEFORMAT_UINT
5907 	     && destination->samplesPerPixel == 1
5908 	     && destination->photometric < 2
5909 	     && destination->bitsPerSample == 8
5910 	     && rst->sampleType == RL2_SAMPLE_UINT8
5911 	     && rst->pixelType == RL2_PIXEL_GRAYSCALE && rst->nBands == 1
5912 	     && destination->width == rst->width)
5913 	ret = tiff_write_strip_gray (destination, rst, row);
5914     else if (destination->sampleFormat == SAMPLEFORMAT_UINT
5915 	     && destination->samplesPerPixel == 1
5916 	     && destination->photometric == 3
5917 	     && destination->bitsPerSample == 8
5918 	     && rst->sampleType == RL2_SAMPLE_UINT8
5919 	     && rst->pixelType == RL2_PIXEL_PALETTE && rst->nBands == 1
5920 	     && destination->width == rst->width)
5921 	ret = tiff_write_strip_palette (destination, rst, row);
5922     else if (destination->sampleFormat == SAMPLEFORMAT_UINT
5923 	     && destination->samplesPerPixel == 1
5924 	     && destination->photometric < 2
5925 	     && destination->bitsPerSample == 1
5926 	     && rst->sampleType == RL2_SAMPLE_1_BIT
5927 	     && rst->pixelType == RL2_PIXEL_MONOCHROME && rst->nBands == 1
5928 	     && destination->width == rst->width)
5929 	ret = tiff_write_strip_monochrome (destination, rst, row);
5930     else if (destination->sampleFormat == SAMPLEFORMAT_INT
5931 	     && destination->samplesPerPixel == 1
5932 	     && destination->photometric < 2
5933 	     && destination->bitsPerSample == 8
5934 	     && rst->sampleType == RL2_SAMPLE_INT8
5935 	     && rst->pixelType == RL2_PIXEL_DATAGRID && rst->nBands == 1
5936 	     && destination->width == rst->width)
5937 	ret = tiff_write_strip_int8 (destination, rst, row);
5938     else if (destination->sampleFormat == SAMPLEFORMAT_UINT
5939 	     && destination->samplesPerPixel == 1
5940 	     && destination->photometric < 2
5941 	     && destination->bitsPerSample == 8
5942 	     && rst->sampleType == RL2_SAMPLE_UINT8
5943 	     && rst->pixelType == RL2_PIXEL_DATAGRID && rst->nBands == 1
5944 	     && destination->width == rst->width)
5945 	ret = tiff_write_strip_uint8 (destination, rst, row);
5946     else if (destination->sampleFormat == SAMPLEFORMAT_INT
5947 	     && destination->samplesPerPixel == 1
5948 	     && destination->photometric < 2
5949 	     && destination->bitsPerSample == 16
5950 	     && rst->sampleType == RL2_SAMPLE_INT16
5951 	     && rst->pixelType == RL2_PIXEL_DATAGRID && rst->nBands == 1
5952 	     && destination->width == rst->width)
5953 	ret = tiff_write_strip_int16 (destination, rst, row);
5954     else if (destination->sampleFormat == SAMPLEFORMAT_UINT
5955 	     && destination->samplesPerPixel == 1
5956 	     && destination->photometric < 2
5957 	     && destination->bitsPerSample == 16
5958 	     && rst->sampleType == RL2_SAMPLE_UINT16
5959 	     && rst->pixelType == RL2_PIXEL_DATAGRID && rst->nBands == 1
5960 	     && destination->width == rst->width)
5961 	ret = tiff_write_strip_uint16 (destination, rst, row);
5962     else if (destination->sampleFormat == SAMPLEFORMAT_INT
5963 	     && destination->samplesPerPixel == 1
5964 	     && destination->photometric < 2
5965 	     && destination->bitsPerSample == 32
5966 	     && rst->sampleType == RL2_SAMPLE_INT32
5967 	     && rst->pixelType == RL2_PIXEL_DATAGRID && rst->nBands == 1
5968 	     && destination->width == rst->width)
5969 	ret = tiff_write_strip_int32 (destination, rst, row);
5970     else if (destination->sampleFormat == SAMPLEFORMAT_UINT
5971 	     && destination->samplesPerPixel == 1
5972 	     && destination->photometric < 2
5973 	     && destination->bitsPerSample == 32
5974 	     && rst->sampleType == RL2_SAMPLE_UINT32
5975 	     && rst->pixelType == RL2_PIXEL_DATAGRID && rst->nBands == 1
5976 	     && destination->width == rst->width)
5977 	ret = tiff_write_strip_uint32 (destination, rst, row);
5978     else if (destination->sampleFormat == SAMPLEFORMAT_IEEEFP
5979 	     && destination->samplesPerPixel == 1
5980 	     && destination->photometric < 2
5981 	     && destination->bitsPerSample == 32
5982 	     && rst->sampleType == RL2_SAMPLE_FLOAT
5983 	     && rst->pixelType == RL2_PIXEL_DATAGRID && rst->nBands == 1
5984 	     && destination->width == rst->width)
5985 	ret = tiff_write_strip_float (destination, rst, row);
5986     else if (destination->sampleFormat == SAMPLEFORMAT_IEEEFP
5987 	     && destination->samplesPerPixel == 1
5988 	     && destination->photometric < 2
5989 	     && destination->bitsPerSample == 64
5990 	     && rst->sampleType == RL2_SAMPLE_DOUBLE
5991 	     && rst->pixelType == RL2_PIXEL_DATAGRID && rst->nBands == 1
5992 	     && destination->width == rst->width)
5993 	ret = tiff_write_strip_double (destination, rst, row);
5994 
5995     if (ret)
5996 	return RL2_OK;
5997     return RL2_ERROR;
5998 }
5999 
6000 static int
tiff_write_tile_multiband8(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row,unsigned int col)6001 tiff_write_tile_multiband8 (rl2PrivTiffDestinationPtr tiff,
6002 			    rl2PrivRasterPtr raster, unsigned int row,
6003 			    unsigned int col)
6004 {
6005 /* writing a TIFF MULTIBAND UINT8 tile - separate planes */
6006     unsigned int y;
6007     unsigned int x;
6008     int band;
6009 
6010     for (band = 0; band < raster->nBands; band++)
6011       {
6012 	  /* handling separate planes - one for each band */
6013 	  unsigned char *p_in = raster->rasterBuffer;
6014 	  unsigned char *p_out = tiff->tiffBuffer;
6015 	  for (y = 0; y < raster->height; y++)
6016 	    {
6017 		for (x = 0; x < raster->width; x++)
6018 		  {
6019 		      *p_out++ = *(p_in + band);
6020 		      p_in += raster->nBands;
6021 		  }
6022 	    }
6023 	  if (TIFFWriteTile (tiff->out, tiff->tiffBuffer, col, row, 0, band) <
6024 	      0)
6025 	      return 0;
6026       }
6027     return 1;
6028 }
6029 
6030 static int
tiff_write_tile_multiband16(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row,unsigned int col)6031 tiff_write_tile_multiband16 (rl2PrivTiffDestinationPtr tiff,
6032 			     rl2PrivRasterPtr raster, unsigned int row,
6033 			     unsigned int col)
6034 {
6035 /* writing a TIFF MULTIBAND UINT16 tile - separate planes */
6036     unsigned int y;
6037     unsigned int x;
6038     int band;
6039 
6040     for (band = 0; band < raster->nBands; band++)
6041       {
6042 	  /* handling separate planes - one for each band */
6043 	  unsigned short *p_in = (unsigned short *) (raster->rasterBuffer);
6044 	  unsigned short *p_out = (unsigned short *) (tiff->tiffBuffer);
6045 	  for (y = 0; y < raster->height; y++)
6046 	    {
6047 		for (x = 0; x < raster->width; x++)
6048 		  {
6049 		      *p_out++ = *(p_in + band);
6050 		      p_in += raster->nBands;
6051 		  }
6052 	    }
6053 	  if (TIFFWriteTile (tiff->out, tiff->tiffBuffer, col, row, 0, band) <
6054 	      0)
6055 	      return 0;
6056       }
6057     return 1;
6058 }
6059 
6060 static int
tiff_write_tile_rgb_u8(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row,unsigned int col)6061 tiff_write_tile_rgb_u8 (rl2PrivTiffDestinationPtr tiff, rl2PrivRasterPtr raster,
6062 			unsigned int row, unsigned int col)
6063 {
6064 /* writing a TIFF RGB tile - UINT8 */
6065     unsigned int y;
6066     unsigned int x;
6067     unsigned char *p_in = raster->rasterBuffer;
6068     unsigned char *p_out = tiff->tiffBuffer;
6069 
6070     for (y = 0; y < raster->height; y++)
6071       {
6072 	  for (x = 0; x < raster->width; x++)
6073 	    {
6074 		*p_out++ = *p_in++;
6075 		*p_out++ = *p_in++;
6076 		*p_out++ = *p_in++;
6077 		if (raster->nBands == 4)
6078 		    p_in++;
6079 	    }
6080       }
6081     if (TIFFWriteTile (tiff->out, tiff->tiffBuffer, col, row, 0, 0) < 0)
6082 	return 0;
6083     return 1;
6084 }
6085 
6086 static int
tiff_write_tile_gray(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row,unsigned int col)6087 tiff_write_tile_gray (rl2PrivTiffDestinationPtr tiff, rl2PrivRasterPtr raster,
6088 		      unsigned int row, unsigned int col)
6089 {
6090 /* writing a TIFF Grayscale tile */
6091     unsigned int y;
6092     unsigned int x;
6093     unsigned char *p_in = raster->rasterBuffer;
6094     unsigned char *p_msk = raster->maskBuffer;
6095     unsigned char *p_out = tiff->tiffBuffer;
6096 
6097     for (y = 0; y < raster->height; y++)
6098       {
6099 	  for (x = 0; x < raster->width; x++)
6100 	    {
6101 		if (p_msk == NULL)
6102 		  {
6103 		      /* there is no Transparency Mask - all opaque pixels */
6104 		      *p_out++ = *p_in++;
6105 		  }
6106 		else
6107 		  {
6108 		      if (*p_msk++ == 0)
6109 			{
6110 			    /* transparent pixel */
6111 			    p_out++;
6112 			}
6113 		      else
6114 			  *p_out++ = *p_in++;
6115 		  }
6116 	    }
6117       }
6118     if (TIFFWriteTile (tiff->out, tiff->tiffBuffer, col, row, 0, 0) < 0)
6119 	return 0;
6120     return 1;
6121 }
6122 
6123 static int
tiff_write_tile_palette(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row,unsigned int col)6124 tiff_write_tile_palette (rl2PrivTiffDestinationPtr tiff,
6125 			 rl2PrivRasterPtr raster, unsigned int row,
6126 			 unsigned int col)
6127 {
6128 /* writing a TIFF Palette tile */
6129     unsigned int y;
6130     unsigned int x;
6131     unsigned char *p_in = raster->rasterBuffer;
6132     unsigned char *p_out = tiff->tiffBuffer;
6133 
6134     for (y = 0; y < raster->height; y++)
6135       {
6136 	  for (x = 0; x < raster->width; x++)
6137 	      *p_out++ = *p_in++;
6138       }
6139     if (TIFFWriteTile (tiff->out, tiff->tiffBuffer, col, row, 0, 0) < 0)
6140 	return 0;
6141     return 1;
6142 }
6143 
6144 static int
tiff_write_tile_monochrome(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row,unsigned int col)6145 tiff_write_tile_monochrome (rl2PrivTiffDestinationPtr tiff,
6146 			    rl2PrivRasterPtr raster, unsigned int row,
6147 			    unsigned int col)
6148 {
6149 /* writing a TIFF Monochrome tile */
6150     unsigned int y;
6151     unsigned int x;
6152     unsigned char byte;
6153     unsigned char pixel;
6154     int pos;
6155     unsigned char *p_in = raster->rasterBuffer;
6156     unsigned char *p_out = tiff->tiffBuffer;
6157 
6158     /* priming a White tile */
6159     for (x = 0; x < TIFFTileSize (tiff->out); x++)
6160 	*p_out++ = 0x00;
6161     p_out = tiff->tiffBuffer;
6162     for (y = 0; y < raster->height; y++)
6163       {
6164 	  /* inserting pixels */
6165 	  pos = 0;
6166 	  byte = 0x00;
6167 	  for (x = 0; x < raster->width; x++)
6168 	    {
6169 		pixel = *p_in++;
6170 		if (pixel == 1)
6171 		  {
6172 		      /* handling a black pixel */
6173 		      switch (pos)
6174 			{
6175 			case 0:
6176 			    byte |= 0x80;
6177 			    break;
6178 			case 1:
6179 			    byte |= 0x40;
6180 			    break;
6181 			case 2:
6182 			    byte |= 0x20;
6183 			    break;
6184 			case 3:
6185 			    byte |= 0x10;
6186 			    break;
6187 			case 4:
6188 			    byte |= 0x08;
6189 			    break;
6190 			case 5:
6191 			    byte |= 0x04;
6192 			    break;
6193 			case 6:
6194 			    byte |= 0x02;
6195 			    break;
6196 			case 7:
6197 			    byte |= 0x01;
6198 			    break;
6199 			};
6200 		  }
6201 		pos++;
6202 		if (pos > 7)
6203 		  {
6204 		      /* exporting an octet */
6205 		      *p_out++ = byte;
6206 		      byte = 0x00;
6207 		      pos = 0;
6208 		  }
6209 	    }
6210       }
6211     if (TIFFWriteTile (tiff->out, tiff->tiffBuffer, col, row, 0, 0) < 0)
6212 	return 0;
6213     return 1;
6214 }
6215 
6216 static int
tiff_write_tile_int8(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row,unsigned int col)6217 tiff_write_tile_int8 (rl2PrivTiffDestinationPtr tiff,
6218 		      rl2PrivRasterPtr raster, unsigned int row,
6219 		      unsigned int col)
6220 {
6221 /* writing a TIFF Grid Int8 tile */
6222     unsigned int y;
6223     unsigned int x;
6224     char *p_in = (char *) (raster->rasterBuffer);
6225     char *p_out = (char *) (tiff->tiffBuffer);
6226 
6227     for (y = 0; y < raster->height; y++)
6228       {
6229 	  for (x = 0; x < raster->width; x++)
6230 	      *p_out++ = *p_in++;
6231       }
6232     if (TIFFWriteTile (tiff->out, tiff->tiffBuffer, col, row, 0, 0) < 0)
6233 	return 0;
6234     return 1;
6235 }
6236 
6237 static int
tiff_write_tile_uint8(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row,unsigned int col)6238 tiff_write_tile_uint8 (rl2PrivTiffDestinationPtr tiff,
6239 		       rl2PrivRasterPtr raster, unsigned int row,
6240 		       unsigned int col)
6241 {
6242 /* writing a TIFF Grid UInt8 tile */
6243     unsigned int y;
6244     unsigned int x;
6245     unsigned char *p_in = raster->rasterBuffer;
6246     unsigned char *p_out = tiff->tiffBuffer;
6247 
6248     for (y = 0; y < raster->height; y++)
6249       {
6250 	  for (x = 0; x < raster->width; x++)
6251 	      *p_out++ = *p_in++;
6252       }
6253     if (TIFFWriteTile (tiff->out, tiff->tiffBuffer, col, row, 0, 0) < 0)
6254 	return 0;
6255     return 1;
6256 }
6257 
6258 static int
tiff_write_tile_int16(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row,unsigned int col)6259 tiff_write_tile_int16 (rl2PrivTiffDestinationPtr tiff,
6260 		       rl2PrivRasterPtr raster, unsigned int row,
6261 		       unsigned int col)
6262 {
6263 /* writing a TIFF Grid Int16 tile */
6264     unsigned int y;
6265     unsigned int x;
6266     short *p_in = (short *) (raster->rasterBuffer);
6267     short *p_out = (short *) (tiff->tiffBuffer);
6268 
6269     for (y = 0; y < raster->height; y++)
6270       {
6271 	  for (x = 0; x < raster->width; x++)
6272 	      *p_out++ = *p_in++;
6273       }
6274     if (TIFFWriteTile (tiff->out, tiff->tiffBuffer, col, row, 0, 0) < 0)
6275 	return 0;
6276     return 1;
6277 }
6278 
6279 static int
tiff_write_tile_uint16(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row,unsigned int col)6280 tiff_write_tile_uint16 (rl2PrivTiffDestinationPtr tiff,
6281 			rl2PrivRasterPtr raster, unsigned int row,
6282 			unsigned int col)
6283 {
6284 /* writing a TIFF Grid UInt16 tile */
6285     unsigned int y;
6286     unsigned int x;
6287     unsigned short *p_in = (unsigned short *) (raster->rasterBuffer);
6288     unsigned short *p_out = (unsigned short *) (tiff->tiffBuffer);
6289 
6290     for (y = 0; y < raster->height; y++)
6291       {
6292 	  for (x = 0; x < raster->width; x++)
6293 	      *p_out++ = *p_in++;
6294       }
6295     if (TIFFWriteTile (tiff->out, tiff->tiffBuffer, col, row, 0, 0) < 0)
6296 	return 0;
6297     return 1;
6298 }
6299 
6300 static int
tiff_write_tile_int32(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row,unsigned int col)6301 tiff_write_tile_int32 (rl2PrivTiffDestinationPtr tiff,
6302 		       rl2PrivRasterPtr raster, unsigned int row,
6303 		       unsigned int col)
6304 {
6305 /* writing a TIFF Grid Int32 tile */
6306     unsigned int y;
6307     unsigned int x;
6308     int *p_in = (int *) (raster->rasterBuffer);
6309     int *p_out = (int *) (tiff->tiffBuffer);
6310 
6311     for (y = 0; y < raster->height; y++)
6312       {
6313 	  for (x = 0; x < raster->width; x++)
6314 	      *p_out++ = *p_in++;
6315       }
6316     if (TIFFWriteTile (tiff->out, tiff->tiffBuffer, col, row, 0, 0) < 0)
6317 	return 0;
6318     return 1;
6319 }
6320 
6321 static int
tiff_write_tile_uint32(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row,unsigned int col)6322 tiff_write_tile_uint32 (rl2PrivTiffDestinationPtr tiff,
6323 			rl2PrivRasterPtr raster, unsigned int row,
6324 			unsigned int col)
6325 {
6326 /* writing a TIFF Grid UInt32 tile */
6327     unsigned int y;
6328     unsigned int x;
6329     unsigned int *p_in = (unsigned int *) (raster->rasterBuffer);
6330     unsigned int *p_out = (unsigned int *) (tiff->tiffBuffer);
6331 
6332     for (y = 0; y < raster->height; y++)
6333       {
6334 	  for (x = 0; x < raster->width; x++)
6335 	      *p_out++ = *p_in++;
6336       }
6337     if (TIFFWriteTile (tiff->out, tiff->tiffBuffer, col, row, 0, 0) < 0)
6338 	return 0;
6339     return 1;
6340 }
6341 
6342 static int
tiff_write_tile_float(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row,unsigned int col)6343 tiff_write_tile_float (rl2PrivTiffDestinationPtr tiff,
6344 		       rl2PrivRasterPtr raster, unsigned int row,
6345 		       unsigned int col)
6346 {
6347 /* writing a TIFF Grid Float tile */
6348     unsigned int y;
6349     unsigned int x;
6350     float *p_in = (float *) (raster->rasterBuffer);
6351     float *p_out = (float *) (tiff->tiffBuffer);
6352 
6353     for (y = 0; y < raster->height; y++)
6354       {
6355 	  for (x = 0; x < raster->width; x++)
6356 	      *p_out++ = *p_in++;
6357       }
6358     if (TIFFWriteTile (tiff->out, tiff->tiffBuffer, col, row, 0, 0) < 0)
6359 	return 0;
6360     return 1;
6361 }
6362 
6363 static int
tiff_write_tile_double(rl2PrivTiffDestinationPtr tiff,rl2PrivRasterPtr raster,unsigned int row,unsigned int col)6364 tiff_write_tile_double (rl2PrivTiffDestinationPtr tiff,
6365 			rl2PrivRasterPtr raster, unsigned int row,
6366 			unsigned int col)
6367 {
6368 /* writing a TIFF Grid Double tile */
6369     unsigned int y;
6370     unsigned int x;
6371     double *p_in = (double *) (raster->rasterBuffer);
6372     double *p_out = (double *) (tiff->tiffBuffer);
6373 
6374     for (y = 0; y < raster->height; y++)
6375       {
6376 	  for (x = 0; x < raster->width; x++)
6377 	      *p_out++ = *p_in++;
6378       }
6379     if (TIFFWriteTile (tiff->out, tiff->tiffBuffer, col, row, 0, 0) < 0)
6380 	return 0;
6381     return 1;
6382 }
6383 
6384 RL2_DECLARE int
rl2_write_tiff_tile(rl2TiffDestinationPtr tiff,rl2RasterPtr raster,unsigned int startRow,unsigned int startCol)6385 rl2_write_tiff_tile (rl2TiffDestinationPtr tiff, rl2RasterPtr raster,
6386 		     unsigned int startRow, unsigned int startCol)
6387 {
6388 /* writing a TIFF tile */
6389     int ret = 0;
6390     rl2PrivTiffDestinationPtr destination = (rl2PrivTiffDestinationPtr) tiff;
6391     rl2PrivRasterPtr rst = (rl2PrivRasterPtr) raster;
6392     if (tiff == NULL)
6393 	return RL2_ERROR;
6394     if (rst == NULL)
6395 	return RL2_ERROR;
6396 
6397     if (destination->sampleFormat == SAMPLEFORMAT_UINT
6398 	&& destination->samplesPerPixel == 3 && destination->photometric == 2
6399 	&& destination->bitsPerSample == 8
6400 	&& rst->sampleType == RL2_SAMPLE_UINT8
6401 	&& rst->pixelType == RL2_PIXEL_RGB && (rst->nBands == 3
6402 					       || rst->nBands == 4)
6403 	&& destination->tileWidth == rst->width
6404 	&& destination->tileHeight == rst->height)
6405 	ret = tiff_write_tile_rgb_u8 (destination, rst, startRow, startCol);
6406     else if (destination->sampleFormat == SAMPLEFORMAT_UINT
6407 	     && destination->samplesPerPixel == 3
6408 	     && destination->photometric == 2
6409 	     && destination->bitsPerSample == 16
6410 	     && rst->sampleType == RL2_SAMPLE_UINT16
6411 	     && rst->pixelType == RL2_PIXEL_RGB && rst->nBands == 3
6412 	     && destination->tileWidth == rst->width
6413 	     && destination->tileHeight == rst->height)
6414 	ret =
6415 	    tiff_write_tile_multiband16 (destination, rst, startRow, startCol);
6416     else if (destination->sampleFormat == SAMPLEFORMAT_UINT
6417 	     && destination->samplesPerPixel >= 2
6418 	     && destination->bitsPerSample == 8
6419 	     && rst->sampleType == RL2_SAMPLE_UINT8
6420 	     && rst->pixelType == RL2_PIXEL_MULTIBAND
6421 	     && rst->nBands == destination->samplesPerPixel
6422 	     && destination->tileWidth == rst->width
6423 	     && destination->tileHeight == rst->height)
6424 	ret = tiff_write_tile_multiband8 (destination, rst, startRow, startCol);
6425     else if (destination->sampleFormat == SAMPLEFORMAT_UINT
6426 	     && destination->samplesPerPixel >= 2
6427 	     && destination->bitsPerSample == 16
6428 	     && rst->sampleType == RL2_SAMPLE_UINT16
6429 	     && rst->pixelType == RL2_PIXEL_MULTIBAND
6430 	     && rst->nBands == destination->samplesPerPixel
6431 	     && destination->tileWidth == rst->width
6432 	     && destination->tileHeight == rst->height)
6433 	ret =
6434 	    tiff_write_tile_multiband16 (destination, rst, startRow, startCol);
6435     else if (destination->sampleFormat == SAMPLEFORMAT_UINT
6436 	     && destination->samplesPerPixel == 1
6437 	     && destination->photometric < 2 && destination->bitsPerSample == 8
6438 	     && rst->sampleType == RL2_SAMPLE_UINT8
6439 	     && rst->pixelType == RL2_PIXEL_GRAYSCALE && rst->nBands == 1
6440 	     && destination->tileWidth == rst->width
6441 	     && destination->tileHeight == rst->height)
6442 	ret = tiff_write_tile_gray (destination, rst, startRow, startCol);
6443     else if (destination->sampleFormat == SAMPLEFORMAT_UINT
6444 	     && destination->samplesPerPixel == 1
6445 	     && destination->photometric == 3
6446 	     && destination->bitsPerSample == 8
6447 	     && (rst->sampleType == RL2_SAMPLE_UINT8
6448 		 || rst->sampleType == RL2_SAMPLE_1_BIT
6449 		 || rst->sampleType == RL2_SAMPLE_2_BIT
6450 		 || rst->sampleType == RL2_SAMPLE_4_BIT)
6451 	     && rst->pixelType == RL2_PIXEL_PALETTE && rst->nBands == 1
6452 	     && destination->tileWidth == rst->width
6453 	     && destination->tileHeight == rst->height)
6454 	ret = tiff_write_tile_palette (destination, rst, startRow, startCol);
6455     else if (destination->sampleFormat == SAMPLEFORMAT_UINT
6456 	     && destination->samplesPerPixel == 1
6457 	     && destination->photometric < 2
6458 	     && destination->bitsPerSample == 1
6459 	     && rst->sampleType == RL2_SAMPLE_1_BIT
6460 	     && rst->pixelType == RL2_PIXEL_MONOCHROME && rst->nBands == 1
6461 	     && destination->tileWidth == rst->width
6462 	     && destination->tileHeight == rst->height)
6463 	ret = tiff_write_tile_monochrome (destination, rst, startRow, startCol);
6464     else if (destination->sampleFormat == SAMPLEFORMAT_INT
6465 	     && destination->samplesPerPixel == 1
6466 	     && destination->photometric < 2
6467 	     && destination->bitsPerSample == 8
6468 	     && rst->sampleType == RL2_SAMPLE_INT8
6469 	     && rst->pixelType == RL2_PIXEL_DATAGRID && rst->nBands == 1
6470 	     && destination->tileWidth == rst->width
6471 	     && destination->tileHeight == rst->height)
6472 	ret = tiff_write_tile_int8 (destination, rst, startRow, startCol);
6473     else if (destination->sampleFormat == SAMPLEFORMAT_UINT
6474 	     && destination->samplesPerPixel == 1
6475 	     && destination->photometric < 2
6476 	     && destination->bitsPerSample == 8
6477 	     && rst->sampleType == RL2_SAMPLE_UINT8
6478 	     && rst->pixelType == RL2_PIXEL_DATAGRID && rst->nBands == 1
6479 	     && destination->tileWidth == rst->width
6480 	     && destination->tileHeight == rst->height)
6481 	ret = tiff_write_tile_uint8 (destination, rst, startRow, startCol);
6482     else if (destination->sampleFormat == SAMPLEFORMAT_INT
6483 	     && destination->samplesPerPixel == 1
6484 	     && destination->photometric < 2
6485 	     && destination->bitsPerSample == 16
6486 	     && rst->sampleType == RL2_SAMPLE_INT16
6487 	     && rst->pixelType == RL2_PIXEL_DATAGRID && rst->nBands == 1
6488 	     && destination->tileWidth == rst->width
6489 	     && destination->tileHeight == rst->height)
6490 	ret = tiff_write_tile_int16 (destination, rst, startRow, startCol);
6491     else if (destination->sampleFormat == SAMPLEFORMAT_UINT
6492 	     && destination->samplesPerPixel == 1
6493 	     && destination->photometric < 2
6494 	     && destination->bitsPerSample == 16
6495 	     && rst->sampleType == RL2_SAMPLE_UINT16
6496 	     && rst->pixelType == RL2_PIXEL_DATAGRID && rst->nBands == 1
6497 	     && destination->tileWidth == rst->width
6498 	     && destination->tileHeight == rst->height)
6499 	ret = tiff_write_tile_uint16 (destination, rst, startRow, startCol);
6500     else if (destination->sampleFormat == SAMPLEFORMAT_INT
6501 	     && destination->samplesPerPixel == 1
6502 	     && destination->photometric < 2
6503 	     && destination->bitsPerSample == 32
6504 	     && rst->sampleType == RL2_SAMPLE_INT32
6505 	     && rst->pixelType == RL2_PIXEL_DATAGRID && rst->nBands == 1
6506 	     && destination->tileWidth == rst->width
6507 	     && destination->tileHeight == rst->height)
6508 	ret = tiff_write_tile_int32 (destination, rst, startRow, startCol);
6509     else if (destination->sampleFormat == SAMPLEFORMAT_UINT
6510 	     && destination->samplesPerPixel == 1
6511 	     && destination->photometric < 2
6512 	     && destination->bitsPerSample == 32
6513 	     && rst->sampleType == RL2_SAMPLE_UINT32
6514 	     && rst->pixelType == RL2_PIXEL_DATAGRID && rst->nBands == 1
6515 	     && destination->tileWidth == rst->width
6516 	     && destination->tileHeight == rst->height)
6517 	ret = tiff_write_tile_uint32 (destination, rst, startRow, startCol);
6518     else if (destination->sampleFormat == SAMPLEFORMAT_IEEEFP
6519 	     && destination->samplesPerPixel == 1
6520 	     && destination->photometric < 2
6521 	     && destination->bitsPerSample == 32
6522 	     && rst->sampleType == RL2_SAMPLE_FLOAT
6523 	     && rst->pixelType == RL2_PIXEL_DATAGRID && rst->nBands == 1
6524 	     && destination->tileWidth == rst->width
6525 	     && destination->tileHeight == rst->height)
6526 	ret = tiff_write_tile_float (destination, rst, startRow, startCol);
6527     else if (destination->sampleFormat == SAMPLEFORMAT_IEEEFP
6528 	     && destination->samplesPerPixel == 1
6529 	     && destination->photometric < 2
6530 	     && destination->bitsPerSample == 64
6531 	     && rst->sampleType == RL2_SAMPLE_DOUBLE
6532 	     && rst->pixelType == RL2_PIXEL_DATAGRID && rst->nBands == 1
6533 	     && destination->tileWidth == rst->width
6534 	     && destination->tileHeight == rst->height)
6535 	ret = tiff_write_tile_double (destination, rst, startRow, startCol);
6536 
6537     if (ret)
6538 	return RL2_OK;
6539     return RL2_ERROR;
6540 }
6541 
6542 RL2_DECLARE int
rl2_write_tiff_worldfile(rl2TiffDestinationPtr tiff)6543 rl2_write_tiff_worldfile (rl2TiffDestinationPtr tiff)
6544 {
6545 /* writing a Worldfile supporting a TIFF destination */
6546     FILE *tfw;
6547     rl2PrivTiffDestinationPtr destination = (rl2PrivTiffDestinationPtr) tiff;
6548     if (destination == NULL)
6549 	return RL2_ERROR;
6550     if (destination->tfw_path == NULL)
6551 	return RL2_ERROR;
6552 
6553     tfw = fopen (destination->tfw_path, "w");
6554     if (tfw == NULL)
6555       {
6556 	  fprintf (stderr, "RL2-TIFF writer: unable to open Worldfile \"%s\"\n",
6557 		   destination->tfw_path);
6558 	  return RL2_ERROR;
6559       }
6560     fprintf (tfw, "        %1.16f\n", destination->hResolution);
6561     fprintf (tfw, "        0.0\n");
6562     fprintf (tfw, "        0.0\n");
6563     fprintf (tfw, "        -%1.16f\n", destination->vResolution);
6564     fprintf (tfw, "        %1.16f\n", destination->minX);
6565     fprintf (tfw, "        %1.16f\n", destination->maxY);
6566     fclose (tfw);
6567     return RL2_OK;
6568 }
6569 
6570 static int
compress_fax4(const unsigned char * buffer,unsigned short width,unsigned short height,unsigned char ** blob,int * blob_size)6571 compress_fax4 (const unsigned char *buffer,
6572 	       unsigned short width,
6573 	       unsigned short height, unsigned char **blob, int *blob_size)
6574 {
6575 /* compressing a TIFF FAX4 block - actual work */
6576     struct memfile clientdata;
6577     TIFF *out = (TIFF *) 0;
6578     tsize_t buf_size;
6579     void *tiff_buffer = NULL;
6580     int y;
6581     int x;
6582     unsigned char byte;
6583     unsigned char pixel;
6584     int pos;
6585     const unsigned char *p_in;
6586     unsigned char *p_out;
6587 
6588 /* suppressing TIFF warnings */
6589     TIFFSetWarningHandler (NULL);
6590 
6591 /* writing into memory */
6592     clientdata.buffer = NULL;
6593     clientdata.malloc_block = 1024;
6594     clientdata.size = 0;
6595     clientdata.eof = 0;
6596     clientdata.current = 0;
6597     out = TIFFClientOpen ("tiff", "w", &clientdata, memory_readproc,
6598 			  memory_writeproc, memory_seekproc, closeproc,
6599 			  memory_sizeproc, mapproc, unmapproc);
6600     if (out == NULL)
6601 	return 0;
6602 
6603 /* setting up the TIFF headers */
6604     TIFFSetField (out, TIFFTAG_SUBFILETYPE, 0);
6605     TIFFSetField (out, TIFFTAG_IMAGEWIDTH, width);
6606     TIFFSetField (out, TIFFTAG_IMAGELENGTH, height);
6607     TIFFSetField (out, TIFFTAG_XRESOLUTION, 300.0);
6608     TIFFSetField (out, TIFFTAG_YRESOLUTION, 300.0);
6609     TIFFSetField (out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
6610     TIFFSetField (out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
6611     TIFFSetField (out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
6612     TIFFSetField (out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
6613     TIFFSetField (out, TIFFTAG_SAMPLESPERPIXEL, 1);
6614     TIFFSetField (out, TIFFTAG_BITSPERSAMPLE, 1);
6615     TIFFSetField (out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);
6616     TIFFSetField (out, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4);
6617     TIFFSetField (out, TIFFTAG_TILEWIDTH, width);
6618     TIFFSetField (out, TIFFTAG_TILELENGTH, height);
6619 
6620 /* allocating the TIFF write buffer */
6621     buf_size = TIFFTileSize (out);
6622     tiff_buffer = malloc (buf_size);
6623     if (tiff_buffer == NULL)
6624 	goto error;
6625 
6626 /* writing a TIFF Monochrome tile */
6627     p_in = buffer;
6628     p_out = tiff_buffer;
6629 
6630     /* priming a White tile */
6631     for (x = 0; x < buf_size; x++)
6632 	*p_out++ = 0x00;
6633     p_out = tiff_buffer;
6634     for (y = 0; y < height; y++)
6635       {
6636 	  /* inserting pixels */
6637 	  pos = 0;
6638 	  byte = 0x00;
6639 	  for (x = 0; x < width; x++)
6640 	    {
6641 		pixel = *p_in++;
6642 		if (pixel == 1)
6643 		  {
6644 		      /* handling a black pixel */
6645 		      switch (pos)
6646 			{
6647 			case 0:
6648 			    byte |= 0x80;
6649 			    break;
6650 			case 1:
6651 			    byte |= 0x40;
6652 			    break;
6653 			case 2:
6654 			    byte |= 0x20;
6655 			    break;
6656 			case 3:
6657 			    byte |= 0x10;
6658 			    break;
6659 			case 4:
6660 			    byte |= 0x08;
6661 			    break;
6662 			case 5:
6663 			    byte |= 0x04;
6664 			    break;
6665 			case 6:
6666 			    byte |= 0x02;
6667 			    break;
6668 			case 7:
6669 			    byte |= 0x01;
6670 			    break;
6671 			};
6672 		  }
6673 		pos++;
6674 		if (pos > 7)
6675 		  {
6676 		      /* exporting an octet */
6677 		      *p_out++ = byte;
6678 		      byte = 0x00;
6679 		      pos = 0;
6680 		  }
6681 	    }
6682       }
6683     if (TIFFWriteTile (out, tiff_buffer, 0, 0, 0, 0) < 0)
6684 	goto error;
6685 
6686     TIFFClose (out);
6687     free (tiff_buffer);
6688     *blob = clientdata.buffer;
6689     *blob_size = clientdata.eof;
6690     return 1;
6691 
6692   error:
6693     TIFFClose (out);
6694     if (tiff_buffer != NULL)
6695 	free (tiff_buffer);
6696     if (clientdata.buffer != NULL)
6697 	free (clientdata.buffer);
6698     return 0;
6699 }
6700 
6701 RL2_DECLARE int
rl2_raster_to_tiff_mono4(rl2RasterPtr rst,unsigned char ** tiff,int * tiff_size)6702 rl2_raster_to_tiff_mono4 (rl2RasterPtr rst, unsigned char **tiff,
6703 			  int *tiff_size)
6704 {
6705 /* creating a TIFF FAX4 block from a raster */
6706     rl2PrivRasterPtr raster = (rl2PrivRasterPtr) rst;
6707     unsigned char sample_type;
6708     unsigned char pixel_type;
6709     unsigned char num_samples;
6710     if (rst == NULL)
6711 	return RL2_ERROR;
6712     if (rl2_get_raster_type (rst, &sample_type, &pixel_type, &num_samples) !=
6713 	RL2_OK)
6714 	return RL2_ERROR;
6715     if (sample_type == RL2_SAMPLE_1_BIT && pixel_type == RL2_PIXEL_MONOCHROME
6716 	&& num_samples == 1)
6717 	;
6718     else
6719 	return RL2_ERROR;
6720 
6721     if (!compress_fax4 (raster->rasterBuffer, raster->width,
6722 			raster->height, tiff, tiff_size))
6723 	return RL2_ERROR;
6724     return RL2_OK;
6725 }
6726 
6727 RL2_PRIVATE int
rl2_decode_tiff_mono4(const unsigned char * tiff,int tiff_sz,unsigned int * xwidth,unsigned int * xheight,unsigned char ** pixels,int * pixels_sz)6728 rl2_decode_tiff_mono4 (const unsigned char *tiff, int tiff_sz,
6729 		       unsigned int *xwidth, unsigned int *xheight,
6730 		       unsigned char **pixels, int *pixels_sz)
6731 {
6732 /* attempting to decode a TIFF FAX4 block */
6733     struct memfile clientdata;
6734     TIFF *in = (TIFF *) 0;
6735     int is_tiled;
6736     uint32 width = 0;
6737     uint32 height = 0;
6738     uint32 tile_width;
6739     uint32 tile_height;
6740     uint16 bits_per_sample;
6741     uint16 samples_per_pixel;
6742     uint16 photometric;
6743     uint16 compression;
6744     uint16 sample_format;
6745     uint16 planar_config;
6746     tsize_t buf_size;
6747     void *tiff_buffer = NULL;
6748     unsigned int x;
6749     unsigned char pixel;
6750     unsigned char *buffer;
6751     int buf_sz;
6752     const unsigned char *p_in;
6753     unsigned char *p_out;
6754 
6755 /* suppressing TIFF warnings */
6756     TIFFSetWarningHandler (NULL);
6757 
6758 /* reading from memory */
6759     clientdata.buffer = (unsigned char *) tiff;
6760     clientdata.malloc_block = 1024;
6761     clientdata.size = tiff_sz;
6762     clientdata.eof = tiff_sz;
6763     clientdata.current = 0;
6764     in = TIFFClientOpen ("tiff", "r", &clientdata, memory_readproc,
6765 			 memory_writeproc, memory_seekproc, closeproc,
6766 			 memory_sizeproc, mapproc, unmapproc);
6767     if (in == NULL)
6768 	return RL2_ERROR;
6769 
6770 /* retrieving the TIFF dimensions */
6771     is_tiled = TIFFIsTiled (in);
6772     if (!is_tiled)
6773 	goto error;
6774     TIFFGetField (in, TIFFTAG_IMAGELENGTH, &height);
6775     TIFFGetField (in, TIFFTAG_IMAGEWIDTH, &width);
6776     TIFFGetField (in, TIFFTAG_TILEWIDTH, &tile_width);
6777     TIFFGetField (in, TIFFTAG_TILELENGTH, &tile_height);
6778     if (tile_width != width)
6779 	goto error;
6780     if (tile_height != height)
6781 	goto error;
6782     TIFFGetField (in, TIFFTAG_BITSPERSAMPLE, &bits_per_sample);
6783     if (bits_per_sample != 1)
6784 	goto error;
6785     TIFFGetField (in, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel);
6786     if (samples_per_pixel != 1)
6787 	goto error;
6788     TIFFGetField (in, TIFFTAG_SAMPLEFORMAT, &sample_format);
6789     if (sample_format != SAMPLEFORMAT_UINT)
6790 	goto error;
6791     TIFFGetField (in, TIFFTAG_PLANARCONFIG, &planar_config);
6792     if (planar_config != PLANARCONFIG_CONTIG)
6793 	goto error;
6794     TIFFGetField (in, TIFFTAG_PHOTOMETRIC, &photometric);
6795     if (photometric != PHOTOMETRIC_MINISWHITE)
6796 	goto error;
6797     TIFFGetField (in, TIFFTAG_COMPRESSION, &compression);
6798     if (compression != COMPRESSION_CCITTFAX4)
6799 	goto error;
6800 
6801 /* allocating the tile buffer */
6802     buf_size = TIFFTileSize (in);
6803     tiff_buffer = malloc (buf_size);
6804     if (tiff_buffer == NULL)
6805 	goto error;
6806 
6807 /* reading and decoding as a single tile */
6808     if (!TIFFReadTile (in, tiff_buffer, 0, 0, 0, 0))
6809 	goto error;
6810 
6811 /* allocating the output buffer */
6812     buf_sz = width * height;
6813     buffer = malloc (buf_sz);
6814     if (buffer == NULL)
6815 	goto error;
6816 
6817     p_in = tiff_buffer;
6818     p_out = buffer;
6819     for (x = 0; x < buf_size; x++)
6820       {
6821 	  pixel = *p_in++;
6822 	  if ((pixel & 0x80) == 0x80)
6823 	      *p_out++ = 1;
6824 	  else
6825 	      *p_out++ = 0;
6826 	  if ((pixel & 0x40) == 0x40)
6827 	      *p_out++ = 1;
6828 	  else
6829 	      *p_out++ = 0;
6830 	  if ((pixel & 0x20) == 0x20)
6831 	      *p_out++ = 1;
6832 	  else
6833 	      *p_out++ = 0;
6834 	  if ((pixel & 0x10) == 0x10)
6835 	      *p_out++ = 1;
6836 	  else
6837 	      *p_out++ = 0;
6838 	  if ((pixel & 0x08) == 0x08)
6839 	      *p_out++ = 1;
6840 	  else
6841 	      *p_out++ = 0;
6842 	  if ((pixel & 0x04) == 0x04)
6843 	      *p_out++ = 1;
6844 	  else
6845 	      *p_out++ = 0;
6846 	  if ((pixel & 0x02) == 0x02)
6847 	      *p_out++ = 1;
6848 	  else
6849 	      *p_out++ = 0;
6850 	  if ((pixel & 0x01) == 0x01)
6851 	      *p_out++ = 1;
6852 	  else
6853 	      *p_out++ = 0;
6854       }
6855 
6856     TIFFClose (in);
6857     if (tiff_buffer != NULL)
6858 	free (tiff_buffer);
6859     *xwidth = width;
6860     *xheight = height;
6861     *pixels = buffer;
6862     *pixels_sz = buf_sz;
6863     return RL2_OK;
6864 
6865   error:
6866     TIFFClose (in);
6867     if (tiff_buffer != NULL)
6868 	free (tiff_buffer);
6869     return RL2_ERROR;
6870 }
6871 
6872 static int
rgb_tiff_common(TIFF * out,const unsigned char * buffer,unsigned short width,unsigned short height)6873 rgb_tiff_common (TIFF * out, const unsigned char *buffer, unsigned short width,
6874 		 unsigned short height)
6875 {
6876 /* common implementation of RGB TIFF export */
6877     tsize_t buf_size;
6878     void *tiff_buffer = NULL;
6879     int y;
6880     int x;
6881     const unsigned char *p_in;
6882     unsigned char *p_out;
6883 
6884 /* setting up the TIFF headers */
6885     TIFFSetField (out, TIFFTAG_SUBFILETYPE, 0);
6886     TIFFSetField (out, TIFFTAG_IMAGEWIDTH, width);
6887     TIFFSetField (out, TIFFTAG_IMAGELENGTH, height);
6888     TIFFSetField (out, TIFFTAG_XRESOLUTION, 300.0);
6889     TIFFSetField (out, TIFFTAG_YRESOLUTION, 300.0);
6890     TIFFSetField (out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
6891     TIFFSetField (out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
6892     TIFFSetField (out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
6893     TIFFSetField (out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
6894     TIFFSetField (out, TIFFTAG_SAMPLESPERPIXEL, 3);
6895     TIFFSetField (out, TIFFTAG_BITSPERSAMPLE, 8);
6896     TIFFSetField (out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
6897     TIFFSetField (out, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
6898     TIFFSetField (out, TIFFTAG_ROWSPERSTRIP, 1);
6899 
6900 /* allocating the TIFF write buffer */
6901     buf_size = TIFFScanlineSize (out);
6902     tiff_buffer = malloc (buf_size);
6903     if (tiff_buffer == NULL)
6904 	goto error;
6905 
6906 /* writing TIFF RGB scanlines */
6907     p_in = buffer;
6908 
6909     for (y = 0; y < height; y++)
6910       {
6911 	  /* inserting pixels */
6912 	  p_out = tiff_buffer;
6913 	  for (x = 0; x < width; x++)
6914 	    {
6915 		*p_out++ = *p_in++;	/* red */
6916 		*p_out++ = *p_in++;	/* green */
6917 		*p_out++ = *p_in++;	/* blue */
6918 	    }
6919 	  if (TIFFWriteScanline (out, tiff_buffer, y, 0) < 0)
6920 	      goto error;
6921       }
6922 
6923     free (tiff_buffer);
6924     return 1;
6925   error:
6926     if (tiff_buffer != NULL)
6927 	free (tiff_buffer);
6928     return 0;
6929 }
6930 
6931 static int
output_rgb_tiff(const unsigned char * buffer,unsigned short width,unsigned short height,unsigned char ** blob,int * blob_size)6932 output_rgb_tiff (const unsigned char *buffer,
6933 		 unsigned short width,
6934 		 unsigned short height, unsigned char **blob, int *blob_size)
6935 {
6936 /* generating an RGB TIFF - actual work */
6937     struct memfile clientdata;
6938     TIFF *out = (TIFF *) 0;
6939 
6940 /* suppressing TIFF warnings */
6941     TIFFSetWarningHandler (NULL);
6942 
6943 /* writing into memory */
6944     clientdata.buffer = NULL;
6945     clientdata.malloc_block = 1024;
6946     clientdata.size = 0;
6947     clientdata.eof = 0;
6948     clientdata.current = 0;
6949     out = TIFFClientOpen ("tiff", "w", &clientdata, memory_readproc,
6950 			  memory_writeproc, memory_seekproc, closeproc,
6951 			  memory_sizeproc, mapproc, unmapproc);
6952     if (out == NULL)
6953 	return 0;
6954 
6955     if (!rgb_tiff_common (out, buffer, width, height))
6956 	goto error;
6957 
6958     TIFFClose (out);
6959     *blob = clientdata.buffer;
6960     *blob_size = clientdata.eof;
6961     return 1;
6962 
6963   error:
6964     TIFFClose (out);
6965     if (clientdata.buffer != NULL)
6966 	free (clientdata.buffer);
6967     return 0;
6968 }
6969 
6970 static int
output_rgb_geotiff(const unsigned char * buffer,unsigned short width,unsigned short height,sqlite3 * handle,double minx,double miny,double maxx,double maxy,int srid,unsigned char ** blob,int * blob_size)6971 output_rgb_geotiff (const unsigned char *buffer,
6972 		    unsigned short width,
6973 		    unsigned short height, sqlite3 * handle, double minx,
6974 		    double miny, double maxx, double maxy, int srid,
6975 		    unsigned char **blob, int *blob_size)
6976 {
6977 /* generating an RGB TIFF - actual work */
6978     struct memfile clientdata;
6979     double tiepoint[6];
6980     double pixsize[3];
6981     double hResolution = (maxx - minx) / (double) width;
6982     double vResolution = (maxy - miny) / (double) height;
6983     char *srs_name = NULL;
6984     char *proj4text = NULL;
6985     GTIF *gtif = (GTIF *) 0;
6986     TIFF *out = (TIFF *) 0;
6987 
6988 /* suppressing TIFF warnings */
6989     TIFFSetWarningHandler (NULL);
6990 
6991 /* writing into memory */
6992     clientdata.buffer = NULL;
6993     clientdata.malloc_block = 1024;
6994     clientdata.size = 0;
6995     clientdata.eof = 0;
6996     clientdata.current = 0;
6997 
6998     out = XTIFFClientOpen ("tiff", "w", &clientdata, memory_readproc,
6999 			   memory_writeproc, memory_seekproc, closeproc,
7000 			   memory_sizeproc, mapproc, unmapproc);
7001     if (out == NULL)
7002 	goto error;
7003     gtif = GTIFNew (out);
7004     if (gtif == NULL)
7005 	goto error;
7006 
7007 /* attempting to retrieve the CRS params */
7008     fetch_crs_params (handle, srid, &srs_name, &proj4text);
7009     if (srs_name == NULL || proj4text == NULL)
7010 	goto error;
7011 
7012 /* setting up the GeoTIFF Tags */
7013     pixsize[0] = hResolution;
7014     pixsize[1] = vResolution;
7015     pixsize[2] = 0.0;
7016     TIFFSetField (out, GTIFF_PIXELSCALE, 3, pixsize);
7017     tiepoint[0] = 0.0;
7018     tiepoint[1] = 0.0;
7019     tiepoint[2] = 0.0;
7020     tiepoint[3] = minx;
7021     tiepoint[4] = maxy;
7022     tiepoint[5] = 0.0;
7023     TIFFSetField (out, GTIFF_TIEPOINTS, 6, tiepoint);
7024     if (srs_name != NULL)
7025 	TIFFSetField (out, GTIFF_ASCIIPARAMS, srs_name);
7026     if (proj4text != NULL)
7027 	GTIFSetFromProj4 (gtif, proj4text);
7028     if (srs_name != NULL)
7029 	GTIFKeySet (gtif, GTCitationGeoKey, TYPE_ASCII, 0, srs_name);
7030     if (is_projected_srs (proj4text))
7031 	GTIFKeySet (gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, srid);
7032     GTIFWriteKeys (gtif);
7033 
7034     if (!rgb_tiff_common (out, buffer, width, height))
7035 	goto error;
7036 
7037     GTIFFree (gtif);
7038     XTIFFClose (out);
7039     *blob = clientdata.buffer;
7040     *blob_size = clientdata.eof;
7041     if (srs_name != NULL)
7042 	free (srs_name);
7043     if (proj4text != NULL)
7044 	free (proj4text);
7045     return 1;
7046 
7047   error:
7048     if (gtif != (GTIF *) 0)
7049 	GTIFFree (gtif);
7050     if (out != (TIFF *) 0)
7051 	XTIFFClose (out);
7052     if (srs_name != NULL)
7053 	free (srs_name);
7054     if (proj4text != NULL)
7055 	free (proj4text);
7056     if (clientdata.buffer != NULL)
7057 	free (clientdata.buffer);
7058     return 0;
7059 }
7060 
7061 static int
palette_tiff_common(TIFF * out,const unsigned char * buffer,unsigned short width,unsigned short height,unsigned char * red,unsigned char * green,unsigned char * blue,int max_palette)7062 palette_tiff_common (TIFF * out, const unsigned char *buffer,
7063 		     unsigned short width, unsigned short height,
7064 		     unsigned char *red, unsigned char *green,
7065 		     unsigned char *blue, int max_palette)
7066 {
7067 /* common implementation of Palette TIFF export */
7068     tsize_t buf_size;
7069     void *tiff_buffer = NULL;
7070     int y;
7071     int x;
7072     int i;
7073     const unsigned char *p_in;
7074     unsigned char *p_out;
7075     uint16 r_plt[256];
7076     uint16 g_plt[256];
7077     uint16 b_plt[256];
7078 
7079 /* preparing the TIFF palette */
7080     for (i = 0; i < 256; i++)
7081       {
7082 	  r_plt[i] = 0;
7083 	  g_plt[i] = 0;
7084 	  b_plt[i] = 0;
7085       }
7086     for (i = 0; i < max_palette; i++)
7087       {
7088 	  r_plt[i] = *(red + i) * 256;
7089 	  g_plt[i] = *(green + i) * 256;
7090 	  b_plt[i] = *(blue + i) * 256;
7091       }
7092 
7093 /* setting up the TIFF headers */
7094     TIFFSetField (out, TIFFTAG_SUBFILETYPE, 0);
7095     TIFFSetField (out, TIFFTAG_IMAGEWIDTH, width);
7096     TIFFSetField (out, TIFFTAG_IMAGELENGTH, height);
7097     TIFFSetField (out, TIFFTAG_XRESOLUTION, 300.0);
7098     TIFFSetField (out, TIFFTAG_YRESOLUTION, 300.0);
7099     TIFFSetField (out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
7100     TIFFSetField (out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
7101     TIFFSetField (out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
7102     TIFFSetField (out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
7103     TIFFSetField (out, TIFFTAG_SAMPLESPERPIXEL, 1);
7104     TIFFSetField (out, TIFFTAG_BITSPERSAMPLE, 8);
7105     TIFFSetField (out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
7106     TIFFSetField (out, TIFFTAG_COLORMAP, r_plt, g_plt, b_plt);
7107     TIFFSetField (out, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
7108     TIFFSetField (out, TIFFTAG_ROWSPERSTRIP, 1);
7109 
7110 /* allocating the TIFF write buffer */
7111     buf_size = TIFFScanlineSize (out);
7112     tiff_buffer = malloc (buf_size);
7113     if (tiff_buffer == NULL)
7114 	goto error;
7115 
7116 /* writing TIFF RGB scanlines */
7117     p_in = buffer;
7118 
7119     for (y = 0; y < height; y++)
7120       {
7121 	  /* inserting pixels */
7122 	  p_out = tiff_buffer;
7123 	  for (x = 0; x < width; x++)
7124 	    {
7125 		unsigned char r = *p_in++;
7126 		unsigned char g = *p_in++;
7127 		unsigned char b = *p_in++;
7128 		unsigned char index = 0;
7129 		for (i = 0; i < max_palette; i++)
7130 		  {
7131 		      if (*(red + i) == r && *(green + i) == g
7132 			  && *(blue + i) == b)
7133 			{
7134 			    index = i;
7135 			    break;
7136 			}
7137 		  }
7138 		*p_out++ = index;
7139 	    }
7140 	  if (TIFFWriteScanline (out, tiff_buffer, y, 0) < 0)
7141 	      goto error;
7142       }
7143 
7144     free (tiff_buffer);
7145     return 1;
7146   error:
7147     if (tiff_buffer != NULL)
7148 	free (tiff_buffer);
7149     return 0;
7150 }
7151 
7152 static int
output_palette_tiff(const unsigned char * buffer,unsigned short width,unsigned short height,unsigned char * red,unsigned char * green,unsigned char * blue,int max_palette,unsigned char ** blob,int * blob_size)7153 output_palette_tiff (const unsigned char *buffer,
7154 		     unsigned short width,
7155 		     unsigned short height, unsigned char *red,
7156 		     unsigned char *green, unsigned char *blue, int max_palette,
7157 		     unsigned char **blob, int *blob_size)
7158 {
7159 /* generating a PALETTE TIFF - actual work */
7160     struct memfile clientdata;
7161     TIFF *out = (TIFF *) 0;
7162 
7163 /* suppressing TIFF warnings */
7164     TIFFSetWarningHandler (NULL);
7165 
7166 /* writing into memory */
7167     clientdata.buffer = NULL;
7168     clientdata.malloc_block = 1024;
7169     clientdata.size = 0;
7170     clientdata.eof = 0;
7171     clientdata.current = 0;
7172     out = TIFFClientOpen ("tiff", "w", &clientdata, memory_readproc,
7173 			  memory_writeproc, memory_seekproc, closeproc,
7174 			  memory_sizeproc, mapproc, unmapproc);
7175     if (out == NULL)
7176 	return 0;
7177 
7178     if (!palette_tiff_common
7179 	(out, buffer, width, height, red, green, blue, max_palette))
7180 	goto error;
7181 
7182     TIFFClose (out);
7183     *blob = clientdata.buffer;
7184     *blob_size = clientdata.eof;
7185     return 1;
7186 
7187   error:
7188     TIFFClose (out);
7189     if (clientdata.buffer != NULL)
7190 	free (clientdata.buffer);
7191     return 0;
7192 }
7193 
7194 static int
output_palette_geotiff(const unsigned char * buffer,unsigned short width,unsigned short height,sqlite3 * handle,double minx,double miny,double maxx,double maxy,int srid,unsigned char * red,unsigned char * green,unsigned char * blue,int max_palette,unsigned char ** blob,int * blob_size)7195 output_palette_geotiff (const unsigned char *buffer,
7196 			unsigned short width,
7197 			unsigned short height, sqlite3 * handle, double minx,
7198 			double miny, double maxx, double maxy, int srid,
7199 			unsigned char *red, unsigned char *green,
7200 			unsigned char *blue, int max_palette,
7201 			unsigned char **blob, int *blob_size)
7202 {
7203 /* generating a PALETTE GeoTIFF - actual work */
7204     struct memfile clientdata;
7205     double tiepoint[6];
7206     double pixsize[3];
7207     double hResolution = (maxx - minx) / (double) width;
7208     double vResolution = (maxy - miny) / (double) height;
7209     char *srs_name = NULL;
7210     char *proj4text = NULL;
7211     GTIF *gtif = (GTIF *) 0;
7212     TIFF *out = (TIFF *) 0;
7213 
7214 /* suppressing TIFF warnings */
7215     TIFFSetWarningHandler (NULL);
7216 
7217 /* writing into memory */
7218     clientdata.buffer = NULL;
7219     clientdata.malloc_block = 1024;
7220     clientdata.size = 0;
7221     clientdata.eof = 0;
7222     clientdata.current = 0;
7223 
7224     out = XTIFFClientOpen ("tiff", "w", &clientdata, memory_readproc,
7225 			   memory_writeproc, memory_seekproc, closeproc,
7226 			   memory_sizeproc, mapproc, unmapproc);
7227     if (out == NULL)
7228 	goto error;
7229     gtif = GTIFNew (out);
7230     if (gtif == NULL)
7231 	goto error;
7232 
7233 /* attempting to retrieve the CRS params */
7234     fetch_crs_params (handle, srid, &srs_name, &proj4text);
7235     if (srs_name == NULL || proj4text == NULL)
7236 	goto error;
7237 
7238 /* setting up the GeoTIFF Tags */
7239     pixsize[0] = hResolution;
7240     pixsize[1] = vResolution;
7241     pixsize[2] = 0.0;
7242     TIFFSetField (out, GTIFF_PIXELSCALE, 3, pixsize);
7243     tiepoint[0] = 0.0;
7244     tiepoint[1] = 0.0;
7245     tiepoint[2] = 0.0;
7246     tiepoint[3] = minx;
7247     tiepoint[4] = maxy;
7248     tiepoint[5] = 0.0;
7249     TIFFSetField (out, GTIFF_TIEPOINTS, 6, tiepoint);
7250     if (srs_name != NULL)
7251 	TIFFSetField (out, GTIFF_ASCIIPARAMS, srs_name);
7252     if (proj4text != NULL)
7253 	GTIFSetFromProj4 (gtif, proj4text);
7254     if (srs_name != NULL)
7255 	GTIFKeySet (gtif, GTCitationGeoKey, TYPE_ASCII, 0, srs_name);
7256     if (is_projected_srs (proj4text))
7257 	GTIFKeySet (gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, srid);
7258     GTIFWriteKeys (gtif);
7259 
7260     if (!palette_tiff_common
7261 	(out, buffer, width, height, red, green, blue, max_palette))
7262 	goto error;
7263 
7264     GTIFFree (gtif);
7265     XTIFFClose (out);
7266     *blob = clientdata.buffer;
7267     *blob_size = clientdata.eof;
7268     if (srs_name != NULL)
7269 	free (srs_name);
7270     if (proj4text != NULL)
7271 	free (proj4text);
7272     return 1;
7273 
7274   error:
7275     if (gtif != (GTIF *) 0)
7276 	GTIFFree (gtif);
7277     if (out != (TIFF *) 0)
7278 	XTIFFClose (out);
7279     if (srs_name != NULL)
7280 	free (srs_name);
7281     if (proj4text != NULL)
7282 	free (proj4text);
7283     if (clientdata.buffer != NULL)
7284 	free (clientdata.buffer);
7285     return 0;
7286 }
7287 
7288 static int
test_palette_tiff(unsigned short width,unsigned short height,const unsigned char * rgb,unsigned char * red,unsigned char * green,unsigned char * blue,int * max_palette)7289 test_palette_tiff (unsigned short width, unsigned short height,
7290 		   const unsigned char *rgb, unsigned char *red,
7291 		   unsigned char *green, unsigned char *blue, int *max_palette)
7292 {
7293 /* testing for an eventual Palette */
7294     int next_palette = 0;
7295     int extra_palette = 0;
7296     int c;
7297     int y;
7298     int x;
7299     const unsigned char *p_in;
7300 
7301     p_in = rgb;
7302     for (y = 0; y < height; y++)
7303       {
7304 	  /* inserting pixels */
7305 	  for (x = 0; x < width; x++)
7306 	    {
7307 		unsigned char r = *p_in++;
7308 		unsigned char g = *p_in++;
7309 		unsigned char b = *p_in++;
7310 		int match = 0;
7311 		for (c = 0; c < next_palette; c++)
7312 		  {
7313 		      if (*(red + c) == r && *(green + c) == g
7314 			  && *(blue + c) == b)
7315 			{
7316 			    /* color already defined into the palette */
7317 			    match = 1;
7318 			    break;
7319 			}
7320 		  }
7321 		if (!match)
7322 		  {
7323 		      /* attempting to insert a color into the palette */
7324 		      if (next_palette < 256)
7325 			{
7326 			    *(red + next_palette) = r;
7327 			    *(green + next_palette) = g;
7328 			    *(blue + next_palette) = b;
7329 			    next_palette++;
7330 			}
7331 		      else
7332 			{
7333 			    extra_palette++;
7334 			    goto palette_invalid;
7335 			}
7336 		  }
7337 	    }
7338       }
7339   palette_invalid:
7340     if (extra_palette)
7341 	return 0;
7342     *max_palette = next_palette;
7343     return 1;
7344 }
7345 
7346 RL2_DECLARE int
rl2_rgb_to_tiff(unsigned int width,unsigned int height,const unsigned char * rgb,unsigned char ** tiff,int * tiff_size)7347 rl2_rgb_to_tiff (unsigned int width, unsigned int height,
7348 		 const unsigned char *rgb, unsigned char **tiff, int *tiff_size)
7349 {
7350 /* creating a TIFF in-memory image from an RGB buffer */
7351     unsigned char red[256];
7352     unsigned char green[256];
7353     unsigned char blue[256];
7354     int max_palette = 0;
7355     if (rgb == NULL)
7356 	return RL2_ERROR;
7357 
7358     if (test_palette_tiff (width, height, rgb, red, green, blue, &max_palette))
7359       {
7360 	  if (!output_palette_tiff
7361 	      (rgb, width, height, red, green, blue, max_palette, tiff,
7362 	       tiff_size))
7363 	      return RL2_ERROR;
7364       }
7365     else
7366       {
7367 	  if (!output_rgb_tiff (rgb, width, height, tiff, tiff_size))
7368 	      return RL2_ERROR;
7369       }
7370     return RL2_OK;
7371 }
7372 
7373 RL2_DECLARE int
rl2_rgb_to_geotiff(unsigned int width,unsigned int height,sqlite3 * handle,double minx,double miny,double maxx,double maxy,int srid,const unsigned char * rgb,unsigned char ** tiff,int * tiff_size)7374 rl2_rgb_to_geotiff (unsigned int width, unsigned int height,
7375 		    sqlite3 * handle, double minx, double miny, double maxx,
7376 		    double maxy, int srid, const unsigned char *rgb,
7377 		    unsigned char **tiff, int *tiff_size)
7378 {
7379 /* creating a GeoTIFF in-memory image from an RGB buffer */
7380     unsigned char red[256];
7381     unsigned char green[256];
7382     unsigned char blue[256];
7383     int max_palette = 0;
7384     if (rgb == NULL)
7385 	return RL2_ERROR;
7386 
7387     if (test_palette_tiff (width, height, rgb, red, green, blue, &max_palette))
7388       {
7389 	  if (!output_palette_geotiff
7390 	      (rgb, width, height, handle, minx, miny, maxx, maxy, srid, red,
7391 	       green, blue, max_palette, tiff, tiff_size))
7392 	      return RL2_ERROR;
7393       }
7394     else
7395       {
7396 	  if (!output_rgb_geotiff
7397 	      (rgb, width, height, handle, minx, miny, maxx, maxy, srid, tiff,
7398 	       tiff_size))
7399 	      return RL2_ERROR;
7400       }
7401     return RL2_OK;
7402 }
7403 
7404 static int
gray_tiff_common(TIFF * out,const unsigned char * buffer,unsigned short width,unsigned short height)7405 gray_tiff_common (TIFF * out, const unsigned char *buffer, unsigned short width,
7406 		  unsigned short height)
7407 {
7408 /* common implementation of Grayscale TIFF export */
7409     tsize_t buf_size;
7410     void *tiff_buffer = NULL;
7411     int y;
7412     int x;
7413     const unsigned char *p_in;
7414     unsigned char *p_out;
7415 
7416 /* setting up the TIFF headers */
7417     TIFFSetField (out, TIFFTAG_SUBFILETYPE, 0);
7418     TIFFSetField (out, TIFFTAG_IMAGEWIDTH, width);
7419     TIFFSetField (out, TIFFTAG_IMAGELENGTH, height);
7420     TIFFSetField (out, TIFFTAG_XRESOLUTION, 300.0);
7421     TIFFSetField (out, TIFFTAG_YRESOLUTION, 300.0);
7422     TIFFSetField (out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
7423     TIFFSetField (out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
7424     TIFFSetField (out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
7425     TIFFSetField (out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
7426     TIFFSetField (out, TIFFTAG_SAMPLESPERPIXEL, 1);
7427     TIFFSetField (out, TIFFTAG_BITSPERSAMPLE, 8);
7428     TIFFSetField (out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
7429     TIFFSetField (out, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
7430     TIFFSetField (out, TIFFTAG_ROWSPERSTRIP, 1);
7431 
7432 /* allocating the TIFF write buffer */
7433     buf_size = TIFFScanlineSize (out);
7434     tiff_buffer = malloc (buf_size);
7435     if (tiff_buffer == NULL)
7436 	goto error;
7437 
7438 /* writing TIFF RGB scanlines */
7439     p_in = buffer;
7440 
7441     for (y = 0; y < height; y++)
7442       {
7443 	  /* inserting pixels */
7444 	  p_out = tiff_buffer;
7445 	  for (x = 0; x < width; x++)
7446 	      *p_out++ = *p_in++;	/* gray */
7447 	  if (TIFFWriteScanline (out, tiff_buffer, y, 0) < 0)
7448 	      goto error;
7449       }
7450 
7451     free (tiff_buffer);
7452     return 1;
7453   error:
7454     if (tiff_buffer != NULL)
7455 	free (tiff_buffer);
7456     return 0;
7457 }
7458 
7459 static int
output_gray_tiff(const unsigned char * buffer,unsigned short width,unsigned short height,unsigned char ** blob,int * blob_size)7460 output_gray_tiff (const unsigned char *buffer,
7461 		  unsigned short width,
7462 		  unsigned short height, unsigned char **blob, int *blob_size)
7463 {
7464 /* generating a Grayscale TIFF - actual work */
7465     struct memfile clientdata;
7466     TIFF *out = (TIFF *) 0;
7467 
7468 /* suppressing TIFF warnings */
7469     TIFFSetWarningHandler (NULL);
7470 
7471 /* writing into memory */
7472     clientdata.buffer = NULL;
7473     clientdata.malloc_block = 1024;
7474     clientdata.size = 0;
7475     clientdata.eof = 0;
7476     clientdata.current = 0;
7477     out = TIFFClientOpen ("tiff", "w", &clientdata, memory_readproc,
7478 			  memory_writeproc, memory_seekproc, closeproc,
7479 			  memory_sizeproc, mapproc, unmapproc);
7480     if (out == NULL)
7481 	return 0;
7482 
7483     if (!gray_tiff_common (out, buffer, width, height))
7484 	goto error;
7485 
7486     TIFFClose (out);
7487     *blob = clientdata.buffer;
7488     *blob_size = clientdata.eof;
7489     return 1;
7490 
7491   error:
7492     TIFFClose (out);
7493     if (clientdata.buffer != NULL)
7494 	free (clientdata.buffer);
7495     return 0;
7496 }
7497 
7498 static int
output_gray_geotiff(const unsigned char * buffer,unsigned short width,unsigned short height,sqlite3 * handle,double minx,double miny,double maxx,double maxy,int srid,unsigned char ** blob,int * blob_size)7499 output_gray_geotiff (const unsigned char *buffer,
7500 		     unsigned short width,
7501 		     unsigned short height, sqlite3 * handle, double minx,
7502 		     double miny, double maxx, double maxy, int srid,
7503 		     unsigned char **blob, int *blob_size)
7504 {
7505 /* generating a Grayscale GeoTIFF - actual work */
7506     struct memfile clientdata;
7507     double tiepoint[6];
7508     double pixsize[3];
7509     double hResolution = (maxx - minx) / (double) width;
7510     double vResolution = (maxy - miny) / (double) height;
7511     char *srs_name = NULL;
7512     char *proj4text = NULL;
7513     GTIF *gtif = (GTIF *) 0;
7514     TIFF *out = (TIFF *) 0;
7515 
7516 /* suppressing TIFF warnings */
7517     TIFFSetWarningHandler (NULL);
7518 
7519 /* writing into memory */
7520     clientdata.buffer = NULL;
7521     clientdata.malloc_block = 1024;
7522     clientdata.size = 0;
7523     clientdata.eof = 0;
7524     clientdata.current = 0;
7525 
7526     out = XTIFFClientOpen ("tiff", "w", &clientdata, memory_readproc,
7527 			   memory_writeproc, memory_seekproc, closeproc,
7528 			   memory_sizeproc, mapproc, unmapproc);
7529     if (out == NULL)
7530 	goto error;
7531     gtif = GTIFNew (out);
7532     if (gtif == NULL)
7533 	goto error;
7534 
7535 /* attempting to retrieve the CRS params */
7536     fetch_crs_params (handle, srid, &srs_name, &proj4text);
7537     if (srs_name == NULL || proj4text == NULL)
7538 	goto error;
7539 
7540 /* setting up the GeoTIFF Tags */
7541     pixsize[0] = hResolution;
7542     pixsize[1] = vResolution;
7543     pixsize[2] = 0.0;
7544     TIFFSetField (out, GTIFF_PIXELSCALE, 3, pixsize);
7545     tiepoint[0] = 0.0;
7546     tiepoint[1] = 0.0;
7547     tiepoint[2] = 0.0;
7548     tiepoint[3] = minx;
7549     tiepoint[4] = maxy;
7550     tiepoint[5] = 0.0;
7551     TIFFSetField (out, GTIFF_TIEPOINTS, 6, tiepoint);
7552     if (srs_name != NULL)
7553 	TIFFSetField (out, GTIFF_ASCIIPARAMS, srs_name);
7554     if (proj4text != NULL)
7555 	GTIFSetFromProj4 (gtif, proj4text);
7556     if (srs_name != NULL)
7557 	GTIFKeySet (gtif, GTCitationGeoKey, TYPE_ASCII, 0, srs_name);
7558     if (is_projected_srs (proj4text))
7559 	GTIFKeySet (gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, srid);
7560     GTIFWriteKeys (gtif);
7561 
7562     if (!gray_tiff_common (out, buffer, width, height))
7563 	goto error;
7564 
7565     GTIFFree (gtif);
7566     XTIFFClose (out);
7567     *blob = clientdata.buffer;
7568     *blob_size = clientdata.eof;
7569     if (srs_name != NULL)
7570 	free (srs_name);
7571     if (proj4text != NULL)
7572 	free (proj4text);
7573     return 1;
7574 
7575   error:
7576     if (gtif != (GTIF *) 0)
7577 	GTIFFree (gtif);
7578     if (out != (TIFF *) 0)
7579 	XTIFFClose (out);
7580     if (srs_name != NULL)
7581 	free (srs_name);
7582     if (proj4text != NULL)
7583 	free (proj4text);
7584     if (clientdata.buffer != NULL)
7585 	free (clientdata.buffer);
7586     return 0;
7587 }
7588 
7589 RL2_DECLARE int
rl2_gray_to_tiff(unsigned int width,unsigned int height,const unsigned char * gray,unsigned char ** tiff,int * tiff_size)7590 rl2_gray_to_tiff (unsigned int width, unsigned int height,
7591 		  const unsigned char *gray, unsigned char **tiff,
7592 		  int *tiff_size)
7593 {
7594 /* creating a TIFF in-memory image from a Grayscale buffer */
7595     if (gray == NULL)
7596 	return RL2_ERROR;
7597 
7598     if (!output_gray_tiff (gray, width, height, tiff, tiff_size))
7599 	return RL2_ERROR;
7600     return RL2_OK;
7601 }
7602 
7603 RL2_DECLARE int
rl2_gray_to_geotiff(unsigned int width,unsigned int height,sqlite3 * handle,double minx,double miny,double maxx,double maxy,int srid,const unsigned char * gray,unsigned char ** tiff,int * tiff_size)7604 rl2_gray_to_geotiff (unsigned int width, unsigned int height,
7605 		     sqlite3 * handle, double minx, double miny, double maxx,
7606 		     double maxy, int srid, const unsigned char *gray,
7607 		     unsigned char **tiff, int *tiff_size)
7608 {
7609 /* creating a GeoTIFF in-memory image from a Grayscale buffer */
7610     if (gray == NULL)
7611 	return RL2_ERROR;
7612 
7613     if (!output_gray_geotiff
7614 	(gray, width, height, handle, minx, miny, maxx, maxy, srid, tiff,
7615 	 tiff_size))
7616 	return RL2_ERROR;
7617     return RL2_OK;
7618 }
7619 
7620 RL2_DECLARE rl2RasterPtr
rl2_raster_from_tiff(const unsigned char * blob,int blob_size)7621 rl2_raster_from_tiff (const unsigned char *blob, int blob_size)
7622 {
7623 /* attempting to create a raster from a TIFF image */
7624     rl2RasterPtr rst = NULL;
7625     struct memfile clientdata;
7626     uint32 width = 0;
7627     uint32 height = 0;
7628     TIFF *in = (TIFF *) 0;
7629     unsigned int x;
7630     unsigned int y;
7631     unsigned int row;
7632     uint32 *rgba;
7633     unsigned char *rgb;
7634     unsigned char *mask;
7635     int rgb_size;
7636     int mask_size;
7637     uint32 *p_in;
7638     unsigned char *p_rgb;
7639     unsigned char *p_mask;
7640     int valid_mask = 0;
7641 
7642 /* suppressing TIFF warnings */
7643     TIFFSetWarningHandler (NULL);
7644 
7645 /* reading from memory */
7646     clientdata.buffer = (unsigned char *) blob;
7647     clientdata.malloc_block = 1024;
7648     clientdata.size = blob_size;
7649     clientdata.eof = blob_size;
7650     clientdata.current = 0;
7651     in = TIFFClientOpen ("tiff", "r", &clientdata, memory_readproc,
7652 			 memory_writeproc, memory_seekproc, closeproc,
7653 			 memory_sizeproc, mapproc, unmapproc);
7654     if (in == NULL)
7655 	return NULL;
7656 
7657 /* retrieving the TIFF dimensions */
7658     TIFFGetField (in, TIFFTAG_IMAGELENGTH, &height);
7659     TIFFGetField (in, TIFFTAG_IMAGEWIDTH, &width);
7660 
7661 /* allocating the RGBA buffer */
7662     rgba = malloc (sizeof (uint32) * width * height);
7663     if (rgba == NULL)
7664 	goto error;
7665 
7666 /* attempting to decode the TIFF */
7667     if (!TIFFReadRGBAImage (in, width, height, rgba, 1))
7668 	goto error;
7669     TIFFClose (in);
7670 
7671 /* rearranging the RGBA buffer */
7672     rgb_size = width * height * 3;
7673     mask_size = width * height;
7674     rgb = malloc (rgb_size);
7675     mask = malloc (mask_size);
7676     if (rgb == NULL || mask == NULL)
7677 	goto error;
7678     p_in = rgba;
7679     row = height - 1;
7680     for (y = 0; y < height; y++)
7681       {
7682 	  /* the TIFF RGBA buffer is bottom-up !!! */
7683 	  p_rgb = rgb + (row * width * 3);
7684 	  p_mask = mask + (row * width);
7685 	  for (x = 0; x < width; x++)
7686 	    {
7687 		/* copying pixels */
7688 		*p_rgb++ = TIFFGetR (*p_in);
7689 		*p_rgb++ = TIFFGetG (*p_in);
7690 		*p_rgb++ = TIFFGetB (*p_in);
7691 		if (TIFFGetA (*p_in) < 128)
7692 		  {
7693 		      *p_mask++ = 0;
7694 		      valid_mask = 1;
7695 		  }
7696 		else
7697 		    *p_mask++ = 1;
7698 		p_in++;
7699 	    }
7700 	  row--;
7701       }
7702     if (!valid_mask)
7703       {
7704 	  free (mask);
7705 	  mask = NULL;
7706 	  mask_size = 0;
7707       }
7708     free (rgba);
7709     rgba = NULL;
7710 
7711 /* creating the raster */
7712     rst =
7713 	rl2_create_raster (width, height, RL2_SAMPLE_UINT8, RL2_PIXEL_RGB, 3,
7714 			   rgb, rgb_size, NULL, mask, mask_size, NULL);
7715     if (rst == NULL)
7716 	goto error;
7717     return rst;
7718 
7719   error:
7720     if (in != (TIFF *) 0)
7721 	TIFFClose (in);
7722     if (rgba != NULL)
7723 	free (rgba);
7724     if (rgb != NULL)
7725 	free (rgb);
7726     if (mask != NULL)
7727 	free (mask);
7728     return NULL;
7729 }
7730