Hi Zeng,

I'm posting the code here so that if anyone else spots glaring errors
in it they can warn you :-)

Note, in my app I was only working with double valued, single-band
coverages but it would be easy to extend this class to deal with more
types and multi-band data.

Let me know if you have any problems with it.

Michael


package org.cafeanimal.geo.gridlayer;

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.DataBuffer;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.media.jai.TiledImage;
import javax.media.jai.iterator.RandomIterFactory;
import javax.media.jai.iterator.WritableRandomIter;
import javax.media.jai.operator.FormatDescriptor;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.geometry.Envelope2D;
import org.geotools.image.ImageWorker;
import org.opengis.coverage.PointOutsideCoverageException;
import org.opengis.geometry.Envelope;
import org.opengis.referencing.operation.MathTransform2D;
import org.opengis.referencing.operation.NoninvertibleTransformException;
import org.opengis.referencing.operation.TransformException;

/**
 *
 * @author Michael Bedward and Murray Ellis
 */
public class WritableGridCoverage {

    private GridCoverage2D gridCov;
    private MathTransform2D worldToGrid = null;
    private double[] dbuf = new double[1];
    private static final int MAX_PENDING_VALUES = 10000;

    private static class PendingValue {
        Point2D.Double pos;
        boolean isGeographic;
        double value;
    }

    private List<PendingValue> pendingValues = new ArrayList<PendingValue>();

    /**
     * Constructor
     * @param gridCov the GridCoverage2D object to be wrapped
     */
    public WritableGridCoverage(GridCoverage2D gridCov) {
        this.gridCov = gridCov;
    }

    public GridCoverage2D getGridCoverage() {
        flushCache(true);
        return gridCov;
    }

    public String getName() {
        return gridCov.getName().toString();
    }

    public int getNumRows() {
        return gridCov.getRenderedImage().getHeight();
    }

    public int getNumCols() {
        return gridCov.getRenderedImage().getWidth();
    }

    public Rectangle2D.Double getBounds() {
        Envelope2D env = gridCov.getEnvelope2D();
        return new Rectangle2D.Double(env.x, env.y, env.width, env.height);
    }

    public double getPixelWidth() {
        return gridCov.getEnvelope2D().getWidth() / getNumCols();
    }

    public double getValueAtPos(Point2D pos) {
        flushCache(true);

        try {
            gridCov.evaluate(pos, dbuf);
        } catch (PointOutsideCoverageException ex) {
            return Double.NaN;
        }

        return dbuf[0];
    }

    public int getValueAtPosAsInt(Point2D pos, int defaultValue) {
        double val = getValueAtPos(pos);
        if (Double.isNaN(val)) {
            return defaultValue;
        } else {
            return (int) Math.round(val);
        }
    }

    public double[] getValuesAtPos(Point2D pos, double[] buf) {
        flushCache(true);

        if (buf == null) {
            buf = new double[gridCov.getNumSampleDimensions()];
        }

        try {
            buf = gridCov.evaluate(pos, buf);
        } catch (PointOutsideCoverageException ex) {
            Arrays.fill(buf, Double.NaN);
        }

        return buf;
    }

    public void saveAsJPEG(File path) {
        try {
            ImageWorker iw = new ImageWorker(gridCov.getRenderedImage());
            if (!iw.isBytes()) {

iw.setImage(FormatDescriptor.create(gridCov.getRenderedImage(),
DataBuffer.TYPE_BYTE, null));
            }
            iw.write(path);
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
    }

    public void setValueAtPos(Point2D pos, int value) {
        Number n = Integer.valueOf(value);
        doSetValue(pos, n);
    }

    public void setValueAtPos(Point2D pos, float value) {
        Number n = new Float(value);
        doSetValue(pos, n);
    }

    public void setValueAtPos(Point2D pos, double value) {
        Number n = new Double(value);
        doSetValue(pos, n);
    }

    private void doSetValue(Point2D pos, Number value) {
        PendingValue pv = new PendingValue();
        pv.pos = new Point2D.Double(pos.getX(), pos.getY());
        pv.isGeographic = true;
        pv.value = value.doubleValue();
        pendingValues.add(pv);
        flushCache(false);
    }

    private void flushCache(boolean force) {
        if (pendingValues.size() >= MAX_PENDING_VALUES || (force &&
pendingValues.size() > 0)) {
            if (worldToGrid == null) {
                try {
                    worldToGrid =
gridCov.getGridGeometry().getGridToCRS2D().inverse();
                } catch (NoninvertibleTransformException ex) {
                    throw new RuntimeException("Could not create
geographic to grid coords transform");
                }
            }

            TiledImage tImg = new TiledImage(gridCov.getRenderedImage(), true);
            WritableRandomIter writeIter =
RandomIterFactory.createWritable(tImg, null);

            Point2D.Double gridPos = new Point2D.Double();
            for (PendingValue pv : pendingValues) {
                if (pv.isGeographic) {
                    try {
                        worldToGrid.transform(pv.pos, gridPos);
                    } catch (TransformException ex) {
                        throw new RuntimeException("Could not
transform location [" +
                                pv.pos + "] to grid coords");
                    }
                } else {
                    gridPos.setLocation(pv.pos);
                }

                writeIter.setSample((int) gridPos.x, (int) gridPos.y,
0, pv.value);
            }

            pendingValues.clear();

            String name = getName();
            Envelope env = gridCov.getEnvelope();
        }
    }
}

------------------------------------------------------------------------------
The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your
production scanning environment may not be a perfect world - but thanks to
Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700
Series Scanner you'll get full speed at 300 dpi even with all image 
processing features enabled. http://p.sf.net/sfu/kodak-com
_______________________________________________
Geotools-gt2-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/geotools-gt2-users

Reply via email to