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

org.refcodes.graphical.GraphicalUtility Maven / Gradle / Ivy

Go to download

Artifact for graphical issues regarding RGB, pixel, fonts, and other stuff (utility).

The newest version!
// /////////////////////////////////////////////////////////////////////////////
// REFCODES.ORG
// =============================================================================
// This code is copyright (c) by Siegfried Steiner, Munich, Germany, distributed
// on an "AS IS" BASIS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, and licen-
// sed under the following (see "http://en.wikipedia.org/wiki/Multi-licensing")
// licenses:
// =============================================================================
// GNU General Public License, v3.0 ("http://www.gnu.org/licenses/gpl-3.0.html")
// together with the GPL linking exception applied; as being applied by the GNU
// Classpath ("http://www.gnu.org/software/classpath/license.html")
// =============================================================================
// Apache License, v2.0 ("http://www.apache.org/licenses/TEXT-2.0")
// =============================================================================
// Please contact the copyright holding author(s) of the software artifacts in
// question for licensing issues not being covered by the above listed licenses,
// also regarding commercial licensing models or regarding the compatibility
// with other open source licenses.
// /////////////////////////////////////////////////////////////////////////////

package org.refcodes.graphical;

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;

/**
 * The Class GraphicalUtility.
 */
public final class GraphicalUtility {

	// /////////////////////////////////////////////////////////////////////////
	// CONSTRUCTORS:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Private empty constructor to prevent instantiation as of being a utility
	 * with just static public methods.
	 */
	private GraphicalUtility() {}

	// /////////////////////////////////////////////////////////////////////////
	// METHODS:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Converts the given RGB value to a gray scale value by averaging the red,
	 * green and blue portions of the RGB value.
	 * 
	 * @param aRgbValue The RGB value to be converted to a grays scale value.
	 * 
	 * @return The gray scale value from the RGB value.
	 */
	public static int toGray( int aRgbValue ) {
		return ( ( toRed( aRgbValue ) + toGreen( aRgbValue ) + toBlue( aRgbValue ) ) / 3 );
	}

	/**
	 * Combines the alpha, red, green and blue values to an RGB value.
	 * 
	 * @param aAlpha The alpha value to use.
	 * @param aRed The red value to use.
	 * @param aGreen The green value to use.
	 * @param aBlue The blue value to use.
	 * 
	 * @return The according RGB value from the alpha, red, green and blue
	 *         values.
	 */
	public static int toRgb( int aAlpha, int aRed, int aGreen, int aBlue ) {
		return ( aAlpha << 24 ) + ( aRed << 16 ) + ( aGreen << 8 ) + aBlue;
	}

	/**
	 * Retrieves the alpha portion of the provided RGB value.
	 * 
	 * @param aRgbValue The RGB value from which to retrieve the alpha portion.
	 * 
	 * @return The alpha portion from the according RGB value.
	 */
	public static int toAlpha( int aRgbValue ) {
		return ( aRgbValue >> 24 ) & 0xFF;
	}

	/**
	 * Retrieves the red portion of the provided RGB value.
	 * 
	 * @param aRgbValue The RGB value from which to retrieve the red portion.
	 * 
	 * @return The red portion from the according RGB value.
	 */
	public static int toRed( int aRgbValue ) {
		return ( aRgbValue >> 16 ) & 0xFF;
	}

	/**
	 * Retrieves the green portion of the provided RGB value.
	 * 
	 * @param aRgbValue The RGB value from which to retrieve the green portion.
	 * 
	 * @return The green portion from the according RGB value.
	 */
	public static int toGreen( int aRgbValue ) {
		return ( aRgbValue >> 8 ) & 0xFF;
	}

	/**
	 * Retrieves the blue portion of the provided RGB value.
	 * 
	 * @param aRgbValue The RGB value from which to retrieve the blue portion.
	 * 
	 * @return The blue portion from the according RGB value.
	 */
	public static int toBlue( int aRgbValue ) {
		return aRgbValue & 0xFF;
	}

	/**
	 * Tries to determine the font size for the given font name and font style
	 * for the given text to fit into the given width (pixels). In case the font
	 * size cannot be detected to make the given text fit exactly into the given
	 * width, then the biggest font size is used with which the text still fits
	 * into the given width. The width of the text will not exceed the given
	 * width.
	 *
	 * @param aText The text to fit into the given (pixel) width.
	 * @param aWidth The (pixel) width into which the given text is to fit.
	 * @param aFontName The font name to use for determining the correct font
	 *        size.
	 * @param aFontStyle The font style to be used
	 * 
	 * @return the font
	 */
	public static Font getAwtFont( String aText, int aWidth, String aFontName, int aFontStyle ) {
		int theFontSize = 5;
		Font eFont;
		Font ePreviousFont = null;
		int eWidth = 0;
		do {
			eFont = new Font( aFontName, aFontStyle, theFontSize );
			eWidth = toPixelWidth( aText, eFont );
			if ( eWidth < aWidth ) {
				ePreviousFont = eFont;
			}
			theFontSize++;
		} while ( eWidth < aWidth );

		if ( eWidth == aWidth ) {
			return eFont;
		}
		if ( ePreviousFont == null ) {
			throw new IllegalArgumentException( "Unable to determine the font size for font \"" + aFontName + "\" with style \"" + aFontStyle + "\" for text \"" + aText + "\" to fit into a width of y <" + aWidth + "> as the smallest font already exceeds this width with width <" + eWidth + ">." );
		}
		return ePreviousFont;
	}

	/**
	 * Loads an SVG image from the given resource (URL) and transforms it to the
	 * required dimension (as SVG is vector graphics and we need a pixel
	 * representation). You can get a resource something like below:
	 * "MyClass.class.getResource( "/chess/qlt_queen_light_transparent.svg" );"
	 *
	 * @param aText the text
	 * @param aFont the font
	 * 
	 * @return The image with the given dimensions transformed from the provided
	 *         SVG resource.
	 */
	// public static Image fromSvgResource( URL aResource, int aWidth, int
	// aHeight ) throws FileNotFoundException, TranscoderException,
	// URISyntaxException {
	// return fromSvgFile( new File( aResource.toURI() ), aWidth, aHeight );
	// }

	/**
	 * Loads an SVG image from the given file and transforms it to the required
	 * dimension (as SVG is vector graphics and we need a pixel representation).
	 * 
	 * @param aFile The file from which to load the SVG file.
	 * @param aWidth The width in pixels of the loaded image.
	 * @param aHeight The height in pixels of the loaded image.
	 * 
	 * @return The image with the given dimensions transformed from the provided
	 *         SVG file.
	 */
	// public static Image fromSvgFile( File aFile, int aWidth, int aHeight )
	// throws FileNotFoundException, TranscoderException {
	// return fromSvgReader( new FileReader( aFile ), aWidth, aHeight );
	// }

	/**
	 * Loads an SVG image from the given string and transforms it to the
	 * required dimension (as SVG is vector graphics and we need a pixel
	 * representation).
	 * 
	 * @param aSvg The SVG text from which to load the SVG file.
	 * @param aWidth The width in pixels of the loaded image.
	 * @param aHeight The height in pixels of the loaded image.
	 * 
	 * @return The image with the given dimensions transformed from the provided
	 *         SVG file.
	 */
	// public static Image fromSvg( String aSvg, int aWidth, int aHeight )
	// throws TranscoderException {
	// CustomTranscoder theTranscoder = new CustomTranscoder();
	// theTranscoder.addTranscodingHint( PNGTranscoder.KEY_WIDTH, (float) aWidth
	// );
	// theTranscoder.addTranscodingHint( PNGTranscoder.KEY_HEIGHT, (float)
	// aHeight );
	// TranscoderInput theInput = new TranscoderInput( aSvg );
	// theTranscoder.transcode( theInput, null );
	// return SwingFXUtils.toFXImage( theTranscoder.getImage(), null );
	// }

	/**
	 * Loads an SVG image from the given reader and transforms it to the
	 * required dimension (as SVG is vector graphics and we need a pixel
	 * representation).
	 * 
	 * @param aReader The reader from which to load the SVG file.
	 * @param aWidth The width in pixels of the loaded image.
	 * @param aHeight The height in pixels of the loaded image.
	 * 
	 * @return The image with the given dimensions transformed from the provided
	 *         SVG file.
	 */
	// public static Image fromSvgStream( InputStream aInputStream, int aWidth,
	// int aHeight ) throws TranscoderException {
	// return fromSvgReader( new BufferedReader(new
	// InputStreamReader(aInputStream)), aWidth, aHeight );
	// }

	/**
	 * Loads an SVG image from the given reader and transforms it to the
	 * required dimension (as SVG is vector graphics and we need a pixel
	 * representation).
	 * 
	 * @param aReader The reader from which to load the SVG file.
	 * @param aWidth The width in pixels of the loaded image.
	 * @param aHeight The height in pixels of the loaded image.
	 * 
	 * @return The image with the given dimensions transformed from the provided
	 *         SVG file.
	 */
	// public static Image fromSvgReader( Reader aReader, int aWidth, int
	// aHeight ) throws TranscoderException {
	// CustomTranscoder theTranscoder = new CustomTranscoder();
	// theTranscoder.addTranscodingHint( PNGTranscoder.KEY_WIDTH, (float) aWidth
	// );
	// theTranscoder.addTranscodingHint( PNGTranscoder.KEY_HEIGHT, (float)
	// aHeight );
	// TranscoderInput theInput = new TranscoderInput( aReader );
	// theTranscoder.transcode( theInput, null );
	// return SwingFXUtils.toFXImage( theTranscoder.getImage(), null );
	// }

	// /////////////////////////////////////////////////////////////////////////
	// HELPER:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Truncates the not set pixels on the left and on the right and determines
	 * the width of the given text with the provided font without the truncated
	 * pixels. Unfortunately the {@link FontMetrics#stringWidth(String)} method
	 * regards some left and some right "border" of the text even though there
	 * are none pixels set for the text there.
	 * 
	 * @param aText The text for which to determine the real truncated width.
	 * @param aFont The font to use to determine the real truncated width.
	 * 
	 * @return The real truncated width.
	 */
	private static int toPixelWidth( String aText, Font aFont ) {
		// int theImageType = BufferedImage.TYPE_USHORT_GRAY;
		// BufferedImage theImage = new BufferedImage( 1, 1, theImageType );

		final int theImageType = BufferedImage.TYPE_USHORT_GRAY;
		BufferedImage theImage = new BufferedImage( 1, 1, theImageType );

		Graphics theGraphics = theImage.getGraphics();
		//	Graphics theGraphics;
		//	try {
		//		theGraphics = theImage.getGraphics();
		//	}
		//
		//	catch ( AWTError e1 ) {
		//		try {
		//			String theBefore = SystemProperty.JAVA_AWT_HEADLESS.getValue();
		//			SystemProperty.JAVA_AWT_HEADLESS.setValue( "true" );
		//			theGraphics = theImage.getGraphics();
		//			System.setProperty( "java.awt.headless", theBefore );
		//		}
		//		catch ( Exception e2 ) {
		//			throw e1;
		//		}
		//	}
		theGraphics.setFont( aFont );
		final FontMetrics theFontMetrics = theGraphics.getFontMetrics();
		final int theWidth = theFontMetrics.stringWidth( aText );
		final int theHeight = theFontMetrics.getHeight();
		theImage = new BufferedImage( theWidth, theHeight, theImageType );
		theGraphics = theImage.getGraphics();
		theGraphics.setFont( aFont );
		final Graphics2D theGraphics2d = (Graphics2D) theGraphics;
		theGraphics2d.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON );
		theGraphics2d.drawString( aText, 0, theHeight );

		int theTrimBegin = 0;
		int theTrimEnd = theWidth;
		int eGray;
		leftOut: for ( int x = 0; x < theWidth; x++ ) {
			for ( int y = 0; y < theHeight; y++ ) {
				eGray = toGray( theImage.getRGB( x, y ) );
				if ( eGray != 0 ) {
					break leftOut;
				}
			}
			theTrimBegin = x + 1;
		}
		rightOut: for ( int x = theWidth - 1; x >= 0; x-- ) {
			for ( int y = 0; y < theHeight; y++ ) {
				eGray = toGray( theImage.getRGB( x, y ) );
				if ( eGray != 0 ) {
					break rightOut;
				}
			}
			theTrimEnd = x - 1;
		}
		final int theTrimmed = theTrimEnd - theTrimBegin - 1;
		return theTrimmed;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy