imageutil.java
来自「world wind java sdk 源码」· Java 代码 · 共 1,510 行 · 第 1/5 页
JAVA
1,510 行
/*Copyright (C) 2001, 2006 United States Governmentas represented by the Administrator of theNational Aeronautics and Space Administration.All Rights Reserved.*/package gov.nasa.worldwind.util;import gov.nasa.worldwind.avlist.*;import gov.nasa.worldwind.exception.WWRuntimeException;import gov.nasa.worldwind.formats.tiff.*;import gov.nasa.worldwind.formats.worldfile.WorldFile;import gov.nasa.worldwind.geom.*;import gov.nasa.worldwind.geom.coords.*;import gov.nasa.worldwind.globes.Earth;import javax.imageio.ImageIO;import java.awt.*;import java.awt.image.*;import java.io.*;import java.util.*;import java.util.List;/** * @author tag * @version $Id: ImageUtil.java 9716 2009-03-27 16:55:14Z dcollins $ */public class ImageUtil{ public static int NEAREST_NEIGHBOR_INTERPOLATION = 1; public static int BILINEAR_INTERPOLATION = 2; public static int IMAGE_TILE_SIZE = 1024; // default size to make subimages public static Color TRANSPARENT = new Color(0, 0, 0, 0); /** * Draws the specified <code>image</code> onto the <code>canvas</code>, scaling or streching the image to fit the * canvas. This will apply a bilinear filter to the image if any scaling or streching is necessary. * * @param image the BufferedImage to draw, potentially scaling or streching to fit the <code>canvas</code>. * @param canvas the BufferedImage to receive the scaled or streched <code>image</code>. * * @throws IllegalArgumentException if either <code>image</code> or <code>canvas</code> is null. */ public static void drawImageOnCanvas(BufferedImage image, BufferedImage canvas) // TODO: rename { if (image == null) { String message = Logging.getMessage("nullValue.ImageIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (canvas == null) { String message = Logging.getMessage("nullValue.CanvasIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } java.awt.Graphics2D g2d = canvas.createGraphics(); try { g2d.setComposite(java.awt.AlphaComposite.Src); g2d.setRenderingHint( java.awt.RenderingHints.KEY_INTERPOLATION, java.awt.RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2d.drawImage(image, 0, 0, canvas.getWidth(), canvas.getHeight(), null); } finally { g2d.dispose(); } } /** * Rasterizes the image into the canvas, given a transform that maps canvas coordinates to image coordinates. * * @param image the source image. * @param canvas the image to receive the transformed source image. * @param canvasToImageTransform <code>Matrix</code> that maps a canvas coordinates to image coordinates. * * @throws IllegalArgumentException if any of <code>image</code>, <code>canvas</code>, or <code>canvasToImageTransform</code> * are null. */ public static void warpImageWithTransform(BufferedImage image, BufferedImage canvas, Matrix canvasToImageTransform) { if (image == null) { String message = Logging.getMessage("nullValue.ImageIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (canvas == null) { String message = Logging.getMessage("nullValue.CanvasIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (canvasToImageTransform == null) { String message = Logging.getMessage("nullValue.MatrixIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } int sourceWidth = image.getWidth(); int sourceHeight = image.getHeight(); int destWidth = canvas.getWidth(); int destHeight = canvas.getHeight(); for (int dy = 0; dy < destHeight; dy++) { for (int dx = 0; dx < destWidth; dx++) { Vec4 vec = new Vec4(dx, dy, 1).transformBy3(canvasToImageTransform); if (vec.x >= 0 && vec.y >= 0 && vec.x <= (sourceWidth - 1) && vec.y <= (sourceHeight - 1)) { int x0 = (int) Math.floor(vec.x); int x1 = (int) Math.ceil(vec.x); double xf = vec.x - x0; int y0 = (int) Math.floor(vec.y); int y1 = (int) Math.ceil(vec.y); double yf = vec.y - y0; int color = interpolateColor(xf, yf, image.getRGB(x0, y0), image.getRGB(x1, y0), image.getRGB(x0, y1), image.getRGB(x1, y1)); canvas.setRGB(dx, dy, color); } } } } /** * Convenience method for transforming a georeferenced source image into a geographically aligned destination image. * The source image is georeferenced by either three four control points. Each control point maps a location in the * source image to a geographic location. This is equivalent to calling {#transformConstrainedImage3} or * {#transformConstrainedImage4}, depending on the number of control points. * * @param sourceImage the source image to transform. * @param imagePoints three or four control points in the source image. * @param geoPoints three or four geographic locations corresponding to each source control point. * @param destImage the destination image to receive the transformed source imnage. * * @return bounding sector for the geographically aligned destination image. * * @throws IllegalArgumentException if any of <code>sourceImage</code>, <code>destImage</code>, * <code>imagePoints</code> or <code>geoPoints</code> is null, or if either * <code>imagePoints</code> or <code>geoPoints</code> have length less than 3. */ public static Sector warpImageWithControlPoints(BufferedImage sourceImage, java.awt.geom.Point2D[] imagePoints, LatLon[] geoPoints, BufferedImage destImage) { if (sourceImage == null) { String message = Logging.getMessage("nullValue.SourceImageIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (destImage == null) { String message = Logging.getMessage("nullValue.DestinationImageIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } String message = validateControlPoints(3, imagePoints, geoPoints); if (message != null) { Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (imagePoints.length >= 4 && geoPoints.length >= 4) { return warpImageWithControlPoints4(sourceImage, imagePoints, geoPoints, destImage); } else // (imagePoints.length == 3) { return warpImageWithControlPoints3(sourceImage, imagePoints, geoPoints, destImage); } } /** * Transforms a georeferenced source image into a geographically aligned destination image. The source image is * georeferenced by four control points. Each control point maps a location in the source image to a geographic * location. * * @param sourceImage the source image to transform. * @param imagePoints four control points in the source image. * @param geoPoints four geographic locations corresponding to each source control point. * @param destImage the destination image to receive the transformed source imnage. * * @return bounding sector for the geographically aligned destination image. * @throws IllegalArgumentException if any of <code>sourceImage</code>, <code>destImage</code>, * <code>imagePoints</code> or <code>geoPoints</code> is null, or if either * <code>imagePoints</code> or <code>geoPoints</code> have length less than 4. */ public static Sector warpImageWithControlPoints4(BufferedImage sourceImage, java.awt.geom.Point2D[] imagePoints, LatLon[] geoPoints, BufferedImage destImage) { if (sourceImage == null) { String message = Logging.getMessage("nullValue.SourceImageIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (destImage == null) { String message = Logging.getMessage("nullValue.DestinationImageIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } String message = validateControlPoints(4, imagePoints, geoPoints); if (message != null) { Logging.logger().severe(message); throw new IllegalArgumentException(message); } // We can only create an affine transform from three of the given points. To increase accruacy, we will compute // the error for each combination of three points, and choose the combination with the least error. java.awt.geom.Point2D[] bestFitImagePoints = new java.awt.geom.Point2D[3]; LatLon[] bestFitGeoPoints = new LatLon[3]; computeBestFittingControlPoints4(imagePoints, geoPoints, bestFitImagePoints, bestFitGeoPoints); return warpImageWithControlPoints3(sourceImage, bestFitImagePoints, bestFitGeoPoints, destImage); } /** * Transforms a georeferenced source image into a geographically aligned destination image. The source image is * georeferenced by three control points. Each control point maps a location in the source image to a geographic * location. * * @param sourceImage the source image to transform. * @param imagePoints three control points in the source image. * @param geoPoints three geographic locations corresponding to each source control point. * @param destImage the destination image to receive the transformed source imnage. * * @return bounding sector for the geographically aligned destination image. * * @throws IllegalArgumentException if any of <code>sourceImage</code>, <code>destImage</code>, * <code>imagePoints</code> or <code>geoPoints</code> is null, or if either * <code>imagePoints</code> or <code>geoPoints</code> have length less than 3. */ public static Sector warpImageWithControlPoints3(BufferedImage sourceImage, java.awt.geom.Point2D[] imagePoints, LatLon[] geoPoints, BufferedImage destImage) { if (sourceImage == null) { String message = Logging.getMessage("nullValue.SourceImageIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (destImage == null) { String message = Logging.getMessage("nullValue.DestinationImageIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } String message = validateControlPoints(3, imagePoints, geoPoints); if (message != null) { Logging.logger().severe(message); throw new IllegalArgumentException(message); } // Compute the destination sector. We want a lat/lon aligned sector that bounds the source image once it is // transformed into a lat/lon aligned image. We compute a matrix that will map source grid coordinates to // geographic coordinates. Then we transform the source image's four corners into geographic coordinates. // The sector we want is the sector that bounds those four geographic coordinates. Matrix gridToGeographic = Matrix.fromImageToGeographic(imagePoints, geoPoints); List<LatLon> corners = computeImageCorners(sourceImage.getWidth(), sourceImage.getHeight(), gridToGeographic); Sector destSector = Sector.boundingSector(corners); if (Sector.isSector(corners) && destSector.isSameSector(corners)) { drawImageOnCanvas(sourceImage, destImage); } else { // Compute a matrix that will map from destination grid coordinates to source grid coordinates. By using // matrix multiplication in this order, an incoming vector will be transformed by the last matrix multiplied, // then the previous, and so on. So an incoming destination coordinate would be transformed into geographic // coordinates, then into source coordinates. Matrix transform = Matrix.IDENTITY; transform = transform.multiply(Matrix.fromGeographicToImage(imagePoints, geoPoints)); transform = transform.multiply(Matrix.fromImageToGeographic(destImage.getWidth(), destImage.getHeight(), destSector)); warpImageWithTransform(sourceImage, destImage, transform); } return destSector; } /** * Transforms a georeferenced source image into a geographically aligned destination image. The source image is * georeferenced by a world file, which defines an affine transform from source coordinates to geographic
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?