src.gov.nasa.worldwindx.examples.util.PowerOfTwoPaddedImage Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of worldwind Show documentation
Show all versions of worldwind Show documentation
World Wind is a collection of components that interactively display 3D geographic information within Java applications or applets.
/*
* Copyright (C) 2012 United States Government as represented by the Administrator of the
* National Aeronautics and Space Administration.
* All Rights Reserved.
*/
package gov.nasa.worldwindx.examples.util;
import gov.nasa.worldwind.util.*;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.*;
import java.io.InputStream;
/**
* The PowerOfTwoPaddedImage class converts images with non-power-of-two dimensions to images with power-of-two
* dimensions. The original image is copied into a power-of-two image, where any pixels not covered by the original
* image are completely transparent. This is a useful property when converting images to OpenGL textures.
* Non-power-of-two textures are handled inconsistently by graphics hardware. Not all hardware supports them, and many
* that do lack full support for the the texturing functionality avialable for power-of-two textures.
*
* PowerOfTwoPaddedImage provides accessors to the converted power-of-two image, the power-of-two image's width and
* height, and the original image's width and height.
*
* @author dcollins
* @version $Id: PowerOfTwoPaddedImage.java 1171 2013-02-11 21:45:02Z dcollins $
*/
public class PowerOfTwoPaddedImage
{
protected BufferedImage image;
protected int width;
protected int height;
protected PowerOfTwoPaddedImage(BufferedImage image, int width, int height)
{
if (image == null)
{
String message = Logging.getMessage("nullValue.ImageIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (width <= 0)
{
String message = Logging.getMessage("Geom.WidthInvalid", width);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (height <= 0)
{
String message = Logging.getMessage("Geom.HeightInvalid", height);
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
this.image = image;
this.width = width;
this.height = height;
}
/**
* Returns a new PowerOfTwoPaddedImage by converting the specified image
to a new image with
* power-of-two dimensions. Any pixels not covered by the original image are completely transparent. If the
* specified image
has power-of-two dimensions, this maintains a reference to the original image
* instead of creating a copy. However, if the specified image
has no alpha channel, this creates a
* copy of the original image with an alpha channel, regardless of the specified image's
dimensions.
* This guarantees that the method {@link #getPowerOfTwoImage()} always returns a BufferedImage with an alpha
* channel. This is a useful property when converting images to OpenGL texture's, when both power-of-two and
* non-power-of-two textures must have an alpha channel for consistent handling.
*
* @param image the BufferedImage to convert to an image with power-of-two dimensions.
*
* @return a new PowerOfTwoPaddedImage representing a power-of-two copy of the specified image
.
*
* @throws IllegalArgumentException if the image is null.
*/
public static PowerOfTwoPaddedImage fromBufferedImage(BufferedImage image)
{
if (image == null)
{
String message = Logging.getMessage("nullValue.ImageIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
BufferedImage potImage = image;
// Create a new image with power of two dimensions and an alpha channel. If the original image has non power
// of two dimensions, or if it does not have alpha channel, it won't display correctly as an Annotation
// background image.
if (!WWMath.isPowerOfTwo(image.getWidth()) || !WWMath.isPowerOfTwo(image.getHeight())
|| image.getTransparency() == Transparency.OPAQUE)
{
int potWidth = WWMath.powerOfTwoCeiling(image.getWidth());
int potHeight = WWMath.powerOfTwoCeiling(image.getHeight());
potImage = ImageUtil.createCompatibleImage(potWidth, potHeight, BufferedImage.TRANSLUCENT);
Graphics2D g2d = potImage.createGraphics();
try
{
g2d.drawImage(image, 0, 0, null);
}
finally
{
g2d.dispose();
}
}
return new PowerOfTwoPaddedImage(potImage, image.getWidth(), image.getHeight());
}
/**
* Returns a new PowerOfTwoPaddedImage from the specified path
, or null if the file referenced by
* path
cannot be read, or is not a readable image. The path
must be a local file path, or
* a valid resource on the classpath. This uses {@link javax.imageio.ImageIO} to read the specified
* path
as a {@link java.awt.image.BufferedImage}. Otherwise, this treats the resultant BufferedImage
* exactly as {@link #fromBufferedImage(java.awt.image.BufferedImage)}.
*
* @param path a local file path, or a valid resource on the classpath.
*
* @return a new PowerOfTwoPaddedImage representing a power-of-two copy of the image located at the specified
* path
, or null if the image file reference by path
cannot be read.
*
* @throws IllegalArgumentException if the path is null.
*/
public static PowerOfTwoPaddedImage fromPath(String path)
{
if (path == null)
{
String message = Logging.getMessage("nullValue.PathIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
Object streamOrException = WWIO.getFileOrResourceAsStream(path, null);
if (streamOrException == null || streamOrException instanceof Exception)
{
Logging.logger().log(java.util.logging.Level.SEVERE, "generic.ExceptionAttemptingToReadImageFile",
streamOrException != null ? streamOrException : path);
return null;
}
try
{
BufferedImage image = ImageIO.read((InputStream) streamOrException);
return fromBufferedImage(image);
}
catch (Exception e)
{
String message = Logging.getMessage("generic.ExceptionAttemptingToReadImageFile", path);
Logging.logger().severe(message);
return null;
}
}
/**
* Returns the width of the original non-power-of-two image, in pixels.
*
* @return the original image's width, in pixels.
*/
public int getOriginalWidth()
{
return this.width;
}
/**
* Returns the height of the original non-power-of-two image, in pixels.
*
* @return the original image's height, in pixels.
*/
public int getOriginalHeight()
{
return this.height;
}
/**
* Returns a copy of the original image as a {@link java.awt.image.BufferedImage} with power-of-two dimensions. Any
* pixels not covered by the original image are completely transparent.
*
* @return a copy of the original image as a BufferedImage.
*/
public BufferedImage getPowerOfTwoImage()
{
return this.image;
}
/**
* Returns the width of the power-of-two image, in pixels.
*
* @return the power-of-two image's width, in pixels.
*/
public int getPowerOfTwoWidth()
{
return this.image.getWidth();
}
/**
* Returns the height of the power-of-two image, in pixels.
*
* @return the power-of-two image's height, in pixels.
*/
public int getPowerOfTwoHeight()
{
return this.image.getHeight();
}
}