Line data Source code
1 : % Copyright (C) 2012-2021,2022 John E. Davis
2 : %
3 : % This file is part of the S-Lang Library and may be distributed under the
4 : % terms of the GNU General Public License. See the file COPYING for
5 : % more information.
6 : %---------------------------------------------------------------------------
7 1 : autoload ("glob", "glob");
8 1 : import ("png");
9 :
10 : % Colormap functions
11 :
12 : private define linear_range (a, b, xa, xb)
13 : {
14 550 : return typecast (xa + ([0:b-a] * (xb-xa)/double(b-a)), UChar_Type);
15 : }
16 :
17 : private define build_colormap_channel (ranges)
18 : {
19 54 : variable r = UChar_Type[256];
20 54 : variable i = 0;
21 54 : loop (length(ranges)/4)
22 : {
23 550 : variable a = ranges[i];
24 550 : variable b = ranges[i+1];
25 550 : variable xa = ranges[i+2];
26 550 : variable xb = ranges[i+3];
27 550 : r[[a:b]] = linear_range (a, b, xa, xb);
28 550 : i += 4;
29 : }
30 54 : return r;
31 : }
32 :
33 : define png_build_colormap (r_ranges, g_ranges, b_ranges)
34 : {
35 18 : return ((build_colormap_channel (r_ranges) shl 16)
36 : + (build_colormap_channel (g_ranges) shl 8)
37 : + (build_colormap_channel (b_ranges)));
38 : }
39 :
40 1 : private variable Color_Maps = Assoc_Type[Array_Type];
41 1 : private variable Color_Map_Dir = path_concat (path_dirname (__FILE__), "cmaps");
42 1 : private variable Png_Namespace = current_namespace ();
43 :
44 : define png_add_colormap (name, map)
45 : {
46 27 : Color_Maps[name] = map;
47 : }
48 :
49 : define png_get_colormap (name)
50 : {
51 27 : if (assoc_key_exists (Color_Maps, name))
52 1 : return Color_Maps[name];
53 :
54 26 : variable mapfile = strcat (name, ".map");
55 26 : variable file = path_concat (Color_Map_Dir, mapfile);
56 26 : if (stat_file (file) == NULL)
57 0 : throw OpenError, "Unable to load colormap $mapfile"$;
58 :
59 26 : () = evalfile (file, Png_Namespace);
60 :
61 26 : if (assoc_key_exists (Color_Maps, name))
62 26 : return Color_Maps[name];
63 :
64 0 : throw DataError, "$file does not contain the $name color map"$;
65 : }
66 :
67 : define png_get_colormap_names ()
68 : {
69 1 : variable maps = glob (path_concat (Color_Map_Dir, "*.map"));
70 1 : maps = array_map (String_Type, &path_basename_sans_extname, maps);
71 1 : variable n = length (maps);
72 1 : variable idx = Char_Type[n];
73 1 : _for (0, n-1, 1)
74 : {
75 26 : variable i = ();
76 26 : !if (assoc_key_exists (Color_Maps, maps[i]))
77 26 : idx[i] = 1;
78 : }
79 1 : return [maps[where(idx)], assoc_get_keys (Color_Maps)];
80 :
81 : }
82 :
83 : define png_rgb_to_gray (rgb)
84 : {
85 2 : variable w = 1.0;
86 2 : w = qualifier ("wghts", w);
87 2 : if (length (w) != 3)
88 1 : w = [w[0], w[0], w[0]];
89 2 : w /= sum(w);
90 2 : if (any(isnan(w) or isinf(w))) w[*] = 1.0/3;
91 :
92 2 : variable gray = (w[2]*(rgb&0xFF) + w[1]*((rgb&0xFF00)shr 8) + w[0]*((rgb&0xFF0000)shr 16));
93 2 : return typecast (__tmp(gray), UChar_Type);
94 : }
95 :
96 : private define normalize_gray (gray, nlevels)
97 : {
98 3 : variable g0 = qualifier ("gmin");
99 3 : variable g1 = qualifier ("gmax");
100 :
101 3 : if ((typeof (gray) == UChar_Type) && (nlevels == 256)
102 : && (g0 == NULL) && (g1 == NULL))
103 0 : return gray;
104 :
105 3 : variable is_bad = isnan(gray) or isinf(gray);
106 3 : variable any_is_bad = any(is_bad);
107 3 : if (any_is_bad)
108 : {
109 1 : variable good_gray = gray [where(is_bad == 0)];
110 2 : if (g0 == NULL) g0 = min (good_gray);
111 2 : if (g1 == NULL) g1 = max (good_gray);
112 : }
113 : else
114 : {
115 4 : if (g0 == NULL) g0 = min(gray);
116 4 : if (g1 == NULL) g1 = max(gray);
117 : }
118 3 : if (g0 > g1) (g0, g1) = (g1, g0);
119 :
120 3 : if (g0 != g1)
121 : {
122 2 : variable factor = (nlevels-1)/double(g1-g0);
123 2 : gray = nint((gray-g0)*factor);
124 2 : gray[where (gray<0)] = 0;
125 2 : gray[where (gray>=nlevels)] = (nlevels-1);
126 : }
127 : else
128 1 : gray = typecast (gray * 0 + 127, Int_Type);
129 :
130 3 : variable bad_level = 0;
131 3 : if (any_is_bad)
132 1 : gray[where(is_bad)] = bad_level;
133 :
134 3 : return gray;
135 : }
136 :
137 : private define gray_to_rgb_with_cmap (gray, cmap)
138 : {
139 1 : if (typeof (cmap) == String_Type)
140 1 : cmap = png_get_colormap (cmap);
141 :
142 1 : gray = normalize_gray (gray, length(cmap);;__qualifiers());
143 1 : return cmap[gray];
144 : }
145 :
146 : define png_gray_to_rgb ()
147 : {
148 : variable gray;
149 3 : if (_NARGS == 2)
150 1 : return gray_to_rgb_with_cmap (;;__qualifiers ());
151 :
152 2 : gray = ();
153 2 : gray = normalize_gray (gray, 256;;__qualifiers ());
154 2 : return gray + (gray shl 8) + (gray shl 16);
155 : }
156 :
157 : define png_rgb_get_r (rgb)
158 : {
159 1 : return typecast ((rgb shr 16) & 0xFF, UChar_Type);
160 : }
161 : define png_rgb_get_g (rgb)
162 : {
163 1 : return typecast ((rgb shr 8) & 0xFF, UChar_Type);
164 : }
165 : define png_rgb_get_b (rgb)
166 : {
167 1 : return typecast (rgb & 0xFF, UChar_Type);
168 : }
169 :
170 1 : $1 = path_concat (path_dirname (__FILE__), "help/pngfuns.hlp");
171 1 : if (NULL != stat_file ($1))
172 1 : add_doc_file ($1);
173 :
174 1 : provide("png");
|