1/*
2    This file is part of darktable,
3    copyright (c) 2014 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 bloom module: get the thresholded lights into buffer */
24kernel void
25bloom_threshold(read_only image2d_t in, write_only image2d_t out, const int width, const int height,
26                  const float scale, const float threshold)
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  float L = pixel.x*scale;
36
37  L = L > threshold ? L : 0.0f;
38
39  write_imagef (out, (int2)(x, y), L);
40}
41
42
43/* horizontal box blur */
44kernel void
45bloom_hblur(read_only image2d_t in, write_only image2d_t out, const int rad,
46      const int width, const int height, const int blocksize, local float *buffer)
47{
48  const int lid = get_local_id(0);
49  const int lsz = get_local_size(0);
50  const int x = get_global_id(0);
51  const int y = get_global_id(1);
52  float pixel = 0.0f;
53
54  /* read pixel and fill center part of buffer */
55  pixel = read_imagef(in, sampleri, (int2)(x, y)).x;
56  buffer[rad + lid] = pixel;
57
58  /* left wing of buffer */
59  for(int n=0; n <= rad/lsz; n++)
60  {
61    const int l = mad24(n, lsz, lid + 1);
62    if(l > rad) continue;
63    const int xx = mad24((int)get_group_id(0), lsz, -l);
64    buffer[rad - l] = read_imagef(in, sampleri, (int2)(xx, y)).x;
65  }
66
67  /* right wing of buffer */
68  for(int n=0; n <= rad/lsz; n++)
69  {
70    const int r = mad24(n, lsz, lsz - lid);
71    if(r > rad) continue;
72    const int xx = mad24((int)get_group_id(0), lsz, lsz - 1 + r);
73    buffer[rad + lsz - 1 + r] = read_imagef(in, sampleri, (int2)(xx, y)).x;
74  }
75
76  barrier(CLK_LOCAL_MEM_FENCE);
77
78  if(x >= width || y >= height) return;
79
80  buffer += lid + rad;
81
82  float sum = 0.0f;
83
84  for (int i=-rad; i<=rad; i++)
85  {
86    sum += buffer[i];
87  }
88
89  pixel = sum/(2*rad+1);
90  write_imagef (out, (int2)(x, y), pixel);
91}
92
93
94/* vertical box blur */
95kernel void
96bloom_vblur(read_only image2d_t in, write_only image2d_t out, const int rad,
97      const int width, const int height, const int blocksize, local float *buffer)
98{
99  const int lid = get_local_id(1);
100  const int lsz = get_local_size(1);
101  const int x = get_global_id(0);
102  const int y = get_global_id(1);
103  float pixel = 0.0f;
104
105  /* read pixel and fill center part of buffer */
106  pixel = read_imagef(in, sampleri, (int2)(x, y)).x;
107  buffer[rad + lid] = pixel;
108
109  /* left wing of buffer */
110  for(int n=0; n <= rad/lsz; n++)
111  {
112    const int l = mad24(n, lsz, lid + 1);
113    if(l > rad) continue;
114    const int yy = mad24((int)get_group_id(1), lsz, -l);
115    buffer[rad - l] = read_imagef(in, sampleri, (int2)(x, yy)).x;
116  }
117
118  /* right wing of buffer */
119  for(int n=0; n <= rad/lsz; n++)
120  {
121    const int r = mad24(n, lsz, lsz - lid);
122    if(r > rad) continue;
123    const int yy = mad24((int)get_group_id(1), lsz, lsz - 1 + r);
124    buffer[rad + lsz - 1 + r] = read_imagef(in, sampleri, (int2)(x, yy)).x;
125  }
126
127  barrier(CLK_LOCAL_MEM_FENCE);
128
129  if(x >= width || y >= height) return;
130
131  buffer += lid + rad;
132
133  float sum = 0.0f;
134
135  for (int i=-rad; i<=rad; i++)
136  {
137    sum += buffer[i];
138  }
139
140  pixel = sum / (2*rad+1);
141  write_imagef (out, (int2)(x, y), pixel);
142}
143
144
145/* final step for bloom module */
146kernel void
147bloom_mix(read_only image2d_t in_a, read_only image2d_t in_b, write_only image2d_t out, const int width, const int height)
148{
149  const int x = get_global_id(0);
150  const int y = get_global_id(1);
151
152  if(x >= width || y >= height) return;
153
154  float4 pixel  = read_imagef(in_a, sampleri, (int2)(x, y));
155  float processed = read_imagef(in_b, sampleri, (int2)(x, y)).x;
156
157  pixel.x = 100.0f-(((100.0f-pixel.x)*(100.0f-processed))/100.0f); // Screen blend
158
159  write_imagef (out, (int2)(x, y), pixel);
160}
161
162