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