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
)
31 gfloat golden_angle
= G_PI
* (3-sqrt(5.0)); /* http://en.wikipedia.org/wiki/Golden_angle */
34 if (g_atomic_int_get (&luts_computed
)==rgamma
)
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
);
50 g_atomic_int_set (&luts_computed
, rgamma
);
55 sample_min_max (GeglBuffer
*buffer
,
57 GeglSamplerGetFun getfun
,
69 gint width
= gegl_buffer_get_width (buffer
);
70 gint height
= gegl_buffer_get_height (buffer
);
80 for (i
=0; i
<samples
; i
++)
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
94 rad_no
= radius_no
++;
96 if (angle_no
>=ANGLE_PRIME
)
98 if (angle
>=ANGLE_PRIME
)
100 if (radius_no
>=RADIUS_PRIME
)
102 if (rad_no
>=RADIUS_PRIME
)
105 rmag
= radiuses
[rad_no
] * radius
;
106 u
= x
+ rmag
* lut_cos
[angle
];
107 v
= y
+ rmag
* lut_sin
[angle
];
119 getfun (sampler
, u
, v
, NULL
, (void*)(&pixel
[0]), GEGL_ABYSS_CLAMP
);
121 if (pixel
[3]>0.0) /* ignore fully transparent pixels */
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
];
147 static inline void compute_envelopes (GeglBuffer
*buffer
,
148 GeglSampler
*sampler
,
149 GeglSamplerGetFun getfun
,
157 gfloat
*min_envelope
,
158 gfloat
*max_envelope
,
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
);
179 for (i
=0;i
<iterations
;i
++)
181 gfloat min
[3], max
[3];
183 sample_min_max (buffer
,
188 min
, max
, pixel
, format
);
192 gfloat range
, relative_brightness
;
194 range
= max
[c
] - min
[c
];
198 relative_brightness
= (pixel
[c
] - min
[c
]) / range
;
202 relative_brightness
= 0.5;
205 relative_brightness_sum
[c
] += relative_brightness
;
206 range_sum
[c
] += range
;
212 gfloat relative_brightness
= relative_brightness_sum
[c
] / iterations
;
213 gfloat range
= range_sum
[c
] / iterations
;
216 max_envelope
[c
] = pixel
[c
] + (1.0 - relative_brightness
) * range
;
218 min_envelope
[c
] = pixel
[c
] - relative_brightness
* range
;