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