|
General questionsQ: What is Java 2D?A: Java 2D is an integral part of the Java SE platform that provides a powerful, flexible framework for device- and resolution-independent 2D graphics. Java 2D handles arbitrary shapes, text, and images and provides a uniform mechanism for performing transformations, such as rotation and scaling, on these objects. With Java 2D, application developers can render to display devices, discover and render to printer devices, read and write in many image formats. There is comprehensive text and font handling and color space support and various rendering techniques and effects are offered.Q: Who needs Java 2D?A: The Java 2D API benefits virtually all desktop developers as it provides the rendering engine for the Swing toolkit and is also used to develop games, and graphics and imaging applications. Java 2D is of benefit to any developer who wants to create a graphically rich end-user experience.Q: Where can I go for more information about Java 2D?A: A good place to start is The 2D Graphics Tutorial. You can also refer to the The Java 2D Programmer's GuideQ: Are there any news groups or mailing lists dedicated to Java 2D?A: JAVA2D-INTEREST@JAVA.SUN.COM is the primary mailing list for those interested in Java2D. All the Java 2D engineers at Sun monitor this alias. The archives for this list can be located at Java2D-interest list archive This mailing list is also linked to the Java 2D forum at java.net: http://forums.java.net/jive/forum.jspa?forumID=69 A few Sun engineers also participate in the Java 2D forums at javagaming.org, which is a great resource for game developers and other performance hungry individuals: http://www.javagaming.org/forums/index.php?board=15.0Programming, Debugging and Performance questionsQ: What's the difference between Graphics and Graphics2D?A: The Graphics class has been around since the first release of Java and supports the more basic rendering operations which are sufficient for many applications. Graphics2D is a subclass of Graphics and adds all the Java 2D API features first introduced in Java 2 in 1998.Q: Is there a list of the various runtime flags that Java2D uses?A: Yes! Check out: http://java.sun.com/j2se/1.5.0/docs/guide/2d/flags.htmlQ: What kinds of graphics hardware acceleration does Java2D use?A: This question has many answers, which depend on things like:
Q: How can I get better performance for my Java2D application?A: The answer depends entirely on what you are trying to do, and what environment you are running on. There are a lot of articles you can read to see if they help you, such as:
Q: Are there any tracing facilities in Java2D to help me track down performance issues in my application?A: Yes. In J2SE 1.4 and above, Sun's implementation of the Java2D API includes a simple system property that can help you determine the source of your performance bottleneck. Simply run your application with the following system property:
-Dsun.java2d.trace=[log[,timestamp]],[count],[out:<filename>],[help],[verbose]
For more information on this tracing facility, refer to the following documentation:http://java.sun.com/j2se/1.5.0/docs/guide/2d/flags.html#trace Image questionsQ: What image-file formats does Java 2D support?A: Through its Image I/O package (javax.imageio) Java 2D supports reading and writing GIF, JPEG, PNG, BMP and WBMP images. The Image I/O package includes support for easily plugging in additional image format support: JAI (Java Advanced Imaging) in particular has developed Image I/O plugins that add reading and writing support for formats such as TIFF and JPEG2000 in its "JAI Image I/O Tools" package, which has no dependency on the core JAI libraries.Q: Which ColorModel should I use if I need optimum performance?A: The best way to improve your performance with ColorModel optimization is to use an opaque ColorModel. If you are using an IndexColorModel, make sure you have no transparent pixel values and no alpha values in cmap arrays, and set hasAlpha to false. If you are using a ComponentColorModel, set Transparency to OPAQUE and hasAlpha to false. If you are using a DirectColorModel, make sure you have no alpha mask, or set the mask to zero. If you are using a BufferedImage, construct it only with one of the types that do not contain alpha.Q: What image types should I use to get the best performance?A: If you are creating an image whose data will be copied to the screen, create the image with the same depth and type of the screen. This way, no translation between the image and the screen is necessary before copying the image. To ensure that the depth and type of your image match the screen, use the createImage(w, h) method of your on-screen component which returns an image that has the same depth as the screen. Alternatively, if you are using a BufferedImage, create it with one of the pre-defined types or use GraphicsConfiguration.createCompatibleImage(w, h) to match the image with the screen format.Q: How do I create a resized copy of an image?A: Here's one way to do it: create a BufferedImage of the desired size and draw the original image into it, scaling on the fly. Note that depending on whether your original image is opaque or non-opaque (that is, if it's translucent or transparent), you may need to create an image with an alpha channel.
BufferedImage createResizedCopy(Image originalImage,
int scaledWidth, int scaledHeight,
boolean preserveAlpha)
{
int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
Graphics2D g = scaledBI.createGraphics();
if (preserveAlpha) {
g.setComposite(AlphaComposite.Src);
}
g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null);
g.dispose();
return scaledBI;
}
You can control the quality of the scaled copy with the Graphics2D.setRenderingHint() method.See http://java.sun.com/j2se/1.5.0/docs/api/java/awt/RenderingHints.html#KEY_INTERPOLATION Add the following before the drawImage() call:
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_[NEAREST_NEIGHBOR
BILINEAR
BICUBIC]);
Q: There are several types of images in Java2D; how do I know which one is appropriate in a particular situation?A: This article attempts to address that general question: http://java.sun.com/developer/technicalArticles/Media/imagestrategies/index.html. You might also look at other articles in this blog, particularly the ones on VolatileImage and BufferedImage objects: http://weblogs.java.net/blog/chetQ: Can I use Java2D to generate dynamic images from my servlet (or other server-side Java application)?A: Certainly! Java2D isn't just for desktop applications. You can use the Java2D API to dynamically generate images in your server application, and then use the Image I/O API to write the image to a File or to anOutputStream
(so that it can be viewed in a browser). For example, you can generate a weather map using real-time weather data, or create a pie chart using data from your accounting database. The possibilites are endless...
Here is a simple example of a servlet that generates a smiley face using Java2D, and then writes a JPEG image that can be viewed in a browser:
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ImageServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("image/jpeg");
// Create image
int width=200, height=200;
BufferedImage image =
new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// Get drawing context
Graphics2D g2d = image.createGraphics();
// Fill background with white
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, width, height);
// Draw a smiley face
g2d.setColor(Color.YELLOW);
g2d.fillOval(10, 10, 180, 180);
g2d.setColor(Color.BLACK);
g2d.fillOval(40, 40, 40, 40);
g2d.fillOval(120, 40, 40, 40);
g2d.fillRect(50, 150, 100, 10);
// Dispose context
g2d.dispose();
// Write image to the output stream
ServletOutputStream os = response.getOutputStream();
ImageIO.write(bi, "jpeg", os);
}
}
Q: I have an application that reads, writes, and processes images (but does not display them) using Java2D. When I run my application on Solaris or Linux, it complains that X11 is not available. What can I do to make my application work in this environment?A: When AWT is initialized, it expects to find an Xserver, regardless of whether it is needed for actual display. Although many image operations using the Image I/O APIs or the JAI optional package might not have any obvious need for display, they often invoke code that needs an AWT resource. For example, calling getGraphics() on aBufferedImage initializes AWT and causes these error messages seen by developers. There is no way to say that a particular API does or does not have this problem; it depends on what particular operations are being invoked, and might also depend on what the application does with the images that is not strictly related to any of the APIs cited above.
There are two possible solutions. As of J2SE 1.4 (and above), the preferred solution is to use the "headless AWT toolkit". This feature allows you to use the Java2D API in a server-side application without the need for a display environment. To specify the headless environment, run your application with the following system property:
-Djava.awt.headless=true
For releases prior to J2SE 1.4 you can provide a "pseudo X-server" to emulate a display environment. One of these Xserver emulators is Xvfb, available for download at http://www.x.org. Another possibility is to start a VNC server (http://www.realvnc.com) and then run your application in that environment.
Xvfb does still have one possible use in J2SE 1.4: A server application may need to display to an Xserver, but requires no user interaction. The headless toolkit won't support this situation, but xvfb will. This is a completely hypothetical scenario and it is not clear if any real world application exhibits such a behavior.
Font and Text questionsQ: What are the capabilities of the Java 2D text rendering system?A: These include:
Q: What are the different ways that text can be rendered using Java 2D?A:
GlyphVector and GlyphMetrics classes if you want to implement custom text layout algorithms. Since glyphs are actually shapes, you can do with glyphs anything that you can do with shapes, such as clipping and stroking.
Q. What font types does Java 2D support?A. The primary and preferred font format is the TrueType font format. Java 2D also supports Opentype layout tables within TrueType fonts for complex text rendering (Arabic, Indic etc). In addition Java 2D supports Postscript Type1 fonts.Q: Are any fonts bundled with Java 2D?A: Yes, the Java SE SDK includes three Lucida TrueType font families: Lucida Sans (Sans Serif), Lucida Typewriter (Terminal/Monospaced) and Lucida Bright (Serif). However, only one font : Lucida Sans Regular is always distributed with the JRE that is installed with Java Plugin for running applets in web browsers to limit download size as TrueType fonts can be quite large. End users can elect to install the other fonts but only Lucida Sans Regular is guaranteed to be always available in any Java application. However since Lucida Sans Regular supports many character sets, such as Basic Latin, Latin 1, Latin Ext A, Greek, Cyrillic, Hebrew, Arabic, currency symbol, super subscripts, number forms, dingbats, it means applications have a guaranteed good base line of support. The font files are located in the $JAVAHOME/jre/lib/fonts directory.Q: How can I list all available fonts?A: You may get a list of all available font family names usingjava.awt.GraphicsEnvironment.getAvailableFontFamilyNames()
or may list all the font instances using java.awt.GraphicsEnvironment.getAllFonts()
In each case the returned list will include the logical fonts such as "Dialog".
java.awt.GraphicsEnvironment.
getAvailableFontFamilyNames() is typically the most useful for presenting a menu
of fonts to a user as a particular style (eg Bold) can requested for a font by
specifying it in the style field of the Font constructor.
For sample code, see the implementation of the Font2DTest demo shipped with the JDK
(demo/jfc/Font2DTest/src)
Q: How can I make my custom font available to my Java application?A: Since Java 2D can locate fonts installed in the O/S one option is to just install the font on your system in the usual platform manner - eg dragging it into the Windows font folder. If you don't want other applications to use your font then there are two other options
createFont() offer even more flexibility in limiting
the visibility of the font. Font instances using such custom fonts cannot normally
be constructed. Instead you must use Font.deriveFont() on the instance returned
from the Font.createFont() method. Therefore only code to which you provide a
references to the Font can use it.
Note that each call to createFont from the same source (file) will create a new
distinct Font which will be GC'd only when it is no longer referenced.
So if you expect to need to use the created Font in many places simultaneously
cache a single copy to derive from rather than re-creating from the source file.
As of Java SE 6, there is a method : GraphicsEnvironment.registerFont()
which gives you the ability to make a "created" font available to Font constructors
and to be listed via Font enumeration APIs. Font.createFont()
and this method combine to provide a way to "install" a Font into the running
JRE so it is available just as O/S installed fonts are. However this Font
does not persist across JRE invocations.
Q: Why does (eg) a 10 pt font in Java applications appear to have a different size from the same font at 10pt in a native application?A: Conversion from the size in points into device pixels depends on device resolution as reported by the platform APIs. Java 2D defaults to assuming 72 dpi. Platform defaults vary. Mac OS also uses 72 dpi. Linux desktops based on GTK (Gnome) or Qt (KDE) typically default to 96 dpi and let the end-user customise what they want to use. Windows defaults to 96 dpi (VGA resolution) and also offers 120 dpi (large fonts size) and lets users further specify a custom resolution. So a couple of things can now be seen
java.awt.Toolkit.getScreenResolution() and use this to apply a simple scale to the
size you specify for fonts.
Q: How to I find if I use a font to display Cyrillic, or Hindi etc?A: UseFont.canDisplay() to find out if there is a glyph matching a given Unicode character in a given font.
Q. How can I specify the text antialiasing/font smoothing settings to be used by Swing in applications on Java SE 6?A. This is generally is a question from users of KDE (on Linux or other Unix) or Windows 2000 who would like to use LCD subpixel text. There's no programmatic way to do it in Java SE 6 (but see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6274842 to see if that has changed since this was written). However if you know what you want you can set a system property :java -Dawt.useSystemAAFontSettings=lcdwhich request to use LCD subpixel text in the most common subpixel configuration There are several useful values for this property as follows :
Q: How do I obtain font metrics?A: You may obtain aFontmetrics instance by calling java.awt.Graphics.getFontMetrics(Font)
This will decribe the font-wide metrics using the current FontRenderContext of the Graphics instance.
Font wide metrics are not specific to a particular piece of text.
It is based on data in the font specified by the font designer to reflect the overall design
of the font. Do not expect that, for example, the reported "ascent" of the font will be as high
as the highest ascent of any glyph in the font.
If you are looking for accurate bounds for string of text - please look at the next question.
FontMetrics are widely used in helping to layout GUIs.
They are also cheap to obtain.
Q. What is the difference between logical, visual and pixel bounds?Logical bounds are the most commonly used and include the ascent, descent, leading and advance of the text. They are useful to position the text correctly, particularly when appending one string after another or for multiple lines of text but they very likely will not enclose the rendered image. Particular examples of this may be glyphs which extend a pixel to the left of the "origin" at which it is drawn. "W" is a particular example - the leftmost long diagonal may extend to the left of the rendering origin. Glyphs in italic fonts are may commonly extend further to the right than the overall "advance" of the text may indicate. These two issues may lead to text being clipped on the left or the right if placed in a tight area measured using the advance of the string. Adding a couple of pixels of padding at each end is probably the simplest workaround for this. Similarly large descenders, or diacritics that are used in European languages may extend beyond the reported descent or ascent. If used to create a tight bounding box for a label for example this may clip at the bottom or top. Extra padding is again the simplest solution. To get the logical bounds of a String one may use any of following methods as appropriate :* Font.getStringBounds(...) * TextLayout.getAscent() * TextLayout.getDescent() * TextLayout.getLeading() * TextLayout.getAdvance() * GlyphVector.getLogicalBounds(...)Note that ascent, descending, and leading which sum to the height, are also available as font-wide properties. That is commonly used in layout of a UI where you would not want the UI to re-layout when the text changes. These font-wide metrics are also not guaranteed to enclose all the text. Visual bounds guarantee that the theoretical outlines of the glyphs are enclosed. But it still might not enclose the rendered image. Visual bounds are returned by * GlyphVector.getVisualBounds(...) * TextLayout.getBounds()Note that TextLayout.getBounds() in fact returns the union of the visual and
logical bounds, including any underline and strikethrough.
Pixel bounds are the most precise for where what matters is the rendered image since
pixel bounds are guaranteed to enclose all pixels and can be useful for finding the area
required to be cleared to fully erase the text. Note that they depend on many factors (position,FontRenderContext, etc.).
Since computing pixel bounds requires that Java 2D retrieve the glyph image and
examine it, it is more expensive to compute than logical bounds.
To obtain pixel bounds use:
* GlyphVector.getPixelBounds(...) * TextLayout.getPixelBounds(...) (new in Java SE 6)Note that TextLayout.getPixelBounds(...) includes the bounds of any underline etc.
Also note that no bounds need completely enclose any other – so use the one that's appropriate to your needs.
Q. What are fractional metrics? What are the consequences of setting the fractional metrics rendering hint on text performance, readability etc? When should I use it?A. In short fractional metrics doesn't affect performance. Principally it affects the spacing between glyphs (characters) which on low resolution (screen) devices can degrade the overall legibility of the text. Understanding this requires some explanation of the topic. "Fractional metrics" is sometimes called "Printer matching" on other platforms. It refers to the fact that characters in a font are optimized for particular font size and output device resolution to improve legibility of text. These optimizations involve rounding to the pixel grid and therefore may affect overall widths of individual glyphs as well as distances between them. The text display system can either choose to round these "advance widths" to an integer so that the text will have consistent spacing, or it can accumulate the positions of the characters using the unrounded, or fractional, values. If it uses the fractional values then the sequence "wi" may not have consistent spacing between the "w" and the "i" at different points along the line. That variation in spacing creates visual noise which is disruptive to the reading process and so is not preferred as the default on the screen. Note that it is only the inter-glyph spacing which changes, not the glyph images, If it uses the rounded values then the inter-character spacings are much more uniform, but each character's rounded spacing introduces some error and over a long string that error accumulates with each character displayed in succession. The result may be either a longer or a shorter overall string compared with factional metrics. That error is also dependent on the resolution at which the text is being displayed such that the relative lengths of strings will vary as you change the zoom factor or the resolution of the output device. As a result, such rounded widths are considered "not matched to the final printed output" or "not Printermatched". They also complicate layout if you want to view the same text at different sizes or magnifications - you have to customize the layout for each zoom level or expect the strings to start overrunning or underrunning their static positioning. Since non-fractional (integer) metrics are required for best screen readibility, that is why integer metrics is the default for Java 2D. The principal reason for turning on fractional metrics is then to closely approximate the layout at high-device resolution when formatting output to a printer, or for displaying a "print preview". The simplest way to look at it is that "Fractional metrics" improve WYSIWYG on the printer at the expense of legibility on low DPI screens.Printing questionsQ:What are the differences between the various printing APIs I see in the JDK?A. These are the printing APIs in the JDK: 1.1 (aka AWT) printing - java.awt.PrintJob
PrinterJob.
So the presently recommended way to print for most applications is to
use java.awt.print.PrinterJob which has methods which leverage javax.print
to enumerate printers, and can accept printing attributes from javax.print
which define job printing behaviour such as duplex printing.
Q Why is it so hard to print from Swing?A. In most cases what this turns out to mean is:
Q: What are the causes of large spool files from java.awt.print.PrinterJob and how can I avoid them?A: This was much more of a problem in earlier releases but as of J2SE 5.0 most applications should not see a problem. Some of it is platform specific and in general things are better on Windows than Solaris and Linux. Printing using non opaque colours, gradient paints, and custom paints can cause individual pages (not the whole print job) to be generated as a raster at device resolution. This can be mitigated in a few ways:
Q: When printing using java.awt.PrinterJob, why does it print each page at least twice (and sometimes much more than that)?A: The root of this is that Java 2D printing needs to be able to print everything that Java 2D can render to the screen, and that includes translucent colours, images etc which cannot always be printed directly in Postscript or GDI except when printing everything as one big image, so the implementation tries to avoid this by calling first to discover the rendering that needs to be done for the page. If its simple opaque rendering then only one more call is needed to render the page. If there are translucent colours then multiple calls are done for "bands" down the page to limit the size of the image being generated and hence constrain peak memory usage.Q How do I keep the information from getting cut off from the top and left sides of the page when I print using the Java 2D printing API?Because many printers cannot print on the entire paper surface, thePageFormat specifies the imageable area of the page:
this is the portion of the page in which it's safe to render.
The specification of the imageable area does not alter the coordinate system;
it is provided so that the contents of the page can be rendered so that they
don't extend into the area where the printer can't print.
If you find that information is clipped from your page, you might need to
translate the information to the imageable area of the page, as shown in
this sample:
public int print(Graphics g, PageFormat pf, int pageIndex)
throws PrinterException
{
Graphics2D g2 = (Graphics2D)g;
g2.translate(pf.getImageableX(),
pf.getImageableY() + 72);
...
}
Q: Why are my 1-pixel wide lines repositioned when I print them? How do I correct this?A: For horizontal or vertical 1-pixel wide line fills, it is generally better to use fillRect rather than drawLine. The rounding of the drawLine method moves lines by half a device pixel, which make the lines appear more consistent whether or not antialiasing is applied. Therefore, if you have a 1-pixel wide line, the line is moved by half of its width. Because this adjustment occurs at the device-space level, your lines can move by half of a line width on printouts from high-resolution printers.Q: How do I trouble shoot printing problems in Windows?First, make sure that you have the latest printer driver. It is advisable to use the printer vendor's version of the driver and you can generally do this by downloading it online at their website. If you have the latest driver and are still having problems, sometimes a simple change in the printer's setting or Window's advanced spool options will fix your problem. You can also go to http://java.sun.com and search the bug archive for similar problem. A workaround may be available there. If not, please file a bug.Q: How do I scale an image to fit a page?Here is a sample code that uses the page's imageable width and height to scale an image.
public int print(Graphics graphics, PageFormat pageFormat, int
pageIndex) throws PrinterException
{
if(pageIndex > 0)
return Printable.NO_SUCH_PAGE;
Graphics2D g2d = (Graphics2D) graphics;
//Set us to the upper left corner
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
AffineTransform at = new AffineTransform();
at.translate(0,0);
//We need to scale the image properly so that it fits on one page.
double xScale = pageFormat.getImageableWidth() / m_image.getWidth();
double yScale = pageFormat.getImageableHeight() / m_image.getHeight();
// Maintain the aspect ratio by taking the min of those 2 factors and
using it to scale both dimensions.
double aspectScale = Math.min(xScale, yScale);
g2d.drawRenderedImage(m_image, at);
return Printable.PAGE_EXISTS;
}
Q: When I print using PDF or HTML using the corresponding DocFlavor, how come it is printed as garbage or plain text?First, do not assume that any of the defined DocFlavors are supported. Use the PrintService's isDocFlavorSupported to find out which flavors are supported. If you find out that it is not supported but know that your printer can handle this then you may go ahead and print it using the DocFlavor.xxx.AUTOSENSE. This is equivalent to printing a raw data. If on the other hand your printer does not support it you need to write your ownPrintService which handles the conversion from PDF/HTML to the printer language e.g. PostScript.
Q: Why is Java unable to print to my CUPS 1.2 printers ?As noted in the CUPS 1.2 releases notes http://www.cups.org/documentation.php/whatsnew.html CUPS now supports Unix Domain Sockets :Networking /Domain Sockets;/ CUPS now supports the much faster UNIX domain sockets for local printingAs a consequence, by default CUPS on Unix/Linux is now configured to listen for connections on both
# Listen /var/run/cups/cups.sock
sh /etc/init.d/cups restart2. Per-user workaround #1 Add a ~/.cups/client.conf file with a "ServerName localhost" line. This will make the CUPS API library prefer localhost as the server to report 3. Per-user workaround #2 Set the CUPS_SERVER environment variable to localhost so that the CUPS API library will use and report that : CUPS_SERVER=localhost; export CUPS_SERVER This approach could if necessary be set only in the environment in which your Java printing application is run and its effects confined to that. There is one additional step to the workaround for at least some systems. JDK looks for"libcups.so". This is usually a symlink to the specific version, eg "libcups.so.2" but on systems without a developer package it may not exist. The solution is to locate the cup library on your system and if necessary create a symbolic link. For example cd /usr/lib ln -s libcups.so.2 libcups.so Rendering questionsQ: What is the Rendering Process?A Rendering is the process of taking a collection of shapes, text, and images and figuring out what colors the pixels should be on a screen or printer. In the Java 2D API, the Graphics2D class is the rendering engine: the Graphics2D object contains state attributes, such as color, and applies these attributes to the primitives when rendering them to various output devices. The seven different attributes are:
Q: What kinds of shapes can I draw using Java 2D?A: The Java 2D API provides classes for drawing basic shapes like rectangles and circles but also allows you to draw any arbitrary shape. The following table lists the classes that represent predetermined shapes.
In addition to these classes that allow you to create
common shapes, the Java 2D API provides two other classes
that allow you to define odd shapes: GeneralPath and Area.
Shapes created with GeneralPath must be created segment
by segment, but this means that you can combine straight lines
and curved lines into a single shape. The Area class
supports constructive area geometry, which allows you to combine
two shapes to create another shape, either by adding or
intersecting the shapes, subtracting one shape from another, or
by subtracting the intersection of the shapes.
To see Java 2D and CAG in action, go to
You can also create a Shape object from a String by calling getOutline on a TextLayout object. After creating the Shape, you can perform operations such as filling and transforming on the Shape. For more information on working with shapes in Java 2D, see the 2D Graphics tutorial. Q: How do I draw on an image?A: If your image is an external image in a format such as JPG then first you load it into a BufferedImage using the javax.imageio.ImageIO class Then you can obtain a Graphics2D for rendering to the in-memory copy of the image. Here's a sample that does this:
BufferedImage bi = null;
try {
bi = ImageIO.read(new File("images/bld.jpg"));
} catch (IOException ioe) {
}
Graphics2D g2d = bi.createGraphics();
g2d.drawLine(10, 10, 20, 20); // draw a line on the image
...
g2d.dispose();
Q: I have a shape whose outline intersects itself. How do I control the filling of the shape?A: You can control the filling of an arbitrary shape by setting the winding rule. The winding rule specifies which part of a shape is considered the inside of the shape. If you have an arbitrary shape with an outline that intersects itself, you might get different filling results depending on which winding rule you choose. Because the GeneralPath class is used to represent such arbitrary shapes, any Shape objects that are instances of GeneralPath can use the setWindingRule(int) method to set the winding rule to either WIND_NON_ZERO or WIND_EVEN_ODD. See the GeneralPath class comments for a description of each winding rule. Note that any given Shape can only have a single winding rule that applies for its entire outline. If you have a complex combination of shapes that overlap and intersect with each other in many places, it may be easier to use the Area class to combine the shapes with explicit intersection, union, subtraction and exclusive or operations rather than to try to control the action of the multiple overlapping sections with a single winding rule.Q: What does it mean to flatten a Shape?A: Flattening is the process of converting the curved lines of a Shape into straight line segments. During rasterization, flattening is often performed on all curved path segments before they are stroked or filled because rendering calculations are much faster for straight lines than for curves. Shape objects provide a getPathIterator(aT, flatness) method which returns a PathIterator object that iterates through the path with only straight line segments that approximate the original path of the Shape. The flatness parameter must be a double value greater than or equal to 0.0 which controls how closely the straight lines approximate the curve. The smaller the number, the closer the straight lines will approximate the curve. The original Shape object is not modified by this method as the flattening is done on the fly as the path is iterated.Q: How do I draw a quadratic arrow-headed curves?A: There is no direct API for doing this. However, the following sample code can be used to achieve this effect.
...
GeneralPath path = new GeneralPath();
float p1x = 10, p1y = 10; // P1
float p2x = 100, p2y = 10; // P2
float cx = 55, cy = 50; // Control point of the curve
float arrSize = 5; // Size of the arrow segments
float adjSize = (float)(arrSize/Math.sqrt(2));
float ex = p2x - cx;
float ey = p2y - cy;
float abs_e = (float)Math.sqrt(ex*ex + ey*ey);
ex /= abs_e;
ey /= abs_e;
// Creating quad arrow
path.moveTo(p1x, p1y);
path.quadTo(cx, cy, p2x, p2y);
path.lineTo(p2x + (ey-ex)*adjSize, p2y - (ex + ey)*adjSize);
path.moveTo(p2x, p2y);
path.lineTo(p2x - (ey + ex)*adjSize, p2y + (ex - ey)*adjSize);
...
Q: Why do I get unexpected results when I use the setTransform method of Graphics2D to perform transformations?A: Because the setTransform method is not intended for adding new coordinate transformations onto an existing transform. In fact, when you use setTransform, you are overwriting the Graphics2D object's current transform, which might be needed for other purposes, such as applying a scaling transformation to adjust for printer resolution. The setTransform method should ONLY be used to restore the Graphics2D transform to an earlier saved state after performing some temporarily transformed rendering.To perform transformations, use these steps:
|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Oracle is reviewing the Sun product roadmap and will provide guidance to customers in accordance with Oracle's standard product communication policies. Any resulting features and timing of release of such features as determined by Oracle's review of roadmaps, are at the sole discretion of Oracle. All product roadmap information, whether communicated by Sun Microsystems or by Oracle, does not represent a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. It is intended for information purposes only, and may not be incorporated into any contract.
|
| ||||||||||||