/* GEGL is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * GEGL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with GEGL; if not, see . * * Copyright 2007, 2009 Øyvind Kolås */ #define ANGLE_PRIME 95273 /* the lookuptables are sized as primes to ensure */ #define RADIUS_PRIME 29537 /* as good as possible variation when using both */ static gfloat lut_cos[ANGLE_PRIME]; static gfloat lut_sin[ANGLE_PRIME]; static gfloat radiuses[RADIUS_PRIME]; static gdouble luts_computed = 0.0; static gint angle_no=0; static gint radius_no=0; static void compute_luts(gdouble rgamma) { gint i; GRand *rand; gfloat golden_angle = G_PI * (3-sqrt(5.0)); /* http://en.wikipedia.org/wiki/Golden_angle */ gfloat angle = 0.0; if (luts_computed==rgamma) return; luts_computed = rgamma; rand = g_rand_new(); for (i=0;i=ANGLE_PRIME) angle_no=0; if (radius_no>=RADIUS_PRIME) radius_no=0; u = x + rmag * lut_cos[angle]; v = y + rmag * lut_sin[angle]; if (u>=width || u<0 || v>=height || v<0) goto retry; { gfloat *pixel = (buf + ((width * v) + u) * 4); if (pixel[3]>0.0) /* ignore fully transparent pixels */ { for (c=0;c<3;c++) { if (pixel[c]best_max[c]) best_max[c]=pixel[c]; } } else { goto retry; } } } for (c=0;c<3;c++) { min[c]=best_min[c]; max[c]=best_max[c]; } } static inline void compute_envelopes (gfloat *buf, gint width, gint height, gint x, gint y, gint radius, gint samples, gint iterations, gboolean same_spray, gdouble rgamma, gfloat *min_envelope, gfloat *max_envelope) { gint i; gint c; gfloat range_sum[4] = {0,0,0,0}; gfloat relative_brightness_sum[4] = {0,0,0,0}; gfloat *pixel = buf + (width*y+x)*4; /* compute lookuptables for the gamma, currently not used/exposed * as a tweakable property */ compute_luts(rgamma); if (same_spray) { angle_no = 0; radius_no = 0; } for (i=0;i0.0) { relative_brightness = (pixel[c] - min[c]) / range; } else { relative_brightness = 0.5; } relative_brightness_sum[c] += relative_brightness; range_sum[c] += range; } } for (c=0;c<3;c++) { gfloat relative_brightness = relative_brightness_sum[c] / iterations; gfloat range = range_sum[c] / iterations; if (max_envelope) max_envelope[c] = pixel[c] + (1.0 - relative_brightness) * range; if (min_envelope) min_envelope[c] = pixel[c] - relative_brightness * range; } }