1/*
2    This file is part of darktable,
3    copyright (c) 2012 ulrich pegelow.
4
5    darktable is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9
10    darktable is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with darktable.  If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#include "common.h"
20#include "colorspace.h"
21
22
23/* first step for soften module: generate overexposed image */
24kernel void
25soften_overexposed(read_only image2d_t in, write_only image2d_t out, const int width, const int height,
26                  const float saturation, const float brightness)
27{
28  const int x = get_global_id(0);
29  const int y = get_global_id(1);
30
31  if(x >= width || y >= height) return;
32
33  float4 pixel = read_imagef(in, sampleri, (int2)(x, y));
34
35  float4 hsl = RGB_2_HSL(pixel);
36
37  hsl.y = clamp(hsl.y * saturation, 0.0f, 1.0f);
38  hsl.z = clamp(hsl.z * brightness, 0.0f, 1.0f);
39
40  pixel = HSL_2_RGB(hsl);
41
42  write_imagef (out, (int2)(x, y), pixel);
43}
44
45/* horizontal gaussian blur */
46kernel void
47soften_hblur(read_only image2d_t in, write_only image2d_t out, global const float *m, const int rad,
48      const int width, const int height, const int blocksize, local float4 *buffer)
49{
50  const int lid = get_local_id(0);
51  const int lsz = get_local_size(0);
52  const int x = get_global_id(0);
53  const int y = get_global_id(1);
54  float4 pixel = (float4)0.0f;
55
56  /* read pixel and fill center part of buffer */
57  pixel = read_imagef(in, sampleri, (int2)(x, y));
58  buffer[rad + lid] = pixel;
59
60  /* left wing of buffer */
61  for(int n=0; n <= rad/lsz; n++)
62  {
63    const int l = mad24(n, lsz, lid + 1);
64    if(l > rad) continue;
65    const int xx = mad24((int)get_group_id(0), lsz, -l);
66    buffer[rad - l] = read_imagef(in, sampleri, (int2)(xx, y));
67  }
68
69  /* right wing of buffer */
70  for(int n=0; n <= rad/lsz; n++)
71  {
72    const int r = mad24(n, lsz, lsz - lid);
73    if(r > rad) continue;
74    const int xx = mad24((int)get_group_id(0), lsz, lsz - 1 + r);
75    buffer[rad + lsz - 1 + r] = read_imagef(in, sampleri, (int2)(xx, y));
76  }
77
78  barrier(CLK_LOCAL_MEM_FENCE);
79
80  if(x >= width || y >= height) return;
81
82  buffer += lid + rad;
83  m += rad;
84
85  float4 sum = (float4)0.0f;
86
87  for (int i=-rad; i<=rad; i++)
88  {
89    sum += buffer[i] * m[i];
90  }
91
92  pixel = sum;
93  write_imagef (out, (int2)(x, y), pixel);
94}
95
96
97/* vertical gaussian blur */
98kernel void
99soften_vblur(read_only image2d_t in, write_only image2d_t out, global const float *m, const int rad,
100      const int width, const int height, const int blocksize, local float4 *buffer)
101{
102  const int lid = get_local_id(1);
103  const int lsz = get_local_size(1);
104  const int x = get_global_id(0);
105  const int y = get_global_id(1);
106  float4 pixel = (float4)0.0f;
107
108  /* read pixel and fill center part of buffer */
109  pixel = read_imagef(in, sampleri, (int2)(x, y));
110  buffer[rad + lid] = pixel;
111
112  /* left wing of buffer */
113  for(int n=0; n <= rad/lsz; n++)
114  {
115    const int l = mad24(n, lsz, lid + 1);
116    if(l > rad) continue;
117    const int yy = mad24((int)get_group_id(1), lsz, -l);
118    buffer[rad - l] = read_imagef(in, sampleri, (int2)(x, yy));
119  }
120
121  /* right wing of buffer */
122  for(int n=0; n <= rad/lsz; n++)
123  {
124    const int r = mad24(n, lsz, lsz - lid);
125    if(r > rad) continue;
126    const int yy = mad24((int)get_group_id(1), lsz, lsz - 1 + r);
127    buffer[rad + lsz - 1 + r] = read_imagef(in, sampleri, (int2)(x, yy));
128  }
129
130  barrier(CLK_LOCAL_MEM_FENCE);
131
132  if(x >= width || y >= height) return;
133
134  buffer += lid + rad;
135  m += rad;
136
137  float4 sum = (float4)0.0f;
138
139  for (int i=-rad; i<=rad; i++)
140  {
141    sum += buffer[i] * m[i];
142  }
143
144  pixel = sum;
145  write_imagef (out, (int2)(x, y), pixel);
146}
147
148
149
150
151/* final step for soften module */
152kernel void
153soften_mix(read_only image2d_t in_a, read_only image2d_t in_b, write_only image2d_t out, const int width, const int height,
154                  const float amount)
155{
156  const int x = get_global_id(0);
157  const int y = get_global_id(1);
158
159  if(x >= width || y >= height) return;
160
161  float4 original  = read_imagef(in_a, sampleri, (int2)(x, y));
162  float4 processed = read_imagef(in_b, sampleri, (int2)(x, y));
163
164  float4 pixel = original * (1.0f - amount) + clamp(processed, (float4)0.0f, (float4)1.0f) * amount;
165  pixel.w = original.w;
166
167  write_imagef (out, (int2)(x, y), pixel);
168}
169
170
171