~unico-team/unico/trunk

« back to all changes in this revision

Viewing changes to unico/exponential-blur.c

  • Committer: Ken VanDine
  • Date: 2012-08-08 16:28:32 UTC
  • mfrom: (139 refactor)
  • mto: (139.1.1 unico)
  • mto: This revision was merged to the branch mainline in revision 140.
  • Revision ID: ken.vandine@canonical.com-20120808162832-vmgto6docfq65f4d
New snapshot from trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* The Unico Theming Engine for Gtk+.
2
 
 * Copyright (C) 2009 Canonical Ltd
3
 
 *
4
 
 * This  library is free  software; you can  redistribute it and/or
5
 
 * modify it  under  the terms  of the  GNU Lesser  General  Public
6
 
 * License  as published  by the Free  Software  Foundation; either
7
 
 * version 2 of the License, or (at your option) any later version.
8
 
 *
9
 
 * This library is distributed  in the hope that it will be useful,
10
 
 * but  WITHOUT ANY WARRANTY; without even  the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
 
 * Lesser General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU Lesser General Public
15
 
 * License  along  with  this library;  if not,  write to  the Free
16
 
 * Software Foundation, Inc., 51  Franklin St, Fifth Floor, Boston,
17
 
 * MA 02110-1301, USA.
18
 
 *
19
 
 * Authored by Mirco "MacSlow" Mueller <mirco.mueller@canonical.com>
20
 
 *
21
 
 * Notes:
22
 
 *   based on exponential-blur algorithm by Jani Huhtanen
23
 
 *
24
 
 */
25
 
 
26
 
/* FIXME: not working yet, unfinished */
27
 
 
28
 
#include <math.h>
29
 
 
30
 
#include "exponential-blur.h"
31
 
 
32
 
static inline void
33
 
_blurinner (guchar* pixel,
34
 
            gint   *zR,
35
 
            gint   *zG,
36
 
            gint   *zB,
37
 
            gint   *zA,
38
 
            gint    alpha,
39
 
            gint    aprec,
40
 
            gint    zprec);
41
 
 
42
 
static inline void
43
 
_blurrow (guchar* pixels,
44
 
          gint    width,
45
 
          gint    height,
46
 
          gint    channels,
47
 
          gint    line,
48
 
          gint    alpha,
49
 
          gint    aprec,
50
 
          gint    zprec);
51
 
 
52
 
static inline void
53
 
_blurcol (guchar* pixels,
54
 
          gint    width,
55
 
          gint    height,
56
 
          gint    channels,
57
 
          gint    col,
58
 
          gint    alpha,
59
 
          gint    aprec,
60
 
          gint    zprec);
61
 
 
62
 
void
63
 
_expblur (guchar* pixels,
64
 
          gint    width,
65
 
          gint    height,
66
 
          gint    channels,
67
 
          gint    radius,
68
 
          gint    aprec,
69
 
          gint    zprec);
70
 
 
71
 
void
72
 
surface_exponential_blur (cairo_surface_t* surface,
73
 
                          guint            radius)
74
 
{
75
 
  guchar*        pixels;
76
 
  guint          width;
77
 
  guint          height;
78
 
  cairo_format_t format;
79
 
 
80
 
  /* sanity checks are done in raico-blur.c */
81
 
 
82
 
  /* before we mess with the surface execute any pending drawing */
83
 
  cairo_surface_flush (surface);
84
 
 
85
 
  pixels = cairo_image_surface_get_data (surface);
86
 
  width  = cairo_image_surface_get_width (surface);
87
 
  height = cairo_image_surface_get_height (surface);
88
 
  format = cairo_image_surface_get_format (surface);
89
 
 
90
 
  switch (format)
91
 
  {
92
 
    case CAIRO_FORMAT_ARGB32:
93
 
      _expblur (pixels, width, height, 4, radius, 16, 7);
94
 
      break;
95
 
    case CAIRO_FORMAT_RGB24:
96
 
      _expblur (pixels, width, height, 3, radius, 16, 7);
97
 
      break;
98
 
    case CAIRO_FORMAT_A8:
99
 
      _expblur (pixels, width, height, 1, radius, 16, 7);
100
 
      break;
101
 
    default:
102
 
      break;
103
 
  }
104
 
 
105
 
  /* inform cairo we altered the surfaces contents */
106
 
  cairo_surface_mark_dirty (surface);        
107
 
}
108
 
 
109
 
/*
110
 
 * pixels   image-data
111
 
 * width    image-width
112
 
 * height   image-height
113
 
 * channels image-channels
114
 
 *
115
 
 * in-place blur of image 'img' with kernel of approximate radius 'radius'
116
 
 *
117
 
 * blurs with two sided exponential impulse response
118
 
 *
119
 
 * aprec = precision of alpha parameter in fixed-point format 0.aprec
120
 
 *
121
 
 * zprec = precision of state parameters zR,zG,zB and zA in fp format 8.zprec
122
 
 */
123
 
void
124
 
_expblur (guchar* pixels,
125
 
          gint    width,
126
 
          gint    height,
127
 
          gint    channels,
128
 
          gint    radius,
129
 
          gint    aprec,
130
 
          gint    zprec)
131
 
{
132
 
  gint alpha;
133
 
  gint row = 0;
134
 
  gint col = 0;
135
 
 
136
 
  if (radius < 1)
137
 
    return;
138
 
 
139
 
  /* calculate the alpha such that 90% of 
140
 
   * the kernel is within the radius.
141
 
   * (Kernel extends to infinity) */
142
 
  alpha = (gint) ((1 << aprec) * (1.0f - expf (-2.3f / (radius + 1.f))));
143
 
 
144
 
  for (; row < height; row++)
145
 
    _blurrow (pixels,
146
 
              width,
147
 
              height,
148
 
              channels,
149
 
              row,
150
 
              alpha,
151
 
              aprec,
152
 
              zprec);
153
 
 
154
 
  for(; col < width; col++)
155
 
    _blurcol (pixels,
156
 
              width,
157
 
              height,
158
 
              channels,
159
 
              col,
160
 
              alpha,
161
 
              aprec,
162
 
              zprec);
163
 
 
164
 
  return;
165
 
}
166
 
 
167
 
static inline void
168
 
_blurinner (guchar* pixel,
169
 
            gint   *zR,
170
 
            gint   *zG,
171
 
            gint   *zB,
172
 
            gint   *zA,
173
 
            gint    alpha,
174
 
            gint    aprec,
175
 
            gint    zprec)
176
 
{
177
 
  gint R;
178
 
  gint G;
179
 
  gint B;
180
 
  guchar A;
181
 
 
182
 
  R = *pixel;
183
 
  G = *(pixel + 1);
184
 
  B = *(pixel + 2);
185
 
  A = *(pixel + 3);
186
 
 
187
 
  *zR += (alpha * ((R << zprec) - *zR)) >> aprec;
188
 
  *zG += (alpha * ((G << zprec) - *zG)) >> aprec;
189
 
  *zB += (alpha * ((B << zprec) - *zB)) >> aprec;
190
 
  *zA += (alpha * ((A << zprec) - *zA)) >> aprec;
191
 
 
192
 
  *pixel       = *zR >> zprec;
193
 
  *(pixel + 1) = *zG >> zprec;
194
 
  *(pixel + 2) = *zB >> zprec;
195
 
  *(pixel + 3) = *zA >> zprec;
196
 
197
 
 
198
 
static inline void
199
 
_blurrow (guchar* pixels,
200
 
          gint    width,
201
 
          gint    height,
202
 
          gint    channels,
203
 
          gint    line,
204
 
          gint    alpha,
205
 
          gint    aprec,
206
 
          gint    zprec)
207
 
{
208
 
  gint    zR;
209
 
  gint    zG;
210
 
  gint    zB;
211
 
  gint    zA;
212
 
  gint    index;
213
 
  guchar* scanline;
214
 
 
215
 
  scanline = &(pixels[line * width * channels]);
216
 
 
217
 
  zR = *scanline << zprec;
218
 
  zG = *(scanline + 1) << zprec;
219
 
  zB = *(scanline + 2) << zprec;
220
 
  zA = *(scanline + 3) << zprec;
221
 
 
222
 
  for (index = 0; index < width; index ++)
223
 
    _blurinner (&scanline[index * channels],
224
 
                &zR,
225
 
                &zG,
226
 
                &zB,
227
 
                &zA,
228
 
                alpha,
229
 
                aprec,
230
 
                zprec);
231
 
 
232
 
  for (index = width - 2; index >= 0; index--)
233
 
    _blurinner (&scanline[index * channels],
234
 
                &zR,
235
 
                &zG,
236
 
                &zB,
237
 
                &zA,
238
 
                alpha,
239
 
                aprec,
240
 
                zprec);
241
 
}
242
 
 
243
 
static inline void
244
 
_blurcol (guchar* pixels,
245
 
          gint    width,
246
 
          gint    height,
247
 
          gint    channels,
248
 
          gint    x,
249
 
          gint    alpha,
250
 
          gint    aprec,
251
 
          gint    zprec)
252
 
{
253
 
  gint zR;
254
 
  gint zG;
255
 
  gint zB;
256
 
  gint zA;
257
 
  gint index;
258
 
  guchar* ptr;
259
 
 
260
 
  ptr = pixels;
261
 
  
262
 
  ptr += x * channels;
263
 
 
264
 
  zR = *((guchar*) ptr    ) << zprec;
265
 
  zG = *((guchar*) ptr + 1) << zprec;
266
 
  zB = *((guchar*) ptr + 2) << zprec;
267
 
  zA = *((guchar*) ptr + 3) << zprec;
268
 
 
269
 
  for (index = width; index < (height - 1) * width; index += width)
270
 
    _blurinner ((guchar*) &ptr[index * channels],
271
 
                &zR,
272
 
                &zG,
273
 
                &zB,
274
 
                &zA,
275
 
                alpha,
276
 
                aprec,
277
 
                zprec);
278
 
 
279
 
  for (index = (height - 2) * width; index >= 0; index -= width)
280
 
    _blurinner ((guchar*) &ptr[index * channels],
281
 
                &zR,
282
 
                &zG,
283
 
                &zB,
284
 
                &zA,
285
 
                alpha,
286
 
                aprec,
287
 
                zprec);
288
 
}