/**
  * Carga los valores de recorte calculados por el filtro TailTrim que ya debería haber sido
  * aplicado. Estos valores estarán salvados en DatasetListStatistics.
  *
  * @param stats
  */
 public void loadTailTrimValues(DatasetListStatistics stats) {
   double[][] result;
   result = (double[][]) stats.getTailTrimValue(red.tailTrimMin);
   if (result != null) red.tailTrimValueMin = result[0][0];
   result = (double[][]) stats.getTailTrimValue(red.tailTrimMax);
   if (result != null) red.tailTrimValueMax = result[0][1];
   result = (double[][]) stats.getTailTrimValue(green.tailTrimMin);
   if (result != null && result.length >= 2) green.tailTrimValueMin = result[1][0];
   result = (double[][]) stats.getTailTrimValue(green.tailTrimMax);
   if (result != null && result.length >= 2) green.tailTrimValueMax = result[1][1];
   result = (double[][]) stats.getTailTrimValue(blue.tailTrimMin);
   if (result != null && result.length >= 3) blue.tailTrimValueMin = result[2][0];
   result = (double[][]) stats.getTailTrimValue(blue.tailTrimMax);
   if (result != null && result.length >= 3) blue.tailTrimValueMax = result[2][1];
 }
 /**
  * Obtiene un objeto LinearStretchParams para una aplicación de realce lineal estandar, es decir,
  * el rango de datos de salida es 0-255 y con solo un tramo para los datos.
  *
  * @param nBands Número de bandas
  * @param tailTrim Recorte de colas
  * @param stats Estadísticas
  * @return LinearStretchParams
  * @throws FileNotOpenException
  * @throws RasterDriverException
  */
 public static LinearStretchParams createStandardParam(
     int[] renderBands, double tailTrim, IStatistics stats, boolean rgb)
     throws FileNotOpenException, RasterDriverException {
   LinearStretchParams leParams = new LinearStretchParams();
   leParams.rgb = rgb;
   try {
     stats.calcFullStatistics();
   } catch (InterruptedException e) {
     return null;
   }
   if (renderBands[0] >= 0) {
     if (rgb)
       leParams.red.stretchIn =
           new double[] {stats.getMinByteUnsigned()[0], stats.getMaxByteUnsigned()[0]};
     else
       leParams.red.stretchIn =
           new double[] {stats.getMin()[renderBands[0]], stats.getMax()[renderBands[0]]};
   }
   leParams.red.stretchOut = new int[] {0, 255};
   leParams.red.tailTrimMin = tailTrim;
   leParams.red.tailTrimMax = tailTrim;
   if (renderBands[1] >= 0) {
     if (rgb)
       leParams.green.stretchIn =
           new double[] {stats.getMinByteUnsigned()[0], stats.getMaxByteUnsigned()[0]};
     else
       leParams.green.stretchIn =
           new double[] {stats.getMin()[renderBands[1]], stats.getMax()[renderBands[1]]};
   }
   leParams.green.stretchOut = new int[] {0, 255};
   leParams.green.tailTrimMin = tailTrim;
   leParams.green.tailTrimMax = tailTrim;
   if (renderBands[2] >= 0) {
     if (rgb)
       leParams.blue.stretchIn =
           new double[] {stats.getMinByteUnsigned()[0], stats.getMaxByteUnsigned()[0]};
     else
       leParams.blue.stretchIn =
           new double[] {stats.getMin()[renderBands[2]], stats.getMax()[renderBands[2]]};
   }
   leParams.blue.stretchOut = new int[] {0, 255};
   leParams.blue.tailTrimMin = tailTrim;
   leParams.blue.tailTrimMax = tailTrim;
   return leParams;
 }
 /** Aplica el eliminado de extremos. Para ello utiliza el segundo máximo y mínimo de entrada. */
 public void applyRemoveEndsToStretchs(DatasetListStatistics stats, int[] renderBands) {
   if (renderBands[0] > -1) red.applyRemoveEndsToStretchs(stats, rgb, renderBands[0]);
   if (renderBands[1] > -1) green.applyRemoveEndsToStretchs(stats, rgb, renderBands[1]);
   if (renderBands[2] > -1) blue.applyRemoveEndsToStretchs(stats, rgb, renderBands[2]);
 }
 /**
  * Asigna el máximo y el mínimo
  *
  * @param stats
  * @param type
  * @param band
  */
 public void setMaxMin(DatasetListStatistics stats, int[] renderBands) {
   if (renderBands[0] > -1) red.setMaxMin(stats, renderBands[0], rgb);
   if (renderBands[1] > -1) green.setMaxMin(stats, renderBands[1], rgb);
   if (renderBands[2] > -1) blue.setMaxMin(stats, renderBands[2], rgb);
 }
 /**
  * Calcula la escala y el desplazamiento teniendo en cuenta que ya tenga todos los valores de
  * entrada asignados.
  */
 public void calcLinearScaleAndOffset() {
   red.calcLinearScaleAndOffset();
   green.calcLinearScaleAndOffset();
   blue.calcLinearScaleAndOffset();
 }
 /**
  * Aplica el recorte de colas sobre los extremos de los máximos y mínimos de entrada. La
  * aplicación de esta función considera que ya se han calculado los valores con
  * loadTailTrimValues.
  */
 public void applyTrimToStretchs() {
   red.applyTrimToStretchs();
   green.applyTrimToStretchs();
   blue.applyTrimToStretchs();
 }
 /**
  * Consulta si tiene algún valor el recorte de colas
  *
  * @return true si tiene valor el recorte de colas y false si no lo tiene
  */
 public boolean hasTailTrim() {
   return (red.hasTailTrim() || green.hasTailTrim() || blue.hasTailTrim());
 }