/* Copyright (C) 2015 Masahiro Kitagawa */
package com.lightcrafts.model.ImageEditor;

import com.lightcrafts.jai.JAIContext;
import com.lightcrafts.jai.opimage.NonLocalMeansFilterOpImage;
import com.lightcrafts.jai.utils.Transform;
import com.lightcrafts.mediax.jai.BorderExtender;
import com.lightcrafts.mediax.jai.PlanarImage;
import com.lightcrafts.model.OperationType;
import com.lightcrafts.model.SliderConfig;

import java.text.DecimalFormat;

public class AdvancedNoiseReductionOperationV5 extends BlendedOperation {
    static final String COLOR_NOISE = "Color_Noise";
    static final String GRAIN_NOISE = "Grain_Noise";
    static final OperationType type = new OperationTypeImpl("Advanced Noise Reduction V5");
    private float chroma_domain = 2;
    private float luma_domain = 2;

    public AdvancedNoiseReductionOperationV5(Rendering rendering, OperationType type) {
        super(rendering, type);
        colorInputOnly = true;

        DecimalFormat format = new DecimalFormat("0.0");

        this.addSliderKey(COLOR_NOISE);
        this.setSliderConfig(COLOR_NOISE, new SliderConfig(0, 20, chroma_domain, 1, false, format));

        this.addSliderKey(GRAIN_NOISE);
        this.setSliderConfig(GRAIN_NOISE, new SliderConfig(0, 20, luma_domain, 1, false, format));
    }

    public boolean neutralDefault() {
        return false;
    }

    public void setSliderValue(String key, double value) {
        value = roundValue(key, value);

        if (key == COLOR_NOISE) {
            chroma_domain = (float) value;
        } else if (key == GRAIN_NOISE) {
            luma_domain = (float) value;
        } else
            return;

        super.setSliderValue(key, value);
    }

    private class NoiseReduction extends BlendedTransform {
        NoiseReduction(PlanarImage source) {
            super(source);
        }

        public PlanarImage setFront() {
            if (chroma_domain == 0 && luma_domain == 0)
                return back;

            PlanarImage front = back;
            BorderExtender borderExtender = BorderExtender.createInstance(BorderExtender.BORDER_REFLECT);
            front = new NonLocalMeansFilterOpImage(back, borderExtender, null, null,
                    luma_domain * scale, 0.02f,
                    chroma_domain * scale, 0.04f);
            front.setProperty(JAIContext.PERSISTENT_CACHE_TAG, Boolean.TRUE);
            return front;
        }
    }

    protected void updateOp(Transform op) {
        op.update();
    }

    protected BlendedTransform createBlendedOp(PlanarImage source) {
        return new NoiseReduction(source);
    }

    public OperationType getType() {
        return type;
    }
}

@@ -548,21 +548,22 @@
 g COLOR_
-NOISE
+RADIUS
  = %22Colo
@@ -564,21 +564,83 @@
  %22Color_
-Noise
+Radius%22;%0A    static final String COLOR_INTENSITY = %22Color_Intensity
 %22;%0A    s
@@ -664,21 +664,22 @@
 g GRAIN_
-NOISE
+RADIUS
  = %22Grai
@@ -680,21 +680,83 @@
  %22Grain_
-Noise
+Radius%22;%0A    static final String GRAIN_INTENSITY = %22Grain_Intensity
 %22;%0A    s
@@ -901,23 +901,93 @@
 oat 
-luma_domain = 2
+chroma_range = 3;%0A    private float luma_domain = 2;%0A    private float luma_range = 3
 ;%0A%0A 
@@ -1227,21 +1227,22 @@
 y(COLOR_
-NOISE
+RADIUS
 );%0A     
@@ -1271,21 +1271,22 @@
 g(COLOR_
-NOISE
+RADIUS
 , new Sl
@@ -1299,18 +1299,17 @@
 nfig(0, 
-20
+5
 , chroma
@@ -1364,27 +1364,179 @@
 iderKey(
-GRAIN_NOISE
+COLOR_INTENSITY);%0A        this.setSliderConfig(COLOR_INTENSITY, new SliderConfig(0, 10, chroma_range, 0.1, false, format));%0A%0A        this.addSliderKey(GRAIN_RADIUS
 );%0A     
@@ -1565,21 +1565,22 @@
 g(GRAIN_
-NOISE
+RADIUS
 , new Sl
@@ -1593,18 +1593,17 @@
 nfig(0, 
-20
+5
 , luma_d
@@ -1628,16 +1628,165 @@
 ormat));
+%0A%0A        this.addSliderKey(GRAIN_INTENSITY);%0A        this.setSliderConfig(GRAIN_INTENSITY, new SliderConfig(0, 10, luma_range, 0.1, false, format));
 %0A    %7D%0A%0A
@@ -1977,21 +1977,48 @@
 = COLOR_
-NOISE
+RADIUS && chroma_domain != value
 ) %7B%0A    
@@ -2086,46 +2086,291 @@
  == 
-GRAIN_NOISE) %7B%0A            luma_domain
+COLOR_INTENSITY && chroma_range != value) %7B%0A            chroma_range = (float) value;%0A        %7D else if (key == GRAIN_RADIUS && luma_domain != value) %7B%0A            luma_domain = (float) value;%0A        %7D else if (key == GRAIN_INTENSITY && luma_range != value) %7B%0A            luma_range
  = (
@@ -2689,27 +2689,67 @@
 == 0 && 
-luma_domain
+chroma_range == 0 && luma_domain == 0 && luma_range
  == 0)%0A 
@@ -3042,24 +3042,45 @@
 ain * scale,
+ luma_range * scale *
  0.02f,%0A    
@@ -3121,13 +3121,36 @@
 ale,
+ chroma_range * scale *
  0.0
-4
+2
 f);%0A

Change ANRV5 slider setup