Although servlets often generate HTML output, they certainly don't always do so. For example, Section 7.3 (Building Excel Spreadsheets) shows a servlet that builds Excel spreadsheets and returns them to the client. Here, we show you how to generate JPEG images. First, let us summarize the two main steps servlets have to perform to build multimedia content.
Putting these two steps together, servlets that generate non-HTML content usually have a section of their doGet or doPost method that looks like this: response.setContentType(" type / subtype "); OutputStream out = response.getOutputStream(); Those are the two general steps required to build non-HTML content. Next, let's look at the specific steps required to generate JPEG images.
Listing 7.7 shows a servlet that reads message , fontName , and fontSize parameters and passes them to the MessageImage utility (Listing 7.8) to create a JPEG image showing the message in the designated face and size, with a gray, oblique - shadowed version of the message shown behind the main string. If the user presses the Show Font List button, then instead of building an image, the servlet displays a list of font names available on the server. Listing 7.7 ShadowedText.javapackage coreservlets; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import java.awt.*; /** Servlet that generates JPEG images representing * a designated message with an oblique-shadowed * version behind it. */ public class ShadowedText extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String wantsList = request.getParameter("showList"); if (wantsList != null) { showFontList(response); } else { String message = request.getParameter("message"); if ((message == null) (message.length() == 0)) { message = "Missing 'message' parameter"; } String fontName = request.getParameter("fontName"); if ((fontName == null) (fontName.length() == 0)) { fontName = "Serif"; } String fontSizeString = request.getParameter("fontSize"); int fontSize; try { fontSize = Integer.parseInt(fontSizeString); } catch(NumberFormatException nfe) { fontSize = 90; } response.setContentType("image/jpeg"); MessageImage.writeJPEG (MessageImage.makeMessageImage(message, fontName, fontSize), response.getOutputStream()); } } private void showFontList(HttpServletResponse response) throws IOException { PrintWriter out = response.getWriter(); String docType = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 " + "Transitional//EN\">\n"; String title = "Fonts Available on Server"; out.println(docType + "<HTML>\n" + "<HEAD><TITLE>" + title + "</TITLE></HEAD>\n" + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1 ALIGN=CENTER>" + title + "</H1>\n" + "<UL>"); String[] fontNames = MessageImage.getFontNames(); for(int i=0; i<fontNames.length; i++) { out.println(" <LI>" + fontNames[i]); } out.println("</UL>\n" + "</BODY></HTML>"); } } Listing 7.8 MessageImage.javapackage coreservlets; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import java.io.*; import javax.imageio.*; /** Utilities for building images showing shadowed messages. * <P> * Requires JDK 1.4 since it uses the ImageIO class. * JDK 1.4 is standard with J2EE-compliant app servers * with servlets 2.4 and JSP 2.0. However, standalone * servlet/JSP engines require only JDK 1.3 or later, and * version 2.3 of the servlet spec requires only JDK * 1.2 or later. So, although most servers run on JDK 1.4, * this code is not necessarily portable across all servers. */ public class MessageImage { /** Creates an Image of a string with an oblique * shadow behind it. Used by the ShadowedText servlet. */ public static BufferedImage makeMessageImage(String message, String fontName, int fontSize) { Font font = new Font(fontName, Font.PLAIN, fontSize); FontMetrics metrics = getFontMetrics(font); int messageWidth = metrics.stringWidth(message); int baselineX = messageWidth/10; int width = messageWidth+2*(baselineX + fontSize); int height = fontSize*7/2; int baselineY = height*8/10; BufferedImage messageImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g2d = (Graphics2D)messageImage.getGraphics(); g2d.setBackground(Color.white); g2d.clearRect(0, 0, width, height); g2d.setFont(font); g2d.translate(baselineX, baselineY); g2d.setPaint(Color.lightGray); AffineTransform origTransform = g2d.getTransform(); g2d.shear(-0.95, 0); g2d.scale(1, 3); g2d.drawString(message, 0, 0); g2d.setTransform(origTransform); g2d.setPaint(Color.black); g2d.drawString(message, 0, 0); return(messageImage); } public static void writeJPEG(BufferedImage image, OutputStream out) { try { ImageIO.write(image, "jpg", out); } catch(IOException ioe) { System.err.println("Error outputting JPEG: " + ioe); } } public static void writeJPEG(BufferedImage image, File file) { try { ImageIO.write(image, "jpg", file); } catch(IOException ioe) { System.err.println("Error writing JPEG file: " + ioe); } } public static String[] getFontNames() { GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); return(env.getAvailableFontFamilyNames()); } /** We need a Graphics object to get a FontMetrics object * (an object that says how big strings are in given fonts). * But, you need an image from which to derive the Graphics * object. Since the size of the "real" image will depend on * how big the string is, we create a very small temporary * image first, get the FontMetrics, figure out how * big the real image should be, then use a real image * of that size. */ private static FontMetrics getFontMetrics(Font font) { BufferedImage tempImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); Graphics2D g2d = (Graphics2D)tempImage.getGraphics(); return(g2d.getFontMetrics(font)); } } Listing 7.9 (Figure 7-6) shows an HTML form used as a front end to the servlet. Figures 7-7 through 7-10 show some possible results. Just to simplify experimentation, Listing 7.10 presents an interactive application that lets you specify the message and font name on the command line, outputting the image to a file. Listing 7.9 ShadowedText.html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD><TITLE>JPEG Generation Service</TITLE></HEAD> <BODY BGCOLOR="#FDF5E6"> <H1 ALIGN="CENTER">JPEG Generation Service</H1> Welcome to the <I>free</I> trial edition of our JPEG generation service. Enter a message, a font name, and a font size below, then submit the form. You will be returned a JPEG image showing the message in the designated font, with an oblique "shadow" of the message behind it. Once you get an image you are satisfied with, right-click on it (or click while holding down the SHIFT key) to save it to your local disk. <P> The server is currently on Windows, so the font name must be either a standard Java font name (e.g., Serif, SansSerif, or Monospaced) or a Windows font name (e.g., Arial Black). Unrecognized font names will revert to Serif. Press the "Show Font List" button for a complete list. <FORM ACTION="/servlet/coreservlets.ShadowedText" > <CENTER> Message: <INPUT TYPE="TEXT" NAME="message"><BR> Font name: <INPUT TYPE="TEXT" NAME="fontName" VALUE="Serif"><BR> Font size: <INPUT TYPE="TEXT" NAME="fontSize" VALUE="90"><P> <INPUT TYPE="SUBMIT" VALUE="Build Image"><P> <INPUT TYPE="SUBMIT" NAME="showList" VALUE="Show Font List"> </CENTER> </FORM> </BODY></HTML> Listing 7.10 ImageTest.javapackage coreservlets; import java.io.*; public class ImageTest { public static void main(String[] args) { String message = "Testing"; String font = "Arial"; if (args.length > 0) { message = args[0]; } if (args.length > 1) { font = args[1]; } MessageImage.writeJPEG (MessageImage.makeMessageImage(message, font, 40), new File("ImageTest.jpg")); } } Figure 7-6. Front end to the image-generation servlet.
Figure 7-7. Result of servlet when the client selects Show Font List.
Figure 7-10. A third possible result of the image-generation servlet.
Figure 7-8. One possible result of the image-generation servlet. The client can save the image to disk as somename .jpg and use it in Web pages or other applications.
Figure 7-9. A second possible result of the image-generation servlet.
|