Package org.geotools.gce.gtopo30

Source Code of org.geotools.gce.gtopo30.NoDataReplacerOpImage

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2001-2008, Open Source Geospatial Foundation (OSGeo)
*
*    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;
*    version 2.1 of the License.
*
*    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.
*/
package org.geotools.gce.gtopo30;




// J2SE dependencies
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.ComponentSampleModel;
import java.awt.image.DataBuffer;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.awt.image.renderable.ParameterBlock;
import java.awt.image.renderable.RenderedImageFactory;
import java.util.logging.Level;
import java.util.logging.LogRecord;

import javax.media.jai.CRIFImpl;
import javax.media.jai.ComponentSampleModelJAI;
import javax.media.jai.ImageLayout;
import javax.media.jai.JAI;
import javax.media.jai.OperationDescriptorImpl;
import javax.media.jai.OperationRegistry;
import javax.media.jai.PlanarImage;
import javax.media.jai.PointOpImage;
import javax.media.jai.iterator.RectIterFactory;
import javax.media.jai.iterator.WritableRectIter;
import javax.media.jai.registry.RenderedRegistryMode;

import org.geotools.coverage.GridSampleDimension;
import org.geotools.coverage.grid.AbstractGridCoverage;
import org.geotools.image.TransfertRectIter;
import org.geotools.resources.i18n.Loggings;
import org.geotools.resources.i18n.LoggingKeys;
import org.geotools.resources.image.ImageUtilities;


/**
* An image that contains transformed samples, specifically this method will transform the NoData value
* using a new supplied one. A new layout is used in order to convert to the required image layout. Default
* values for this operation can be used to set the NoData and the layout to the values needed for
* the GTOPO30 writer.
*
* Images are created using the
* {@code NoDataReplacerOpImage.NoDataReplacerCRIF} inner class, where "CRIF" stands for
* {@link java.awt.image.renderable.ContextualRenderedImageFactory}. The image
* operation name is "org.geotools.gce.NoDataReplacer".
*
*
*
* @source $URL$
* @version $Id$
* @author Simone Giannecchini
*
* @since 2.2
*/
public final class NoDataReplacerOpImage extends PointOpImage {
    /**The operation name.*/
    public static final String OPERATION_NAME = "org.geotools.gce.gtopo30.NoDataReplacer";

    /**Constant that tell me the margin when checking for equality with floating point values*/
  private double EPS;

  /**Old no data value.*/
  private Number oldNoData;

  /**New no data value.*/
  private int newNoData;

  /**It tells me whether or not the old no data is NaN.*/
  private boolean oldNoDataIsNaN;




    /**
     * Constructs a new {@code NoDataReplacerOpImage}.
     *
     * @param image      The source image.
     * @param oldNoData The old NoData value to be substituted.
     * @param newNoData The new NoData value to be employed.
     * @param EPS Margin for equality checks.
     * @param hints Suplpied RenderingHints.
     */
    private NoDataReplacerOpImage(final RenderedImage  image,
                             final Number oldNoData,
                             final Short newNoData,
                             final Double EPS,
                             final RenderingHints hints)
    {
        super(image, NoDataReplacerOpImage.getRightLayout(image), hints, false);
        this.EPS = EPS.doubleValue();
        this.oldNoData=oldNoData;
        this.oldNoDataIsNaN=Double.isNaN(oldNoData.doubleValue());
        this.newNoData=newNoData.intValue();

        permitInPlaceOperation();
    }

    /**
     * @todo Creation of non banded sample models
   * @param image Image to work on.
   * @return New Image Layout.
   */
  private static ImageLayout getRightLayout(RenderedImage image) {

    final SampleModel sm=image.getSampleModel();
    final int dataType=DataBuffer.TYPE_SHORT;
    if(sm.getDataType()==dataType)
      return new ImageLayout(image);
    final ColorModel cm=image.getColorModel();
    if(sm instanceof ComponentSampleModel)
    {
          final ColorModel newCm = new ComponentColorModel(
              cm.getColorSpace(),
              false,
              false,
              cm.getTransparency(),
              dataType);
          final SampleModel newSm = new ComponentSampleModelJAI(
              dataType,
              sm.getWidth(),
              sm.getHeight(),
              ((ComponentSampleModel)sm).getPixelStride(),
              ((ComponentSampleModel)sm).getScanlineStride(),
              ((ComponentSampleModel)sm).getBankIndices(),
              ((ComponentSampleModel)sm).getBandOffsets()
              );

       final        ImageLayout layout = ImageUtilities.getImageLayout(image);
       layout.setColorModel(newCm);
       layout.setSampleModel(newSm);
       return layout;
    }
    else
      ;//do nothing for the moment

    return null;
  }



  /**
     * Computes one of the destination image tile.
     *
     * @todo There is two optimisations we could do here:
     *       <ul>
     *         <li>If source and destination are the same raster, then a single
     *             {@link WritableRectIter} object would be more efficient (the
     *             hard work is to detect if source and destination are the same).</li>
     *         <li>If the destination image is a single-banded, non-interleaved
     *             sample model, we could apply the transform directly in the
     *             {@link java.awt.image.DataBuffer}. We can even avoid to copy
     *             sample value if source and destination raster are the same.</li>
     *       </ul>
     *
     * @param sources  An array of length 1 with source image.
     * @param dest     The destination tile.
     * @param destRect the rectangle within the destination to be written.
     */
    protected void computeRect(final PlanarImage[] sources,
                               final WritableRaster   dest,
                               final Rectangle    destRect)
    {
        final PlanarImage source = sources[0];
        WritableRectIter iterator = RectIterFactory.createWritable(dest, destRect);
        if (true) {
            // TODO: Detect if source and destination rasters are the same. If they are
            //       the same, we should skip this block. Iteration will then be faster.
            iterator = TransfertRectIter.create(RectIterFactory.create(source, destRect), iterator);
        }
        formatRect(iterator);
    }




   /**
     * Transform a raster. Only the current band in {@code iterator} will be transformed.
     * The transformed value are write back in the {@code iterator}. If a different
     * destination raster is wanted, a {@link org.geotools.resources.image.DualRectIter}
     * may be used.
     *
     * @param  iterator An iterator to iterate among the samples to transform.
     */
  private void formatRect(WritableRectIter iterator) {


    double actualValue=0.0;
        iterator.startLines();
        if (!iterator.finishedLines())
          do {
            iterator.startPixels();
            if (!iterator.finishedPixels())
              do {

                  //get the actual value
                    actualValue = iterator.getSampleDouble();

                    //substituting a NaN
                    if(oldNoDataIsNaN)
                      if(Double.isNaN(actualValue))
                          iterator.setSample(newNoData);
                    else
                      if(Math.abs(oldNoData.doubleValue()-actualValue)<=EPS)
                        iterator.setSample(newNoData);
                      else
                        iterator.setSample(actualValue);

              }
                  while (!iterator.nextPixelDone());
            }
            while (!iterator.nextLineDone());



  }




  /////////////////////////////////////////////////////////////////////////////////
    ////////                                                                 ////////
    ////////        REGISTRATION OF "NoDataReplacer" IMAGE OPERATION        ////////
    ////////                                                                 ////////
    /////////////////////////////////////////////////////////////////////////////////
    /**
     * The operation descriptor for the "NoDataReplacer" operation. This operation
     * is used to change the format of an Image while replacing the NoData value with a new
     * one as requested. The difference between this method and the usual format operation presents
     * in JAI is the possibility to replace the NoData value directly when it is like Double.NaN or
     * Float.NaN.
     *
     */
    private static final class NoDataReplacerDescriptor extends OperationDescriptorImpl {
    /**
     * Comment for <code>serialVersionUID</code>
     */
    private static final long serialVersionUID = 1L;

    /**
         * Construct the descriptor.
         */
        public NoDataReplacerDescriptor() {
            super(new String[][]{{"GlobalName",  OPERATION_NAME},
                                 {"LocalName",   OPERATION_NAME},
                                 {"Vendor",      "Geotools 2"},
                                 {"Description", "Nodata replacement and layout adjustment."},
                                 {"DocURL",      "http://www.geotools.org/"},
                                 {"Version",     "1.0"}},
                  new String[]   {RenderedRegistryMode.MODE_NAME}, 1,
                  new String[]   {"oldNoData","newNoData","EPS"},          // Argument names
                  new Class []   {Number.class,Short.class,Double.class}, // Argument classes
                  new Object[]   {new Double(Double.NaN),new Short((short)-9999),new Double(10.0E-6)},        // Default values for parameters,
                  null // No restriction on valid parameter values.
            );
        }

        /**
         * Returns {@code true} if the parameters are valids. This implementation check
         * that the number of bands in the source image is equals to the number of supplied
         * sample dimensions, and that all sample dimensions has categories.
         *
         * @param modeName The mode name (usually "Rendered").
         * @param param The parameter block for the operation to performs.
         * @param message A buffer for formatting an error message if any.
         */
        protected boolean validateParameters(final String      modeName,
                                             final ParameterBlock param,
                                             final StringBuffer message)
        {
            if (!super.validateParameters(modeName, param, message)) {
                return false;
            }
            try{
//              param.
//              final RenderedImage source = (RenderedImage) param.getSource(0);
//              final Number  oldNoData= (Number) param.getObjectParameter(0);
//              final Number  newNoData= (Number) param.getObjectParameter(1);
//              final Double  EPS=  (Double) param.getObjectParameter(1);
            }
            catch(Exception e){
              message.append(e.getMessage());
              return false;
            }
            return true;
        }
    }

    /**
     * The {@link RenderedImageFactory} for the "SampleTranscode" operation.
     */
    private static final class NoDataReplacerCRIF extends CRIFImpl {
        /**
         * Creates a {@link RenderedImage} representing the results of an imaging
         * operation for a given {@link ParameterBlock} and {@link RenderingHints}.
         */
        public RenderedImage create(final ParameterBlock param,
                                    final RenderingHints hints)
        {
            final RenderedImage source = (RenderedImage) param.getSource(0);

            final Number  oldNoData= (Number) param.getObjectParameter(0);
            final Short  newNoData= (Short) param.getObjectParameter(1);
            final Double  EPS=  (Double) param.getObjectParameter(2);
            return new NoDataReplacerOpImage(source, oldNoData,newNoData,EPS, hints);
        }


    }

    /**
     * Register the "SampleTranscode" image operation to the operation registry of
     * the specified JAI instance. This method is invoked by the static initializer
     * of {@link GridSampleDimension}.
     */
    public static void register(final JAI jai) {
        final OperationRegistry registry = jai.getOperationRegistry();
        try {
            registry.registerDescriptor(new NoDataReplacerDescriptor());
            registry.registerFactory(RenderedRegistryMode.MODE_NAME, OPERATION_NAME,
                                     "gce.geotools.org", new NoDataReplacerCRIF());
        } catch (IllegalArgumentException exception) {
            final LogRecord record = Loggings.format(Level.SEVERE,
                   LoggingKeys.CANT_REGISTER_JAI_OPERATION_$1, OPERATION_NAME);
            record.setSourceClassName("GridSampleDimension");
            record.setSourceMethodName("<classinit>");
            record.setThrown(exception);
            AbstractGridCoverage.LOGGER.log(record);
        }
    }
}
TOP

Related Classes of org.geotools.gce.gtopo30.NoDataReplacerOpImage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.