Update Chinese (China) translation
[gegl.git] / operations / common / envelopes.h
blobe769a11a88f0155c0a058f2311fc830165a3d5b1
1 /* GEGL is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 3 of the License, or (at your option) any later version.
6 * GEGL is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with GEGL; if not, see <https://www.gnu.org/licenses/>.
14 * Copyright 2007, 2009 Øyvind Kolås <pippin@gimp.org>
17 #define ANGLE_PRIME 95273 /* the lookuptables are sized as primes to ensure */
18 #define RADIUS_PRIME 29537 /* as good as possible variation when using both */
20 static gfloat lut_cos[ANGLE_PRIME];
21 static gfloat lut_sin[ANGLE_PRIME];
22 static gfloat radiuses[RADIUS_PRIME];
23 static gint luts_computed = 0;
24 static gint angle_no=0;
25 static gint radius_no=0;
27 static void compute_luts(gint rgamma)
29 gint i;
30 GRand *rand;
31 gfloat golden_angle = G_PI * (3-sqrt(5.0)); /* http://en.wikipedia.org/wiki/Golden_angle */
32 gfloat angle = 0.0;
34 if (g_atomic_int_get (&luts_computed)==rgamma)
35 return;
36 rand = g_rand_new();
38 for (i=0;i<ANGLE_PRIME;i++)
40 lut_cos[i] = cos(angle);
41 lut_sin[i] = sin(angle);
42 angle += golden_angle;
44 for (i=0;i<RADIUS_PRIME;i++)
46 radiuses[i] = pow(g_rand_double_range (rand, 0.0, 1.0), rgamma);
49 g_rand_free(rand);
50 g_atomic_int_set (&luts_computed, rgamma);
54 static inline void
55 sample_min_max (GeglBuffer *buffer,
56 GeglSampler *sampler,
57 GeglSamplerGetFun getfun,
58 gint x,
59 gint y,
60 gint radius,
61 gint samples,
62 gfloat *min,
63 gfloat *max,
64 gfloat *pixel,
65 const Babl *format)
67 gfloat best_min[3];
68 gfloat best_max[3];
69 gint width = gegl_buffer_get_width (buffer);
70 gint height = gegl_buffer_get_height (buffer);
72 gint i, c;
74 for (c=0;c<3;c++)
76 best_min[c]=pixel[c];
77 best_max[c]=pixel[c];
80 for (i=0; i<samples; i++)
82 gint u, v;
83 gfloat rmag;
84 gint angle;
85 gint rad_no;
86 gint max_retries = samples;
88 retry: /* if we've sampled outside the valid image
89 area, we grab another sample instead, this
90 should potentially work better than mirroring
91 or extending with an abyss policy
93 angle = angle_no++;
94 rad_no = radius_no ++;
96 if (angle_no>=ANGLE_PRIME)
97 angle_no=0;
98 if (angle>=ANGLE_PRIME)
99 angle=0;
100 if (radius_no>=RADIUS_PRIME)
101 radius_no=0;
102 if (rad_no>=RADIUS_PRIME)
103 rad_no=0;
105 rmag = radiuses[rad_no] * radius;
106 u = x + rmag * lut_cos[angle];
107 v = y + rmag * lut_sin[angle];
109 if (u>=width ||
110 u<0 ||
111 v>=height ||
112 v<0)
114 goto retry;
118 gfloat pixel[4];
119 getfun (sampler, u, v, NULL, (void*)(&pixel[0]), GEGL_ABYSS_CLAMP);
121 if (pixel[3]>0.0) /* ignore fully transparent pixels */
123 for (c=0;c<3;c++)
125 if (pixel[c]<best_min[c])
126 best_min[c]=pixel[c];
128 if (pixel[c]>best_max[c])
129 best_max[c]=pixel[c];
132 else
134 max_retries--;
135 if (max_retries>0)
136 goto retry;
140 for (c=0;c<3;c++)
142 min[c]=best_min[c];
143 max[c]=best_max[c];
147 static inline void compute_envelopes (GeglBuffer *buffer,
148 GeglSampler *sampler,
149 GeglSamplerGetFun getfun,
150 gint x,
151 gint y,
152 gint radius,
153 gint samples,
154 gint iterations,
155 gboolean same_spray,
156 gdouble rgamma,
157 gfloat *min_envelope,
158 gfloat *max_envelope,
159 gfloat *pixel,
160 const Babl *format)
162 gint i;
163 gint c;
164 gfloat range_sum[4] = {0,0,0,0};
165 gfloat relative_brightness_sum[4] = {0,0,0,0};
167 getfun (sampler, x, y, NULL, (void*)(&pixel[0]), GEGL_ABYSS_CLAMP);
169 /* compute lookuptables for the gamma, currently not used/exposed
170 * as a tweakable property */
171 compute_luts(rgamma);
173 if (same_spray)
175 angle_no = 0;
176 radius_no = 0;
179 for (i=0;i<iterations;i++)
181 gfloat min[3], max[3];
183 sample_min_max (buffer,
184 sampler,
185 getfun,
186 x, y,
187 radius, samples,
188 min, max, pixel, format);
190 for (c=0;c<3;c++)
192 gfloat range, relative_brightness;
194 range = max[c] - min[c];
196 if (range>0.0)
198 relative_brightness = (pixel[c] - min[c]) / range;
200 else
202 relative_brightness = 0.5;
205 relative_brightness_sum[c] += relative_brightness;
206 range_sum[c] += range;
210 for (c=0;c<3;c++)
212 gfloat relative_brightness = relative_brightness_sum[c] / iterations;
213 gfloat range = range_sum[c] / iterations;
215 if (max_envelope)
216 max_envelope[c] = pixel[c] + (1.0 - relative_brightness) * range;
217 if (min_envelope)
218 min_envelope[c] = pixel[c] - relative_brightness * range;