package gdsc.utils;
/*-----------------------------------------------------------------------------
* GDSC Plugins for ImageJ
*
* Copyright (C) 2011 Alex Herbert
* Genome Damage and Stability Centre
* University of Sussex, UK
*
* 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.
*---------------------------------------------------------------------------*/
import ij.ImagePlus;
import ij.gui.DialogListener;
import ij.gui.GenericDialog;
import ij.plugin.filter.ExtendedPlugInFilter;
import ij.plugin.filter.PlugInFilterRunner;
import ij.process.ColorProcessor;
import ij.process.ImageProcessor;
import java.awt.AWTEvent;
import java.awt.Color;
import gdsc.UsageTracker;
/**
* Alows an RGB image to be filtered using HSB limits.
*/
public class HSB_Filter implements ExtendedPlugInFilter, DialogListener
{
private int flags = DOES_RGB | SNAPSHOT;
private static final String TITLE = "HSB Filter";
private float[] h = null, s = null, b = null;
// Allow to be set by others in the package
static float hue = 0;
static float hueWidth = 1f / 6f;
static float saturation = 0.5f;
static float saturationWidth = 0.5f;
static float brightness = 0.5f;
static float brightnessWidth = 0.5f;
/*
* (non-Javadoc)
*
* @see ij.plugin.filter.PlugInFilter#setup(java.lang.String, ij.ImagePlus)
*/
public int setup(String arg, ImagePlus imp)
{
UsageTracker.recordPlugin(this.getClass(), arg);
if (imp == null)
{
return DONE;
}
return flags;
}
/*
* (non-Javadoc)
*
* @see ij.plugin.filter.ExtendedPlugInFilter#showDialog(ij.ImagePlus, java.lang.String,
* ij.plugin.filter.PlugInFilterRunner)
*/
public int showDialog(ImagePlus imp, String command, PlugInFilterRunner pfr)
{
GenericDialog gd = new GenericDialog(TITLE);
// Set-up the HSB images
ColorProcessor cp = (ColorProcessor) imp.getProcessor().duplicate();
getHSB((int[]) cp.getPixels());
gd.addSlider("Hue", 0.01, 1, hue);
gd.addSlider("Hue_width", 0.01, 1, hueWidth);
gd.addSlider("Saturation", 0.01, 1, saturation);
gd.addSlider("Saturation_width", 0.01, 1, saturationWidth);
gd.addSlider("Brightness", 0.01, 1, brightness);
gd.addSlider("Brightness_width", 0.01, 1, brightnessWidth);
gd.addHelp(gdsc.help.URL.UTILITY);
gd.addPreviewCheckbox(pfr);
gd.addDialogListener(this);
gd.showDialog();
if (gd.wasCanceled() || !dialogItemChanged(gd, null))
return DONE;
return flags;
}
private void getHSB(int[] pixels)
{
int c, rr, gg, bb;
float[] hsb = new float[3];
h = new float[pixels.length];
s = new float[pixels.length];
b = new float[pixels.length];
for (int i = 0; i < pixels.length; i++)
{
c = pixels[i];
rr = (c & 0xff0000) >> 16;
gg = (c & 0xff00) >> 8;
bb = c & 0xff;
hsb = Color.RGBtoHSB(rr, gg, bb, hsb);
h[i] = hsb[0];
s[i] = hsb[1];
b[i] = hsb[2];
}
}
/*
* (non-Javadoc)
*
* @see ij.gui.DialogListener#dialogItemChanged(ij.gui.GenericDialog, java.awt.AWTEvent)
*/
public boolean dialogItemChanged(GenericDialog gd, AWTEvent e)
{
hue = (float) gd.getNextNumber();
hueWidth = (float) gd.getNextNumber();
saturation = (float) gd.getNextNumber();
saturationWidth = (float) gd.getNextNumber();
brightness = (float) gd.getNextNumber();
brightnessWidth = (float) gd.getNextNumber();
return !gd.invalidNumber();
}
/*
* (non-Javadoc)
*
* @see ij.plugin.filter.ExtendedPlugInFilter#setNPasses(int)
*/
public void setNPasses(int nPasses)
{
// Do nothing
}
/*
* (non-Javadoc)
*
* @see ij.plugin.filter.PlugInFilter#run(ij.process.ImageProcessor)
*/
public void run(ImageProcessor inputProcessor)
{
final float minH = (float) (hue - hueWidth);
final float maxH = (float) (hue + hueWidth);
final float minS = (float) (saturation - saturationWidth);
final float maxS = (float) (saturation + saturationWidth);
final float minB = (float) (brightness - brightnessWidth);
final float maxB = (float) (brightness + brightnessWidth);
for (int i = 0; i < s.length; i++)
{
float hh = h[i];
final float ss = s[i];
final float bb = b[i];
if (hh < minH) // Hue wraps around 0-1 values
hh += 1;
if (hh > maxH)
{
inputProcessor.set(i, 0);
continue;
}
if (ss < minS || ss > maxS)
{
inputProcessor.set(i, 0);
continue;
}
if (bb < minB || bb > maxB)
{
inputProcessor.set(i, 0);
continue;
}
}
}
}