/*
   Gongenhao Guided Bilateral + SimoneT TV colors emulation 1.0 Shader
   
   Original Guided Bilateral shader by Gongenhao:

   https://www.shadertoy.com/view/XtfSz4

   Copyright (C) 2016 SimoneT - simone1tarditi@gmail.com

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   This program 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    
*/

// conversion from NTSC RGB Reference White D65 ( color space used by NA/Japan TV's ) to XYZ

vec3 ntscrgb_2_xyz( vec3 c ) {

    //Inverse Companding
    vec3 v = vec3( pow( c.r, 2.2 ), pow( c.g, 2.2 ), pow( c.b, 2.2  ) ); 
    return v *
        mat3(  0.6068909,  0.1735011,  0.2003480,
 	       0.2989164,  0.5865990,  0.1144845,
 	       0.0000000,  0.0660957,  1.1162243 );
}

// conversion from XYZ to sRGB Reference White D65 ( color space used by windows ) 

vec3 xyz_2_srgb( vec3 c ) {

    vec3 v =  c *         
	mat3(  3.2404542, -1.5371385, -0.4985314,
	      -0.9692660,  1.8760108,  0.0415560,
 	       0.0556434, -0.2040259,  1.0572252 );

    //Companding
    v.r = ( v.r > 0.0031308 ) ? (( 1.055 * pow( v.r, ( 1.0 / 2.4 ))) - 0.055 ) : 12.92 * v.r;
    v.g = ( v.g > 0.0031308 ) ? (( 1.055 * pow( v.g, ( 1.0 / 2.4 ))) - 0.055 ) : 12.92 * v.g;
    v.b = ( v.b > 0.0031308 ) ? (( 1.055 * pow( v.b, ( 1.0 / 2.4 ))) - 0.055 ) : 12.92 * v.b;
    return v;
}

// NTSC RGB to sRGB

vec3 ntscrgb_2_srgb( vec3 c ) { 
     return xyz_2_srgb( ntscrgb_2_xyz( c ) ); 
}

float sigma_s=0.01;
float sigma_c=0.1;
float filter_window=0.1;

uniform sampler2D texture;
uniform vec4 OGL2InvSize;

vec3 guidedFilter(sampler2D tex, sampler2D tex_guide, vec2 uv, float sigma_s, float sigma_c)
{
    vec2 wsize = OGL2InvSize.xy;
    vec3 res_v = vec3(0.0,0.0,0.0);
    float res_w = 0.0;
    vec3 center_g=texture2D(tex_guide,uv).rgb;
    float sigma_i=0.5*wsize.x*wsize.x/sigma_s/sigma_s;
    for (float i = -7.0; i <= 7.0; i++) {
        for (float j= -7.0; j<= 7.0; j++) {
            vec3 tmp_v=texture2D(tex,uv+vec2(float(i)*wsize.x,float(j)*wsize.y)).rgb;   
            //vec3 tmp_g=texture2D(tex_guide,uv+vec2(float(i)*wsize.x,float(j)*wsize.y)).rgb;   
	    vec3 tmp_g=tmp_v;		
            vec3 diff_g=(tmp_g-center_g);
            float tmp_w=exp(-(i*i+j*j)*sigma_i);
            tmp_w*=exp(-(dot(diff_g,diff_g)/2.0/sigma_c/sigma_c));
            res_v+=tmp_v*tmp_w;
            res_w+=tmp_w;   
        }
    }
    vec3 res = res_v/res_w;
    return res;
}

void main(void)
{
	vec2 uv = gl_TexCoord[0].xy;    
    //guided filter
    // use iChannel0 to guide the filtering of noise image iChannel1
    vec3 result = ntscrgb_2_srgb(guidedFilter( texture, texture,uv,sigma_s,sigma_c));   
    gl_FragColor = vec4(result,1.0);
}
