All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.uci.ics.jung.visualization.PivotingImageShaper Maven / Gradle / Ivy

/*
 * Copyright (c) 2005, The JUNG Authors
 * All rights reserved.
 *
 * This software is open-source under the BSD license; see either "license.txt"
 * or https://github.com/jrtom/jung/blob/master/LICENSE for a description.
 *
 * Created on Jun 17, 2005
 */

package edu.uci.ics.jung.visualization;

import java.awt.Shape;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;

/**
 * Provides Supplier methods that, given a BufferedImage, an Image, or the fileName of an image,
 * will return a java.awt.Shape that is the contiguous traced outline of the opaque part of the
 * image. This could be used to define an image for use in a Node, where the shape used for picking
 * and edge-arrow placement follows the opaque part of an image that has a transparent background.
 * The methods try to detect lines in order to minimize points in the path
 *
 * @author Tom Nelson
 */
public class PivotingImageShaper {

  /** the number of pixels to skip while sampling the images edges */
  static int sample = 1;
  /** the first x coordinate of the shape. Used to discern when we are done */
  static int firstx = 0;

  /**
   * Given an image, possibly with a transparent background, return the Shape of the opaque part of
   * the image
   *
   * @param image the image whose shape is being returned
   * @return the Shape
   */
  public static Shape getShape(BufferedImage image) {
    firstx = 0;
    return leftEdge(image, new GeneralPath());
  }

  private static Point2D detectLine(
      Point2D p1, Point2D p2, Point2D p, Line2D line, GeneralPath path) {
    if (p2 == null) {
      p2 = p;
      line.setLine(p1, p2);
    }
    // check for line
    else if (line.ptLineDistSq(p) < 1) { // its on the line
      // make it p2
      p2.setLocation(p);
    } else { // its not on the current line
      p1.setLocation(p2);
      p2.setLocation(p);
      line.setLine(p1, p2);
      path.lineTo((float) p1.getX(), (float) p1.getY());
    }
    return p2;
  }
  /**
   * trace the left side of the image
   *
   * @param image
   * @param path
   * @return
   */
  private static Shape leftEdge(BufferedImage image, GeneralPath path) {
    int lastj = 0;
    Point2D p1 = null;
    Point2D p2 = null;
    Line2D line = new Line2D.Float();
    for (int i = 0; i < image.getHeight(); i += sample) {
      boolean aPointExistsOnThisLine = false;
      // go until we reach an opaque point, then stop
      for (int j = 0; j < image.getWidth(); j += sample) {
        if ((image.getRGB(j, i) & 0xff000000) != 0) {
          // this is a point I want
          Point2D p = new Point2D.Float(j, i);
          aPointExistsOnThisLine = true;
          if (path.getCurrentPoint() != null) {
            // this is a continuation of a path
            p2 = detectLine(p1, p2, p, line, path);
          } else {
            // this is the first point in the path
            path.moveTo(j, i);
            firstx = j;
            p1 = p;
          }
          lastj = j;
          break;
        }
      }
      if (aPointExistsOnThisLine == false) {
        break;
      }
    }
    return bottomEdge(image, path, lastj);
  }

  /**
   * trace the bottom of the image
   *
   * @param image
   * @param path
   * @param start
   * @return
   */
  private static Shape bottomEdge(BufferedImage image, GeneralPath path, int start) {
    int lastj = 0;
    Point2D p1 = path.getCurrentPoint();
    Point2D p2 = null;
    Line2D line = new Line2D.Float();
    for (int i = start; i < image.getWidth(); i += sample) {
      boolean aPointExistsOnThisLine = false;
      for (int j = image.getHeight() - 1; j >= 0; j -= sample) {
        if ((image.getRGB(i, j) & 0xff000000) != 0) {
          // this is a point I want
          Point2D p = new Point2D.Float(i, j);
          aPointExistsOnThisLine = true;
          p2 = detectLine(p1, p2, p, line, path);
          lastj = j;
          break;
        }
      }
      if (aPointExistsOnThisLine == false) {
        break;
      }
    }
    return rightEdge(image, path, lastj);
  }

  /**
   * trace the right side of the image
   *
   * @param image
   * @param path
   * @param start
   * @return
   */
  private static Shape rightEdge(BufferedImage image, GeneralPath path, int start) {
    int lastj = 0;
    Point2D p1 = path.getCurrentPoint();
    Point2D p2 = null;
    Line2D line = new Line2D.Float();
    for (int i = start; i >= 0; i -= sample) {
      boolean aPointExistsOnThisLine = false;

      for (int j = image.getWidth() - 1; j >= 0; j -= sample) {
        if ((image.getRGB(j, i) & 0xff000000) != 0) {
          // this is a point I want
          Point2D p = new Point2D.Float(j, i);
          aPointExistsOnThisLine = true;
          p2 = detectLine(p1, p2, p, line, path);
          lastj = j;
          break;
        }
      }
      if (aPointExistsOnThisLine == false) {
        break;
      }
    }
    return topEdge(image, path, lastj);
  }

  /**
   * trace the top of the image
   *
   * @param image
   * @param path
   * @param start
   * @return
   */
  private static Shape topEdge(BufferedImage image, GeneralPath path, int start) {
    Point2D p1 = path.getCurrentPoint();
    Point2D p2 = null;
    Line2D line = new Line2D.Float();
    for (int i = start; i >= firstx; i -= sample) {
      boolean aPointExistsOnThisLine = false;
      for (int j = 0; j < image.getHeight(); j += sample) {
        if ((image.getRGB(i, j) & 0xff000000) != 0) {
          // this is a point I want
          Point2D p = new Point2D.Float(i, j);
          aPointExistsOnThisLine = true;
          p2 = detectLine(p1, p2, p, line, path);
          break;
        }
      }
      if (aPointExistsOnThisLine == false) {
        break;
      }
    }
    path.closePath();
    return path;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy