Using Filters to Dynamically Output Graphics

Reviews
Shared by: Jharan Parmar
Stats
views:
83
rating:
not rated
reviews:
0
posted:
5/24/2008
language:
English
pages:
0
Using Filters to Dynamically Output Graphics by Kevin Hoyt Senior Engineer Sales May 2002 Copyright © 2002 Macromedia, Inc. All rights reserved. The information contained in this document represents the current view of Macromedia on the issue discussed as of the date of publication. Because Macromedia must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Macromedia, and Macromedia cannot guarantee the accuracy of any information presented after the date of publication. This white paper is for information purposes only. MACROMEDIA MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS DOCUMENT. Macromedia may have patents, patent applications, trademark, copyright or other intellectual property rights covering the subject matter of this document. Except as expressly provided in any written license agreement from Macromedia, the furnishing of this document does not give you any license to these patents, trademarks, copyrights or other intellectual property. {INSERT OUR MARKS IN THE DOCUMENT} are either trademarks or registered trademarks of Macromedia, Inc. in the United States and/or other countries. The names of actual companies and products mentioned herein may be the trademarks of their respective owners. Macromedia, Inc. 600 Townsend Street San Francisco, CA 94103 415–252–2000 Using Filters to Dynamically Output Graphics Contents Using servlet filters ............................................................................................................ 1 Dynamically create a graphic ....................................................................................................................... 2 Implementing a servlet filter......................................................................................................................... 4 Deploying the servlet filter ........................................................................................................................... 6 Conclusion ........................................................................................................................ 8 May 2002 Page iii Using Filters to Dynamically Output Graphics Servlet filters are an exciting addition to Java 2 Platform, Enterprise Edition (J2EE) 1.3. The capability to intercept and modify HTTP calls before they access any web container resource, or after a resource has been processed, lends itself to many practical applications. The Java Servlet Specification 2.3 provides a few examples for developers that deal with authentication, logging, and XML transformations. Using the inherent graphics capability of Java, you can physically alter existing images before they display in a web page. This white paper describes how you can use servlet filters to dynamically output graphics. Download the Windows source file Download the Macintosh source file When the file decompresses, a folder named XXX is created on your system. If you have trouble downloading or decompressing the files, see TechNote 13686. Using servlet filters Servlet filters provide the capability to intercept and modify HTTP calls before they access any web container resource, or after a resource has been processed. There are many practical applications for using servlet filters, and the Java Servlet Specification 2.3 contains a few examples for developers to consider, such as authentication, logging, and XML transformations. One of the more interesting possibilities lies in exposing Java’s robust two-dimensional and threedimensional manipulation capabilities. Using the graphics capability in Java, you can physically alter existing images before they display in a web page. A stock photography site is one example of a practical application. The site won’t expose its photographers images as-is–they are valuable assets. More commonly, stock photography sites present the requested image with some blemish. This could be as simple as displaying a version of the image that has been substantially reduced in size, or as complex as presenting a watermark over the image itself. A typical solution might be to have multiple sets of the image that represent different views; however, that can easily become a resource nightmare. Disk space is inexpensive, but if you have several hundred thousand high-resolution images with several counterparts, you quickly consume even the heftiest of disks. Another solution might be to have a servlet modify the image as it goes out; while this is a good approach, modifying the image is not part of your application logic. If you modify the images in an overnight batch process, it still eats up the disk space. A servlet filter can solve this type of processing. A filter can alter images before they are requested and clean up afterward, and a filter does not interfere with your application logic. Filters do not have to be tied to a servlet, JavaServer Page (JSP), or other dynamic resource, and you can use them on static HTML files or images. Having the container watch for requests on image files, then run the filter when those file types are requested, is an exceptionally elegant process. It is also easy to change the style of modification based on parameters or requirements without changing the application logic. May 2002 Page 1 Using Filters to Dynamically Output Graphics Using servlet filters To do this, you must read an image from disk, modify the in-memory representation of that image, and then write the new file back to the disk. After the image-processing component is complete, you build the filter that leverages it. You also need this filter to manage resource usage. Finally, you must deploy the filter by modifying the web container’s property file. This last step is probably the easiest, but it accomplishes a significant amount of work, such as letting the container know that the filter is present and where it resides, mapping the invocation of the filter to request patterns, and offering configuration parameters for the filter itself. Dynamically create a graphic When dynamically creating an image file, the first problem you must consider is loading the image from disk. Servlet filters are part of the Servlet API, and essentially function as servlets. If you try to load an image from disk using common methods, the image might not load completely before the filter continues processing. This could result in renderings that are incomplete or, worse, throw an error. To get around this, you can use the java.awt.MediaTracker class. You might remember the MediaTracker class from when you began learning Java, because it is often included in the introductory applet examples. The MediaTracker class lets you add java.awt.Image objects to it, and then stops processing until they are all loaded; but there is a catch. In order to work properly, the MediaTracker constructor expects a java.awt.Component object. You can use this to your advantage by encapsulating the image modification routines in a Component subclass for reuse by other applications. Image MediaTracker stock = Toolkit.getDefaultToolkit().getImage( file ); tracker = new MediaTracker( this ); // Load stock image and marker image tracker.addImage( stock, 0 ); tracker.addImage( stamp, 0 ); // Wait for all the images to load try { tracker.waitForAll(); } catch( InterruptedException ie ) { System.out.println( "Interrupted: " + ie.getMessage() ); } Although the Component class has its own java.awt.Graphics object, you use an instance of the java.awt.image.BufferedImage class to do the drawing. The reasoning for this is the solution to the next problem that you encounter when trying to dynamically create an image–how do I create a JPEG file? Java multimedia API’s grow on a regular basis, however, there is an old standby that you can leverage when you create JPEG images. The com.sun.image.codec.jpeg.JPEGCodec class is included in Sun JDK and JRE distributions for Java 2, and makes quick work of what otherwise be a daunting task. Page 2 May 2002 Using Filters to Dynamically Output Graphics The JPEGCodec class is a factory for obtaining encoder and decoder objects. We can get a JPEGEncoder object by calling the static JPEGCodec.createJPEGEncoder() method. This method takes two parameters; the first being the output stream to write the encoded bits to, and the second is the bits to encode in the form of a JPEGEncodeParam object. We can get a JPEGEncodeParam object by leveraging the JPEGCodec.getDefaultJPEGEncodeParam() static method, which expects a BufferedImage object. Of course the catch is that if we used the Component objects Graphics object, we wouldn’t have access to a BufferedImage representation of its contents. Although this might seem like a complex approach to generating a JPEG image file, the code is quite elegant. BufferedImage Graphics2D JPEGImageEncoder buffer = new BufferedImage( 375, 250, BufferedImage.TYPE_INT_RGB ); g = buffer.createGraphics(); encoder = null; // Draw image in memory g.drawImage( stock, 0, 0, 375, 250, this ); g.drawImage( stamp, 3, 3, this ); // Create JPEG image in specified output path try { encoder = JPEGCodec.createJPEGEncoder( new FileOutputStream( outPath + file ), JPEGCodec.getDefaultJPEGEncodeParam( buffer ) ); encoder.encode( buffer ); } catch( FileNotFoundException fnfe ) { System.out.println( "File output: " + fnfe.getMessage() ); } catch( IOException ioe ) { System.out.println( "Disk access: " + ioe.getMessage() ); } A Graphics object results from the BufferedImage.getGraphics() method, and this makes drawing the new image easy when you use Graphics.drawXXX() methods. So you have a way to track image loading, a way to draw the new image, and a way to create that image on disk in JPEG format. The last thing that you do is to parameterize the code so that it can generate the desired results more efficiently by using classes. Parameterization can be taken in a many directions, and to many extremes, this example uses only a few pieces of data. You must know where the original image is located on disk, where to create this new thumbnail image, the name of the file to read and create, and which image is used as a watermark. In your implementation, you can leverage access methods for details like image size, where the watermark goes, or image color depth. import import import import java.io.*; java.awt.*; java.awt.image.*; com.sun.image.codec.jpeg.*; public class StockComponent extends Component { public StockComponent() {;} public void build( String inPath, String outPath, String file, String marker ) { BufferedImage buffer = null; Graphics2D g = null; Image stock = null; Image stamp = null; JPEGImageEncoder encoder = null; MediaTracker tracker = new MediaTracker( this ); May 2002 Page 3 Using Filters to Dynamically Output Graphics Using servlet filters // Initialize objects buffer = new BufferedImage( 375, 250, BufferedImage.TYPE_INT_RGB ); g = buffer.createGraphics(); stock = Toolkit.getDefaultToolkit().getImage( inPath + file ); stamp = Toolkit.getDefaultToolkit().getImage( marker ); // Load stock image and marker image tracker.addImage( stock, 0 ); tracker.addImage( stamp, 0 ); // Wait for all the images to load try { tracker.waitForAll(); } catch( InterruptedException ie ) { System.out.println( "Tracking problem: " + ie.getMessage() ); } // Assemble modified stock photo image g.drawImage( stock, 0, 0, 375, 250, this ); g.drawImage( stamp, 3, 3, this ); // Try and encode and create the image on disk try { encoder = JPEGCodec.createJPEGEncoder( new FileOutputStream( outPath + file ), JPEGCodec.getDefaultJPEGEncodeParam( buffer ) ); encoder.encode( buffer ); } catch( FileNotFoundException fnfe ) { System.out.println( "File output: " + fnfe.getMessage() ); } catch( IOException ioe ) { System.out.println( "Disk access: " + ioe.getMessage() ); } } } Implementing a servlet filter You can now build a filter class that leverages all the image creation routines; with the exception of a few details, creating a servlet filter is similar to creating a servlet. The javax.servlet.Filter class is an interface and has a series of methods that you can implement when you use it. In this example, you use the Filter.doFilter() method, which is invoked by the web container before reaching mapped resources and again after processing those resources. When processing images, you can use a large number of resources for every request. You must be especially careful of how you use system resources in high-load applications. For this reason, you want the filter to be somewhat intelligent about the way it behaves. One way to reduce system load would be to generate only the necessary images. This means that if a thumbnail has been generated already by another process, then you probably don’t need to generate it again. Likewise, while you can use the web containers property file to isolate which resources require invocation of the filter, it is beneficial to place some restrictions in the filter logic itself. For example, if you set the filter to be run on all JPEG files (by extension), you must generate only image thumbnails of JPEG files that are in the stock photography directory. You can perform both objectives with the following simple file-system check: Page 4 May 2002 Using Filters to Dynamically Output Graphics protected boolean check( String path ) { File checker = new File( path ); return checker.exists(); } If the thumbnail image does not exist, and the requested file is in the stock photography directory, then you can leverage the prebuilt component. You might also consider parameterization as well. We can use the javax.servlet.FilterConfig object to get initialization parameters from the web containers property file. In most cases, the FilterConfig object is stored as a private property of the filter class during the Filter.init() method. You probably don’t want your stock photography directory to be accessible by the web container, so you can put it somewhere else on the server and tell the filter where to look. Ideally, put the stock photography images on a file server with a mapped drive. You could store file names and paths in a database, which provides a myriad of possibilities. For the purposes of this example, however, database processing code bloats the example; directory searching can be done in a relatively few lines of code and is substantially faster. The other bits of information this filter requires are where to place the final thumbnail image and where to find the watermark image. You could also provide initialization parameters for thumbnail size, color depth, and so on. Keep in mind that a filter is called before and after the mapped resource is processed. The last thing you want to do with the filter to conserve system resources is to make the filter clean up after itself when it is destroyed. An easy way to do this is to place a file deletion routine in the destroy method. The destroy method is called whenever the filter object is no longer needed, or is otherwise removed from the container (container shutdown). import java.io.*; import javax.servlet.*; import javax.servlet.http.*; // Implement Filter interface public class StockFilter implements Filter { // FilterConfig object for class reference private FilterConfig config = null; // No constructor operations public StockFilter() {;} // Override initialization method in Filter interface public void init( FilterConfig config ) { this.config = config; } // Override the operational method of the Filter interface public void doFilter( ServletRequest req, ServletResponse res, FilterChain chain ) throws IOException, ServletException { HttpServletRequest hreq = ( HttpServletRequest )req; int parse = 0; StockComponent stock = new StockComponent(); String uri = hreq.getRequestURI(); String file = null; // Extract the image name parse = uri.lastIndexOf( "/" ) + 1; file = uri.substring( parse, uri.length() ); May 2002 Page 5 Using Filters to Dynamically Output Graphics Using servlet filters // Don't duplicate work if thumbnail version already exists if( !check( config.getInitParameter( "IMAGE_PATH" ) + file ) ) { // First verify this is a stock image photo if( check( config.getInitParameter( "STOCK_PATH" ) + file ) ) { // Build the image stock.build( config.getInitParameter( "STOCK_PATH" ), config.getInitParameter( "IMAGE_PATH" ), file, config.getInitParameter( "MARKER" ) ); } } // Keep the filter moving chain.doFilter( req, res ); } // Check for existance of stock image protected boolean check( String path ) { File checker = new File( path ); } return checker.exists(); // Clean up on demand protected void clean() { // Retrieve directory path and get full list of files File images = new File( config.getInitParameter( "IMAGE_PATH" ) ); File[] list = images.listFiles(); // Remove the files from images directory that exist in both directories for( int f = 0; f < list.length; f++ ) { if( check( config.getInitParameter( "STOCK_PATH" ) + list[f].getName() ) ) { list[f].delete(); } } } // Remove all image thumbnails on undeploy or container shutdown public void destroy() { clean(); } } Deploying the servlet filter The next step takes you out of the Java world and on to using XML. The filter classes must go into the {application-root}/WEB-INF/classes directory. Then you include the information about the filter in the container by modifying the web.xml file, located in the {application-root}/WEB-INF directory. The first step is to define the filter, its name, and the class to which it relates. Then you specify a series of initialization parameters so that the class knows where to look for images, where to put newly created images, and where to find a watermark image. You can define additional parameters as necessary or use and another means of specifying this data. Stock Page 6 May 2002 Using Filters to Dynamically Output Graphics Stock StockFilter STOCK_PATH ___some path___ IMAGE_PATH ___some path___ MARKER ___file path___ You must also map the filter to requests for various types of resources. This requires care because mapping that is too general can cause an overload in system resources. For example, if you use “/*” for any resource in the web application, that indicates every HTML, JSP, servlet, image, external CSS or JavaScript, or XML file that you might be using. This does not mean one run of the filter for the request of an HTML page; rather, if that HTML page contains multiple images, or other external resources, the filter is invoked twice for each resource request. For this reason, you map to requests for the image directory; for more control, you could invoke the filter only for requests of JPEG images. Stock /images/* There are some other considerations in the design of this filter. Initially, the image output directory is empty and available to the web container. The stock photography directory, in this example, has one stock photo image; in any production environment, of course, it has more. You make a request for a simple HTML page–not HTML displayed by a JSP or a servlet. That HTML page contains an IMG tag that specifies a static SRC attribute of “images/sf-tamframe.jpg”. This points directly to the image output directory. With this in mind, you might wonder how the image gets from the stock photography directory to the image output directory when you have no dynamic files and aren’t making a request of the image output directory. Remember that requests for images inside HTML pages are actually separate HTTP requests. Also remember that even though you are requesting a static HTML page, filters are invoked by the web container independent of dynamic application-logic components, such as JSP or servlets. The answer lies in the mapping that you set up in the previous step. Thus, this task can greatly impact how your application performs. Servlet Filter Example (stock photo) May 2002 Page 7 Using Filters to Dynamically Output Graphics Conclusion Conclusion This article reviews how to create dynamic images by using the various provided Java classes. Then it describes how to create a filter that leveraged the image creation component. You also made the filter somewhat intelligent so that you didn’t overextend your system resources. You pulled it all together by placing the class files, telling the web container about the filter, and creating a simple HTML page that caused the filter invocation. Stock photography is one example, however, other parallels can be drawn. For example, it might be that topography software can be leveraged in a similar way. You might use this method with generated imagery, for example MapQuest, in preparing what might otherwise be unusable image formats for display. Sometimes, servlet filters can be misunderstood as after-the-fact servlet inheritance, or underpowered server-side includes. Indeed, servlet filters have a unique niche and can be used for a variety of very powerful applications that use dynamic and static content. It is important to remember to use the right technology for the right purpose. For example, did you know that the same objective could probably be accomplished more easily using Macromedia Flash? For more information on Macromedia Flash and Java connectivity, see the JRun 4 documentation about Macromedia Flash Remoting. You can use servlet filters in various ways. They are a key part of J2EE 1.3 and should be considered for your current application or the next. Page 8 May 2002

Related docs
The Essentials of Filters
Views: 46  |  Downloads: 3
SPSS Output and Graphics for Publication
Views: 305  |  Downloads: 8
Tunable Optical Filters
Views: 63  |  Downloads: 4
GRAPHICS TECHNOLOGY
Views: 8  |  Downloads: 1
Reconstruction Filters in Computer Graphics
Views: 2  |  Downloads: 0
05- Filters
Views: 0  |  Downloads: 0
Wave_ Filters
Views: 2  |  Downloads: 0
Java Input Output
Views: 184  |  Downloads: 2
Dynamically Routing with BGP4
Views: 148  |  Downloads: 5
Speaking Dynamically Pro Windows Outline
Views: 5  |  Downloads: 0
premium docs
Other docs by Jharan Parmar
Voice Readiness
Views: 158  |  Downloads: 12
Programming loosely coupled data oriented system
Views: 150  |  Downloads: 3
Oracle’s Commitment to the eclipse community
Views: 208  |  Downloads: 4
Oracle Support for the Spring Framework
Views: 431  |  Downloads: 15
Secure an SOA
Views: 424  |  Downloads: 22
The right infrastructure of SOA
Views: 257  |  Downloads: 33
Service Oriented Architecture
Views: 324  |  Downloads: 57
KDDI and WiMAX
Views: 365  |  Downloads: 27
Wireless Lan Security
Views: 290  |  Downloads: 31
Wireless LAN Networking
Views: 361  |  Downloads: 87
Virtual organisation
Views: 155  |  Downloads: 9
Using a JSTL in JRun 4
Views: 308  |  Downloads: 0
USB
Views: 89  |  Downloads: 0
The Payoff Killer Applications
Views: 92  |  Downloads: 0
Technical Distinctions of ODF and OOXML
Views: 200  |  Downloads: 0