1 /*
2 / gaiagraphics_image.c
3 /
4 / image methods
5 /
6 / version 1.0, 2010 July 20
7 /
8 / Author: Sandro Furieri a.furieri@lqt.it
9 /
10 / Copyright (C) 2010  Alessandro Furieri
11 /
12 /    This program is free software: you can redistribute it and/or modify
13 /    it under the terms of the GNU Lesser General Public License as published by
14 /    the Free Software Foundation, either version 3 of the License, or
15 /    (at your option) any later version.
16 /
17 /    This program is distributed in the hope that it will be useful,
18 /    but WITHOUT ANY WARRANTY; without even the implied warranty of
19 /    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 /    GNU Lesser General Public License for more details.
21 /
22 /    You should have received a copy of the GNU Lesser General Public License
23 /    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 /
25 */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <float.h>
31 #include <math.h>
32 #include <limits.h>
33 
34 #include "gaiagraphics.h"
35 #include "gaiagraphics_internals.h"
36 
37 GGRAPH_PRIVATE gGraphImageInfosPtr
gg_image_infos_create(int pixel_format,int width,int height,int bits_per_sample,int samples_per_pixel,int sample_format,const char * srs_name,const char * proj4text)38 gg_image_infos_create (int pixel_format, int width, int height,
39 		       int bits_per_sample, int samples_per_pixel,
40 		       int sample_format, const char *srs_name,
41 		       const char *proj4text)
42 {
43 /* creating an image infos struct */
44     gGraphImageInfosPtr img;
45     int len;
46     char *SrsName = NULL;
47     char *Proj4Text = NULL;
48 
49 /* checking PIXEL_FORMAT */
50     if (pixel_format == GG_PIXEL_RGB || pixel_format == GG_PIXEL_RGBA
51 	|| pixel_format == GG_PIXEL_ARGB || pixel_format == GG_PIXEL_BGR
52 	|| pixel_format == GG_PIXEL_GRAYSCALE
53 	|| pixel_format == GG_PIXEL_PALETTE || pixel_format == GG_PIXEL_GRID
54 	|| pixel_format == GG_PIXEL_UNKNOWN)
55 	;
56     else
57 	return NULL;
58 
59     if (srs_name)
60       {
61 	  len = strlen (srs_name);
62 	  SrsName = malloc (len + 1);
63 	  if (!SrsName)
64 	      return NULL;
65 	  strcpy (SrsName, srs_name);
66       }
67     if (proj4text)
68       {
69 	  len = strlen (proj4text);
70 	  Proj4Text = malloc (len + 1);
71 	  if (!Proj4Text)
72 	    {
73 		if (SrsName)
74 		    free (SrsName);
75 		return NULL;
76 	    }
77 	  strcpy (Proj4Text, proj4text);
78       }
79 
80 /* allocating the image INFOS struct */
81     img = malloc (sizeof (gGraphImage));
82     if (!img)
83 	return NULL;
84 
85     img->signature = GG_IMAGE_INFOS_MAGIC_SIGNATURE;
86     img->width = width;
87     img->height = height;
88     img->bits_per_sample = bits_per_sample;
89     img->samples_per_pixel = samples_per_pixel;
90     img->sample_format = sample_format;
91     img->pixel_format = pixel_format;
92     img->max_palette = 0;
93     img->is_transparent = 0;
94     img->tile_width = -1;
95     img->tile_height = -1;
96     img->rows_per_strip = -1;
97     img->compression = GGRAPH_TIFF_COMPRESSION_NONE;
98     img->scale_1_2 = 0;
99     img->scale_1_4 = 0;
100     img->scale_1_8 = 0;
101     img->is_georeferenced = 0;
102     img->srid = -1;
103     img->srs_name = SrsName;
104     img->proj4text = Proj4Text;
105     img->upper_left_x = DBL_MAX;
106     img->upper_left_y = DBL_MAX;
107     img->pixel_x_size = 0.0;
108     img->pixel_y_size = 0.0;
109     img->no_data_value = 0.0 - DBL_MAX;
110     img->min_value = DBL_MAX;
111     img->max_value = 0.0 - DBL_MAX;
112 
113     return img;
114 }
115 
116 GGRAPH_PRIVATE void
gg_image_infos_destroy(gGraphImageInfosPtr img)117 gg_image_infos_destroy (gGraphImageInfosPtr img)
118 {
119 /* destroying an image INFOS struct */
120     if (!img)
121 	return;
122     if (img->srs_name)
123 	free (img->srs_name);
124     if (img->proj4text)
125 	free (img->proj4text);
126     free (img);
127 }
128 
129 GGRAPH_PRIVATE gGraphImagePtr
gg_image_create(int pixel_format,int width,int height,int bits_per_sample,int samples_per_pixel,int sample_format,const char * srs_name,const char * proj4text)130 gg_image_create (int pixel_format, int width, int height, int bits_per_sample,
131 		 int samples_per_pixel, int sample_format, const char *srs_name,
132 		 const char *proj4text)
133 {
134 /* creating a generic image */
135     gGraphImagePtr img;
136     int len;
137     char *SrsName = NULL;
138     char *Proj4Text = NULL;
139 
140 /* checking PIXEL_FORMAT */
141     if (pixel_format == GG_PIXEL_RGB || pixel_format == GG_PIXEL_RGBA
142 	|| pixel_format == GG_PIXEL_ARGB || pixel_format == GG_PIXEL_BGR
143 	|| pixel_format == GG_PIXEL_GRAYSCALE
144 	|| pixel_format == GG_PIXEL_PALETTE || pixel_format == GG_PIXEL_GRID)
145 	;
146     else
147 	return NULL;
148     if (sample_format == GGRAPH_SAMPLE_UINT
149 	|| sample_format == GGRAPH_SAMPLE_INT
150 	|| sample_format == GGRAPH_SAMPLE_FLOAT)
151 	;
152     else
153 	return NULL;
154 
155     if (srs_name)
156       {
157 	  len = strlen (srs_name);
158 	  if (len > 0)
159 	    {
160 		SrsName = malloc (len + 1);
161 		if (!SrsName)
162 		    return NULL;
163 		strcpy (SrsName, srs_name);
164 	    }
165       }
166     if (proj4text)
167       {
168 	  len = strlen (proj4text);
169 	  if (len > 0)
170 	    {
171 		Proj4Text = malloc (len + 1);
172 		if (!Proj4Text)
173 		  {
174 		      if (SrsName)
175 			  free (SrsName);
176 		      return NULL;
177 		  }
178 		strcpy (Proj4Text, proj4text);
179 	    }
180       }
181 
182 /* allocating the image struct */
183     img = malloc (sizeof (gGraphImage));
184     if (!img)
185 	return NULL;
186 
187     img->signature = GG_IMAGE_MAGIC_SIGNATURE;
188     img->pixels = NULL;
189     img->width = width;
190     img->height = height;
191     img->bits_per_sample = bits_per_sample;
192     img->samples_per_pixel = samples_per_pixel;
193     img->sample_format = sample_format;
194     img->pixel_format = pixel_format;
195     img->max_palette = 0;
196     img->is_transparent = 0;
197     img->tile_width = -1;
198     img->tile_height = -1;
199     img->rows_per_strip = -1;
200     img->compression = GGRAPH_TIFF_COMPRESSION_NONE;
201     img->is_georeferenced = 0;
202     img->srid = -1;
203     img->srs_name = SrsName;
204     img->proj4text = Proj4Text;
205     img->upper_left_x = DBL_MAX;
206     img->upper_left_y = DBL_MAX;
207     img->pixel_x_size = 0.0;
208     img->pixel_y_size = 0.0;
209     img->no_data_value = 0.0 - DBL_MAX;
210     img->min_value = DBL_MAX;
211     img->max_value = 0.0 - DBL_MAX;
212 
213 /* computing the scanline size */
214     if (pixel_format == GG_PIXEL_GRAYSCALE || pixel_format == GG_PIXEL_PALETTE)
215       {
216 	  img->scanline_width = width;
217 	  img->pixel_size = 1;
218       }
219     else if (pixel_format == GG_PIXEL_RGB || pixel_format == GG_PIXEL_BGR)
220       {
221 	  img->scanline_width = width * 3;
222 	  img->pixel_size = 3;
223       }
224     else if (pixel_format == GG_PIXEL_GRID)
225       {
226 	  if (sample_format == GGRAPH_SAMPLE_FLOAT)
227 	    {
228 		if (bits_per_sample == 32)
229 		  {
230 		      /* float */
231 		      img->scanline_width = width * 4;
232 		      img->pixel_size = 8;
233 		  }
234 		else
235 		  {
236 		      /* double */
237 		      img->scanline_width = width * 8;
238 		      img->pixel_size = 8;
239 		  }
240 	    }
241 	  else
242 	    {
243 		/* UINT or INT */
244 		if (bits_per_sample == 8)
245 		  {
246 		      /* 8bits int */
247 		      img->scanline_width = width;
248 		      img->pixel_size = 1;
249 		  }
250 		else if (bits_per_sample == 16)
251 		  {
252 		      /* 16bits int */
253 		      img->scanline_width = width * 2;
254 		      img->pixel_size = 2;
255 		  }
256 		else
257 		  {
258 		      /* 32bits int */
259 		      img->scanline_width = width * 4;
260 		      img->pixel_size = 4;
261 		  }
262 	    }
263       }
264     else
265       {
266 	  /* RGBA, ARGB or BGRA */
267 	  img->scanline_width = width * 4;
268 	  img->pixel_size = 4;
269       }
270 
271 /* allocating the pixel buffer */
272     img->pixels = malloc (img->scanline_width * height);
273     if (!img->pixels)
274       {
275 	  free (img);
276 	  return NULL;
277       }
278     return img;
279 }
280 
281 GGRAPH_PRIVATE gGraphImagePtr
gg_image_create_from_bitmap(unsigned char * bitmap,int pixel_format,int width,int height,int bits_per_sample,int samples_per_pixel,int sample_format,const char * srs_name,const char * proj4text)282 gg_image_create_from_bitmap (unsigned char *bitmap, int pixel_format, int width,
283 			     int height, int bits_per_sample,
284 			     int samples_per_pixel, int sample_format,
285 			     const char *srs_name, const char *proj4text)
286 {
287 /* creating a generic image */
288     gGraphImagePtr img;
289     int len;
290     char *SrsName = NULL;
291     char *Proj4Text = NULL;
292 
293 /* checking PIXEL_FORMAT */
294     if (pixel_format == GG_PIXEL_RGB || pixel_format == GG_PIXEL_RGBA
295 	|| pixel_format == GG_PIXEL_ARGB || pixel_format == GG_PIXEL_BGR
296 	|| pixel_format == GG_PIXEL_GRAYSCALE
297 	|| pixel_format == GG_PIXEL_PALETTE || pixel_format == GG_PIXEL_GRID)
298 	;
299     else
300 	return NULL;
301     if (sample_format == GGRAPH_SAMPLE_UINT
302 	|| sample_format == GGRAPH_SAMPLE_INT
303 	|| sample_format == GGRAPH_SAMPLE_FLOAT)
304 	;
305     else
306 	return NULL;
307 
308     if (srs_name)
309       {
310 	  len = strlen (srs_name);
311 	  if (len > 0)
312 	    {
313 		SrsName = malloc (len + 1);
314 		if (!SrsName)
315 		    return NULL;
316 		strcpy (SrsName, srs_name);
317 	    }
318       }
319     if (proj4text)
320       {
321 	  len = strlen (proj4text);
322 	  if (len > 0)
323 	    {
324 		Proj4Text = malloc (len + 1);
325 		if (!Proj4Text)
326 		  {
327 		      if (SrsName)
328 			  free (SrsName);
329 		      return NULL;
330 		  }
331 		strcpy (Proj4Text, proj4text);
332 	    }
333       }
334 
335 /* allocating the image struct */
336     img = malloc (sizeof (gGraphImage));
337     if (!img)
338 	return NULL;
339 
340     img->signature = GG_IMAGE_MAGIC_SIGNATURE;
341     img->pixels = NULL;
342     img->width = width;
343     img->height = height;
344     img->bits_per_sample = bits_per_sample;
345     img->samples_per_pixel = samples_per_pixel;
346     img->sample_format = sample_format;
347     img->pixel_format = pixel_format;
348     img->max_palette = 0;
349     img->is_transparent = 0;
350     img->tile_width = -1;
351     img->tile_height = -1;
352     img->rows_per_strip = -1;
353     img->compression = GGRAPH_TIFF_COMPRESSION_NONE;
354     img->is_georeferenced = 0;
355     img->srid = -1;
356     img->srs_name = SrsName;
357     img->proj4text = Proj4Text;
358     img->upper_left_x = DBL_MAX;
359     img->upper_left_y = DBL_MAX;
360     img->pixel_x_size = 0.0;
361     img->pixel_y_size = 0.0;
362     img->no_data_value = 0.0 - DBL_MAX;
363     img->min_value = DBL_MAX;
364     img->max_value = 0.0 - DBL_MAX;
365 
366 /* computing the scanline size */
367     if (pixel_format == GG_PIXEL_GRAYSCALE || pixel_format == GG_PIXEL_PALETTE)
368       {
369 	  img->scanline_width = width;
370 	  img->pixel_size = 1;
371       }
372     else if (pixel_format == GG_PIXEL_RGB || pixel_format == GG_PIXEL_BGR)
373       {
374 	  img->scanline_width = width * 3;
375 	  img->pixel_size = 3;
376       }
377     else if (pixel_format == GG_PIXEL_GRID)
378       {
379 	  if (sample_format == GGRAPH_SAMPLE_FLOAT)
380 	    {
381 		if (bits_per_sample == 32)
382 		  {
383 		      /* float */
384 		      img->scanline_width = width * 4;
385 		      img->pixel_size = 8;
386 		  }
387 		else
388 		  {
389 		      /* double */
390 		      img->scanline_width = width * 8;
391 		      img->pixel_size = 8;
392 		  }
393 	    }
394 	  else
395 	    {
396 		/* UINT or INT */
397 		if (bits_per_sample == 8)
398 		  {
399 		      /* 8bits int */
400 		      img->scanline_width = width;
401 		      img->pixel_size = 1;
402 		  }
403 		else if (bits_per_sample == 16)
404 		  {
405 		      /* 16bits int */
406 		      img->scanline_width = width * 2;
407 		      img->pixel_size = 2;
408 		  }
409 		else
410 		  {
411 		      /* 32bits int */
412 		      img->scanline_width = width * 4;
413 		      img->pixel_size = 4;
414 		  }
415 	    }
416       }
417     else
418       {
419 	  /* RGBA, ARGB or BGRA */
420 	  img->scanline_width = width * 4;
421 	  img->pixel_size = 4;
422       }
423 
424 /* setting up the pixel buffer */
425     img->pixels = bitmap;
426     return img;
427 }
428 
429 GGRAPH_PRIVATE void
gg_image_destroy(gGraphImagePtr img)430 gg_image_destroy (gGraphImagePtr img)
431 {
432 /* destroying a generic image */
433     if (!img)
434 	return;
435     if (img->pixels)
436 	free (img->pixels);
437     if (img->srs_name)
438 	free (img->srs_name);
439     if (img->proj4text)
440 	free (img->proj4text);
441     free (img);
442 }
443 
444 GGRAPH_PRIVATE gGraphStripImagePtr
gg_strip_image_create(FILE * file_handle,int codec_id,int pixel_format,int width,int height,int bits_per_sample,int samples_per_pixel,int sample_format,const char * srs_name,const char * proj4text)445 gg_strip_image_create (FILE * file_handle, int codec_id, int pixel_format,
446 		       int width, int height, int bits_per_sample,
447 		       int samples_per_pixel, int sample_format,
448 		       const char *srs_name, const char *proj4text)
449 {
450 /* creating a file-based image implementing access by strips */
451     gGraphStripImagePtr img;
452     int len;
453     char *SrsName = NULL;
454     char *Proj4Text = NULL;
455 
456 /* checking PIXEL_FORMAT */
457     if (pixel_format == GG_PIXEL_RGB || pixel_format == GG_PIXEL_RGBA
458 	|| pixel_format == GG_PIXEL_ARGB || pixel_format == GG_PIXEL_BGR
459 	|| pixel_format == GG_PIXEL_GRAYSCALE
460 	|| pixel_format == GG_PIXEL_PALETTE || pixel_format == GG_PIXEL_GRID)
461 	;
462     else
463 	return NULL;
464     if (sample_format == GGRAPH_SAMPLE_UINT
465 	|| sample_format == GGRAPH_SAMPLE_INT
466 	|| sample_format == GGRAPH_SAMPLE_FLOAT)
467 	;
468     else
469 	return NULL;
470 
471     if (srs_name)
472       {
473 	  len = strlen (srs_name);
474 	  if (len > 0)
475 	    {
476 		SrsName = malloc (len + 1);
477 		if (!SrsName)
478 		    return NULL;
479 		strcpy (SrsName, srs_name);
480 	    }
481       }
482     if (proj4text)
483       {
484 	  len = strlen (proj4text);
485 	  if (len > 0)
486 	    {
487 		Proj4Text = malloc (len + 1);
488 		if (!Proj4Text)
489 		  {
490 		      if (SrsName)
491 			  free (SrsName);
492 		      return NULL;
493 		  }
494 		strcpy (Proj4Text, proj4text);
495 	    }
496       }
497 
498 /* allocating the image struct */
499     img = malloc (sizeof (gGraphStripImage));
500     if (!img)
501 	return NULL;
502 
503     img->signature = GG_STRIP_IMAGE_MAGIC_SIGNATURE;
504     img->file_handle = file_handle;
505     img->codec_id = codec_id;
506     img->rows_per_block = 0;
507     img->current_available_rows = 0;
508     img->codec_data = NULL;
509     img->pixels = NULL;
510     img->next_row = 0;
511     img->codec_data = NULL;
512     img->width = width;
513     img->height = height;
514     img->bits_per_sample = bits_per_sample;
515     img->samples_per_pixel = samples_per_pixel;
516     img->sample_format = sample_format;
517     img->pixel_format = pixel_format;
518     img->max_palette = 0;
519     img->is_transparent = 0;
520     img->tile_width = -1;
521     img->tile_height = -1;
522     img->rows_per_strip = -1;
523     img->compression = GGRAPH_TIFF_COMPRESSION_NONE;
524     img->is_georeferenced = 0;
525     img->srid = -1;
526     img->srs_name = SrsName;
527     img->proj4text = Proj4Text;
528     img->upper_left_x = DBL_MAX;
529     img->upper_left_y = DBL_MAX;
530     img->pixel_x_size = 0.0;
531     img->pixel_y_size = 0.0;
532     img->no_data_value = 0.0 - DBL_MAX;
533     img->min_value = DBL_MAX;
534     img->max_value = 0.0 - DBL_MAX;
535 
536 /* computing the scanline size */
537     if (pixel_format == GG_PIXEL_GRAYSCALE || pixel_format == GG_PIXEL_PALETTE)
538       {
539 	  img->scanline_width = width;
540 	  img->pixel_size = 1;
541       }
542     else if (pixel_format == GG_PIXEL_RGB || pixel_format == GG_PIXEL_BGR)
543       {
544 	  img->scanline_width = width * 3;
545 	  img->pixel_size = 3;
546       }
547     else if (pixel_format == GG_PIXEL_GRID)
548       {
549 	  if (sample_format == GGRAPH_SAMPLE_FLOAT)
550 	    {
551 		if (bits_per_sample == 32)
552 		  {
553 		      /* float */
554 		      img->scanline_width = width * 4;
555 		      img->pixel_size = 8;
556 		  }
557 		else
558 		  {
559 		      /* double */
560 		      img->scanline_width = width * 8;
561 		      img->pixel_size = 8;
562 		  }
563 	    }
564 	  else
565 	    {
566 		/* UINT or INT */
567 		if (bits_per_sample == 8)
568 		  {
569 		      /* 8bits int */
570 		      img->scanline_width = width;
571 		      img->pixel_size = 1;
572 		  }
573 		else if (bits_per_sample == 16)
574 		  {
575 		      /* 16bits int */
576 		      img->scanline_width = width * 2;
577 		      img->pixel_size = 2;
578 		  }
579 		else
580 		  {
581 		      /* 32bits int */
582 		      img->scanline_width = width * 4;
583 		      img->pixel_size = 4;
584 		  }
585 	    }
586       }
587     else
588       {
589 	  /* RGBA, ARGB or BGRA */
590 	  img->scanline_width = width * 4;
591 	  img->pixel_size = 4;
592       }
593 
594     return img;
595 }
596 
597 GGRAPH_PRIVATE void
gg_strip_image_destroy(gGraphStripImagePtr img)598 gg_strip_image_destroy (gGraphStripImagePtr img)
599 {
600 /* destroying a file-based image implementing access by strips */
601     if (!img)
602 	return;
603     if (img->codec_id == GGRAPH_IMAGE_PNG)
604 	gg_png_codec_destroy (img->codec_data);
605     if (img->codec_id == GGRAPH_IMAGE_JPEG)
606 	gg_jpeg_codec_destroy (img->codec_data);
607     if (img->codec_id == GGRAPH_IMAGE_TIFF
608 	|| img->codec_id == GGRAPH_IMAGE_GEOTIFF)
609 	gg_tiff_codec_destroy (img->codec_data);
610     if (img->codec_id == GGRAPH_IMAGE_HGT)
611 	gg_grid_codec_destroy (img->codec_data);
612     if (img->file_handle)
613 	fclose (img->file_handle);
614     if (img->pixels)
615 	free (img->pixels);
616     if (img->srs_name)
617 	free (img->srs_name);
618     if (img->proj4text)
619 	free (img->proj4text);
620     free (img);
621 }
622 
623 GGRAPH_PRIVATE void
gg_image_clone_georeferencing(const gGraphImagePtr dst,const gGraphImagePtr src)624 gg_image_clone_georeferencing (const gGraphImagePtr dst,
625 			       const gGraphImagePtr src)
626 {
627 /* adjusting georeferencing infos between two images */
628     double size_x;
629     double size_y;
630     int len;
631     char *SrsName = NULL;
632     char *Proj4Text = NULL;
633     if (src->is_georeferenced)
634       {
635 	  if (src->srs_name)
636 	    {
637 		len = strlen (src->srs_name);
638 		if (len > 0)
639 		  {
640 		      SrsName = malloc (len + 1);
641 		      if (SrsName)
642 			  strcpy (SrsName, src->srs_name);
643 		  }
644 	    }
645 	  if (src->proj4text)
646 	    {
647 		len = strlen (src->proj4text);
648 		if (len > 0)
649 		  {
650 		      Proj4Text = malloc (len + 1);
651 		      if (Proj4Text)
652 			  strcpy (Proj4Text, src->proj4text);
653 		  }
654 	    }
655       }
656 
657 /* cleaning up destination georeferencing */
658     dst->is_georeferenced = 0;
659     dst->srid = -1;
660     if (dst->srs_name)
661 	free (dst->srs_name);
662     if (dst->proj4text)
663 	free (dst->proj4text);
664     dst->srs_name = NULL;
665     dst->proj4text = NULL;
666     dst->upper_left_x = DBL_MAX;
667     dst->upper_left_y = DBL_MAX;
668     dst->pixel_x_size = 0.0;
669     dst->pixel_y_size = 0.0;
670     if (src->is_georeferenced == 0)
671 	return;
672 
673 /* setting up destination georeferencing */
674     dst->is_georeferenced = 1;
675     dst->srid = src->srid;
676     dst->srs_name = SrsName;
677     dst->proj4text = Proj4Text;
678     dst->upper_left_x = src->upper_left_x;
679     dst->upper_left_y = src->upper_left_y;
680     size_x = (double) (src->width) * src->pixel_x_size;
681     size_y = (double) (src->height) * src->pixel_y_size;
682     dst->pixel_x_size = size_x / (double) (dst->width);
683     dst->pixel_y_size = size_y / (double) (dst->height);
684 
685 }
686 
687 static void
sub_set_georeferencing(const gGraphImagePtr dst,const gGraphImagePtr src,int upper_left_x,int upper_left_y)688 sub_set_georeferencing (const gGraphImagePtr dst, const gGraphImagePtr src,
689 			int upper_left_x, int upper_left_y)
690 {
691 /* adjusting georeferencing infos between two images [ImageSubSet] */
692     int len;
693     char *SrsName = NULL;
694     char *Proj4Text = NULL;
695     if (src->is_georeferenced)
696       {
697 	  if (src->srs_name)
698 	    {
699 		len = strlen (src->srs_name);
700 		if (len > 0)
701 		  {
702 		      SrsName = malloc (len + 1);
703 		      if (SrsName)
704 			  strcpy (SrsName, src->srs_name);
705 		  }
706 	    }
707 	  if (src->proj4text)
708 	    {
709 		len = strlen (src->proj4text);
710 		if (len > 0)
711 		  {
712 		      Proj4Text = malloc (len + 1);
713 		      if (Proj4Text)
714 			  strcpy (Proj4Text, src->proj4text);
715 		  }
716 	    }
717       }
718 
719 /* cleaning up destination georeferencing */
720     dst->is_georeferenced = 0;
721     dst->srid = -1;
722     if (dst->srs_name)
723 	free (dst->srs_name);
724     if (dst->proj4text)
725 	free (dst->proj4text);
726     dst->srs_name = NULL;
727     dst->proj4text = NULL;
728     dst->upper_left_x = DBL_MAX;
729     dst->upper_left_y = DBL_MAX;
730     dst->pixel_x_size = 0.0;
731     dst->pixel_y_size = 0.0;
732     if (src->is_georeferenced == 0)
733 	return;
734 
735 /* setting up destination georeferencing */
736     dst->is_georeferenced = 1;
737     dst->srid = src->srid;
738     dst->srs_name = SrsName;
739     dst->proj4text = Proj4Text;
740     dst->upper_left_x =
741 	src->upper_left_x + ((double) upper_left_x * src->pixel_x_size);
742     dst->upper_left_y =
743 	src->upper_left_y - ((double) upper_left_y * src->pixel_y_size);
744     dst->pixel_x_size = src->pixel_x_size;
745     dst->pixel_y_size = src->pixel_y_size;
746 
747 }
748 
749 GGRAPH_PRIVATE void
gg_image_sub_set(const gGraphImagePtr dst,const gGraphImagePtr src,int upper_left_x,int upper_left_y)750 gg_image_sub_set (const gGraphImagePtr dst, const gGraphImagePtr src,
751 		  int upper_left_x, int upper_left_y)
752 {
753 /* creating an ImageSubSet */
754     int x;
755     int y;
756     int dx;
757     int dy = 0;
758     int c;
759     unsigned char *p_in;
760     unsigned char *p_out;
761 
762     if (src->pixel_format != dst->pixel_format)
763       {
764 	  /* an absolutely unexpected condition !!!! */
765 	  return;
766       }
767 
768     for (y = upper_left_y; y < src->height; y++, dy++)
769       {
770 	  if (dy >= dst->height)
771 	      break;
772 	  dx = 0;
773 	  p_in = src->pixels + (y * src->scanline_width);
774 	  p_in += upper_left_x * src->pixel_size;
775 	  p_out = dst->pixels + (dy * dst->scanline_width);
776 	  for (x = upper_left_x; x < src->width; x++, dx++)
777 	    {
778 		if (dx >= dst->width)
779 		    break;
780 		/* copying pixel's components */
781 		for (c = 0; c < src->pixel_size; c++)
782 		    *p_out++ = *p_in++;
783 	    }
784       }
785     if (src->pixel_format == GG_PIXEL_PALETTE)
786       {
787 	  /* copying palette entries */
788 	  for (x = 0; x < src->max_palette; x++)
789 	    {
790 		dst->palette_red[x] = src->palette_red[x];
791 		dst->palette_green[x] = src->palette_green[x];
792 		dst->palette_blue[x] = src->palette_blue[x];
793 	    }
794 	  dst->max_palette = src->max_palette;
795       }
796 
797 /* computing georeferencing */
798     sub_set_georeferencing (dst, src, upper_left_x, upper_left_y);
799 }
800 
801 static unsigned char
to_grayscale(unsigned char r,unsigned char g,unsigned char b)802 to_grayscale (unsigned char r, unsigned char g, unsigned char b)
803 {
804 /* computing a grayscale value */
805     double dval =
806 	(0.3 * (double) r) + (0.59 * (double) g) + (0.11 * (double) b);
807     int ival = (int) dval;
808     if (ival < 0)
809 	ival = 0;
810     if (ival > 255)
811 	ival = 255;
812     return (unsigned char) ival;
813 }
814 
815 GGRAPH_PRIVATE void
gg_image_fill(const gGraphImagePtr img,unsigned char r,unsigned char g,unsigned char b,unsigned char alpha)816 gg_image_fill (const gGraphImagePtr img, unsigned char r, unsigned char g,
817 	       unsigned char b, unsigned char alpha)
818 {
819 /* filling the image with given color */
820     int x;
821     int y;
822     unsigned char *p;
823     unsigned char gray;
824 
825 /* resetting the palette anyway */
826     img->max_palette = 1;
827     img->palette_red[0] = r;
828     img->palette_green[0] = g;
829     img->palette_blue[0] = b;
830 
831 /* precomputing a grayscale value anyway */
832     if (r == g && g == b)
833 	gray = r;
834     else
835 	gray = to_grayscale (r, g, b);
836 
837     for (y = 0; y < img->height; y++)
838       {
839 	  /* setting pixels by scanline */
840 	  p = img->pixels + (y * img->scanline_width);
841 	  for (x = 0; x < img->width; x++)
842 	    {
843 		/* setting pixels */
844 		if (img->pixel_format == GG_PIXEL_RGB)
845 		  {
846 		      *p++ = r;
847 		      *p++ = g;
848 		      *p++ = b;
849 		  }
850 		else if (img->pixel_format == GG_PIXEL_RGBA)
851 		  {
852 		      *p++ = r;
853 		      *p++ = g;
854 		      *p++ = b;
855 		      *p++ = alpha;
856 		  }
857 		else if (img->pixel_format == GG_PIXEL_ARGB)
858 		  {
859 		      *p++ = alpha;
860 		      *p++ = r;
861 		      *p++ = g;
862 		      *p++ = b;
863 		  }
864 		else if (img->pixel_format == GG_PIXEL_BGR)
865 		  {
866 		      *p++ = b;
867 		      *p++ = g;
868 		      *p++ = r;
869 		  }
870 		else if (img->pixel_format == GG_PIXEL_BGRA)
871 		  {
872 		      *p++ = b;
873 		      *p++ = g;
874 		      *p++ = r;
875 		      *p++ = alpha;
876 		  }
877 		else if (img->pixel_format == GG_PIXEL_GRAYSCALE)
878 		    *p++ = gray;
879 		else if (img->pixel_format == GG_PIXEL_PALETTE)
880 		    *p++ = 0;
881 	    }
882       }
883 }
884 
885 GGRAPH_PRIVATE unsigned char
gg_match_palette(const gGraphImagePtr img,unsigned char r,unsigned char g,unsigned char b)886 gg_match_palette (const gGraphImagePtr img, unsigned char r, unsigned char g,
887 		  unsigned char b)
888 {
889 /* handling palette colors */
890     int index;
891     double min_dist = DBL_MAX;
892     double dist;
893     int min_index;
894     for (index = 0; index < img->max_palette; index++)
895       {
896 	  /* searching if already defined */
897 	  if (img->palette_red[index] == r && img->palette_green[index] == g
898 	      && img->palette_blue[index] == b)
899 	      return (unsigned char) index;
900       }
901     if (img->max_palette < 255)
902       {
903 	  /* inserting a new palette entry */
904 	  unsigned char i = img->max_palette;
905 	  img->max_palette += 1;
906 	  img->palette_red[i] = r;
907 	  img->palette_green[i] = g;
908 	  img->palette_blue[i] = b;
909 	  return i;
910       }
911 /* all right, the palette is already fully populated */
912     for (index = 0; index < img->max_palette; index++)
913       {
914 	  /* computing the minimal euclidean distance */
915 	  dist =
916 	      sqrt (((img->palette_red[index] - r) * (img->palette_red[index] -
917 						      r)) +
918 		    ((img->palette_green[index] -
919 		      g) * (img->palette_green[index] - g)) +
920 		    ((img->palette_blue[index] -
921 		      b) * (img->palette_blue[index] - b)));
922 	  if (dist < min_dist)
923 	    {
924 		min_dist = dist;
925 		min_index = index;
926 	    }
927       }
928     return (unsigned char) min_index;
929 }
930 
931 static void
shrink_by(const gGraphImagePtr dst,const gGraphImagePtr src)932 shrink_by (const gGraphImagePtr dst, const gGraphImagePtr src)
933 {
934 /*
935 / this code is widely base upon the original wxWidgets gwxImage wxImage::ShrinkBy(() function
936 */
937     int xFactor = src->width / dst->width;
938     int yFactor = src->height / dst->height;
939     int x;
940     int y;
941     int x1;
942     int y1;
943     int y_offset;
944     int x_offset;
945     unsigned char red;
946     unsigned char green;
947     unsigned char blue;
948     unsigned char gray;
949     unsigned char *p;
950     for (y = 0; y < dst->height; y++)
951       {
952 	  for (x = 0; x < dst->width; x++)
953 	    {
954 		/* determine average */
955 		unsigned int avgRed = 0;
956 		unsigned int avgGreen = 0;
957 		unsigned int avgBlue = 0;
958 		unsigned int counter = 0;
959 		for (y1 = 0; y1 < yFactor; ++y1)
960 		  {
961 		      y_offset = (y * yFactor + y1);
962 		      for (x1 = 0; x1 < xFactor; ++x1)
963 			{
964 			    x_offset = (x * xFactor) + x1;
965 			    p = src->pixels + (y_offset * src->scanline_width);
966 			    if (src->pixel_format == GG_PIXEL_RGB)
967 			      {
968 				  p += x_offset * 3;
969 				  red = *p++;
970 				  green = *p++;
971 				  blue = *p;
972 			      }
973 			    else if (src->pixel_format == GG_PIXEL_RGBA)
974 			      {
975 				  p += x_offset * 4;
976 				  red = *p++;
977 				  green = *p++;
978 				  blue = *p;
979 			      }
980 			    else if (src->pixel_format == GG_PIXEL_ARGB)
981 			      {
982 				  p += x_offset * 4;
983 				  p++;
984 				  red = *p++;
985 				  green = *p++;
986 				  blue = *p;
987 			      }
988 			    else if (src->pixel_format == GG_PIXEL_BGR)
989 			      {
990 				  p += x_offset * 3;
991 				  blue = *p++;
992 				  green = *p++;
993 				  red = *p;
994 			      }
995 			    else if (src->pixel_format == GG_PIXEL_BGRA)
996 			      {
997 				  p += x_offset * 4;
998 				  blue = *p++;
999 				  green = *p++;
1000 				  red = *p;
1001 			      }
1002 			    else if (src->pixel_format == GG_PIXEL_GRAYSCALE)
1003 			      {
1004 				  p += x_offset;
1005 				  red = *p;
1006 				  green = *p;
1007 				  blue = *p;
1008 			      }
1009 			    else if (src->pixel_format == GG_PIXEL_PALETTE)
1010 			      {
1011 				  p += x_offset;
1012 				  red = src->palette_red[*p];
1013 				  green = src->palette_green[*p];
1014 				  blue = src->palette_blue[*p];
1015 			      }
1016 			    avgRed += red;
1017 			    avgGreen += green;
1018 			    avgBlue += blue;
1019 			    counter++;
1020 			}
1021 		  }
1022 		/* storing the pixel into destination */
1023 		red = avgRed / counter;
1024 		green = avgGreen / counter;
1025 		blue = avgBlue / counter;
1026 		p = dst->pixels + (y * dst->scanline_width);
1027 		if (dst->pixel_format == GG_PIXEL_RGB)
1028 		  {
1029 		      p += x * 3;
1030 		      *p++ = red;
1031 		      *p++ = green;
1032 		      *p = blue;
1033 		  }
1034 		else if (dst->pixel_format == GG_PIXEL_RGBA)
1035 		  {
1036 		      p += x * 4;
1037 		      *p++ = red;
1038 		      *p++ = green;
1039 		      *p++ = blue;
1040 		      *p = 255;	/* opaque */
1041 		  }
1042 		else if (dst->pixel_format == GG_PIXEL_ARGB)
1043 		  {
1044 		      p += x * 4;
1045 		      *p++ = 255;	/* opaque */
1046 		      *p++ = red;
1047 		      *p++ = green;
1048 		      *p = blue;
1049 		  }
1050 		else if (dst->pixel_format == GG_PIXEL_BGR)
1051 		  {
1052 		      p += x * 3;
1053 		      *p++ = blue;
1054 		      *p++ = green;
1055 		      *p = red;
1056 		  }
1057 		else if (dst->pixel_format == GG_PIXEL_BGRA)
1058 		  {
1059 		      p += x * 4;
1060 		      *p++ = blue;
1061 		      *p++ = green;
1062 		      *p++ = red;
1063 		      *p = 255;	/* opaque */
1064 		  }
1065 		else if (dst->pixel_format == GG_PIXEL_GRAYSCALE)
1066 		  {
1067 		      p += x;
1068 		      if (red == green && green == blue)
1069 			  gray = red;
1070 		      else
1071 			  gray = to_grayscale (red, green, blue);
1072 		      *p = gray;
1073 		  }
1074 		else if (dst->pixel_format == GG_PIXEL_PALETTE)
1075 		  {
1076 		      unsigned char index =
1077 			  gg_match_palette (dst, red, green, blue);
1078 		      p += x;
1079 		      *p = index;
1080 		  }
1081 	    }
1082       }
1083 }
1084 
1085 GGRAPH_PRIVATE void
gg_image_resize(const gGraphImagePtr dst,const gGraphImagePtr src)1086 gg_image_resize (const gGraphImagePtr dst, const gGraphImagePtr src)
1087 {
1088 /*
1089 / this function builds an ordinary quality resized image, applying pixel replication
1090 /
1091 / this code is widely base upon the original wxWidgets gwxImage wxImage::Scale(() function
1092 / wxIMAGE_QUALITY_NORMAL
1093 */
1094     int x_delta;
1095     int y_delta;
1096     int y;
1097     int j;
1098     int x;
1099     int i;
1100     unsigned char red;
1101     unsigned char green;
1102     unsigned char blue;
1103     unsigned char alpha;
1104     unsigned char gray;
1105     unsigned char *p;
1106 
1107     if ((src->width % dst->width) == 0 && src->width >= dst->width
1108 	&& (src->height % dst->height) == 0 && src->height >= dst->height)
1109       {
1110 	  shrink_by (dst, src);
1111 	  return;
1112       }
1113     x = src->width;
1114     y = src->height;
1115     x_delta = (x << 16) / dst->width;
1116     y_delta = (y << 16) / dst->height;
1117     y = 0;
1118     for (j = 0; j < dst->height; j++)
1119       {
1120 	  x = 0;
1121 	  for (i = 0; i < dst->width; i++)
1122 	    {
1123 		/* retrieving the origin pixel */
1124 		p = src->pixels + ((y >> 16) * src->scanline_width);
1125 		if (src->pixel_format == GG_PIXEL_RGB)
1126 		  {
1127 		      p += (x >> 16) * 3;
1128 		      red = *p++;
1129 		      green = *p++;
1130 		      blue = *p;
1131 		      alpha = 255;
1132 		  }
1133 		else if (src->pixel_format == GG_PIXEL_RGBA)
1134 		  {
1135 		      p += (x >> 16) * 4;
1136 		      red = *p++;
1137 		      green = *p++;
1138 		      blue = *p++;
1139 		      alpha = *p;
1140 		  }
1141 		else if (src->pixel_format == GG_PIXEL_ARGB)
1142 		  {
1143 		      p += (x >> 16) * 4;
1144 		      alpha = *p++;
1145 		      red = *p++;
1146 		      green = *p++;
1147 		      blue = *p;
1148 		  }
1149 		else if (src->pixel_format == GG_PIXEL_BGR)
1150 		  {
1151 		      p += (x >> 16) * 3;
1152 		      blue = *p++;
1153 		      green = *p++;
1154 		      red = *p;
1155 		      alpha = 255;
1156 		  }
1157 		else if (src->pixel_format == GG_PIXEL_BGRA)
1158 		  {
1159 		      p += (x >> 16) * 4;
1160 		      blue = *p++;
1161 		      green = *p++;
1162 		      red = *p++;
1163 		      alpha = *p;
1164 		  }
1165 		else if (src->pixel_format == GG_PIXEL_GRAYSCALE)
1166 		  {
1167 		      p += (x >> 16);
1168 		      red = *p;
1169 		      green = *p;
1170 		      blue = *p;
1171 		      alpha = 255;
1172 		  }
1173 		else if (src->pixel_format == GG_PIXEL_PALETTE)
1174 		  {
1175 		      p += (x >> 16);
1176 		      red = src->palette_red[*p];
1177 		      green = src->palette_green[*p];
1178 		      blue = src->palette_blue[*p];
1179 		      alpha = 255;
1180 		  }
1181 		/* setting the destination pixel */
1182 		p = dst->pixels + (j * dst->scanline_width);
1183 		if (dst->pixel_format == GG_PIXEL_RGB)
1184 		  {
1185 		      p += i * 3;
1186 		      *p++ = red;
1187 		      *p++ = green;
1188 		      *p = blue;
1189 		  }
1190 		else if (dst->pixel_format == GG_PIXEL_RGBA)
1191 		  {
1192 		      p += i * 4;
1193 		      *p++ = red;
1194 		      *p++ = green;
1195 		      *p++ = blue;
1196 		      *p = alpha;
1197 		  }
1198 		else if (dst->pixel_format == GG_PIXEL_ARGB)
1199 		  {
1200 		      p += i * 4;
1201 		      *p++ = alpha;
1202 		      *p++ = red;
1203 		      *p++ = green;
1204 		      *p = blue;
1205 		  }
1206 		else if (dst->pixel_format == GG_PIXEL_BGR)
1207 		  {
1208 		      p += i * 3;
1209 		      *p++ = blue;
1210 		      *p++ = green;
1211 		      *p = red;
1212 		  }
1213 		else if (dst->pixel_format == GG_PIXEL_BGRA)
1214 		  {
1215 		      p += i * 4;
1216 		      *p++ = blue;
1217 		      *p++ = green;
1218 		      *p++ = red;
1219 		      *p = alpha;
1220 		  }
1221 		else if (dst->pixel_format == GG_PIXEL_GRAYSCALE)
1222 		  {
1223 		      p += i;
1224 		      if (red == green && green == blue)
1225 			  gray = red;
1226 		      else
1227 			  gray = to_grayscale (red, green, blue);
1228 		      *p = gray;
1229 		  }
1230 		else if (dst->pixel_format == GG_PIXEL_PALETTE)
1231 		  {
1232 		      unsigned char index =
1233 			  gg_match_palette (dst, red, green, blue);
1234 		      p += i;
1235 		      *p = index;
1236 		  }
1237 		x += x_delta;
1238 	    }
1239 	  y += y_delta;
1240       }
1241 }
1242 
1243 static void
shrink_grid_by(const gGraphImagePtr dst,const gGraphImagePtr src)1244 shrink_grid_by (const gGraphImagePtr dst, const gGraphImagePtr src)
1245 {
1246 /*
1247 / this code is widely base upon the original wxWidgets gwxImage wxImage::ShrinkBy(() function
1248 */
1249     int xFactor = src->width / dst->width;
1250     int yFactor = src->height / dst->height;
1251     int x;
1252     int y;
1253     int x1;
1254     int y1;
1255     int y_offset;
1256     int x_offset;
1257     short short_value;
1258     unsigned short ushort_value;
1259     int int_value;
1260     unsigned int uint_value;
1261     float float_value;
1262     double double_value;
1263     short *p_short;
1264     unsigned short *p_ushort;
1265     int *p_int;
1266     unsigned int *p_uint;
1267     float *p_float;
1268     double *p_double;
1269     for (y = 0; y < dst->height; y++)
1270       {
1271 	  for (x = 0; x < dst->width; x++)
1272 	    {
1273 		/* determine average */
1274 		int is_nodata = 0;
1275 		double avg;
1276 		unsigned int counter = 0;
1277 		unsigned char *p;
1278 		for (y1 = 0; y1 < yFactor; ++y1)
1279 		  {
1280 		      y_offset = (y * yFactor + y1);
1281 		      for (x1 = 0; x1 < xFactor; ++x1)
1282 			{
1283 			    x_offset = (x * xFactor) + x1;
1284 			    p = src->pixels + (y_offset * src->scanline_width);
1285 			    if (src->pixel_format == GG_PIXEL_GRID)
1286 			      {
1287 				  p += x_offset * (src->bits_per_sample / 8);
1288 				  switch (src->sample_format)
1289 				    {
1290 				    case GGRAPH_SAMPLE_INT:
1291 					if (src->bits_per_sample == 16)
1292 					  {
1293 					      p_short = (short *) p;
1294 					      short_value = *p_short;
1295 					      if (short_value ==
1296 						  src->no_data_value)
1297 						  is_nodata = 1;
1298 					      if (!is_nodata)
1299 						  avg += short_value;
1300 					  }
1301 					else
1302 					  {
1303 					      p_int = (int *) p;
1304 					      int_value = *p_int;
1305 					      if (int_value ==
1306 						  src->no_data_value)
1307 						  is_nodata = 1;
1308 					      if (!is_nodata)
1309 						  avg += int_value;
1310 					  }
1311 					break;
1312 				    case GGRAPH_SAMPLE_UINT:
1313 					if (src->bits_per_sample == 16)
1314 					  {
1315 					      p_ushort = (unsigned short *) p;
1316 					      ushort_value = *p_ushort;
1317 					      if (ushort_value ==
1318 						  src->no_data_value)
1319 						  is_nodata = 1;
1320 					      if (!is_nodata)
1321 						  avg += ushort_value;
1322 					  }
1323 					else
1324 					  {
1325 					      p_uint = (unsigned int *) p;
1326 					      uint_value = *p_uint;
1327 					      if (uint_value ==
1328 						  src->no_data_value)
1329 						  is_nodata = 1;
1330 					      if (!is_nodata)
1331 						  avg += uint_value;
1332 					  }
1333 					break;
1334 				    case GGRAPH_SAMPLE_FLOAT:
1335 					if (src->bits_per_sample == 32)
1336 					  {
1337 					      p_float = (float *) p;
1338 					      float_value = *p_float;
1339 					      if (float_value ==
1340 						  src->no_data_value)
1341 						  is_nodata = 1;
1342 					      if (!is_nodata)
1343 						  avg += float_value;
1344 					  }
1345 					else
1346 					  {
1347 					      p_double = (double *) p;
1348 					      double_value = *p_double;
1349 					      if (double_value ==
1350 						  src->no_data_value)
1351 						  is_nodata = 1;
1352 					      if (!is_nodata)
1353 						  avg += double_value;
1354 					  }
1355 					break;
1356 				    };
1357 			      }
1358 			    counter++;
1359 			}
1360 		  }
1361 		/* storing the pixel into destination */
1362 		p = dst->pixels + (y * dst->scanline_width);
1363 		if (dst->pixel_format == GG_PIXEL_GRID)
1364 		  {
1365 		      p += x * (dst->bits_per_sample / 8);
1366 		      switch (dst->sample_format)
1367 			{
1368 			case GGRAPH_SAMPLE_INT:
1369 			    if (dst->bits_per_sample == 16)
1370 			      {
1371 				  p_short = (short *) p;
1372 				  if (is_nodata)
1373 				      *p_short = (short) (dst->no_data_value);
1374 				  else
1375 				      *p_short = (short) (avg / counter);
1376 			      }
1377 			    else
1378 			      {
1379 				  p_int = (int *) p;
1380 				  if (is_nodata)
1381 				      *p_int = (int) (dst->no_data_value);
1382 				  else
1383 				      *p_int = (int) (avg / counter);
1384 			      }
1385 			    break;
1386 			case GGRAPH_SAMPLE_UINT:
1387 			    if (dst->bits_per_sample == 16)
1388 			      {
1389 				  p_ushort = (unsigned short *) p;
1390 				  if (is_nodata)
1391 				      *p_ushort =
1392 					  (unsigned short) (dst->no_data_value);
1393 				  else
1394 				      *p_ushort =
1395 					  (unsigned short) (avg / counter);
1396 			      }
1397 			    else
1398 			      {
1399 				  p_uint = (unsigned int *) p;
1400 				  if (is_nodata)
1401 				      *p_uint =
1402 					  (unsigned int) (dst->no_data_value);
1403 				  else
1404 				      *p_uint = (unsigned int) (avg / counter);
1405 			      }
1406 			    break;
1407 			case GGRAPH_SAMPLE_FLOAT:
1408 			    if (dst->bits_per_sample == 32)
1409 			      {
1410 				  p_float = (float *) p;
1411 				  if (is_nodata)
1412 				      *p_float = (float) (dst->no_data_value);
1413 				  else
1414 				      *p_float = (float) (avg / counter);
1415 			      }
1416 			    else
1417 			      {
1418 				  p_double = (double *) p;
1419 				  if (is_nodata)
1420 				      *p_double = dst->no_data_value;
1421 				  else
1422 				      *p_double = avg / counter;
1423 			      }
1424 			    break;
1425 			};
1426 		  }
1427 	    }
1428       }
1429 }
1430 
1431 GGRAPH_PRIVATE void
gg_grid_resize(const gGraphImagePtr dst,const gGraphImagePtr src)1432 gg_grid_resize (const gGraphImagePtr dst, const gGraphImagePtr src)
1433 {
1434 /*
1435 / this function builds an ordinary quality resized GRID, applying pixel replication
1436 /
1437 / this code is widely base upon the original wxWidgets gwxImage wxImage::Scale(() function
1438 / wxIMAGE_QUALITY_NORMAL
1439 */
1440     int x_delta;
1441     int y_delta;
1442     int y;
1443     int j;
1444     int x;
1445     int i;
1446     short short_value;
1447     unsigned short ushort_value;
1448     int int_value;
1449     unsigned int uint_value;
1450     float float_value;
1451     double double_value;
1452     short *p_short;
1453     unsigned short *p_ushort;
1454     int *p_int;
1455     unsigned int *p_uint;
1456     float *p_float;
1457     double *p_double;
1458 
1459     if ((src->width % dst->width) == 0 && src->width >= dst->width
1460 	&& (src->height % dst->height) == 0 && src->height >= dst->height)
1461       {
1462 	  shrink_grid_by (dst, src);
1463 	  return;
1464       }
1465     x = src->width;
1466     y = src->height;
1467     x_delta = (x << 16) / dst->width;
1468     y_delta = (y << 16) / dst->height;
1469     y = 0;
1470     for (j = 0; j < dst->height; j++)
1471       {
1472 	  x = 0;
1473 	  for (i = 0; i < dst->width; i++)
1474 	    {
1475 		/* retrieving the origin pixel */
1476 		unsigned char *p =
1477 		    src->pixels + ((y >> 16) * src->scanline_width);
1478 		if (src->pixel_format == GG_PIXEL_GRID)
1479 		  {
1480 		      p += (x >> 16) * (src->bits_per_sample / 8);
1481 		      switch (src->sample_format)
1482 			{
1483 			case GGRAPH_SAMPLE_INT:
1484 			    if (src->bits_per_sample == 16)
1485 			      {
1486 				  p_short = (short *) p;
1487 				  short_value = *p_short;
1488 				  p += sizeof (short);
1489 			      }
1490 			    else
1491 			      {
1492 				  p_int = (int *) p;
1493 				  int_value = *p_int;
1494 				  p += sizeof (int);
1495 			      }
1496 			    break;
1497 			case GGRAPH_SAMPLE_UINT:
1498 			    if (src->bits_per_sample == 16)
1499 			      {
1500 				  p_ushort = (unsigned short *) p;
1501 				  ushort_value = *p_ushort;
1502 				  p += sizeof (unsigned short);
1503 			      }
1504 			    else
1505 			      {
1506 				  p_uint = (unsigned int *) p;
1507 				  uint_value = *p_uint;
1508 				  p += sizeof (unsigned int);
1509 			      }
1510 			    break;
1511 			case GGRAPH_SAMPLE_FLOAT:
1512 			    if (src->bits_per_sample == 32)
1513 			      {
1514 				  p_float = (float *) p;
1515 				  float_value = *p_float;
1516 				  p += sizeof (float);
1517 			      }
1518 			    else
1519 			      {
1520 				  p_double = (double *) p;
1521 				  double_value = *p_double;
1522 				  p += sizeof (double);
1523 			      }
1524 			    break;
1525 			};
1526 		  }
1527 		/* setting the destination pixel */
1528 		p = dst->pixels + (j * dst->scanline_width);
1529 		if (dst->pixel_format == GG_PIXEL_GRID)
1530 		  {
1531 		      p += i * (dst->bits_per_sample / 8);
1532 		      switch (dst->sample_format)
1533 			{
1534 			case GGRAPH_SAMPLE_INT:
1535 			    if (dst->bits_per_sample == 16)
1536 			      {
1537 				  p_short = (short *) p;
1538 				  *p_short = short_value;
1539 			      }
1540 			    else
1541 			      {
1542 				  p_int = (int *) p;
1543 				  *p_int = int_value;
1544 			      }
1545 			    break;
1546 			case GGRAPH_SAMPLE_UINT:
1547 			    if (dst->bits_per_sample == 16)
1548 			      {
1549 				  p_ushort = (unsigned short *) p;
1550 				  *p_ushort = ushort_value;
1551 			      }
1552 			    else
1553 			      {
1554 				  p_uint = (unsigned int *) p;
1555 				  *p_uint = uint_value;
1556 			      }
1557 			    break;
1558 			case GGRAPH_SAMPLE_FLOAT:
1559 			    if (dst->bits_per_sample == 32)
1560 			      {
1561 				  p_float = (float *) p;
1562 				  *p_float = float_value;
1563 			      }
1564 			    else
1565 			      {
1566 				  p_double = (double *) p;
1567 				  *p_double = double_value;
1568 			      }
1569 			    break;
1570 			};
1571 		  }
1572 		x += x_delta;
1573 	    }
1574 	  y += y_delta;
1575       }
1576 }
1577 
1578 #define floor2(exp) ((long) exp)
1579 
1580 GGRAPH_PRIVATE void
gg_make_thumbnail(const gGraphImagePtr thumbnail,const gGraphImagePtr image)1581 gg_make_thumbnail (const gGraphImagePtr thumbnail, const gGraphImagePtr image)
1582 {
1583 /*
1584 / this function builds an high quality thumbnail image, applying pixel interpolation
1585 /
1586 / this code is widely base upon the original GD gdImageCopyResampled() function
1587 */
1588     int x, y;
1589     double sy1, sy2, sx1, sx2;
1590     unsigned char r;
1591     unsigned char g;
1592     unsigned char b;
1593     unsigned char a;
1594     unsigned char gray;
1595     unsigned char *p;
1596     for (y = 0; y < thumbnail->height; y++)
1597       {
1598 	  sy1 =
1599 	      ((double) y) * (double) image->height /
1600 	      (double) thumbnail->height;
1601 	  sy2 =
1602 	      ((double) (y + 1)) * (double) image->height /
1603 	      (double) thumbnail->height;
1604 	  for (x = 0; x < thumbnail->width; x++)
1605 	    {
1606 		double sx, sy;
1607 		double spixels = 0;
1608 		double red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
1609 		sx1 =
1610 		    ((double) x) * (double) image->width /
1611 		    (double) thumbnail->width;
1612 		sx2 =
1613 		    ((double) (x + 1)) * (double) image->width /
1614 		    (double) thumbnail->width;
1615 		sy = sy1;
1616 		do
1617 		  {
1618 		      double yportion;
1619 		      if (floor2 (sy) == floor2 (sy1))
1620 			{
1621 			    yportion = 1.0 - (sy - floor2 (sy));
1622 			    if (yportion > sy2 - sy1)
1623 			      {
1624 				  yportion = sy2 - sy1;
1625 			      }
1626 			    sy = floor2 (sy);
1627 			}
1628 		      else if (sy == floor2 (sy2))
1629 			{
1630 			    yportion = sy2 - floor2 (sy2);
1631 			}
1632 		      else
1633 			{
1634 			    yportion = 1.0;
1635 			}
1636 		      sx = sx1;
1637 		      do
1638 			{
1639 			    double xportion;
1640 			    double pcontribution;
1641 			    if (floor2 (sx) == floor2 (sx1))
1642 			      {
1643 				  xportion = 1.0 - (sx - floor2 (sx));
1644 				  if (xportion > sx2 - sx1)
1645 				    {
1646 					xportion = sx2 - sx1;
1647 				    }
1648 				  sx = floor2 (sx);
1649 			      }
1650 			    else if (sx == floor2 (sx2))
1651 			      {
1652 				  xportion = sx2 - floor2 (sx2);
1653 			      }
1654 			    else
1655 			      {
1656 				  xportion = 1.0;
1657 			      }
1658 			    pcontribution = xportion * yportion;
1659 			    /* retrieving the origin pixel */
1660 			    p = image->pixels +
1661 				((int) sy * image->scanline_width);
1662 			    if (image->pixel_format == GG_PIXEL_RGB)
1663 			      {
1664 				  p += (int) sx *3;
1665 				  r = *p++;
1666 				  g = *p++;
1667 				  b = *p;
1668 				  a = 255;
1669 			      }
1670 			    else if (image->pixel_format == GG_PIXEL_RGBA)
1671 			      {
1672 				  p += (int) sx *4;
1673 				  r = *p++;
1674 				  g = *p++;
1675 				  b = *p++;
1676 				  a = *p;
1677 			      }
1678 			    else if (image->pixel_format == GG_PIXEL_ARGB)
1679 			      {
1680 				  p += (int) sx *4;
1681 				  a = *p++;
1682 				  r = *p++;
1683 				  g = *p++;
1684 				  b = *p;
1685 			      }
1686 			    else if (image->pixel_format == GG_PIXEL_BGR)
1687 			      {
1688 				  p += (int) sx *3;
1689 				  b = *p++;
1690 				  g = *p++;
1691 				  r = *p;
1692 				  a = 255;
1693 			      }
1694 			    else if (image->pixel_format == GG_PIXEL_BGRA)
1695 			      {
1696 				  p += (int) sx *4;
1697 				  b = *p++;
1698 				  g = *p++;
1699 				  r = *p++;
1700 				  a = *p;
1701 			      }
1702 			    else if (image->pixel_format == GG_PIXEL_GRAYSCALE)
1703 			      {
1704 				  p += (int) sx;
1705 				  r = *p;
1706 				  g = *p;
1707 				  b = *p;
1708 				  a = 255;
1709 			      }
1710 			    else if (image->pixel_format == GG_PIXEL_PALETTE)
1711 			      {
1712 				  p += (int) sx;
1713 				  r = image->palette_red[*p];
1714 				  g = image->palette_green[*p];
1715 				  b = image->palette_blue[*p];
1716 				  a = 255;
1717 			      }
1718 			    red += r * pcontribution;
1719 			    green += g * pcontribution;
1720 			    blue += b * pcontribution;
1721 			    alpha += a * pcontribution;
1722 			    spixels += xportion * yportion;
1723 			    sx += 1.0;
1724 			}
1725 		      while (sx < sx2);
1726 		      sy += 1.0;
1727 		  }
1728 		while (sy < sy2);
1729 		if (spixels != 0.0)
1730 		  {
1731 		      red /= spixels;
1732 		      green /= spixels;
1733 		      blue /= spixels;
1734 		      alpha /= spixels;
1735 		  }
1736 		if (red > 255.0)
1737 		    red = 255.0;
1738 		if (green > 255.0)
1739 		    green = 255.0;
1740 		if (blue > 255.0)
1741 		    blue = 255.0;
1742 		if (alpha > 255.0)
1743 		    alpha = 255.0;
1744 		/* setting the destination pixel */
1745 		p = thumbnail->pixels + (y * thumbnail->scanline_width);
1746 		if (thumbnail->pixel_format == GG_PIXEL_RGB)
1747 		  {
1748 		      p += x * 3;
1749 		      *p++ = (unsigned char) red;
1750 		      *p++ = (unsigned char) green;
1751 		      *p = (unsigned char) blue;
1752 		  }
1753 		else if (thumbnail->pixel_format == GG_PIXEL_RGBA)
1754 		  {
1755 		      p += x * 4;
1756 		      *p++ = (unsigned char) red;
1757 		      *p++ = (unsigned char) green;
1758 		      *p++ = (unsigned char) blue;
1759 		      *p = (unsigned char) alpha;
1760 		  }
1761 		else if (thumbnail->pixel_format == GG_PIXEL_ARGB)
1762 		  {
1763 		      p += x * 4;
1764 		      *p++ = (unsigned char) alpha;
1765 		      *p++ = (unsigned char) red;
1766 		      *p++ = (unsigned char) green;
1767 		      *p = (unsigned char) blue;
1768 		  }
1769 		else if (thumbnail->pixel_format == GG_PIXEL_BGR)
1770 		  {
1771 		      p += x * 3;
1772 		      *p++ = (unsigned char) blue;
1773 		      *p++ = (unsigned char) green;
1774 		      *p = (unsigned char) red;
1775 		  }
1776 		else if (thumbnail->pixel_format == GG_PIXEL_BGRA)
1777 		  {
1778 		      p += x * 4;
1779 		      *p++ = (unsigned char) blue;
1780 		      *p++ = (unsigned char) green;
1781 		      *p++ = (unsigned char) red;
1782 		      *p = (unsigned char) alpha;
1783 		  }
1784 		else if (thumbnail->pixel_format == GG_PIXEL_GRAYSCALE)
1785 		  {
1786 		      p += x;
1787 		      if (red == green && green == blue)
1788 			  gray = (unsigned char) red;
1789 		      else
1790 			  gray =
1791 			      to_grayscale ((unsigned char) red,
1792 					    (unsigned char) green,
1793 					    (unsigned char) blue);
1794 		      *p = gray;
1795 		  }
1796 		else if (thumbnail->pixel_format == GG_PIXEL_PALETTE)
1797 		  {
1798 		      unsigned char index =
1799 			  gg_match_palette (thumbnail, (unsigned char) red,
1800 					    (unsigned char) green,
1801 					    (unsigned char) blue);
1802 		      p += x;
1803 		      *p = index;
1804 		  }
1805 	    }
1806       }
1807 }
1808 
1809 GGRAPH_PRIVATE void
gg_make_grid_thumbnail(const gGraphImagePtr thumbnail,const gGraphImagePtr image)1810 gg_make_grid_thumbnail (const gGraphImagePtr thumbnail,
1811 			const gGraphImagePtr image)
1812 {
1813 /*
1814 / this function builds an high quality thumbnail image, applying pixel interpolation
1815 /
1816 / this code is widely base upon the original GD gdImageCopyResampled() function
1817 */
1818     int x, y;
1819     double sy1, sy2, sx1, sx2;
1820     short short_value;
1821     unsigned short ushort_value;
1822     int int_value;
1823     unsigned int uint_value;
1824     float float_value;
1825     double double_value;
1826     short *p_short;
1827     unsigned short *p_ushort;
1828     int *p_int;
1829     unsigned int *p_uint;
1830     float *p_float;
1831     double *p_double;
1832     unsigned char *p;
1833     for (y = 0; y < thumbnail->height; y++)
1834       {
1835 	  sy1 =
1836 	      ((double) y) * (double) image->height /
1837 	      (double) thumbnail->height;
1838 	  sy2 =
1839 	      ((double) (y + 1)) * (double) image->height /
1840 	      (double) thumbnail->height;
1841 	  for (x = 0; x < thumbnail->width; x++)
1842 	    {
1843 		double sx, sy;
1844 		double spixels = 0;
1845 		double avg = 0.0;
1846 		int is_nodata = 0;
1847 		sx1 =
1848 		    ((double) x) * (double) image->width /
1849 		    (double) thumbnail->width;
1850 		sx2 =
1851 		    ((double) (x + 1)) * (double) image->width /
1852 		    (double) thumbnail->width;
1853 		sy = sy1;
1854 		do
1855 		  {
1856 		      double yportion;
1857 		      if (floor2 (sy) == floor2 (sy1))
1858 			{
1859 			    yportion = 1.0 - (sy - floor2 (sy));
1860 			    if (yportion > sy2 - sy1)
1861 			      {
1862 				  yportion = sy2 - sy1;
1863 			      }
1864 			    sy = floor2 (sy);
1865 			}
1866 		      else if (sy == floor2 (sy2))
1867 			{
1868 			    yportion = sy2 - floor2 (sy2);
1869 			}
1870 		      else
1871 			{
1872 			    yportion = 1.0;
1873 			}
1874 		      sx = sx1;
1875 		      do
1876 			{
1877 			    double xportion;
1878 			    double pcontribution;
1879 			    if (floor2 (sx) == floor2 (sx1))
1880 			      {
1881 				  xportion = 1.0 - (sx - floor2 (sx));
1882 				  if (xportion > sx2 - sx1)
1883 				    {
1884 					xportion = sx2 - sx1;
1885 				    }
1886 				  sx = floor2 (sx);
1887 			      }
1888 			    else if (sx == floor2 (sx2))
1889 			      {
1890 				  xportion = sx2 - floor2 (sx2);
1891 			      }
1892 			    else
1893 			      {
1894 				  xportion = 1.0;
1895 			      }
1896 			    pcontribution = xportion * yportion;
1897 			    /* retrieving the origin pixel */
1898 			    p = image->pixels +
1899 				((int) sy * image->scanline_width);
1900 			    if (image->pixel_format == GG_PIXEL_GRID)
1901 			      {
1902 				  p += (int) sx *(image->bits_per_sample / 8);
1903 				  switch (image->sample_format)
1904 				    {
1905 				    case GGRAPH_SAMPLE_INT:
1906 					if (image->bits_per_sample == 16)
1907 					  {
1908 					      p_short = (short *) p;
1909 					      short_value = *p_short;
1910 					      if (short_value ==
1911 						  image->no_data_value)
1912 						  is_nodata = 1;
1913 					      else
1914 						  avg +=
1915 						      (double) short_value
1916 						      * pcontribution;
1917 					  }
1918 					else
1919 					  {
1920 					      p_int = (int *) p;
1921 					      int_value = *p_int;
1922 					      if (int_value ==
1923 						  image->no_data_value)
1924 						  is_nodata = 1;
1925 					      else
1926 						  avg +=
1927 						      (double) int_value
1928 						      * pcontribution;
1929 					  }
1930 					break;
1931 				    case GGRAPH_SAMPLE_UINT:
1932 					if (image->bits_per_sample == 16)
1933 					  {
1934 					      p_ushort = (unsigned short *) p;
1935 					      ushort_value = *p_ushort;
1936 					      if (ushort_value ==
1937 						  image->no_data_value)
1938 						  is_nodata = 1;
1939 					      else
1940 						  avg +=
1941 						      (double) ushort_value
1942 						      * pcontribution;
1943 					  }
1944 					else
1945 					  {
1946 					      p_uint = (unsigned int *) p;
1947 					      uint_value = *p_uint;
1948 					      if (uint_value ==
1949 						  image->no_data_value)
1950 						  is_nodata = 1;
1951 					      else
1952 						  avg +=
1953 						      (double) uint_value
1954 						      * pcontribution;
1955 					  }
1956 					break;
1957 				    case GGRAPH_SAMPLE_FLOAT:
1958 					if (image->bits_per_sample == 32)
1959 					  {
1960 					      p_float = (float *) p;
1961 					      float_value = *p_float;
1962 					      if (float_value ==
1963 						  image->no_data_value)
1964 						  is_nodata = 1;
1965 					      else
1966 						  avg +=
1967 						      (double) float_value
1968 						      * pcontribution;
1969 					  }
1970 					else
1971 					  {
1972 					      p_double = (double *) p;
1973 					      double_value = *p_double;
1974 					      if (double_value ==
1975 						  image->no_data_value)
1976 						  is_nodata = 1;
1977 					      else
1978 						  avg +=
1979 						      double_value *
1980 						      pcontribution;
1981 					  }
1982 					break;
1983 				    };
1984 			      }
1985 			    spixels += xportion * yportion;
1986 			    sx += 1.0;
1987 			}
1988 		      while (sx < sx2);
1989 		      sy += 1.0;
1990 		  }
1991 		while (sy < sy2);
1992 		if (spixels != 0.0)
1993 		  {
1994 		      if (!is_nodata)
1995 			  avg /= spixels;
1996 		  }
1997 		/* setting the destination pixel */
1998 		p = thumbnail->pixels + (y * thumbnail->scanline_width);
1999 		if (thumbnail->pixel_format == GG_PIXEL_GRID)
2000 		  {
2001 		      p += x * (thumbnail->bits_per_sample / 8);
2002 		      switch (thumbnail->sample_format)
2003 			{
2004 			case GGRAPH_SAMPLE_INT:
2005 			    if (thumbnail->bits_per_sample == 16)
2006 			      {
2007 				  p_short = (short *) p;
2008 				  if (is_nodata)
2009 				      *p_short =
2010 					  (short) (thumbnail->no_data_value);
2011 				  else
2012 				      *p_short = (short) avg;
2013 			      }
2014 			    else
2015 			      {
2016 				  p_int = (int *) p;
2017 				  if (is_nodata)
2018 				      *p_int = (int) (thumbnail->no_data_value);
2019 				  else
2020 				      *p_int = (int) avg;
2021 			      }
2022 			    break;
2023 			case GGRAPH_SAMPLE_UINT:
2024 			    if (thumbnail->bits_per_sample == 16)
2025 			      {
2026 				  p_ushort = (unsigned short *) p;
2027 				  if (is_nodata)
2028 				      *p_ushort =
2029 					  (unsigned
2030 					   short) (thumbnail->no_data_value);
2031 				  else
2032 				      *p_ushort = (unsigned short) avg;
2033 			      }
2034 			    else
2035 			      {
2036 				  p_uint = (unsigned int *) p;
2037 				  if (is_nodata)
2038 				      *p_uint =
2039 					  (unsigned
2040 					   int) (thumbnail->no_data_value);
2041 				  else
2042 				      *p_uint = (unsigned int) avg;
2043 			      }
2044 			    break;
2045 			case GGRAPH_SAMPLE_FLOAT:
2046 			    if (thumbnail->bits_per_sample == 32)
2047 			      {
2048 				  p_float = (float *) p;
2049 				  if (is_nodata)
2050 				      *p_float =
2051 					  (float) (thumbnail->no_data_value);
2052 				  else
2053 				      *p_float = (float) avg;
2054 			      }
2055 			    else
2056 			      {
2057 				  p_double = (double *) p;
2058 				  if (is_nodata)
2059 				      *p_double = thumbnail->no_data_value;
2060 				  else
2061 				      *p_double = avg;
2062 			      }
2063 			    break;
2064 			};
2065 		  }
2066 	    }
2067       }
2068 }
2069 
2070 GGRAPH_PRIVATE int
gg_convert_image_to_grid_int16(const gGraphImagePtr img)2071 gg_convert_image_to_grid_int16 (const gGraphImagePtr img)
2072 {
2073 /* converting this grid-image to Int16 */
2074     int x;
2075     int y;
2076     void *pixels;
2077     short value;
2078     unsigned char *p_in;
2079     short *p_out;
2080 
2081     if (img->pixel_format != GG_PIXEL_GRID)
2082 	return GGRAPH_INVALID_IMAGE;
2083 
2084     if (img->sample_format == GGRAPH_SAMPLE_INT && img->bits_per_sample == 16)
2085 	return GGRAPH_OK;
2086 
2087     pixels = malloc (img->width * img->height * sizeof (short));
2088     if (!pixels)
2089 	return GGRAPH_INSUFFICIENT_MEMORY;
2090     for (y = 0; y < img->height; y++)
2091       {
2092 	  /* processing any scanline */
2093 	  p_in = img->pixels + (y * img->scanline_width);
2094 	  p_out = pixels;
2095 	  p_out += (y * img->width);
2096 	  for (x = 0; x < img->width; x++)
2097 	    {
2098 		/* retrieving the origin pixel */
2099 		if (img->sample_format == GGRAPH_SAMPLE_UINT
2100 		    && img->bits_per_sample == 16)
2101 		  {
2102 		      value = (short) *((unsigned short *) p_in);
2103 		      p_in += sizeof (unsigned short);
2104 		  }
2105 		if (img->sample_format == GGRAPH_SAMPLE_INT
2106 		    && img->bits_per_sample == 32)
2107 		  {
2108 		      value = (short) *((int *) p_in);
2109 		      p_in += sizeof (int);
2110 		  }
2111 		if (img->sample_format == GGRAPH_SAMPLE_UINT
2112 		    && img->bits_per_sample == 32)
2113 		  {
2114 		      value = (short) *((unsigned int *) p_in);
2115 		      p_in += sizeof (unsigned int);
2116 		  }
2117 		if (img->sample_format == GGRAPH_SAMPLE_FLOAT
2118 		    && img->bits_per_sample == 32)
2119 		  {
2120 		      value = (short) *((float *) p_in);
2121 		      p_in += sizeof (float);
2122 		  }
2123 		if (img->sample_format == GGRAPH_SAMPLE_FLOAT
2124 		    && img->bits_per_sample == 64)
2125 		  {
2126 		      value = (short) *((double *) p_in);
2127 		      p_in += sizeof (double);
2128 		  }
2129 		/* setting the destination pixel */
2130 		*p_out++ = value;
2131 	    }
2132       }
2133 
2134     free (img->pixels);
2135     img->pixels = pixels;
2136     img->pixel_format = GG_PIXEL_GRID;
2137     img->scanline_width = img->width * sizeof (short);
2138     img->pixel_size = sizeof (short);
2139     img->sample_format = GGRAPH_SAMPLE_INT;
2140     img->bits_per_sample = 16;
2141     return GGRAPH_OK;
2142 }
2143 
2144 GGRAPH_PRIVATE int
gg_convert_image_to_grid_uint16(const gGraphImagePtr img)2145 gg_convert_image_to_grid_uint16 (const gGraphImagePtr img)
2146 {
2147 /* converting this grid-image to UInt16 */
2148     int x;
2149     int y;
2150     void *pixels;
2151     unsigned short value;
2152     unsigned char *p_in;
2153     unsigned short *p_out;
2154 
2155     if (img->pixel_format != GG_PIXEL_GRID)
2156 	return GGRAPH_INVALID_IMAGE;
2157 
2158     if (img->sample_format == GGRAPH_SAMPLE_UINT && img->bits_per_sample == 16)
2159 	return GGRAPH_OK;
2160 
2161     pixels = malloc (img->width * img->height * sizeof (unsigned short));
2162     if (!pixels)
2163 	return GGRAPH_INSUFFICIENT_MEMORY;
2164     for (y = 0; y < img->height; y++)
2165       {
2166 	  /* processing any scanline */
2167 	  p_in = img->pixels + (y * img->scanline_width);
2168 	  p_out = pixels;
2169 	  p_out += (y * img->width);
2170 	  for (x = 0; x < img->width; x++)
2171 	    {
2172 		/* retrieving the origin pixel */
2173 		if (img->sample_format == GGRAPH_SAMPLE_INT
2174 		    && img->bits_per_sample == 16)
2175 		  {
2176 		      value = (unsigned short) *((short *) p_in);
2177 		      p_in += sizeof (short);
2178 		  }
2179 		if (img->sample_format == GGRAPH_SAMPLE_INT
2180 		    && img->bits_per_sample == 32)
2181 		  {
2182 		      value = (unsigned short) *((int *) p_in);
2183 		      p_in += sizeof (int);
2184 		  }
2185 		if (img->sample_format == GGRAPH_SAMPLE_UINT
2186 		    && img->bits_per_sample == 32)
2187 		  {
2188 		      value = (unsigned short) *((unsigned int *) p_in);
2189 		      p_in += sizeof (unsigned int);
2190 		  }
2191 		if (img->sample_format == GGRAPH_SAMPLE_FLOAT
2192 		    && img->bits_per_sample == 32)
2193 		  {
2194 		      value = (unsigned short) *((float *) p_in);
2195 		      p_in += sizeof (float);
2196 		  }
2197 		if (img->sample_format == GGRAPH_SAMPLE_FLOAT
2198 		    && img->bits_per_sample == 64)
2199 		  {
2200 		      value = (unsigned short) *((double *) p_in);
2201 		      p_in += sizeof (double);
2202 		  }
2203 		/* setting the destination pixel */
2204 		*p_out++ = value;
2205 	    }
2206       }
2207 
2208     free (img->pixels);
2209     img->pixels = pixels;
2210     img->pixel_format = GG_PIXEL_GRID;
2211     img->scanline_width = img->width * sizeof (unsigned short);
2212     img->pixel_size = sizeof (unsigned short);
2213     img->sample_format = GGRAPH_SAMPLE_UINT;
2214     img->bits_per_sample = 16;
2215     return GGRAPH_OK;
2216 }
2217 
2218 GGRAPH_PRIVATE int
gg_convert_image_to_grid_int32(const gGraphImagePtr img)2219 gg_convert_image_to_grid_int32 (const gGraphImagePtr img)
2220 {
2221 /* converting this grid-image to Int32 */
2222     int x;
2223     int y;
2224     void *pixels;
2225     int value;
2226     unsigned char *p_in;
2227     int *p_out;
2228 
2229     if (img->pixel_format != GG_PIXEL_GRID)
2230 	return GGRAPH_INVALID_IMAGE;
2231 
2232     if (img->sample_format == GGRAPH_SAMPLE_INT && img->bits_per_sample == 32)
2233 	return GGRAPH_OK;
2234 
2235     pixels = malloc (img->width * img->height * sizeof (int));
2236     if (!pixels)
2237 	return GGRAPH_INSUFFICIENT_MEMORY;
2238     for (y = 0; y < img->height; y++)
2239       {
2240 	  /* processing any scanline */
2241 	  p_in = img->pixels + (y * img->scanline_width);
2242 	  p_out = pixels;
2243 	  p_out += (y * img->width);
2244 	  for (x = 0; x < img->width; x++)
2245 	    {
2246 		/* retrieving the origin pixel */
2247 		if (img->sample_format == GGRAPH_SAMPLE_INT
2248 		    && img->bits_per_sample == 16)
2249 		  {
2250 		      value = (int) *((short *) p_in);
2251 		      p_in += sizeof (short);
2252 		  }
2253 		if (img->sample_format == GGRAPH_SAMPLE_UINT
2254 		    && img->bits_per_sample == 16)
2255 		  {
2256 		      value = (int) *((unsigned short *) p_in);
2257 		      p_in += sizeof (unsigned short);
2258 		  }
2259 		if (img->sample_format == GGRAPH_SAMPLE_UINT
2260 		    && img->bits_per_sample == 32)
2261 		  {
2262 		      value = (int) *((unsigned int *) p_in);
2263 		      p_in += sizeof (unsigned int);
2264 		  }
2265 		if (img->sample_format == GGRAPH_SAMPLE_FLOAT
2266 		    && img->bits_per_sample == 32)
2267 		  {
2268 		      value = (int) *((float *) p_in);
2269 		      p_in += sizeof (float);
2270 		  }
2271 		if (img->sample_format == GGRAPH_SAMPLE_FLOAT
2272 		    && img->bits_per_sample == 64)
2273 		  {
2274 		      value = (int) *((double *) p_in);
2275 		      p_in += sizeof (double);
2276 		  }
2277 		/* setting the destination pixel */
2278 		*p_out++ = value;
2279 	    }
2280       }
2281 
2282     free (img->pixels);
2283     img->pixels = pixels;
2284     img->pixel_format = GG_PIXEL_GRID;
2285     img->scanline_width = img->width * sizeof (int);
2286     img->pixel_size = sizeof (int);
2287     img->sample_format = GGRAPH_SAMPLE_INT;
2288     img->bits_per_sample = 32;
2289     return GGRAPH_OK;
2290 }
2291 
2292 GGRAPH_PRIVATE int
gg_convert_image_to_grid_uint32(const gGraphImagePtr img)2293 gg_convert_image_to_grid_uint32 (const gGraphImagePtr img)
2294 {
2295 /* converting this grid-image to UInt32 */
2296     int x;
2297     int y;
2298     void *pixels;
2299     unsigned int value;
2300     unsigned char *p_in;
2301     unsigned int *p_out;
2302 
2303     if (img->pixel_format != GG_PIXEL_GRID)
2304 	return GGRAPH_INVALID_IMAGE;
2305 
2306     if (img->sample_format == GGRAPH_SAMPLE_UINT && img->bits_per_sample == 32)
2307 	return GGRAPH_OK;
2308 
2309     pixels = malloc (img->width * img->height * sizeof (unsigned short));
2310     if (!pixels)
2311 	return GGRAPH_INSUFFICIENT_MEMORY;
2312     for (y = 0; y < img->height; y++)
2313       {
2314 	  /* processing any scanline */
2315 	  p_in = img->pixels + (y * img->scanline_width);
2316 	  p_out = pixels;
2317 	  p_out += (y * img->width);
2318 	  for (x = 0; x < img->width; x++)
2319 	    {
2320 		/* retrieving the origin pixel */
2321 		if (img->sample_format == GGRAPH_SAMPLE_INT
2322 		    && img->bits_per_sample == 16)
2323 		  {
2324 		      value = (unsigned int) *((short *) p_in);
2325 		      p_in += sizeof (short);
2326 		  }
2327 		if (img->sample_format == GGRAPH_SAMPLE_UINT
2328 		    && img->bits_per_sample == 16)
2329 		  {
2330 		      value = (unsigned int) *((unsigned short *) p_in);
2331 		      p_in += sizeof (unsigned short);
2332 		  }
2333 		if (img->sample_format == GGRAPH_SAMPLE_INT
2334 		    && img->bits_per_sample == 32)
2335 		  {
2336 		      value = (unsigned int) *((int *) p_in);
2337 		      p_in += sizeof (int);
2338 		  }
2339 		if (img->sample_format == GGRAPH_SAMPLE_FLOAT
2340 		    && img->bits_per_sample == 32)
2341 		  {
2342 		      value = (unsigned int) *((float *) p_in);
2343 		      p_in += sizeof (float);
2344 		  }
2345 		if (img->sample_format == GGRAPH_SAMPLE_FLOAT
2346 		    && img->bits_per_sample == 64)
2347 		  {
2348 		      value = (unsigned int) *((double *) p_in);
2349 		      p_in += sizeof (double);
2350 		  }
2351 		/* setting the destination pixel */
2352 		*p_out++ = value;
2353 	    }
2354       }
2355 
2356     free (img->pixels);
2357     img->pixels = pixels;
2358     img->pixel_format = GG_PIXEL_GRID;
2359     img->scanline_width = img->width * sizeof (unsigned int);
2360     img->pixel_size = sizeof (unsigned int);
2361     img->sample_format = GGRAPH_SAMPLE_UINT;
2362     img->bits_per_sample = 32;
2363     return GGRAPH_OK;
2364 }
2365 
2366 GGRAPH_PRIVATE int
gg_convert_image_to_grid_float(const gGraphImagePtr img)2367 gg_convert_image_to_grid_float (const gGraphImagePtr img)
2368 {
2369 /* converting this grid-image to Float */
2370     int x;
2371     int y;
2372     void *pixels;
2373     float value;
2374     unsigned char *p_in;
2375     float *p_out;
2376 
2377     if (img->pixel_format != GG_PIXEL_GRID)
2378 	return GGRAPH_INVALID_IMAGE;
2379 
2380     if (img->sample_format == GGRAPH_SAMPLE_FLOAT && img->bits_per_sample == 32)
2381 	return GGRAPH_OK;
2382 
2383     pixels = malloc (img->width * img->height * sizeof (short));
2384     if (!pixels)
2385 	return GGRAPH_INSUFFICIENT_MEMORY;
2386     for (y = 0; y < img->height; y++)
2387       {
2388 	  /* processing any scanline */
2389 	  p_in = img->pixels + (y * img->scanline_width);
2390 	  p_out = pixels;
2391 	  p_out += (y * img->width);
2392 	  for (x = 0; x < img->width; x++)
2393 	    {
2394 		/* retrieving the origin pixel */
2395 		if (img->sample_format == GGRAPH_SAMPLE_INT
2396 		    && img->bits_per_sample == 16)
2397 		  {
2398 		      value = (float) *((short *) p_in);
2399 		      p_in += sizeof (short);
2400 		  }
2401 		if (img->sample_format == GGRAPH_SAMPLE_UINT
2402 		    && img->bits_per_sample == 16)
2403 		  {
2404 		      value = (float) *((unsigned short *) p_in);
2405 		      p_in += sizeof (unsigned short);
2406 		  }
2407 		if (img->sample_format == GGRAPH_SAMPLE_INT
2408 		    && img->bits_per_sample == 32)
2409 		  {
2410 		      value = (float) *((int *) p_in);
2411 		      p_in += sizeof (int);
2412 		  }
2413 		if (img->sample_format == GGRAPH_SAMPLE_UINT
2414 		    && img->bits_per_sample == 32)
2415 		  {
2416 		      value = (float) *((unsigned int *) p_in);
2417 		      p_in += sizeof (unsigned int);
2418 		  }
2419 		if (img->sample_format == GGRAPH_SAMPLE_FLOAT
2420 		    && img->bits_per_sample == 64)
2421 		  {
2422 		      value = (float) *((double *) p_in);
2423 		      p_in += sizeof (double);
2424 		  }
2425 		/* setting the destination pixel */
2426 		*p_out++ = value;
2427 	    }
2428       }
2429 
2430     free (img->pixels);
2431     img->pixels = pixels;
2432     img->pixel_format = GG_PIXEL_GRID;
2433     img->scanline_width = img->width * sizeof (float);
2434     img->pixel_size = sizeof (float);
2435     img->sample_format = GGRAPH_SAMPLE_INT;
2436     img->bits_per_sample = 32;
2437     return GGRAPH_OK;
2438 }
2439 
2440 GGRAPH_PRIVATE int
gg_convert_image_to_grid_double(const gGraphImagePtr img)2441 gg_convert_image_to_grid_double (const gGraphImagePtr img)
2442 {
2443 /* converting this grid-image to Double */
2444     int x;
2445     int y;
2446     void *pixels;
2447     double value;
2448     unsigned char *p_in;
2449     double *p_out;
2450 
2451     if (img->pixel_format != GG_PIXEL_GRID)
2452 	return GGRAPH_INVALID_IMAGE;
2453 
2454     if (img->sample_format == GGRAPH_SAMPLE_FLOAT && img->bits_per_sample == 64)
2455 	return GGRAPH_OK;
2456 
2457     pixels = malloc (img->width * img->height * sizeof (short));
2458     if (!pixels)
2459 	return GGRAPH_INSUFFICIENT_MEMORY;
2460     for (y = 0; y < img->height; y++)
2461       {
2462 	  /* processing any scanline */
2463 	  p_in = img->pixels + (y * img->scanline_width);
2464 	  p_out = pixels;
2465 	  p_out += (y * img->width);
2466 	  for (x = 0; x < img->width; x++)
2467 	    {
2468 		/* retrieving the origin pixel */
2469 		if (img->sample_format == GGRAPH_SAMPLE_INT
2470 		    && img->bits_per_sample == 16)
2471 		  {
2472 		      value = (double) *((short *) p_in);
2473 		      p_in += sizeof (short);
2474 		  }
2475 		if (img->sample_format == GGRAPH_SAMPLE_UINT
2476 		    && img->bits_per_sample == 16)
2477 		  {
2478 		      value = (double) *((unsigned short *) p_in);
2479 		      p_in += sizeof (unsigned short);
2480 		  }
2481 		if (img->sample_format == GGRAPH_SAMPLE_INT
2482 		    && img->bits_per_sample == 32)
2483 		  {
2484 		      value = (double) *((int *) p_in);
2485 		      p_in += sizeof (int);
2486 		  }
2487 		if (img->sample_format == GGRAPH_SAMPLE_UINT
2488 		    && img->bits_per_sample == 32)
2489 		  {
2490 		      value = (double) *((unsigned int *) p_in);
2491 		      p_in += sizeof (unsigned int);
2492 		  }
2493 		if (img->sample_format == GGRAPH_SAMPLE_FLOAT
2494 		    && img->bits_per_sample == 32)
2495 		  {
2496 		      value = (double) *((float *) p_in);
2497 		      p_in += sizeof (float);
2498 		  }
2499 		/* setting the destination pixel */
2500 		*p_out++ = value;
2501 	    }
2502       }
2503 
2504     free (img->pixels);
2505     img->pixels = pixels;
2506     img->pixel_format = GG_PIXEL_GRID;
2507     img->scanline_width = img->width * sizeof (double);
2508     img->pixel_size = sizeof (double);
2509     img->sample_format = GGRAPH_SAMPLE_FLOAT;
2510     img->bits_per_sample = 64;
2511     return GGRAPH_OK;
2512 }
2513 
2514 GGRAPH_PRIVATE int
gg_convert_image_to_rgb(const gGraphImagePtr img)2515 gg_convert_image_to_rgb (const gGraphImagePtr img)
2516 {
2517 /* converting this image to RGB */
2518     int x;
2519     int y;
2520     void *pixels;
2521     unsigned char red;
2522     unsigned char green;
2523     unsigned char blue;
2524     unsigned char *p_in;
2525     unsigned char *p_out;
2526 
2527     if (img->pixel_format == GG_PIXEL_RGB || img->pixel_format == GG_PIXEL_RGBA
2528 	|| img->pixel_format == GG_PIXEL_ARGB
2529 	|| img->pixel_format == GG_PIXEL_BGR
2530 	|| img->pixel_format == GG_PIXEL_BGRA
2531 	|| img->pixel_format == GG_PIXEL_GRAYSCALE
2532 	|| img->pixel_format == GG_PIXEL_PALETTE)
2533 	;
2534     else
2535 	return GGRAPH_INVALID_IMAGE;
2536 
2537     if (img->pixel_format == GG_PIXEL_RGB)
2538 	return GGRAPH_OK;
2539 
2540     pixels = malloc (img->width * img->height * 3);
2541     if (!pixels)
2542 	return GGRAPH_INSUFFICIENT_MEMORY;
2543     for (y = 0; y < img->height; y++)
2544       {
2545 	  /* processing any scanline */
2546 	  p_in = img->pixels + (y * img->scanline_width);
2547 	  p_out = pixels;
2548 	  p_out += (y * img->width * 3);
2549 	  for (x = 0; x < img->width; x++)
2550 	    {
2551 		/* retrieving the origin pixel */
2552 		if (img->pixel_format == GG_PIXEL_RGBA)
2553 		  {
2554 		      red = *p_in++;
2555 		      green = *p_in++;
2556 		      blue = *p_in++;
2557 		      p_in++;	/* skipping alpha */
2558 		  }
2559 		else if (img->pixel_format == GG_PIXEL_ARGB)
2560 		  {
2561 		      p_in++;	/* skipping alpha */
2562 		      red = *p_in++;
2563 		      green = *p_in++;
2564 		      blue = *p_in++;
2565 		  }
2566 		else if (img->pixel_format == GG_PIXEL_BGR)
2567 		  {
2568 		      blue = *p_in++;
2569 		      green = *p_in++;
2570 		      red = *p_in++;
2571 		  }
2572 		else if (img->pixel_format == GG_PIXEL_BGRA)
2573 		  {
2574 		      blue = *p_in++;
2575 		      green = *p_in++;
2576 		      red = *p_in++;
2577 		      p_in++;	/* skipping alpha */
2578 		  }
2579 		else if (img->pixel_format == GG_PIXEL_GRAYSCALE)
2580 		  {
2581 		      red = *p_in++;
2582 		      green = red;
2583 		      blue = red;
2584 
2585 		  }
2586 		else if (img->pixel_format == GG_PIXEL_PALETTE)
2587 		  {
2588 		      int index = *p_in++;
2589 		      red = img->palette_red[index];
2590 		      green = img->palette_green[index];
2591 		      blue = img->palette_blue[index];
2592 		  }
2593 		/* setting the destination pixel */
2594 		*p_out++ = red;
2595 		*p_out++ = green;
2596 		*p_out++ = blue;
2597 	    }
2598       }
2599 
2600     free (img->pixels);
2601     img->pixels = pixels;
2602     img->pixel_format = GG_PIXEL_RGB;
2603     img->scanline_width = img->width * 3;
2604     img->pixel_size = 3;
2605     img->max_palette = 0;
2606     return GGRAPH_OK;
2607 }
2608 
2609 GGRAPH_PRIVATE int
gg_convert_image_to_rgba(const gGraphImagePtr img)2610 gg_convert_image_to_rgba (const gGraphImagePtr img)
2611 {
2612 /* converting this image to RGBA */
2613     int x;
2614     int y;
2615     void *pixels;
2616     unsigned char red;
2617     unsigned char green;
2618     unsigned char blue;
2619     unsigned char alpha;
2620     unsigned char *p_in;
2621     unsigned char *p_out;
2622 
2623     if (img->pixel_format == GG_PIXEL_RGB || img->pixel_format == GG_PIXEL_RGBA
2624 	|| img->pixel_format == GG_PIXEL_ARGB
2625 	|| img->pixel_format == GG_PIXEL_BGR
2626 	|| img->pixel_format == GG_PIXEL_BGRA
2627 	|| img->pixel_format == GG_PIXEL_GRAYSCALE
2628 	|| img->pixel_format == GG_PIXEL_PALETTE)
2629 	;
2630     else
2631 	return GGRAPH_INVALID_IMAGE;
2632 
2633     if (img->pixel_format == GG_PIXEL_RGBA)
2634 	return GGRAPH_OK;
2635 
2636     pixels = malloc (img->width * img->height * 4);
2637     if (!pixels)
2638 	return GGRAPH_INSUFFICIENT_MEMORY;
2639     for (y = 0; y < img->height; y++)
2640       {
2641 	  /* processing any scanline */
2642 	  p_in = img->pixels + (y * img->scanline_width);
2643 	  p_out = pixels;
2644 	  p_out += (y * img->width * 4);
2645 	  for (x = 0; x < img->width; x++)
2646 	    {
2647 		/* retrieving the origin pixel */
2648 		if (img->pixel_format == GG_PIXEL_RGB)
2649 		  {
2650 		      red = *p_in++;
2651 		      green = *p_in++;
2652 		      blue = *p_in++;
2653 		      alpha = 255;
2654 		  }
2655 		else if (img->pixel_format == GG_PIXEL_ARGB)
2656 		  {
2657 		      alpha = *p_in++;
2658 		      red = *p_in++;
2659 		      green = *p_in++;
2660 		      blue = *p_in++;
2661 		  }
2662 		else if (img->pixel_format == GG_PIXEL_BGR)
2663 		  {
2664 		      blue = *p_in++;
2665 		      green = *p_in++;
2666 		      red = *p_in++;
2667 		      alpha = 255;
2668 		  }
2669 		else if (img->pixel_format == GG_PIXEL_BGRA)
2670 		  {
2671 		      blue = *p_in++;
2672 		      green = *p_in++;
2673 		      red = *p_in++;
2674 		      alpha = *p_in++;
2675 		  }
2676 		else if (img->pixel_format == GG_PIXEL_GRAYSCALE)
2677 		  {
2678 		      red = *p_in++;
2679 		      green = red;
2680 		      blue = red;
2681 		      alpha = 255;
2682 		  }
2683 		else if (img->pixel_format == GG_PIXEL_PALETTE)
2684 		  {
2685 		      int index = *p_in++;
2686 		      red = img->palette_red[index];
2687 		      green = img->palette_green[index];
2688 		      blue = img->palette_blue[index];
2689 		      alpha = 255;
2690 		  }
2691 		/* setting the destination pixel */
2692 		*p_out++ = red;
2693 		*p_out++ = green;
2694 		*p_out++ = blue;
2695 		*p_out++ = alpha;
2696 	    }
2697       }
2698 
2699     free (img->pixels);
2700     img->pixels = pixels;
2701     img->pixel_format = GG_PIXEL_RGBA;
2702     img->scanline_width = img->width * 4;
2703     img->pixel_size = 4;
2704     img->max_palette = 0;
2705     return GGRAPH_OK;
2706 }
2707 
2708 GGRAPH_PRIVATE int
gg_convert_image_to_argb(const gGraphImagePtr img)2709 gg_convert_image_to_argb (const gGraphImagePtr img)
2710 {
2711 /* converting this image to ARGB */
2712     int x;
2713     int y;
2714     void *pixels;
2715     unsigned char red;
2716     unsigned char green;
2717     unsigned char blue;
2718     unsigned char alpha;
2719     unsigned char *p_in;
2720     unsigned char *p_out;
2721 
2722     if (img->pixel_format == GG_PIXEL_RGB || img->pixel_format == GG_PIXEL_RGBA
2723 	|| img->pixel_format == GG_PIXEL_ARGB
2724 	|| img->pixel_format == GG_PIXEL_BGR
2725 	|| img->pixel_format == GG_PIXEL_BGRA
2726 	|| img->pixel_format == GG_PIXEL_GRAYSCALE
2727 	|| img->pixel_format == GG_PIXEL_PALETTE)
2728 	;
2729     else
2730 	return GGRAPH_INVALID_IMAGE;
2731 
2732     if (img->pixel_format == GG_PIXEL_ARGB)
2733 	return GGRAPH_OK;
2734 
2735     pixels = malloc (img->width * img->height * 4);
2736     if (!pixels)
2737 	return GGRAPH_INSUFFICIENT_MEMORY;
2738     for (y = 0; y < img->height; y++)
2739       {
2740 	  /* processing any scanline */
2741 	  p_in = img->pixels + (y * img->scanline_width);
2742 	  p_out = pixels;
2743 	  p_out += (y * img->width * 4);
2744 	  for (x = 0; x < img->width; x++)
2745 	    {
2746 		/* retrieving the origin pixel */
2747 		if (img->pixel_format == GG_PIXEL_RGB)
2748 		  {
2749 		      red = *p_in++;
2750 		      green = *p_in++;
2751 		      blue = *p_in++;
2752 		      alpha = 255;
2753 		  }
2754 		else if (img->pixel_format == GG_PIXEL_RGBA)
2755 		  {
2756 		      red = *p_in++;
2757 		      green = *p_in++;
2758 		      blue = *p_in++;
2759 		      alpha = *p_in++;
2760 		  }
2761 		else if (img->pixel_format == GG_PIXEL_BGR)
2762 		  {
2763 		      blue = *p_in++;
2764 		      green = *p_in++;
2765 		      red = *p_in++;
2766 		      alpha = 255;
2767 		  }
2768 		else if (img->pixel_format == GG_PIXEL_BGRA)
2769 		  {
2770 		      blue = *p_in++;
2771 		      green = *p_in++;
2772 		      red = *p_in++;
2773 		      alpha = *p_in++;
2774 		  }
2775 		else if (img->pixel_format == GG_PIXEL_GRAYSCALE)
2776 		  {
2777 		      red = *p_in++;
2778 		      green = red;
2779 		      blue = red;
2780 		      alpha = 255;
2781 		  }
2782 		else if (img->pixel_format == GG_PIXEL_PALETTE)
2783 		  {
2784 		      int index = *p_in++;
2785 		      red = img->palette_red[index];
2786 		      green = img->palette_green[index];
2787 		      blue = img->palette_blue[index];
2788 		      alpha = 255;
2789 		  }
2790 		/* setting the destination pixel */
2791 		*p_out++ = alpha;
2792 		*p_out++ = red;
2793 		*p_out++ = green;
2794 		*p_out++ = blue;
2795 	    }
2796       }
2797 
2798     free (img->pixels);
2799     img->pixels = pixels;
2800     img->pixel_format = GG_PIXEL_ARGB;
2801     img->scanline_width = img->width * 4;
2802     img->pixel_size = 4;
2803     img->max_palette = 0;
2804     return GGRAPH_OK;
2805 }
2806 
2807 GGRAPH_PRIVATE int
gg_convert_image_to_bgr(const gGraphImagePtr img)2808 gg_convert_image_to_bgr (const gGraphImagePtr img)
2809 {
2810 /* converting this image to BGR */
2811     int x;
2812     int y;
2813     void *pixels;
2814     unsigned char red;
2815     unsigned char green;
2816     unsigned char blue;
2817     unsigned char *p_in;
2818     unsigned char *p_out;
2819 
2820     if (img->pixel_format == GG_PIXEL_RGB || img->pixel_format == GG_PIXEL_RGBA
2821 	|| img->pixel_format == GG_PIXEL_ARGB
2822 	|| img->pixel_format == GG_PIXEL_BGR
2823 	|| img->pixel_format == GG_PIXEL_BGRA
2824 	|| img->pixel_format == GG_PIXEL_GRAYSCALE
2825 	|| img->pixel_format == GG_PIXEL_PALETTE)
2826 	;
2827     else
2828 	return GGRAPH_INVALID_IMAGE;
2829 
2830     if (img->pixel_format == GG_PIXEL_BGR)
2831 	return GGRAPH_OK;
2832 
2833     pixels = malloc (img->width * img->height * 3);
2834     if (!pixels)
2835 	return GGRAPH_INSUFFICIENT_MEMORY;
2836     for (y = 0; y < img->height; y++)
2837       {
2838 	  /* processing any scanline */
2839 	  p_in = img->pixels + (y * img->scanline_width);
2840 	  p_out = pixels;
2841 	  p_out += (y * img->width * 3);
2842 	  for (x = 0; x < img->width; x++)
2843 	    {
2844 		/* retrieving the origin pixel */
2845 		if (img->pixel_format == GG_PIXEL_RGB)
2846 		  {
2847 		      red = *p_in++;
2848 		      green = *p_in++;
2849 		      blue = *p_in++;
2850 		  }
2851 		else if (img->pixel_format == GG_PIXEL_RGBA)
2852 		  {
2853 		      red = *p_in++;
2854 		      green = *p_in++;
2855 		      blue = *p_in++;
2856 		      p_in++;	/* skipping alpha */
2857 		  }
2858 		else if (img->pixel_format == GG_PIXEL_ARGB)
2859 		  {
2860 		      p_in++;	/* skipping alpha */
2861 		      blue = *p_in++;
2862 		      green = *p_in++;
2863 		      red = *p_in++;
2864 		  }
2865 		else if (img->pixel_format == GG_PIXEL_BGRA)
2866 		  {
2867 		      blue = *p_in++;
2868 		      green = *p_in++;
2869 		      red = *p_in++;
2870 		      p_in++;	/* skipping alpha */
2871 		  }
2872 		else if (img->pixel_format == GG_PIXEL_GRAYSCALE)
2873 		  {
2874 		      red = *p_in++;
2875 		      green = red;
2876 		      blue = red;
2877 		  }
2878 		else if (img->pixel_format == GG_PIXEL_PALETTE)
2879 		  {
2880 		      int index = *p_in++;
2881 		      red = img->palette_red[index];
2882 		      green = img->palette_green[index];
2883 		      blue = img->palette_blue[index];
2884 		  }
2885 		/* setting the destination pixel */
2886 		*p_out++ = blue;
2887 		*p_out++ = green;
2888 		*p_out++ = red;
2889 	    }
2890       }
2891 
2892     free (img->pixels);
2893     img->pixels = pixels;
2894     img->pixel_format = GG_PIXEL_BGR;
2895     img->scanline_width = img->width * 3;
2896     img->pixel_size = 3;
2897     img->max_palette = 0;
2898     return GGRAPH_OK;
2899 }
2900 
2901 GGRAPH_PRIVATE int
gg_convert_image_to_bgra(const gGraphImagePtr img)2902 gg_convert_image_to_bgra (const gGraphImagePtr img)
2903 {
2904 /* converting this image to BGRA */
2905     int x;
2906     int y;
2907     void *pixels;
2908     unsigned char red;
2909     unsigned char green;
2910     unsigned char blue;
2911     unsigned char alpha;
2912     unsigned char *p_in;
2913     unsigned char *p_out;
2914 
2915     if (img->pixel_format == GG_PIXEL_RGB || img->pixel_format == GG_PIXEL_RGBA
2916 	|| img->pixel_format == GG_PIXEL_ARGB
2917 	|| img->pixel_format == GG_PIXEL_BGR
2918 	|| img->pixel_format == GG_PIXEL_BGRA
2919 	|| img->pixel_format == GG_PIXEL_GRAYSCALE
2920 	|| img->pixel_format == GG_PIXEL_PALETTE)
2921 	;
2922     else
2923 	return GGRAPH_INVALID_IMAGE;
2924 
2925     if (img->pixel_format == GG_PIXEL_ARGB)
2926 	return GGRAPH_OK;
2927 
2928     pixels = malloc (img->width * img->height * 4);
2929     if (!pixels)
2930 	return GGRAPH_INSUFFICIENT_MEMORY;
2931     for (y = 0; y < img->height; y++)
2932       {
2933 	  /* processing any scanline */
2934 	  p_in = img->pixels + (y * img->scanline_width);
2935 	  p_out = pixels;
2936 	  p_out += (y * img->width * 4);
2937 	  for (x = 0; x < img->width; x++)
2938 	    {
2939 		/* retrieving the origin pixel */
2940 		if (img->pixel_format == GG_PIXEL_RGB)
2941 		  {
2942 		      red = *p_in++;
2943 		      green = *p_in++;
2944 		      blue = *p_in++;
2945 		      alpha = 255;
2946 		  }
2947 		else if (img->pixel_format == GG_PIXEL_RGBA)
2948 		  {
2949 		      red = *p_in++;
2950 		      green = *p_in++;
2951 		      blue = *p_in++;
2952 		      alpha = *p_in++;
2953 		  }
2954 		else if (img->pixel_format == GG_PIXEL_ARGB)
2955 		  {
2956 		      alpha = *p_in++;
2957 		      blue = *p_in++;
2958 		      green = *p_in++;
2959 		      red = *p_in++;
2960 		  }
2961 		else if (img->pixel_format == GG_PIXEL_BGR)
2962 		  {
2963 		      blue = *p_in++;
2964 		      green = *p_in++;
2965 		      red = *p_in++;
2966 		      alpha = 255;
2967 		  }
2968 		else if (img->pixel_format == GG_PIXEL_GRAYSCALE)
2969 		  {
2970 		      red = *p_in++;
2971 		      green = red;
2972 		      blue = red;
2973 		      alpha = 255;
2974 		  }
2975 		else if (img->pixel_format == GG_PIXEL_PALETTE)
2976 		  {
2977 		      int index = *p_in++;
2978 		      red = img->palette_red[index];
2979 		      green = img->palette_green[index];
2980 		      blue = img->palette_blue[index];
2981 		      alpha = 255;
2982 		  }
2983 		/* setting the destination pixel */
2984 		*p_out++ = blue;
2985 		*p_out++ = green;
2986 		*p_out++ = red;
2987 		*p_out++ = alpha;
2988 	    }
2989       }
2990 
2991     free (img->pixels);
2992     img->pixels = pixels;
2993     img->pixel_format = GG_PIXEL_BGRA;
2994     img->scanline_width = img->width * 4;
2995     img->pixel_size = 4;
2996     img->max_palette = 0;
2997     return GGRAPH_OK;
2998 }
2999 
3000 GGRAPH_PRIVATE int
gg_convert_image_to_grayscale(const gGraphImagePtr img)3001 gg_convert_image_to_grayscale (const gGraphImagePtr img)
3002 {
3003 /* converting this image to GRAYSCALE */
3004     int x;
3005     int y;
3006     void *pixels;
3007     unsigned char red;
3008     unsigned char green;
3009     unsigned char blue;
3010     unsigned char gray;
3011     unsigned char *p_in;
3012     unsigned char *p_out;
3013 
3014     if (img->pixel_format == GG_PIXEL_RGB || img->pixel_format == GG_PIXEL_RGBA
3015 	|| img->pixel_format == GG_PIXEL_ARGB
3016 	|| img->pixel_format == GG_PIXEL_BGR
3017 	|| img->pixel_format == GG_PIXEL_BGRA
3018 	|| img->pixel_format == GG_PIXEL_GRAYSCALE
3019 	|| img->pixel_format == GG_PIXEL_PALETTE)
3020 	;
3021     else
3022 	return GGRAPH_INVALID_IMAGE;
3023 
3024     if (img->pixel_format == GG_PIXEL_GRAYSCALE)
3025 	return GGRAPH_OK;
3026 
3027     pixels = malloc (img->width * img->height);
3028     if (!pixels)
3029 	return GGRAPH_INSUFFICIENT_MEMORY;
3030     for (y = 0; y < img->height; y++)
3031       {
3032 	  /* processing any scanline */
3033 	  p_in = img->pixels + (y * img->scanline_width);
3034 	  p_out = pixels;
3035 	  p_out += (y * img->width);
3036 	  for (x = 0; x < img->width; x++)
3037 	    {
3038 		/* retrieving the origin pixel */
3039 		if (img->pixel_format == GG_PIXEL_RGB)
3040 		  {
3041 		      red = *p_in++;
3042 		      green = *p_in++;
3043 		      blue = *p_in++;
3044 		  }
3045 		else if (img->pixel_format == GG_PIXEL_RGBA)
3046 		  {
3047 		      red = *p_in++;
3048 		      green = *p_in++;
3049 		      blue = *p_in++;
3050 		      p_in++;	/* skipping alpha */
3051 		  }
3052 		else if (img->pixel_format == GG_PIXEL_ARGB)
3053 		  {
3054 		      p_in++;	/* skipping alpha */
3055 		      blue = *p_in++;
3056 		      green = *p_in++;
3057 		      red = *p_in++;
3058 		  }
3059 		else if (img->pixel_format == GG_PIXEL_BGR)
3060 		  {
3061 		      blue = *p_in++;
3062 		      green = *p_in++;
3063 		      red = *p_in++;
3064 		  }
3065 		else if (img->pixel_format == GG_PIXEL_BGRA)
3066 		  {
3067 		      blue = *p_in++;
3068 		      green = *p_in++;
3069 		      red = *p_in++;
3070 		      p_in++;	/* skipping alpha */
3071 		  }
3072 		else if (img->pixel_format == GG_PIXEL_PALETTE)
3073 		  {
3074 		      int index = *p_in++;
3075 		      red = img->palette_red[index];
3076 		      green = img->palette_green[index];
3077 		      blue = img->palette_blue[index];
3078 		  }
3079 		/* setting the destination pixel */
3080 		gray = to_grayscale (red, green, blue);
3081 		*p_out++ = gray;
3082 	    }
3083       }
3084 
3085     free (img->pixels);
3086     img->pixels = pixels;
3087     img->pixel_format = GG_PIXEL_GRAYSCALE;
3088     img->scanline_width = img->width;
3089     img->pixel_size = 1;
3090     img->max_palette = 0;
3091     return GGRAPH_OK;
3092 }
3093 
3094 GGRAPH_PRIVATE int
gg_convert_image_to_palette(const gGraphImagePtr img)3095 gg_convert_image_to_palette (const gGraphImagePtr img)
3096 {
3097 /* converting this image to PALETTE */
3098     int x;
3099     int y;
3100     void *pixels;
3101     unsigned char red;
3102     unsigned char green;
3103     unsigned char blue;
3104     unsigned char index;
3105     unsigned char *p_in;
3106     unsigned char *p_out;
3107 
3108     if (img->pixel_format == GG_PIXEL_RGB || img->pixel_format == GG_PIXEL_RGBA
3109 	|| img->pixel_format == GG_PIXEL_ARGB
3110 	|| img->pixel_format == GG_PIXEL_BGR
3111 	|| img->pixel_format == GG_PIXEL_BGRA
3112 	|| img->pixel_format == GG_PIXEL_GRAYSCALE
3113 	|| img->pixel_format == GG_PIXEL_PALETTE)
3114 	;
3115     else
3116 	return GGRAPH_INVALID_IMAGE;
3117 
3118     if (img->pixel_format == GG_PIXEL_PALETTE)
3119 	return GGRAPH_OK;
3120 
3121     pixels = malloc (img->width * img->height);
3122     if (!pixels)
3123 	return GGRAPH_INSUFFICIENT_MEMORY;
3124     img->max_palette = 0;
3125     for (y = 0; y < img->height; y++)
3126       {
3127 	  /* processing any scanline */
3128 	  p_in = img->pixels + (y * img->scanline_width);
3129 	  p_out = pixels;
3130 	  p_out += (y * img->width);
3131 	  for (x = 0; x < img->width; x++)
3132 	    {
3133 		/* retrieving the origin pixel */
3134 		if (img->pixel_format == GG_PIXEL_RGB)
3135 		  {
3136 		      red = *p_in++;
3137 		      green = *p_in++;
3138 		      blue = *p_in++;
3139 		  }
3140 		else if (img->pixel_format == GG_PIXEL_RGBA)
3141 		  {
3142 		      red = *p_in++;
3143 		      green = *p_in++;
3144 		      blue = *p_in++;
3145 		      p_in++;	/* skipping alpha */
3146 		  }
3147 		else if (img->pixel_format == GG_PIXEL_ARGB)
3148 		  {
3149 		      p_in++;	/* skipping alpha */
3150 		      blue = *p_in++;
3151 		      green = *p_in++;
3152 		      red = *p_in++;
3153 		  }
3154 		else if (img->pixel_format == GG_PIXEL_BGR)
3155 		  {
3156 		      blue = *p_in++;
3157 		      green = *p_in++;
3158 		      red = *p_in++;
3159 		      p_in++;	/* skipping alpha */
3160 		  }
3161 		else if (img->pixel_format == GG_PIXEL_BGRA)
3162 		  {
3163 		      blue = *p_in++;
3164 		      green = *p_in++;
3165 		      red = *p_in++;
3166 		      p_in++;	/* skipping alpha */
3167 		  }
3168 		else if (img->pixel_format == GG_PIXEL_GRAYSCALE)
3169 		  {
3170 		      red = *p_in++;
3171 		      green = red;
3172 		      blue = red;
3173 		  }
3174 		/* setting the destination pixel */
3175 		index = gg_match_palette (img, red, green, blue);
3176 		*p_out++ = index;
3177 	    }
3178       }
3179 
3180     free (img->pixels);
3181     img->pixels = pixels;
3182     img->pixel_format = GG_PIXEL_PALETTE;
3183     img->scanline_width = img->width;
3184     img->pixel_size = 1;
3185     return GGRAPH_OK;
3186 }
3187 
3188 GGRAPH_PRIVATE int
gg_convert_image_to_monochrome(const gGraphImagePtr img)3189 gg_convert_image_to_monochrome (const gGraphImagePtr img)
3190 {
3191 /* converting this image to MONOCHROME */
3192     int x;
3193     int y;
3194     void *pixels;
3195     unsigned char red;
3196     unsigned char green;
3197     unsigned char blue;
3198     unsigned char index;
3199     unsigned char *p_in;
3200     unsigned char *p_out;
3201 
3202     if (img->pixel_format == GG_PIXEL_RGB || img->pixel_format == GG_PIXEL_RGBA
3203 	|| img->pixel_format == GG_PIXEL_ARGB
3204 	|| img->pixel_format == GG_PIXEL_BGR
3205 	|| img->pixel_format == GG_PIXEL_BGRA
3206 	|| img->pixel_format == GG_PIXEL_GRAYSCALE
3207 	|| img->pixel_format == GG_PIXEL_PALETTE)
3208 	;
3209     else
3210 	return GGRAPH_INVALID_IMAGE;
3211 
3212     if (img->pixel_format == GG_PIXEL_PALETTE
3213 	&& gg_is_image_monochrome_ready (img) == GGRAPH_TRUE)
3214 	return GGRAPH_OK;
3215 
3216     pixels = malloc (img->width * img->height);
3217     if (!pixels)
3218 	return GGRAPH_INSUFFICIENT_MEMORY;
3219     for (y = 0; y < img->height; y++)
3220       {
3221 	  /* processing any scanline */
3222 	  p_in = img->pixels + (y * img->scanline_width);
3223 	  p_out = pixels;
3224 	  p_out += (y * img->width);
3225 	  for (x = 0; x < img->width; x++)
3226 	    {
3227 		/* retrieving the origin pixel */
3228 		if (img->pixel_format == GG_PIXEL_RGB)
3229 		  {
3230 		      red = *p_in++;
3231 		      green = *p_in++;
3232 		      blue = *p_in++;
3233 		  }
3234 		else if (img->pixel_format == GG_PIXEL_RGBA)
3235 		  {
3236 		      red = *p_in++;
3237 		      green = *p_in++;
3238 		      blue = *p_in++;
3239 		      p_in++;	/* skipping alpha */
3240 		  }
3241 		else if (img->pixel_format == GG_PIXEL_ARGB)
3242 		  {
3243 		      p_in++;	/* skipping alpha */
3244 		      blue = *p_in++;
3245 		      green = *p_in++;
3246 		      red = *p_in++;
3247 		  }
3248 		else if (img->pixel_format == GG_PIXEL_BGR)
3249 		  {
3250 		      blue = *p_in++;
3251 		      green = *p_in++;
3252 		      red = *p_in++;
3253 		      p_in++;	/* skipping alpha */
3254 		  }
3255 		else if (img->pixel_format == GG_PIXEL_BGRA)
3256 		  {
3257 		      blue = *p_in++;
3258 		      green = *p_in++;
3259 		      red = *p_in++;
3260 		      p_in++;	/* skipping alpha */
3261 		  }
3262 		else if (img->pixel_format == GG_PIXEL_GRAYSCALE)
3263 		  {
3264 		      red = *p_in++;
3265 		      green = red;
3266 		      blue = red;
3267 		  }
3268 		else if (img->pixel_format == GG_PIXEL_PALETTE)
3269 		  {
3270 		      int index = *p_in++;
3271 		      red = img->palette_red[index];
3272 		      green = img->palette_green[index];
3273 		      blue = img->palette_blue[index];
3274 		  }
3275 		/* setting the destination pixel */
3276 		if (red == 0 && green == 0 && blue == 0)
3277 		    index = 0;
3278 		else if (red == 255 && green == 255 && blue == 255)
3279 		    index = 1;
3280 		else
3281 		  {
3282 		      /* neither WHITE nor BLACK */
3283 		      unsigned char gray = to_grayscale (red, green, blue);
3284 		      if (gray < 128)
3285 			{
3286 			    /* defaulting to BLACK */
3287 			    index = 0;
3288 			}
3289 		      else
3290 			{
3291 			    /* defaulting to WHITE */
3292 			    index = 1;
3293 			}
3294 		  }
3295 		*p_out++ = index;
3296 	    }
3297       }
3298 
3299     free (img->pixels);
3300     img->pixels = pixels;
3301     img->pixel_format = GG_PIXEL_PALETTE;
3302     img->scanline_width = img->width;
3303     img->pixel_size = 1;
3304     img->max_palette = 2;
3305     img->palette_red[0] = 0;
3306     img->palette_green[0] = 0;
3307     img->palette_blue[0] = 0;
3308     img->palette_red[1] = 255;
3309     img->palette_green[1] = 255;
3310     img->palette_blue[1] = 255;
3311     return GGRAPH_OK;
3312 }
3313 
3314 GGRAPH_PRIVATE int
gg_is_image_monochrome_ready(gGraphImagePtr img)3315 gg_is_image_monochrome_ready (gGraphImagePtr img)
3316 {
3317 /*
3318 / checking if this Image is into the Monochrome colorspace and ready to be used
3319 / expected: palette, 2 colors, black&white
3320 */
3321     int i;
3322     int black = 0;
3323     int white = 0;
3324     if (img->pixel_format != GG_PIXEL_PALETTE)
3325 	return GGRAPH_FALSE;
3326     if (img->max_palette != 2)
3327 	return GGRAPH_FALSE;
3328     for (i = 0; i < img->max_palette; i++)
3329       {
3330 	  if (img->palette_red[i] == 0 && img->palette_green[i] == 0
3331 	      && img->palette_blue[i] == 0)
3332 	      black = 1;
3333 	  if (img->palette_red[i] == 255 && img->palette_green[i] == 255
3334 	      && img->palette_blue[i] == 255)
3335 	      white = 1;
3336       }
3337     if (black && white)
3338 	return GGRAPH_TRUE;
3339     return GGRAPH_FALSE;
3340 }
3341 
3342 GGRAPH_PRIVATE int
gg_is_image_monochrome(gGraphImagePtr img)3343 gg_is_image_monochrome (gGraphImagePtr img)
3344 {
3345 /* checking if this Image is into the Monochrome colorspace */
3346     int x;
3347     int y;
3348     unsigned char red;
3349     unsigned char green;
3350     unsigned char blue;
3351     unsigned char *p_in;
3352     for (y = 0; y < img->height; y++)
3353       {
3354 	  p_in = img->pixels + (y * img->scanline_width);
3355 	  for (x = 0; x < img->width; x++)
3356 	    {
3357 		/* retrieving a pixel */
3358 		if (img->pixel_format == GG_PIXEL_RGB)
3359 		  {
3360 		      red = *p_in++;
3361 		      green = *p_in++;
3362 		      blue = *p_in++;
3363 		  }
3364 		else if (img->pixel_format == GG_PIXEL_RGBA)
3365 		  {
3366 		      red = *p_in++;
3367 		      green = *p_in++;
3368 		      blue = *p_in++;
3369 		      p_in++;	/* skipping alpha */
3370 		  }
3371 		else if (img->pixel_format == GG_PIXEL_ARGB)
3372 		  {
3373 		      p_in++;	/* skipping alpha */
3374 		      blue = *p_in++;
3375 		      green = *p_in++;
3376 		      red = *p_in++;
3377 		  }
3378 		else if (img->pixel_format == GG_PIXEL_BGR)
3379 		  {
3380 		      blue = *p_in++;
3381 		      green = *p_in++;
3382 		      red = *p_in++;
3383 		  }
3384 		else if (img->pixel_format == GG_PIXEL_BGRA)
3385 		  {
3386 		      blue = *p_in++;
3387 		      green = *p_in++;
3388 		      red = *p_in++;
3389 		      p_in++;	/* skipping alpha */
3390 		  }
3391 		else if (img->pixel_format == GG_PIXEL_GRAYSCALE)
3392 		  {
3393 		      red = *p_in++;
3394 		      green = red;
3395 		      blue = red;
3396 		  }
3397 		else if (img->pixel_format == GG_PIXEL_PALETTE)
3398 		  {
3399 		      int index = *p_in++;
3400 		      red = img->palette_red[index];
3401 		      green = img->palette_green[index];
3402 		      blue = img->palette_blue[index];
3403 		  }
3404 		if (red == 0 && green == 0 && blue == 0)
3405 		    continue;
3406 		if (red == 255 && green == 255 && blue == 255)
3407 		    continue;
3408 		return GGRAPH_FALSE;
3409 	    }
3410       }
3411     return GGRAPH_TRUE;
3412 }
3413 
3414 GGRAPH_PRIVATE int
gg_is_image_grayscale(gGraphImagePtr img)3415 gg_is_image_grayscale (gGraphImagePtr img)
3416 {
3417 /* checking if this Image is into the GrayScale colorspace */
3418     int x;
3419     int y;
3420     unsigned char red;
3421     unsigned char green;
3422     unsigned char blue;
3423     unsigned char *p_in;
3424     if (img->pixel_format == GG_PIXEL_GRAYSCALE)
3425 	return GGRAPH_TRUE;
3426     for (y = 0; y < img->height; y++)
3427       {
3428 	  p_in = img->pixels + (y * img->scanline_width);
3429 	  for (x = 0; x < img->width; x++)
3430 	    {
3431 		/* retrieving a pixel */
3432 		if (img->pixel_format == GG_PIXEL_RGB)
3433 		  {
3434 		      red = *p_in++;
3435 		      green = *p_in++;
3436 		      blue = *p_in++;
3437 		  }
3438 		else if (img->pixel_format == GG_PIXEL_RGBA)
3439 		  {
3440 		      red = *p_in++;
3441 		      green = *p_in++;
3442 		      blue = *p_in++;
3443 		      p_in++;	/* skipping alpha */
3444 		  }
3445 		else if (img->pixel_format == GG_PIXEL_ARGB)
3446 		  {
3447 		      p_in++;	/* skipping alpha */
3448 		      blue = *p_in++;
3449 		      green = *p_in++;
3450 		      red = *p_in++;
3451 		  }
3452 		else if (img->pixel_format == GG_PIXEL_BGR)
3453 		  {
3454 		      blue = *p_in++;
3455 		      green = *p_in++;
3456 		      red = *p_in++;
3457 		  }
3458 		else if (img->pixel_format == GG_PIXEL_BGRA)
3459 		  {
3460 		      blue = *p_in++;
3461 		      green = *p_in++;
3462 		      red = *p_in++;
3463 		      p_in++;	/* skipping alpha */
3464 		  }
3465 		else if (img->pixel_format == GG_PIXEL_PALETTE)
3466 		  {
3467 		      int index = *p_in++;
3468 		      red = img->palette_red[index];
3469 		      green = img->palette_green[index];
3470 		      blue = img->palette_blue[index];
3471 		  }
3472 		if (red == green && green == blue)
3473 		    continue;
3474 		return GGRAPH_FALSE;
3475 	    }
3476       }
3477     return GGRAPH_TRUE;
3478 }
3479 
3480 static int
palette_check(gGraphImagePtr img,unsigned char r,unsigned char g,unsigned char b)3481 palette_check (gGraphImagePtr img, unsigned char r, unsigned char g,
3482 	       unsigned char b)
3483 {
3484     unsigned char index;
3485     for (index = 0; index < img->max_palette; index++)
3486       {
3487 	  /* searching if already defined */
3488 	  if (img->palette_red[index] == r && img->palette_green[index] == g
3489 	      && img->palette_blue[index] == b)
3490 	      return GGRAPH_TRUE;
3491       }
3492     if (img->max_palette < 255)
3493       {
3494 	  /* inserting a new palette entry */
3495 	  unsigned char i = img->max_palette;
3496 	  img->max_palette += 1;
3497 	  img->palette_red[i] = r;
3498 	  img->palette_green[i] = g;
3499 	  img->palette_blue[i] = b;
3500 	  return GGRAPH_TRUE;
3501       }
3502     return GGRAPH_FALSE;
3503 }
3504 
3505 GGRAPH_PRIVATE int
gg_is_image_palette256(gGraphImagePtr img)3506 gg_is_image_palette256 (gGraphImagePtr img)
3507 {
3508 /* checking if this Image may be represented using a 256 colors palette */
3509     int x;
3510     int y;
3511     unsigned char red;
3512     unsigned char green;
3513     unsigned char blue;
3514     unsigned char *p_in;
3515     if (img->pixel_format == GG_PIXEL_PALETTE
3516 	|| img->pixel_format == GG_PIXEL_GRAYSCALE)
3517 	return GGRAPH_TRUE;
3518     img->max_palette = 0;
3519     for (y = 0; y < img->height; y++)
3520       {
3521 	  p_in = img->pixels + (y * img->scanline_width);
3522 	  for (x = 0; x < img->width; x++)
3523 	    {
3524 		/* retrieving a pixel */
3525 		if (img->pixel_format == GG_PIXEL_RGB)
3526 		  {
3527 		      red = *p_in++;
3528 		      green = *p_in++;
3529 		      blue = *p_in++;
3530 		  }
3531 		else if (img->pixel_format == GG_PIXEL_RGBA)
3532 		  {
3533 		      red = *p_in++;
3534 		      green = *p_in++;
3535 		      blue = *p_in++;
3536 		      p_in++;	/* skipping alpha */
3537 		  }
3538 		else if (img->pixel_format == GG_PIXEL_ARGB)
3539 		  {
3540 		      p_in++;	/* skipping alpha */
3541 		      blue = *p_in++;
3542 		      green = *p_in++;
3543 		      red = *p_in++;
3544 		  }
3545 		else if (img->pixel_format == GG_PIXEL_BGR)
3546 		  {
3547 		      blue = *p_in++;
3548 		      green = *p_in++;
3549 		      red = *p_in++;
3550 		  }
3551 		else if (img->pixel_format == GG_PIXEL_BGRA)
3552 		  {
3553 		      blue = *p_in++;
3554 		      green = *p_in++;
3555 		      red = *p_in++;
3556 		      p_in++;	/* skipping alpha */
3557 		  }
3558 		if (palette_check (img, red, green, blue) == GGRAPH_FALSE)
3559 		    return GGRAPH_FALSE;
3560 	    }
3561       }
3562     return GGRAPH_TRUE;
3563 }
3564 
3565 static gGraphImagePtr
raw_monochrome(unsigned char * p,int width,int height)3566 raw_monochrome (unsigned char *p, int width, int height)
3567 {
3568 /* creating a visible image from RAW MONOCHROME */
3569     int x;
3570     int y;
3571     int line_width;
3572     gGraphImagePtr img = gg_image_create (GG_PIXEL_PALETTE, width, height, 8, 1,
3573 					  GGRAPH_SAMPLE_UINT, NULL, NULL);
3574 
3575     if (!img)
3576 	return NULL;
3577 
3578     img->max_palette = 2;
3579     img->palette_red[0] = 255;
3580     img->palette_green[0] = 255;
3581     img->palette_blue[0] = 255;
3582     img->palette_red[1] = 0;
3583     img->palette_green[1] = 0;
3584     img->palette_blue[1] = 0;
3585 
3586     line_width = width / 8;
3587     if ((line_width * 8) < width)
3588 	line_width++;
3589 
3590     for (y = 0; y < height; y++)
3591       {
3592 	  unsigned char *p_in = p + (y * line_width);
3593 	  unsigned char *p_out = img->pixels + (y * img->scanline_width);
3594 	  unsigned char byte = 0x00;
3595 	  unsigned char px;
3596 	  int pixel;
3597 	  int pos = 0;
3598 	  for (x = 0; x < width; x++)
3599 	    {
3600 		if (pos == 0)
3601 		    byte = *p_in++;
3602 		pixel = 0;
3603 		switch (pos)
3604 		  {
3605 		  case 0:
3606 		      px = byte & 0x80;
3607 		      if (px == 0x80)
3608 			  pixel = 1;
3609 		      break;
3610 		  case 1:
3611 		      px = byte & 0x40;
3612 		      if (px == 0x40)
3613 			  pixel = 1;
3614 		      break;
3615 		  case 2:
3616 		      px = byte & 0x20;
3617 		      if (px == 0x20)
3618 			  pixel = 1;
3619 		      break;
3620 		  case 3:
3621 		      px = byte & 0x10;
3622 		      if (px == 0x10)
3623 			  pixel = 1;
3624 		      break;
3625 		  case 4:
3626 		      px = byte & 0x08;
3627 		      if (px == 0x08)
3628 			  pixel = 1;
3629 		      break;
3630 		  case 5:
3631 		      px = byte & 0x04;
3632 		      if (px == 0x04)
3633 			  pixel = 1;
3634 		      break;
3635 		  case 6:
3636 		      px = byte & 0x02;
3637 		      if (px == 0x02)
3638 			  pixel = 1;
3639 		      break;
3640 		  case 7:
3641 		      px = byte & 0x01;
3642 		      if (px == 0x01)
3643 			  pixel = 1;
3644 		      break;
3645 		  };
3646 		*p_out++ = pixel;
3647 		pos++;
3648 		if (pos > 7)
3649 		  {
3650 		      byte = 0x00;
3651 		      pos = 0;
3652 		  }
3653 	    }
3654       }
3655     return img;
3656 }
3657 
3658 static gGraphImagePtr
raw_rgb(unsigned char * p,int width,int height)3659 raw_rgb (unsigned char *p, int width, int height)
3660 {
3661 /* creating a visible image from RAW RGB */
3662     int y;
3663     gGraphImagePtr img =
3664 	gg_image_create (GG_PIXEL_RGB, width, height, 8, 3, GGRAPH_SAMPLE_UINT,
3665 			 NULL, NULL);
3666 
3667     if (!img)
3668 	return NULL;
3669 
3670     for (y = 0; y < height; y++)
3671       {
3672 	  unsigned char *p_in = p + (y * img->scanline_width);
3673 	  unsigned char *p_out = img->pixels + (y * img->scanline_width);
3674 	  memcpy (p_out, p_in, img->scanline_width);
3675       }
3676     return img;
3677 }
3678 
3679 static gGraphImagePtr
raw_grayscale(unsigned char * p,int width,int height)3680 raw_grayscale (unsigned char *p, int width, int height)
3681 {
3682 /* creating a visible image from RAW GRAYSCALE */
3683     int y;
3684     gGraphImagePtr img =
3685 	gg_image_create (GG_PIXEL_GRAYSCALE, width, height, 8, 1,
3686 			 GGRAPH_SAMPLE_UINT, NULL, NULL);
3687 
3688     if (!img)
3689 	return NULL;
3690 
3691     for (y = 0; y < height; y++)
3692       {
3693 	  unsigned char *p_in = p + (y * img->scanline_width);
3694 	  unsigned char *p_out = img->pixels + (y * img->scanline_width);
3695 	  memcpy (p_out, p_in, img->scanline_width);
3696       }
3697     return img;
3698 }
3699 
3700 static gGraphImagePtr
raw_palette(unsigned char * p,int width,int height)3701 raw_palette (unsigned char *p, int width, int height)
3702 {
3703 /* creating a visible image from RAW PALETTE */
3704     int x;
3705     int y;
3706     gGraphImagePtr img = gg_image_create (GG_PIXEL_PALETTE, width, height, 8, 1,
3707 					  GGRAPH_SAMPLE_UINT, NULL, NULL);
3708 
3709     if (!img)
3710 	return NULL;
3711 
3712     srand (1);
3713     for (y = 0; y < height; y++)
3714       {
3715 	  unsigned char *p_in = p + (y * img->scanline_width);
3716 	  unsigned char *p_out = img->pixels + (y * img->scanline_width);
3717 	  for (x = 0; x < width; x++)
3718 	    {
3719 		unsigned int col;
3720 		int idx = *p_in++;
3721 		*p_out++ = idx;
3722 		if (img->max_palette < (idx + 1))
3723 		  {
3724 		      img->max_palette = idx + 1;
3725 		      col = 255 - (unsigned int) rand () % 256;
3726 		      img->palette_red[idx] = col;
3727 		      col = (unsigned int) rand () % 256;
3728 		      img->palette_green[idx] = col;
3729 		      col = 255 - (unsigned int) rand () % 256;
3730 		      img->palette_blue[idx] = col;
3731 		  }
3732 	    }
3733       }
3734     return img;
3735 }
3736 
3737 static gGraphImagePtr
raw_int16(unsigned char * p,int width,int height,int endian)3738 raw_int16 (unsigned char *p, int width, int height, int endian)
3739 {
3740 /* creating a visible image from RAW GRID-INT16 */
3741     int x;
3742     int y;
3743     int endian_arch = gg_endian_arch ();
3744     unsigned char *p_in;
3745     short value;
3746     short min = SHRT_MAX;
3747     short max = SHRT_MIN;
3748     double step;
3749     double gray;
3750     gGraphImagePtr img =
3751 	gg_image_create (GG_PIXEL_GRAYSCALE, width, height, 8, 1,
3752 			 GGRAPH_SAMPLE_UINT, NULL, NULL);
3753 
3754     if (!img)
3755 	return NULL;
3756 
3757     for (y = 0; y < height; y++)
3758       {
3759 	  /* identifying Min/Max values */
3760 	  p_in = p + (y * width * sizeof (short));
3761 	  for (x = 0; x < width; x++)
3762 	    {
3763 		value = gg_import_int16 (p_in, endian, endian_arch);
3764 		p_in += sizeof (short);
3765 		if (value > max)
3766 		    max = value;
3767 		if (value < min)
3768 		    min = value;
3769 	    }
3770       }
3771     step = (double) (max - min) / 256.0;
3772     for (y = 0; y < height; y++)
3773       {
3774 	  /* visualizing as Grayscale */
3775 	  unsigned char *p_out = img->pixels + (y * img->scanline_width);
3776 	  p_in = p + (y * width * sizeof (short));
3777 	  for (x = 0; x < width; x++)
3778 	    {
3779 		value = gg_import_int16 (p_in, endian, endian_arch);
3780 		p_in += sizeof (short);
3781 		gray = (double) (value - min) / step;
3782 		if (gray < 0.0)
3783 		    gray = 0.0;
3784 		if (gray > 255)
3785 		    gray = 255.0;
3786 		*p_out++ = (short) gray;
3787 	    }
3788       }
3789     return img;
3790 }
3791 
3792 static gGraphImagePtr
raw_int32(unsigned char * p,int width,int height,int endian)3793 raw_int32 (unsigned char *p, int width, int height, int endian)
3794 {
3795 /* creating a visible image from RAW GRID-INT32 */
3796     int x;
3797     int y;
3798     int endian_arch = gg_endian_arch ();
3799     unsigned char *p_in;
3800     int value;
3801     int min = INT_MAX;
3802     int max = INT_MIN;
3803     double step;
3804     double gray;
3805     gGraphImagePtr img =
3806 	gg_image_create (GG_PIXEL_GRAYSCALE, width, height, 8, 1,
3807 			 GGRAPH_SAMPLE_UINT, NULL, NULL);
3808 
3809     if (!img)
3810 	return NULL;
3811 
3812     for (y = 0; y < height; y++)
3813       {
3814 	  /* identifying Min/Max values */
3815 	  p_in = p + (y * width * sizeof (int));
3816 	  for (x = 0; x < width; x++)
3817 	    {
3818 		value = gg_import_int32 (p_in, endian, endian_arch);
3819 		p_in += sizeof (int);
3820 		if (value > max)
3821 		    max = value;
3822 		if (value < min)
3823 		    min = value;
3824 	    }
3825       }
3826     step = (double) (max - min) / 256.0;
3827     for (y = 0; y < height; y++)
3828       {
3829 	  /* visualizing as Grayscale */
3830 	  unsigned char *p_out = img->pixels + (y * img->scanline_width);
3831 	  p_in = p + (y * width * sizeof (int));
3832 	  for (x = 0; x < width; x++)
3833 	    {
3834 		value = gg_import_int32 (p_in, endian, endian_arch);
3835 		p_in += sizeof (int);
3836 		gray = (double) (value - min) / step;
3837 		if (gray < 0.0)
3838 		    gray = 0.0;
3839 		if (gray > 255)
3840 		    gray = 255.0;
3841 		*p_out++ = (short) gray;
3842 	    }
3843       }
3844     return img;
3845 }
3846 
3847 static gGraphImagePtr
raw_uint16(unsigned char * p,int width,int height,int endian)3848 raw_uint16 (unsigned char *p, int width, int height, int endian)
3849 {
3850 /* creating a visible image from RAW GRID-UINT16 */
3851     int x;
3852     int y;
3853     int endian_arch = gg_endian_arch ();
3854     unsigned char *p_in;
3855     unsigned short value;
3856     unsigned short min = USHRT_MAX;
3857     unsigned short max = 0;
3858     double step;
3859     double gray;
3860     gGraphImagePtr img =
3861 	gg_image_create (GG_PIXEL_GRAYSCALE, width, height, 8, 1,
3862 			 GGRAPH_SAMPLE_UINT, NULL, NULL);
3863 
3864     if (!img)
3865 	return NULL;
3866 
3867     for (y = 0; y < height; y++)
3868       {
3869 	  /* identifying Min/Max values */
3870 	  p_in = p + (y * width * sizeof (unsigned short));
3871 	  for (x = 0; x < width; x++)
3872 	    {
3873 		value = gg_import_uint16 (p_in, endian, endian_arch);
3874 		p_in += sizeof (unsigned short);
3875 		if (value > max)
3876 		    max = value;
3877 		if (value < min)
3878 		    min = value;
3879 	    }
3880       }
3881     step = (double) (max - min) / 256.0;
3882     for (y = 0; y < height; y++)
3883       {
3884 	  /* visualizing as Grayscale */
3885 	  unsigned char *p_out = img->pixels + (y * img->scanline_width);
3886 	  p_in = p + (y * width * sizeof (unsigned short));
3887 	  for (x = 0; x < width; x++)
3888 	    {
3889 		value = gg_import_uint16 (p_in, endian, endian_arch);
3890 		p_in += sizeof (unsigned short);
3891 		gray = (double) (value - min) / step;
3892 		if (gray < 0.0)
3893 		    gray = 0.0;
3894 		if (gray > 255)
3895 		    gray = 255.0;
3896 		*p_out++ = (short) gray;
3897 	    }
3898       }
3899     return img;
3900 }
3901 
3902 static gGraphImagePtr
raw_uint32(unsigned char * p,int width,int height,int endian)3903 raw_uint32 (unsigned char *p, int width, int height, int endian)
3904 {
3905 /* creating a visible image from RAW GRID-UINT32 */
3906     int x;
3907     int y;
3908     int endian_arch = gg_endian_arch ();
3909     unsigned char *p_in;
3910     unsigned int value;
3911     unsigned int min = UINT_MAX;
3912     unsigned int max = 0;
3913     double step;
3914     double gray;
3915     gGraphImagePtr img =
3916 	gg_image_create (GG_PIXEL_GRAYSCALE, width, height, 8, 1,
3917 			 GGRAPH_SAMPLE_UINT, NULL, NULL);
3918 
3919     if (!img)
3920 	return NULL;
3921 
3922     for (y = 0; y < height; y++)
3923       {
3924 	  /* identifying Min/Max values */
3925 	  p_in = p + (y * width * sizeof (int));
3926 	  for (x = 0; x < width; x++)
3927 	    {
3928 		value = gg_import_uint32 (p_in, endian, endian_arch);
3929 		p_in += sizeof (unsigned int);
3930 		if (value > max)
3931 		    max = value;
3932 		if (value < min)
3933 		    min = value;
3934 	    }
3935       }
3936     step = (double) (max - min) / 256.0;
3937     for (y = 0; y < height; y++)
3938       {
3939 	  /* visualizing as Grayscale */
3940 	  unsigned char *p_out = img->pixels + (y * img->scanline_width);
3941 	  p_in = p + (y * width * sizeof (unsigned int));
3942 	  for (x = 0; x < width; x++)
3943 	    {
3944 		value = gg_import_uint32 (p_in, endian, endian_arch);
3945 		p_in += sizeof (unsigned int);
3946 		gray = (double) (value - min) / step;
3947 		if (gray < 0.0)
3948 		    gray = 0.0;
3949 		if (gray > 255)
3950 		    gray = 255.0;
3951 		*p_out++ = (short) gray;
3952 	    }
3953       }
3954     return img;
3955 }
3956 
3957 static gGraphImagePtr
raw_float(unsigned char * p,int width,int height,int endian)3958 raw_float (unsigned char *p, int width, int height, int endian)
3959 {
3960 /* creating a visible image from RAW GRID-FLOAT */
3961     int x;
3962     int y;
3963     int endian_arch = gg_endian_arch ();
3964     unsigned char *p_in;
3965     float value;
3966     float min = FLT_MAX;
3967     float max = 0.0 - FLT_MAX;
3968     double step;
3969     double gray;
3970     gGraphImagePtr img =
3971 	gg_image_create (GG_PIXEL_GRAYSCALE, width, height, 8, 1,
3972 			 GGRAPH_SAMPLE_UINT, NULL, NULL);
3973 
3974     if (!img)
3975 	return NULL;
3976 
3977     for (y = 0; y < height; y++)
3978       {
3979 	  /* identifying Min/Max values */
3980 	  p_in = p + (y * width * sizeof (float));
3981 	  for (x = 0; x < width; x++)
3982 	    {
3983 		value = gg_import_float (p_in, endian, endian_arch);
3984 		p_in += sizeof (float);
3985 		if (value > max)
3986 		    max = value;
3987 		if (value < min)
3988 		    min = value;
3989 	    }
3990       }
3991     step = (double) (max - min) / 256.0;
3992     for (y = 0; y < height; y++)
3993       {
3994 	  /* visualizing as Grayscale */
3995 	  unsigned char *p_out = img->pixels + (y * img->scanline_width);
3996 	  p_in = p + (y * width * sizeof (float));
3997 	  for (x = 0; x < width; x++)
3998 	    {
3999 		value = gg_import_float (p_in, endian, endian_arch);
4000 		p_in += sizeof (float);
4001 		gray = (double) (value - min) / step;
4002 		if (gray < 0.0)
4003 		    gray = 0.0;
4004 		if (gray > 255)
4005 		    gray = 255.0;
4006 		*p_out++ = (short) gray;
4007 	    }
4008       }
4009     return img;
4010 }
4011 
4012 static gGraphImagePtr
raw_double(unsigned char * p,int width,int height,int endian)4013 raw_double (unsigned char *p, int width, int height, int endian)
4014 {
4015 /* creating a visible image from RAW GRID-DOUBLE */
4016     int x;
4017     int y;
4018     int endian_arch = gg_endian_arch ();
4019     unsigned char *p_in;
4020     double value;
4021     double min = DBL_MAX;
4022     double max = 0.0 - DBL_MAX;
4023     double step;
4024     double gray;
4025     gGraphImagePtr img =
4026 	gg_image_create (GG_PIXEL_GRAYSCALE, width, height, 8, 1,
4027 			 GGRAPH_SAMPLE_UINT, NULL, NULL);
4028 
4029     if (!img)
4030 	return NULL;
4031 
4032     for (y = 0; y < height; y++)
4033       {
4034 	  /* identifying Min/Max values */
4035 	  p_in = p + (y * width * sizeof (float));
4036 	  for (x = 0; x < width; x++)
4037 	    {
4038 		value = gg_import_double (p_in, endian, endian_arch);
4039 		p_in += sizeof (double);
4040 		if (value > max)
4041 		    max = value;
4042 		if (value < min)
4043 		    min = value;
4044 	    }
4045       }
4046     step = (double) (max - min) / 256.0;
4047     for (y = 0; y < height; y++)
4048       {
4049 	  /* visualizing as Grayscale */
4050 	  unsigned char *p_out = img->pixels + (y * img->scanline_width);
4051 	  p_in = p + (y * width * sizeof (double));
4052 	  for (x = 0; x < width; x++)
4053 	    {
4054 		value = gg_import_double (p_in, endian, endian_arch);
4055 		p_in += sizeof (double);
4056 		gray = (value - min) / step;
4057 		if (gray < 0.0)
4058 		    gray = 0.0;
4059 		if (gray > 255)
4060 		    gray = 255.0;
4061 		*p_out++ = (short) gray;
4062 	    }
4063       }
4064     return img;
4065 }
4066 
4067 GGRAPH_PRIVATE int
gg_image_from_raw(int mem_buf_size,const void * mem_buf,gGraphImagePtr * image_handle)4068 gg_image_from_raw (int mem_buf_size, const void *mem_buf,
4069 		   gGraphImagePtr * image_handle)
4070 {
4071 /* importing a RAW image */
4072     gGraphImagePtr img = NULL;
4073     int width;
4074     int height;
4075     int line_width;
4076     unsigned char *p = (unsigned char *) mem_buf;
4077     short start_signature;
4078     short end_signature;
4079     int endian_arch = gg_endian_arch ();
4080 
4081     *image_handle = NULL;
4082     if (mem_buf_size < (int) (sizeof (short) * 4))
4083 	return GGRAPH_ERROR;
4084 
4085 /* checking the magic signature */
4086     start_signature = gg_import_int16 (p, 1, endian_arch);
4087     p = (unsigned char *) mem_buf + mem_buf_size - sizeof (short);
4088     end_signature = gg_import_int16 (p, 1, endian_arch);
4089     if (start_signature == GG_MONOCHROME_START
4090 	&& end_signature == GG_MONOCHROME_END)
4091       {
4092 	  p = (unsigned char *) mem_buf + sizeof (short);
4093 	  width = gg_import_int16 (p, 0, endian_arch);
4094 	  p += sizeof (short);
4095 	  height = gg_import_int16 (p, 0, endian_arch);
4096 	  p += sizeof (short);
4097 	  line_width = width / 8;
4098 	  if ((line_width * 8) < width)
4099 	      line_width++;
4100 	  if ((line_width * height) !=
4101 	      (int) (mem_buf_size - (4 * sizeof (short))))
4102 	      return GGRAPH_ERROR;
4103 	  img = raw_monochrome (p, width, height);
4104 	  if (!img)
4105 	      return GGRAPH_ERROR;
4106 	  *image_handle = img;
4107 	  return GGRAPH_OK;
4108       }
4109     if ((start_signature == GG_ADAM7_1_RGB_START
4110 	 && end_signature == GG_ADAM7_1_RGB_END) ||
4111 	(start_signature == GG_ADAM7_3_RGB_START
4112 	 && end_signature == GG_ADAM7_3_RGB_END) ||
4113 	(start_signature == GG_ADAM7_5_RGB_START
4114 	 && end_signature == GG_ADAM7_5_RGB_END))
4115       {
4116 	  p = (unsigned char *) mem_buf + sizeof (short);
4117 	  width = gg_import_int16 (p, 1, endian_arch);
4118 	  p += sizeof (short);
4119 	  height = gg_import_int16 (p, 1, endian_arch);
4120 	  p += sizeof (short);
4121 	  line_width = width * 3;
4122 	  if ((line_width * height) !=
4123 	      (int) (mem_buf_size - (4 * sizeof (short))))
4124 	      return GGRAPH_ERROR;
4125 	  img = raw_rgb (p, width, height);
4126 	  if (!img)
4127 	      return GGRAPH_ERROR;
4128 	  *image_handle = img;
4129 	  return GGRAPH_OK;
4130       }
4131     if ((start_signature == GG_ADAM7_1_GRAYSCALE_START
4132 	 && end_signature == GG_ADAM7_1_GRAYSCALE_END) ||
4133 	(start_signature == GG_ADAM7_3_GRAYSCALE_START
4134 	 && end_signature == GG_ADAM7_3_GRAYSCALE_END) ||
4135 	(start_signature == GG_ADAM7_5_GRAYSCALE_START
4136 	 && end_signature == GG_ADAM7_5_GRAYSCALE_END))
4137       {
4138 	  p = (unsigned char *) mem_buf + sizeof (short);
4139 	  width = gg_import_int16 (p, 1, endian_arch);
4140 	  p += sizeof (short);
4141 	  height = gg_import_int16 (p, 1, endian_arch);
4142 	  p += sizeof (short);
4143 	  line_width = width;
4144 	  if ((line_width * height) !=
4145 	      (int) (mem_buf_size - (4 * sizeof (short))))
4146 	      return GGRAPH_ERROR;
4147 	  img = raw_grayscale (p, width, height);
4148 	  if (!img)
4149 	      return GGRAPH_ERROR;
4150 	  *image_handle = img;
4151 	  return GGRAPH_OK;
4152       }
4153     if ((start_signature == GG_ADAM7_1_PALETTE_START
4154 	 && end_signature == GG_ADAM7_1_PALETTE_END) ||
4155 	(start_signature == GG_ADAM7_3_PALETTE_START
4156 	 && end_signature == GG_ADAM7_3_PALETTE_END) ||
4157 	(start_signature == GG_ADAM7_5_PALETTE_START
4158 	 && end_signature == GG_ADAM7_5_PALETTE_END))
4159       {
4160 	  p = (unsigned char *) mem_buf + sizeof (short);
4161 	  width = gg_import_int16 (p, 1, endian_arch);
4162 	  p += sizeof (short);
4163 	  height = gg_import_int16 (p, 1, endian_arch);
4164 	  p += sizeof (short);
4165 	  line_width = width;
4166 	  if ((line_width * height) !=
4167 	      (int) (mem_buf_size - (4 * sizeof (short))))
4168 	      return GGRAPH_ERROR;
4169 	  img = raw_palette (p, width, height);
4170 	  if (!img)
4171 	      return GGRAPH_ERROR;
4172 	  *image_handle = img;
4173 	  return GGRAPH_OK;
4174       }
4175     if ((start_signature == GG_ADAM7_1_INT16_START
4176 	 && end_signature == GG_ADAM7_1_INT16_END) ||
4177 	(start_signature == GG_ADAM7_3_INT16_START
4178 	 && end_signature == GG_ADAM7_3_INT16_END) ||
4179 	(start_signature == GG_ADAM7_5_INT16_START
4180 	 && end_signature == GG_ADAM7_5_INT16_END))
4181       {
4182 	  p = (unsigned char *) mem_buf + sizeof (short);
4183 	  width = gg_import_int16 (p, 1, endian_arch);
4184 	  p += sizeof (short);
4185 	  height = gg_import_int16 (p, 1, endian_arch);
4186 	  p += sizeof (short);
4187 	  line_width = width * sizeof (short);
4188 	  if ((line_width * height) !=
4189 	      (int) (mem_buf_size - (4 * sizeof (short))))
4190 	      return GGRAPH_ERROR;
4191 	  img = raw_int16 (p, width, height, 1);
4192 	  if (!img)
4193 	      return GGRAPH_ERROR;
4194 	  *image_handle = img;
4195 	  return GGRAPH_OK;
4196       }
4197     if ((start_signature == GG_ADAM7_1_UINT16_START
4198 	 && end_signature == GG_ADAM7_1_UINT16_END) ||
4199 	(start_signature == GG_ADAM7_3_UINT16_START
4200 	 && end_signature == GG_ADAM7_3_UINT16_END) ||
4201 	(start_signature == GG_ADAM7_5_UINT16_START
4202 	 && end_signature == GG_ADAM7_5_UINT16_END))
4203       {
4204 	  p = (unsigned char *) mem_buf + sizeof (short);
4205 	  width = gg_import_int16 (p, 1, endian_arch);
4206 	  p += sizeof (short);
4207 	  height = gg_import_int16 (p, 1, endian_arch);
4208 	  p += sizeof (short);
4209 	  line_width = width * sizeof (unsigned short);
4210 	  if ((line_width * height) !=
4211 	      (int) (mem_buf_size - (4 * sizeof (short))))
4212 	      return GGRAPH_ERROR;
4213 	  img = raw_uint16 (p, width, height, 1);
4214 	  if (!img)
4215 	      return GGRAPH_ERROR;
4216 	  *image_handle = img;
4217 	  return GGRAPH_OK;
4218       }
4219     if ((start_signature == GG_ADAM7_1_INT32_START
4220 	 && end_signature == GG_ADAM7_1_INT32_END) ||
4221 	(start_signature == GG_ADAM7_3_INT32_START
4222 	 && end_signature == GG_ADAM7_3_INT32_END) ||
4223 	(start_signature == GG_ADAM7_5_INT32_START
4224 	 && end_signature == GG_ADAM7_5_INT32_END))
4225       {
4226 	  p = (unsigned char *) mem_buf + sizeof (short);
4227 	  width = gg_import_int16 (p, 1, endian_arch);
4228 	  p += sizeof (short);
4229 	  height = gg_import_int16 (p, 1, endian_arch);
4230 	  p += sizeof (short);
4231 	  line_width = width * sizeof (int);
4232 	  if ((line_width * height) !=
4233 	      (int) (mem_buf_size - (4 * sizeof (short))))
4234 	      return GGRAPH_ERROR;
4235 	  img = raw_int32 (p, width, height, 1);
4236 	  if (!img)
4237 	      return GGRAPH_ERROR;
4238 	  *image_handle = img;
4239 	  return GGRAPH_OK;
4240       }
4241     if ((start_signature == GG_ADAM7_1_UINT32_START
4242 	 && end_signature == GG_ADAM7_1_UINT32_END) ||
4243 	(start_signature == GG_ADAM7_3_UINT32_START
4244 	 && end_signature == GG_ADAM7_3_UINT32_END) ||
4245 	(start_signature == GG_ADAM7_5_UINT32_START
4246 	 && end_signature == GG_ADAM7_5_UINT32_END))
4247       {
4248 	  p = (unsigned char *) mem_buf + sizeof (short);
4249 	  width = gg_import_int16 (p, 1, endian_arch);
4250 	  p += sizeof (short);
4251 	  height = gg_import_int16 (p, 1, endian_arch);
4252 	  p += sizeof (short);
4253 	  line_width = width * sizeof (unsigned int);
4254 	  if ((line_width * height) !=
4255 	      (int) (mem_buf_size - (4 * sizeof (short))))
4256 	      return GGRAPH_ERROR;
4257 	  img = raw_uint32 (p, width, height, 1);
4258 	  if (!img)
4259 	      return GGRAPH_ERROR;
4260 	  *image_handle = img;
4261 	  return GGRAPH_OK;
4262       }
4263     if ((start_signature == GG_ADAM7_1_FLOAT_START
4264 	 && end_signature == GG_ADAM7_1_FLOAT_END) ||
4265 	(start_signature == GG_ADAM7_3_FLOAT_START
4266 	 && end_signature == GG_ADAM7_3_FLOAT_END) ||
4267 	(start_signature == GG_ADAM7_5_FLOAT_START
4268 	 && end_signature == GG_ADAM7_5_FLOAT_END))
4269       {
4270 	  p = (unsigned char *) mem_buf + sizeof (short);
4271 	  width = gg_import_int16 (p, 1, endian_arch);
4272 	  p += sizeof (short);
4273 	  height = gg_import_int16 (p, 1, endian_arch);
4274 	  p += sizeof (short);
4275 	  line_width = width * sizeof (float);
4276 	  if ((line_width * height) !=
4277 	      (int) (mem_buf_size - (4 * sizeof (short))))
4278 	      return GGRAPH_ERROR;
4279 	  img = raw_float (p, width, height, 1);
4280 	  if (!img)
4281 	      return GGRAPH_ERROR;
4282 	  *image_handle = img;
4283 	  return GGRAPH_OK;
4284       }
4285     if ((start_signature == GG_ADAM7_1_DOUBLE_START
4286 	 && end_signature == GG_ADAM7_1_DOUBLE_END) ||
4287 	(start_signature == GG_ADAM7_3_DOUBLE_START
4288 	 && end_signature == GG_ADAM7_3_DOUBLE_END) ||
4289 	(start_signature == GG_ADAM7_5_DOUBLE_START
4290 	 && end_signature == GG_ADAM7_5_DOUBLE_END))
4291       {
4292 	  p = (unsigned char *) mem_buf + sizeof (short);
4293 	  width = gg_import_int16 (p, 1, endian_arch);
4294 	  p += sizeof (short);
4295 	  height = gg_import_int16 (p, 1, endian_arch);
4296 	  p += sizeof (short);
4297 	  line_width = width * sizeof (double);
4298 	  if ((line_width * height) !=
4299 	      (int) (mem_buf_size - (4 * sizeof (short))))
4300 	      return GGRAPH_ERROR;
4301 	  img = raw_double (p, width, height, 1);
4302 	  if (!img)
4303 	      return GGRAPH_ERROR;
4304 	  *image_handle = img;
4305 	  return GGRAPH_OK;
4306       }
4307 
4308     p = (unsigned char *) mem_buf;
4309     start_signature = gg_import_int16 (p, 0, endian_arch);
4310     p = (unsigned char *) mem_buf + mem_buf_size - sizeof (short);
4311     end_signature = gg_import_int16 (p, 0, endian_arch);
4312     if ((start_signature == GG_ADAM7_0_RGB_START
4313 	 && end_signature == GG_ADAM7_0_RGB_END) ||
4314 	(start_signature == GG_ADAM7_2_RGB_START
4315 	 && end_signature == GG_ADAM7_2_RGB_END) ||
4316 	(start_signature == GG_ADAM7_4_RGB_START
4317 	 && end_signature == GG_ADAM7_4_RGB_END) ||
4318 	(start_signature == GG_ADAM7_6_RGB_START
4319 	 && end_signature == GG_ADAM7_6_RGB_END))
4320       {
4321 	  p = (unsigned char *) mem_buf + sizeof (short);
4322 	  width = gg_import_int16 (p, 0, endian_arch);
4323 	  p += sizeof (short);
4324 	  height = gg_import_int16 (p, 0, endian_arch);
4325 	  p += sizeof (short);
4326 	  img = raw_rgb (p, width, height);
4327 	  if (!img)
4328 	      return GGRAPH_ERROR;
4329 	  *image_handle = img;
4330 	  return GGRAPH_OK;
4331       }
4332     if ((start_signature == GG_ADAM7_0_GRAYSCALE_START
4333 	 && end_signature == GG_ADAM7_0_GRAYSCALE_END) ||
4334 	(start_signature == GG_ADAM7_2_GRAYSCALE_START
4335 	 && end_signature == GG_ADAM7_2_GRAYSCALE_END) ||
4336 	(start_signature == GG_ADAM7_4_GRAYSCALE_START
4337 	 && end_signature == GG_ADAM7_4_GRAYSCALE_END) ||
4338 	(start_signature == GG_ADAM7_6_GRAYSCALE_START
4339 	 && end_signature == GG_ADAM7_6_GRAYSCALE_END))
4340       {
4341 	  p = (unsigned char *) mem_buf + sizeof (short);
4342 	  width = gg_import_int16 (p, 0, endian_arch);
4343 	  p += sizeof (short);
4344 	  height = gg_import_int16 (p, 0, endian_arch);
4345 	  p += sizeof (short);
4346 	  img = raw_grayscale (p, width, height);
4347 	  if (!img)
4348 	      return GGRAPH_ERROR;
4349 	  *image_handle = img;
4350 	  return GGRAPH_OK;
4351       }
4352     if ((start_signature == GG_ADAM7_0_PALETTE_START
4353 	 && end_signature == GG_ADAM7_0_PALETTE_END) ||
4354 	(start_signature == GG_ADAM7_2_PALETTE_START
4355 	 && end_signature == GG_ADAM7_2_PALETTE_END) ||
4356 	(start_signature == GG_ADAM7_4_PALETTE_START
4357 	 && end_signature == GG_ADAM7_4_PALETTE_END) ||
4358 	(start_signature == GG_ADAM7_6_PALETTE_START
4359 	 && end_signature == GG_ADAM7_6_PALETTE_END))
4360       {
4361 	  p = (unsigned char *) mem_buf + sizeof (short);
4362 	  width = gg_import_int16 (p, 0, endian_arch);
4363 	  p += sizeof (short);
4364 	  height = gg_import_int16 (p, 0, endian_arch);
4365 	  p += sizeof (short);
4366 	  img = raw_palette (p, width, height);
4367 	  if (!img)
4368 	      return GGRAPH_ERROR;
4369 	  *image_handle = img;
4370 	  return GGRAPH_OK;
4371       }
4372     if ((start_signature == GG_ADAM7_0_INT16_START
4373 	 && end_signature == GG_ADAM7_0_INT16_END) ||
4374 	(start_signature == GG_ADAM7_2_INT16_START
4375 	 && end_signature == GG_ADAM7_2_INT16_END) ||
4376 	(start_signature == GG_ADAM7_4_INT16_START
4377 	 && end_signature == GG_ADAM7_4_INT16_END) ||
4378 	(start_signature == GG_ADAM7_6_INT16_START
4379 	 && end_signature == GG_ADAM7_6_INT16_END))
4380       {
4381 	  p = (unsigned char *) mem_buf + sizeof (short);
4382 	  width = gg_import_int16 (p, 0, endian_arch);
4383 	  p += sizeof (short);
4384 	  height = gg_import_int16 (p, 0, endian_arch);
4385 	  p += sizeof (short);
4386 	  img = raw_int16 (p, width, height, 0);
4387 	  if (!img)
4388 	      return GGRAPH_ERROR;
4389 	  *image_handle = img;
4390 	  return GGRAPH_OK;
4391       }
4392     if ((start_signature == GG_ADAM7_0_UINT16_START
4393 	 && end_signature == GG_ADAM7_0_UINT16_END) ||
4394 	(start_signature == GG_ADAM7_2_UINT16_START
4395 	 && end_signature == GG_ADAM7_2_UINT16_END) ||
4396 	(start_signature == GG_ADAM7_4_UINT16_START
4397 	 && end_signature == GG_ADAM7_4_UINT16_END) ||
4398 	(start_signature == GG_ADAM7_6_UINT16_START
4399 	 && end_signature == GG_ADAM7_6_UINT16_END))
4400       {
4401 	  p = (unsigned char *) mem_buf + sizeof (short);
4402 	  width = gg_import_int16 (p, 0, endian_arch);
4403 	  p += sizeof (short);
4404 	  height = gg_import_int16 (p, 0, endian_arch);
4405 	  p += sizeof (short);
4406 	  img = raw_uint16 (p, width, height, 0);
4407 	  if (!img)
4408 	      return GGRAPH_ERROR;
4409 	  *image_handle = img;
4410 	  return GGRAPH_OK;
4411       }
4412     if ((start_signature == GG_ADAM7_0_INT32_START
4413 	 && end_signature == GG_ADAM7_0_INT32_END) ||
4414 	(start_signature == GG_ADAM7_2_INT32_START
4415 	 && end_signature == GG_ADAM7_2_INT32_END) ||
4416 	(start_signature == GG_ADAM7_4_INT32_START
4417 	 && end_signature == GG_ADAM7_4_INT32_END) ||
4418 	(start_signature == GG_ADAM7_6_INT32_START
4419 	 && end_signature == GG_ADAM7_6_INT32_END))
4420       {
4421 	  p = (unsigned char *) mem_buf + sizeof (short);
4422 	  width = gg_import_int16 (p, 0, endian_arch);
4423 	  p += sizeof (short);
4424 	  height = gg_import_int16 (p, 0, endian_arch);
4425 	  p += sizeof (short);
4426 	  img = raw_int32 (p, width, height, 0);
4427 	  if (!img)
4428 	      return GGRAPH_ERROR;
4429 	  *image_handle = img;
4430 	  return GGRAPH_OK;
4431       }
4432     if ((start_signature == GG_ADAM7_0_UINT32_START
4433 	 && end_signature == GG_ADAM7_0_UINT32_END) ||
4434 	(start_signature == GG_ADAM7_2_UINT32_START
4435 	 && end_signature == GG_ADAM7_2_UINT32_END) ||
4436 	(start_signature == GG_ADAM7_4_UINT32_START
4437 	 && end_signature == GG_ADAM7_4_UINT32_END) ||
4438 	(start_signature == GG_ADAM7_6_UINT32_START
4439 	 && end_signature == GG_ADAM7_6_UINT32_END))
4440       {
4441 	  p = (unsigned char *) mem_buf + sizeof (short);
4442 	  width = gg_import_int16 (p, 0, endian_arch);
4443 	  p += sizeof (short);
4444 	  height = gg_import_int16 (p, 0, endian_arch);
4445 	  p += sizeof (short);
4446 	  img = raw_uint32 (p, width, height, 0);
4447 	  if (!img)
4448 	      return GGRAPH_ERROR;
4449 	  *image_handle = img;
4450 	  return GGRAPH_OK;
4451       }
4452     if ((start_signature == GG_ADAM7_0_FLOAT_START
4453 	 && end_signature == GG_ADAM7_0_FLOAT_END) ||
4454 	(start_signature == GG_ADAM7_2_FLOAT_START
4455 	 && end_signature == GG_ADAM7_2_FLOAT_END) ||
4456 	(start_signature == GG_ADAM7_4_FLOAT_START
4457 	 && end_signature == GG_ADAM7_4_FLOAT_END) ||
4458 	(start_signature == GG_ADAM7_6_FLOAT_START
4459 	 && end_signature == GG_ADAM7_6_FLOAT_END))
4460       {
4461 	  p = (unsigned char *) mem_buf + sizeof (short);
4462 	  width = gg_import_int16 (p, 0, endian_arch);
4463 	  p += sizeof (short);
4464 	  height = gg_import_int16 (p, 0, endian_arch);
4465 	  p += sizeof (short);
4466 	  img = raw_float (p, width, height, 0);
4467 	  if (!img)
4468 	      return GGRAPH_ERROR;
4469 	  *image_handle = img;
4470 	  return GGRAPH_OK;
4471       }
4472     if ((start_signature == GG_ADAM7_0_DOUBLE_START
4473 	 && end_signature == GG_ADAM7_0_DOUBLE_END) ||
4474 	(start_signature == GG_ADAM7_2_DOUBLE_START
4475 	 && end_signature == GG_ADAM7_2_DOUBLE_END) ||
4476 	(start_signature == GG_ADAM7_4_DOUBLE_START
4477 	 && end_signature == GG_ADAM7_4_DOUBLE_END) ||
4478 	(start_signature == GG_ADAM7_6_DOUBLE_START
4479 	 && end_signature == GG_ADAM7_6_DOUBLE_END))
4480       {
4481 	  p = (unsigned char *) mem_buf + sizeof (short);
4482 	  width = gg_import_int16 (p, 0, endian_arch);
4483 	  p += sizeof (short);
4484 	  height = gg_import_int16 (p, 0, endian_arch);
4485 	  p += sizeof (short);
4486 	  img = raw_double (p, width, height, 0);
4487 	  if (!img)
4488 	      return GGRAPH_ERROR;
4489 	  *image_handle = img;
4490 	  return GGRAPH_OK;
4491       }
4492 
4493     return GGRAPH_ERROR;
4494 }
4495 
4496 static int
is_near_transparent(unsigned char r,unsigned char g,unsigned char b,const gGraphImagePtr img)4497 is_near_transparent (unsigned char r, unsigned char g, unsigned char b,
4498 		     const gGraphImagePtr img)
4499 {
4500 /* checking if this one is a near-transparent value */
4501     int diff;
4502     if (r == img->transparent_red && g == img->transparent_green
4503 	&& b == img->transparent_blue)
4504 	return 0;
4505     diff = r - img->transparent_red;
4506     if (diff <= 8 && diff >= -8)
4507 	;
4508     else
4509 	return 0;
4510     diff = g - img->transparent_green;
4511     if (diff <= 8 && diff >= -8)
4512 	;
4513     else
4514 	return 0;
4515     diff = b - img->transparent_blue;
4516     if (diff <= 8 && diff >= -8)
4517 	;
4518     else
4519 	return 0;
4520     return 1;
4521 }
4522 
4523 GGRAPH_PRIVATE int
gg_resample_transparent_rgb(const gGraphImagePtr img)4524 gg_resample_transparent_rgb (const gGraphImagePtr img)
4525 {
4526 /*
4527 / resampling colors so to make near-transparent values
4528 / to be really transparent
4529 */
4530     int x;
4531     int y;
4532     unsigned char *p_in;
4533     unsigned char *p_out;
4534     unsigned char r;
4535     unsigned char g;
4536     unsigned char b;
4537 
4538     if (img->pixel_format != GG_PIXEL_RGB)
4539 	return GGRAPH_ERROR;
4540 
4541     for (y = 0; y < img->height; y++)
4542       {
4543 	  p_in = img->pixels + (y * img->scanline_width);
4544 	  p_out = img->pixels + (y * img->scanline_width);
4545 	  for (x = 0; x < img->width; x++)
4546 	    {
4547 		r = *p_in++;
4548 		g = *p_in++;
4549 		b = *p_in++;
4550 		if (is_near_transparent (r, g, b, img))
4551 		  {
4552 		      *p_out++ = img->transparent_red;
4553 		      *p_out++ = img->transparent_green;
4554 		      *p_out++ = img->transparent_blue;
4555 		  }
4556 		else
4557 		    p_out += 3;
4558 	    }
4559       }
4560     return GGRAPH_OK;
4561 }
4562 
4563 GGRAPH_PRIVATE int
gg_resample_transparent_rgba(const gGraphImagePtr img)4564 gg_resample_transparent_rgba (const gGraphImagePtr img)
4565 {
4566 /*
4567 / resampling colors so to make near-transparent values
4568 / to be really transparent
4569 */
4570     int x;
4571     int y;
4572     unsigned char *p_in;
4573     unsigned char *p_out;
4574     unsigned char r;
4575     unsigned char g;
4576     unsigned char b;
4577 
4578     if (img->pixel_format != GG_PIXEL_RGBA)
4579 	return GGRAPH_ERROR;
4580 
4581     for (y = 0; y < img->height; y++)
4582       {
4583 	  p_in = img->pixels + (y * img->scanline_width);
4584 	  p_out = img->pixels + (y * img->scanline_width);
4585 	  for (x = 0; x < img->width; x++)
4586 	    {
4587 		r = *p_in++;
4588 		g = *p_in++;
4589 		b = *p_in++;
4590 		p_in++;
4591 		if (is_near_transparent (r, g, b, img))
4592 		  {
4593 		      *p_out++ = img->transparent_red;
4594 		      *p_out++ = img->transparent_green;
4595 		      *p_out++ = img->transparent_blue;
4596 		      *p_out++ = 0;
4597 		  }
4598 		else
4599 		    p_out += 4;
4600 	    }
4601       }
4602     return GGRAPH_OK;
4603 }
4604 
4605 GGRAPH_PRIVATE int
gg_resample_transparent_grayscale(const gGraphImagePtr img)4606 gg_resample_transparent_grayscale (const gGraphImagePtr img)
4607 {
4608 /*
4609 / resampling colors so to make near-transparent values
4610 / to be really transparent
4611 */
4612     int x;
4613     int y;
4614     unsigned char r;
4615     unsigned char g;
4616     unsigned char b;
4617     unsigned char *p_in;
4618     unsigned char *p_out;
4619 
4620     if (img->pixel_format != GG_PIXEL_GRAYSCALE)
4621 	return GGRAPH_ERROR;
4622     if (img->transparent_red == img->transparent_green
4623 	&& img->transparent_red == img->transparent_blue)
4624 	;
4625     else
4626 	return GGRAPH_OK;
4627 
4628     for (y = 0; y < img->height; y++)
4629       {
4630 	  p_in = img->pixels + (y * img->scanline_width);
4631 	  p_out = img->pixels + (y * img->scanline_width);
4632 	  for (x = 0; x < img->width; x++)
4633 	    {
4634 		r = *p_in++;
4635 		g = r;
4636 		b = r;
4637 		if (is_near_transparent (r, g, b, img))
4638 		    *p_out = img->transparent_red;
4639 		p_out++;
4640 	    }
4641       }
4642     return GGRAPH_OK;
4643 }
4644 
4645 GGRAPH_PRIVATE int
gg_resample_transparent_palette(const gGraphImagePtr img)4646 gg_resample_transparent_palette (const gGraphImagePtr img)
4647 {
4648 /*
4649 / resampling colors so to make near-transparent values
4650 / to be really transparent
4651 */
4652     int x;
4653     int y;
4654     int idx;
4655     unsigned char r;
4656     unsigned char g;
4657     unsigned char b;
4658     int transparent_idx = -1;
4659     unsigned char *p_in;
4660     unsigned char *p_out;
4661 
4662     if (img->pixel_format != GG_PIXEL_RGB)
4663 	return GGRAPH_ERROR;
4664     for (idx = 0; idx < img->max_palette; idx++)
4665       {
4666 	  if (img->palette_red[idx] == img->transparent_red &&
4667 	      img->palette_green[idx] == img->transparent_green &&
4668 	      img->palette_blue[idx] == img->transparent_blue)
4669 	    {
4670 		transparent_idx = idx;
4671 		break;
4672 	    }
4673       }
4674     if (transparent_idx < 0)
4675 	return GGRAPH_OK;
4676 
4677     for (y = 0; y < img->height; y++)
4678       {
4679 	  p_in = img->pixels + (y * img->scanline_width);
4680 	  p_out = p_in;
4681 	  for (x = 0; x < img->width; x++)
4682 	    {
4683 		idx = *p_in++;
4684 		r = img->palette_red[idx];
4685 		g = img->palette_green[idx];
4686 		b = img->palette_blue[idx];
4687 		if (is_near_transparent (r, g, b, img))
4688 		    *p_out = transparent_idx;
4689 		p_out++;
4690 	    }
4691       }
4692     return GGRAPH_OK;
4693 }
4694