/*
* Geotools 2 - OpenSource mapping toolkit
* (C) 2003, Geotools Project Management Committee (PMC)
* (C) 2001, Institut de Recherche pour le Développement
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* Contacts:
* UNITED KINGDOM: James Macgill
* mailto:j.macgill@geog.leeds.ac.uk
*
* FRANCE: Surveillance de l'Environnement Assistée par Satellite
* Institut de Recherche pour le Développement / US-Espace
* mailto:seasnet@teledetection.fr
*
* CANADA: Observatoire du Saint-Laurent
* Institut Maurice-Lamontagne
* mailto:osl@osl.gc.ca
*/
package org.geotools.gp;
// Collections
import java.util.List;
import javax.media.jai.ParameterList;
import javax.media.jai.util.Range;
import org.geotools.cv.Category;
import org.geotools.cv.SampleDimension;
/**
* Make a color ramp more "gradual" for geophysics categories. This operation applies only on the
* color palette of geophysics categories (i.e. category for which {@link Category#isQuantitative}
* returns true
). If it find a range of sample values using the same color, then this
* operation will interpolate the colors in the color palette. This interpolation give a smoother
* appeareance to images that uses this color palette.
*
* Example: Consider the following color palette. Sample values 0-2 are red, * 3-5 are green and 6-8 are blue. In each block of identical color, this operation lets the * first occurence inchanged and interpolate all others. The last block of color (blue in our * example) is inchanged since we don't know which color come next. * *
* * @source $URL$ * @version $Id$ * @author Martin Desruisseaux */ final class GradualColormapOperation extends IndexColorOperation { /** * Constante indiquant qu'il faut garder la première couleur * lorsqu'une plage de couleurs constantes est rencontrée. */ private static final int KEEP_LOWER_COLOR = +1; /** * Constante indiquant qu'il faut garder la dernière couleur * lorsqu'une plage de couleurs constantes est rencontrée. */ private static final int KEEP_UPPER_COLOR = -1; /** * Constante indiquant quelle couleur il faut garder * lorsque l'opérateur trouve une plage de couleurs * identiques. * * @task TODO: Allow setting this parameter from the ParameterList. */ private final int mode = KEEP_LOWER_COLOR; /** * Construit une opération qui interpolera les couleurs. * * @param mode Indique quelle couleur il faut garder lorsque l'opérateur trouve une plage de * couleurs identiques. La valeur {@link #KEEP_LOWER_COLOR} indique qu'il faut * laisser inchangée la première couleur de la plage et interpoler les autres * (la dernière couleur de la plage sera donc la plus affectée). La valeur * {@link #KEEP_UPPER_COLOR} indique au contraire qu'il faut laisser inchangée * la dernière couleur de la plage et interpoler les autres (la première couleur * sera donc la plus affectée). */ public GradualColormapOperation() { super("GradualColormap", MONADIC); } /** * Transform the supplied RGB colors. */ protected SampleDimension transformColormap(final int[] ARGB, final int band, final SampleDimension sampleDimension, final ParameterList parameters) { final List categories = sampleDimension.getCategories(); for (int j=categories.size(); --j>=0;) { final Category category = (Category) categories.get(j); if (category.isQuantitative()) { final Range range = category.getRange(); int sens = +1; int lower = (int)Math.ceil (((Number)range.getMinValue()).doubleValue()); int upper = (int)Math.floor(((Number)range.getMaxValue()).doubleValue()); if (!range.isMinIncluded()) lower++; if (!range.isMaxIncluded()) upper--; if (mode == KEEP_UPPER_COLOR) { sens = -1; final int swap = lower; lower = upper; upper = swap; } for (int i=lower; i!=upper;) { int color = ARGB[i]; final int lo = i; final int Ai = (color >>> 24) & 0xFF; final int Ri = (color >>> 16) & 0xFF; final int Gi = (color >>> 8) & 0xFF; final int Bi = (color >>> 0) & 0xFF; int Af,Rf,Gf,Bf; int up=lo; do { up += sens; color = ARGB[up]; Af = (color >>> 24) & 0xFF; Rf = (color >>> 16) & 0xFF; Gf = (color >>> 8) & 0xFF; Bf = (color >>> 0) & 0xFF; } while (up!=upper && Rf==Ri && Gf==Gi && Bf==Bi); final double delta = (double)(up-lo); final double fA = (double)(Af-Ai) / delta; final double fR = (double)(Rf-Ri) / delta; final double fG = (double)(Gf-Gi) / delta; final double fB = (double)(Bf-Bi) / delta; while ((i+=sens) != up) { final double i0 = i-lo; ARGB[i] = ((Ai + (int)Math.rint(i0*fA)) << 24) | ((Ri + (int)Math.rint(i0*fR)) << 16) | ((Gi + (int)Math.rint(i0*fG)) << 8) | ((Bi + (int)Math.rint(i0*fB)) << 0); } } } } return sampleDimension; } }* sample RGB before RGB after * ------ ---------- --------- * 00 .. FF0000 ...... FF0000 * 01 FF0000 AA5500 * 02 FF0000 55AA00 * 03 .. 00FF00 ...... 00FF00 * 04 00FF00 00AA55 * 05 00FF00 0055AA * 06 .. 0000FF ...... 0000FF * 07 0000FF 0000FF * 08 0000FF 0000FF *