Package com.bbn.openmap.plugin.earthImage

Source Code of com.bbn.openmap.plugin.earthImage.EarthImagePlugIn$ImageTranslator

// **********************************************************************
//
// <copyright>
//
//  BBN Technologies
//  10 Moulton Street
//  Cambridge, MA 02138
//  (617) 873-8000
//
//  Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/plugin/earthImage/EarthImagePlugIn.java,v $
// $RCSfile: EarthImagePlugIn.java,v $
// $Revision: 1.2.2.2 $
// $Date: 2005/08/09 21:17:57 $
// $Author: dietrick $
//
// **********************************************************************

package com.bbn.openmap.plugin.earthImage;

import java.awt.Component;
import java.awt.Image;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.awt.image.PixelGrabber;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;

import com.bbn.openmap.LatLonPoint;
import com.bbn.openmap.image.BufferedImageHelper;
import com.bbn.openmap.image.ImageServerConstants;
import com.bbn.openmap.omGraphics.OMGraphicList;
import com.bbn.openmap.omGraphics.OMRaster;
import com.bbn.openmap.plugin.AbstractPlugIn;
import com.bbn.openmap.proj.Projection;
import com.bbn.openmap.util.Debug;
import com.bbn.openmap.util.PropUtils;

/**
* This class takes an image of the earth, and creates a background
* image from it that matches an OpenMap projection. It currently
* assumes that the degrees/pixel ratios are constant in both
* directions, the coordinate system origins in both directions are at
* the center of the picture, and that the left an right edges of the
* images are at -180/180 degrees longitude, and that the top and
* bottom of the edges are at 90/-90 degrees latitude. I think the
* code will work for images that do not cover the entire earth in
* this manner, as long as the degree/pixel ratios are the same, but
* the ImageTranslator limies would have to be adjusted to fit the
* source image.
*
* #For the pluging layer
* pluginlayer.class=com.bbn.openmap.plugin.PlugInLayer
* pluginlayer.prettyName=Whatever
* pluginlayer.plugin=com.bbn.openmap.plugin.earthImage.EarthImagePlugIn
* pluginlayer.plugin.image=path to file, URL or resource.
*/
public class EarthImagePlugIn extends AbstractPlugIn implements
        ImageServerConstants {

    protected BufferedImage bi = null;
    protected ImageTranslator it = null;
    public final static String ImageProperty = "image";
    protected String imageString = null;

    public EarthImagePlugIn() {}

    public EarthImagePlugIn(Component comp) {
        super(comp);
    }

    /**
     * @param p projection of the screen, holding scale, center
     *        coords, height, width.
     * @return an OMGraphicList containing an OMRaster with the image
     *         to be displayed.
     */
    public OMGraphicList getRectangle(Projection p) {
        OMGraphicList list = new OMGraphicList();

        // The first time through with a good bi, the it will be
        // created later. This routine will only be executed if the
        // image icon is no good.
        if (bi == null && it == null) {
            return list;
        }

        OMRaster ras = null;

        if (it == null) {
            it = new ImageTranslator(bi);
            bi = null; // don't hold onto it.
        }

        ras = it.getImage(p);

        if (ras != null) {
            list.add(ras);
        }

        list.generate(p);
        return list;
    }

    /**
     * Method to set the properties in the PropertyConsumer. The
     * prefix is a string that should be prepended to each property
     * key (in addition to a separating '.') in order for the
     * PropertyConsumer to uniquely identify properies meant for it,
     * in the midst of of Properties meant for several objects.
     *
     * @param prefix a String used by the PropertyConsumer to prepend
     *        to each property value it wants to look up -
     *        setList.getProperty(prefix.propertyKey). If the prefix
     *        had already been set, then the prefix passed in should
     *        replace that previous value.
     * @param setList a Properties object that the PropertyConsumer
     *        can use to retrieve expected properties it can use for
     *        configuration.
     */
    public void setProperties(String prefix, Properties setList) {
        super.setProperties(prefix, setList);

        String realPrefix = PropUtils.getScopedPropertyPrefix(prefix);

        imageString = setList.getProperty(realPrefix + ImageProperty);

        if (imageString == null || imageString.equals("")) {
            Debug.error("EarthImagePlugIn needs an image.");
            Debug.output(setList.toString());
            return;
        } else if (Debug.debugging("earthimage")) {
            Debug.output("EarthImagePlugIn:  fetching " + realPrefix
                    + ImageProperty + " : " + imageString);
        }
        try {
            URL url = PropUtils.getResourceOrFileOrURL(this, imageString);
            bi = BufferedImageHelper.getBufferedImage(url, 0, 0, -1, -1);

            if (Debug.debugging("earthimage") && bi != null) {
                Debug.output("EarthImagePlugIn: buffered image OK");
            }
        } catch (MalformedURLException murle) {
            Debug.error("EarthImagePlugIn: image path is not good: "
                    + imageString);
        } catch (InterruptedException ie) {
            Debug.error("EarthImagePlugIn: problem reading image from path: "
                    + imageString);
        }
    }

    public Properties getProperties(Properties props) {
        props = super.getProperties(props);

        String prefix = PropUtils.getScopedPropertyPrefix(this);

        props.put(prefix + ImageProperty, (imageString == null ? ""
                : imageString));

        return props;
    }

    public Properties getPropertyInfo(Properties props) {
        props = super.getPropertyInfo(props);
        props.put(ImageProperty, "Path to image file (URL, resource or file)");
        props.put(ImageProperty + ScopedEditorProperty,
                "com.bbn.openmap.util.propertyEditor.FUPropertyEditor");

        props.put(initPropertiesProperty, ImageProperty);

        return props;
    }

    /**
     * The ImageTranslator is the object that takes the BufferedImage
     * and creates the OMRaster from it based on a Projection object.
     */
    public class ImageTranslator {

        protected int[] pixels = null;

        /** Image Icon width, */
        public int iwidth;
        /** Image Icon height, */
        public int iheight;
        /**
         * Horizontal degrees/pixel in the source BufferedImage.
         * Assumed to be constant across the image.
         */
        public float hor_dpp;
        /**
         * Vertical degrees/pixel in the source BufferedImage. Assumed
         * to be constant across the image.
         */
        public float ver_dpp;
        /**
         * The vertical origin pixel location in the source image for
         * the coordinate system origin (0 degrees latitude).
         */
        public int verOrigin;
        /**
         * The horizontal origin pixel location in the source image
         * for the coordinate system origin (0 degrees longitude).
         */
        public int horOrigin;

        /**
         * Create an image translator for an image assumed to be world
         * wide coverage, with the top at 90 degrees, the bottom at
         * -90, the left side at -180 and the right side at 180.
         * Assumes the origin point is in the middle of the image.
         */
        public ImageTranslator(BufferedImage bi) {
            if (bi != null) {
                iwidth = bi.getWidth();
                iheight = bi.getHeight();

                verOrigin = iheight / 2;
                horOrigin = iwidth / 2;

                hor_dpp = 360f / (float) iwidth;
                ver_dpp = 180f / (float) iheight;

                if (Debug.debugging("earthimage")) {
                    Debug.output("ImageTranslator: getting image pixels w:"
                            + iwidth + ", h:" + iheight + "\n     hor dpp:"
                            + hor_dpp + ", ver dpp:" + ver_dpp);
                }

                pixels = getPixels(bi, 0, 0, iwidth, iheight);

                // See if this saves on memory. Seems to.
                bi = null;
            }
        }

        /**
         * The pixels used in the OMRaster.
         */
        int[] tmpPixels = new int[0];

        /**
         * Given a projection, create an OMRaster that reflects the
         * image warped to that projection.
         */
        public OMRaster getImage(Projection p) {
            if (pixels != null && p != null) {
                int projHeight = p.getHeight();
                int projWidth = p.getWidth();

                // See if we can reuse the pixel array we have.
                if (tmpPixels.length != projWidth * projHeight) {
                    tmpPixels = new int[projWidth * projHeight];
                }

                ///////////////////////////////////
                // For Testing...
                //              LatLonPoint ul = p.getUpperLeft();
                //              LatLonPoint lr = p.getLowerRight();

                //              int ulhorIndex = horOrigin +
                // (int)(ul.getLongitude()/hor_dpp);
                //              int ulverIndex = verOrigin -
                // (int)(ul.getLatitude()/ver_dpp);

                //              int lrhorIndex = horOrigin +
                // (int)(lr.getLongitude()/hor_dpp);
                //              int lrverIndex = verOrigin -
                // (int)(lr.getLatitude()/ver_dpp);

                //              Debug.output("The image file will be referenced
                // from:\n " +
                //                           ulhorIndex + ", " + ulverIndex + "\n " +
                //                           lrhorIndex + ", " + lrverIndex);
                ///////////////////////////////////

                int clear = 0x00000000;

                Point ctp = new Point();
                LatLonPoint llp = new LatLonPoint();
                LatLonPoint center = p.getCenter();

                for (int i = 0; i < projWidth; i++) {
                    for (int j = 0; j < projHeight; j++) {
                        p.inverse(i, j, llp);

                        // index into the OMRaster pixel array
                        int tmpIndex = i + (j * projWidth);

                        // If the llp calculated isn't on the map,
                        // don't bother drawing it. Could be a space
                        // point in Orthographic projection, for
                        // instance.
                        if (llp.equals(center)) {
                            p.forward(llp, ctp);
                            if (ctp.x != i || ctp.y != j) {
                                tmpPixels[tmpIndex] = clear;
                                continue;
                            }
                        }

                        // Find the corresponding pixel location in
                        // the source image.
                        int horIndex = horOrigin
                                + (int) (llp.getLongitude() / hor_dpp);
                        int verIndex = verOrigin
                                - (int) (llp.getLatitude() / ver_dpp);

                        if (horIndex < 0 || horIndex >= iwidth || verIndex < 0
                                || verIndex >= iheight) {
                            // pixel not on the source image. This
                            // happens if the image doesn't cover the
                            // entire earth.
                            continue;
                        }

                        int imageIndex = horIndex + (verIndex * iwidth);

                        if (imageIndex >= 0 && imageIndex < pixels.length) {
                            tmpPixels[tmpIndex] = pixels[imageIndex];
                            //                      } else {
                            //                          Debug.message("earthimage",
                            // "ImageTranslator: outside pixel
                            // range");
                        }
                    }
                }

                Debug.message("earthimage",
                        "ImageTranslator: finished creating image");
                return new OMRaster(0, 0, projWidth, projHeight, tmpPixels);
            } else {
                Debug.message("earthimage",
                        "ImageTranslator: problem creating image");
            }

            // If you get here, something's not right.
            return null;
        }

        /**
         * Get the pixels from the BufferedImage. If anything goes
         * wrong, returns a int[0].
         */
        protected int[] getPixels(Image img, int x, int y, int w, int h) {
            int[] pixels = new int[w * h];
            PixelGrabber pg = new PixelGrabber(img, x, y, w, h, pixels, 0, w);
            try {
                pg.grabPixels();
            } catch (InterruptedException e) {
                Debug.error("ImageTranslator: interrupted waiting for pixels!");
                return new int[0];
            }

            if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
                System.err.println("ImageTranslator: image fetch aborted or errored");
                return new int[0];
            }

            return pixels;
        }
    }
}
TOP

Related Classes of com.bbn.openmap.plugin.earthImage.EarthImagePlugIn$ImageTranslator

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.