001: /*
002: * ImageUtilities.java
003: *
004: * Created on March 16, 2007, 4:34 PM
005: *
006: * Copyright 2006-2007 Nigel Hughes
007: *
008: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
009: * in compliance with the License. You may obtain a copy of the License at http://www.apache.org/
010: * licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
012: * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
013: * governing permissions and limitations under the License.
014: */
015:
016: package com.blogofbug.utility;
017:
018: import java.awt.Color;
019: import java.awt.Font;
020: import java.awt.Graphics;
021: import java.awt.Graphics2D;
022: import java.awt.GraphicsConfiguration;
023: import java.awt.GraphicsEnvironment;
024: import java.awt.Image;
025: import java.awt.RenderingHints;
026: import java.awt.Transparency;
027: import java.awt.font.FontRenderContext;
028: import java.awt.font.LineBreakMeasurer;
029: import java.awt.font.TextAttribute;
030: import java.awt.font.TextLayout;
031: import java.awt.image.BufferedImage;
032: import java.io.IOException;
033: import java.net.MalformedURLException;
034: import java.net.URL;
035: import java.text.AttributedCharacterIterator;
036: import java.text.AttributedString;
037: import java.util.Hashtable;
038: import java.util.LinkedList;
039: import javax.imageio.ImageIO;
040: import javax.swing.JComponent;
041:
042: /**
043: * Static class with utility methods for images
044: *
045: * @author nigel
046: */
047: public class ImageUtilities {
048:
049: /**
050: * Creates an image compatible with the current display
051: *
052: * @return A BufferedImage with the appropriate color model
053: */
054: public static BufferedImage createCompatibleImage(int width,
055: int height) {
056: GraphicsConfiguration configuration = GraphicsEnvironment
057: .getLocalGraphicsEnvironment().getDefaultScreenDevice()
058: .getDefaultConfiguration();
059:
060: //Create a buffered image which is the right (translucent) format for the current graphics device, this
061: //should ensure the fastest possible performance. Adding on some extra height to make room for the reflection
062: return configuration.createCompatibleImage(width, height,
063: Transparency.TRANSLUCENT);
064: }
065:
066: public static BufferedImage loadCompatibleImageResource(Class from,
067: String resource) {
068: return loadCompatibleImage(from.getResource(resource)
069: .toString());
070: }
071:
072: /**
073: * Loads an image in a format compatible with the current display
074: *
075: *
076: * @return A BufferedImage with the appropriate color model
077: */
078: public static BufferedImage loadCompatibleImage(String imageURL) {
079: Image image = null;
080: try {
081: image = ImageIO.read(new URL(imageURL));
082: } catch (MalformedURLException ex) {
083: ex.printStackTrace();
084: return null;
085: } catch (IOException ex) {
086: ex.printStackTrace();
087: return null;
088: }
089: if (image == null) {
090: return null;
091: }
092:
093: GraphicsConfiguration configuration = GraphicsEnvironment
094: .getLocalGraphicsEnvironment().getDefaultScreenDevice()
095: .getDefaultConfiguration();
096:
097: //Create a buffered image which is the right (translucent) format for the current graphics device, this
098: //should ensure the fastest possible performance. Adding on some extra height to make room for the reflection
099: BufferedImage originalImage = configuration
100: .createCompatibleImage(image.getWidth(null), image
101: .getHeight(null), Transparency.TRANSLUCENT);
102:
103: //Blit the loaded image onto the optimized surface by creating a graphics context for the new image
104: Graphics2D g = originalImage.createGraphics();
105: //Draw the original image
106: g.drawImage(image, 0, 0, null);
107: g.dispose();
108: return originalImage;
109: }
110:
111: /**
112: * Produces a resized image that is of the given dimensions
113: *
114: * @param image The original image
115: * @param width The desired width
116: * @param height The desired height
117: * @return The new BufferedImage
118: */
119: public static BufferedImage scaledImage(BufferedImage image,
120: int width, int height) {
121: BufferedImage newImage = createCompatibleImage(width, height);
122: Graphics graphics = newImage.createGraphics();
123:
124: graphics.drawImage(image, 0, 0, width, height, null);
125:
126: graphics.dispose();
127: return newImage;
128: }
129:
130: /**
131: * Produces a copy of the supplied image
132: *
133: * @param image The original image
134: * @return The new BufferedImage
135: */
136: public static BufferedImage copyImage(BufferedImage image) {
137: return scaledImage(image, image.getWidth(), image.getHeight());
138: }
139:
140: /**
141: * Renders a paragraph of text (line breaks ignored) to an image (created and returned).
142: *
143: * @param font The font to use
144: * @param textColor The color of the text
145: * @param text The message
146: * @param width The width the text should be limited to
147: * @return An image with the text rendered into it
148: */
149: public static BufferedImage renderTextToImage(Font font,
150: Color textColor, String text, int width) {
151: Hashtable map = new Hashtable();
152: map.put(TextAttribute.FONT, font);
153: AttributedString attributedString = new AttributedString(text,
154: map);
155: AttributedCharacterIterator paragraph = attributedString
156: .getIterator();
157:
158: FontRenderContext frc = new FontRenderContext(null, false,
159: false);
160: int paragraphStart = paragraph.getBeginIndex();
161: int paragraphEnd = paragraph.getEndIndex();
162: LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(
163: paragraph, frc);
164:
165: float drawPosY = 0;
166:
167: //First time around, just determine the height
168: while (lineMeasurer.getPosition() < paragraphEnd) {
169: TextLayout layout = lineMeasurer.nextLayout(width);
170:
171: // Move it down
172: drawPosY += layout.getAscent() + layout.getDescent()
173: + layout.getLeading();
174: }
175:
176: BufferedImage image = ImageUtilities.createCompatibleImage(
177: width, (int) drawPosY);
178: Graphics2D graphics = (Graphics2D) image.getGraphics();
179: graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
180: RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
181:
182: drawPosY = 0;
183: lineMeasurer.setPosition(paragraphStart);
184: while (lineMeasurer.getPosition() < paragraphEnd) {
185: TextLayout layout = lineMeasurer.nextLayout(width);
186:
187: // Move y-coordinate by the ascent of the layout.
188: drawPosY += layout.getAscent();
189:
190: /* Compute pen x position. If the paragraph is
191: right-to-left, we want to align the TextLayouts
192: to the right edge of the panel.
193: */
194: float drawPosX;
195: if (layout.isLeftToRight()) {
196: drawPosX = 0;
197: } else {
198: drawPosX = width - layout.getAdvance();
199: }
200:
201: // Draw the TextLayout at (drawPosX, drawPosY).
202: layout.draw(graphics, drawPosX, drawPosY);
203:
204: // Move y-coordinate in preparation for next layout.
205: drawPosY += layout.getDescent() + layout.getLeading();
206: }
207:
208: graphics.dispose();
209: return image;
210: }
211:
212: /**
213: * Renders multiple paragraphs of text in an array to an image (created and returned).
214: *
215: * @param font The font to use
216: * @param textColor The color of the text
217: * @param text The message in an array of strings (one paragraph in each
218: * @param width The width the text should be limited to
219: * @return An image with the text rendered into it
220: */
221: public static BufferedImage renderTextToImage(Font font,
222: Color textColor, String text[], int width) {
223: LinkedList<BufferedImage> images = new LinkedList<BufferedImage>();
224:
225: int totalHeight = 0;
226:
227: for (String paragraph : text) {
228: BufferedImage paraImage = renderTextToImage(font,
229: textColor, paragraph, width);
230: totalHeight += paraImage.getHeight();
231: images.add(paraImage);
232: }
233:
234: BufferedImage image = createCompatibleImage(width, totalHeight);
235: Graphics2D graphics = (Graphics2D) image.createGraphics();
236:
237: int y = 0;
238:
239: for (BufferedImage paraImage : images) {
240: graphics.drawImage(paraImage, 0, y, null);
241: y += paraImage.getHeight();
242: }
243:
244: graphics.dispose();
245: return image;
246: }
247:
248: /**
249: * Renders a component into an image, which is useful for playing with the component's
250: * resultant image in special effects or transitions
251: *
252: * @param component The component to render
253: * @return A buffered image with the rendered component.
254: */
255: public static BufferedImage renderComponentToImage(
256: JComponent component) {
257: //Create the image
258: BufferedImage image = createCompatibleImage(component
259: .getWidth(), component.getHeight());
260:
261: //Render the component onto the image
262: Graphics graphics = image.createGraphics();
263: // component.update(graphics);
264: component.paint(graphics);
265: graphics.dispose();
266: return image;
267: }
268: }
|