= Image Tweak Xephyrus Tag Libraries
Version 0.3 Reference Documentation
Introduction

The Image Tweak Tag Library provides an easy way to do some simple image manipulations on image files from within JSP pages.

Usage Notes

The tags in this tag library are modeled similarly to those of the Xephyrus Data Structures tag library. There are container tags and worker tags.

Well, really, there's only one container tag: 'image'. All worker tags must be wrapped in an 'image' container tag. As many workers as needed can be applied to a single image by including the tags within the same container. They will be applied in order.

The 'image' tag can read a source image from a file or a URL, and will write the resulting image either to a static file or to a dynamically generated "on-the-fly" file. If an on-the-fly file is written, the full URL of that file will be output by the image tag. On-the-fly files will be cleaned up at some reasonably later time.

Of the worker tags, there are three kinds: tags that report things (called "Info" tags), tags that draw (called "Composite" tags) and tags that just mess with what's there (called "Twiddle" tags). In version 0.3: There are two Info tags, 'width' and 'height'. There are two Composite tags, 'mask' and 'drawText'. There are two Twiddle tags, 'scale' and 'crop'.

For example, to create an on-the-fly, scaled-down image and present it:

<itk:image inUrl="someimage.jpg" var="thumbname">
  <itk:scale width="100" />
</itk:image>
<img src="<c:out value='${pageScope.thumbname}' />" />

If you try to run this tag library on a headless server -- that is, a server that does not have a GUI installed, like Apache on Linux with no X Windows -- you will likely get an error that says something like: "Can't connect to X11 window server using ':0.0' as the value of the DISPLAY variable." This is a known issue with older versions of Java. See Bug Parade #4281163 (requires free registration) for details on the issue.

To fix this problem:

  • If you are running Java 1.4 or later:
    Add the system property "java.awt.headless" to your environment with a value of "true." Do this by specifying "-Djava.awt.headless=true" on the command line that starts the JVM.
  • If you are running an earlier version of Java:
    You can do one of the following.
    • Use the PJA Toolkit to provide an alternate image drawing system. Details and installation notes can be found here.
    • Use the X Virtual Frame Buffer (or Xvfb). This is an X server emulator that can run on headless machines. It is part of the XFree86 X Windowing System. More information can be found here.

Deployment

To deploy this tag library for use with your web application, follow these steps:

  • Copy the tag library descriptor file (imagetweak.tld) to the /WEB-INF/tld subdirectory of your web application.
  • Copy the tag library JAR file (xephyrus-imagetweak.jar) to the /WEB-INF/lib subdirectory of your web application.
  • Add a <taglib> element to your web application deployment descriptor in /WEB-INF/web.xml that looks like this:
    <taglib>
      <taglib-uri>/xephyrus-imagetweak</taglib-uri>
      <taglib-location>/WEB-INF/tld/xephyrus-imagetweak.tld</taglib-location>
    </taglib>

To use the tags from this library in your JSP pages, add the following directive at the top of each page:

<%@ taglib uri="/xephyrus-imagetweak" prefix="itk" %>

where "itk" is the tag name prefix you wish to use for tags from this library. You can change this value to any prefix you like.

Example

A simple example of a JSP using the Xephyrus Image Tweak Tag Library is available in full syntax-color highlighting.
  View It   Run It

Tag Summary
image Loads and saves an image, and provides a frame for all the image manipulations to work within.
scale Scales the image.
crop Crops the image.
mask Masks the image with another image using the specified compositing (blending) rule.
drawText Writes text onto the image using the specified font and compositing rule.
width Retrieves the width of the image.
height Retrieves the height of the image.
Tag Reference
image

The 'image' tag is the only container tag in this library. All other tags must be framed by an 'image' tag.

The image tag can load images to work with from a file on the local file system, or a relative or absolute URL. Yes, you can even load an image from some FTP server somewhere if you really want to.

Similarly, it can write the resulting image to either an absolute file location, or to a temporary "on-the-fly" file location within the current serving context. When "on-the-fly" files are used, the tag will output the actual name of the file written, adding in a url base if one has been specified. The output can be redirected to a scoped variable if needed.

On-the-fly images written to the file system are deleted at some reasonably later time. The files for any given object will be deleted either when the object is garbage collected, or when the tag is serviced and the images have been lingering for longer than the tags current definition of a "reasonably later time."

To impose your own "reasonably later time" definition, set the system property "imagetweak.onthefly.ttl" to the number of minutes you want the files to linger for. They will linger for at least that long. They will not be removed until either that tag object is used again or that tag object is garbage collected.

The tag can write the image in any format that Java's image extensions understands. Currently that list includes: JPEGs, PNGs, and GIFs.

Attribute Class Required? EL? Default
Description
inFile
java.lang.File or
java.lang.String
if no 'inUrl' yes
Provides the image to transmogrify in the form of either a File object or a full path name. The magical prefix '~' (tilde) is supported to refer to the currently served path.
inUrl
java.lang.String if no 'inFile' yes
Provides the image to transmogrify in the form of either an absolute or relative URL. If an absolute URL is provided, it can be of any protocol supported by the JVM. However, caution should be used when accessing other servers, as failure to load the URL will cause a JspTagException to be thrown.
outFile
java.lang.String no yes
The full pathname of which to write the resulting image. If this is specified, the written file is considered "permanent" which is to say, "Not on-the-fly." If not, it is "on-the-fly." The magical prefix '~' (tilde) is supported to refer to the currently served path.
urlBase
java.lang.String no yes the base being served
The URL path for the resulting on-the-fly image. This must be within the scope of the current serving context. In other words, it should be relative to the current page being served. It should not include a file name; that will be determined dynamically. This is ignored if the 'outFile' attribute is specified.
format
java.lang.String no yes JPEG
The format in which to write the resulting image file. Currently supported formats are: JPEG, PNG, GIF.
var
java.lang.String no yes
If the resulting image is written to an on-the-fly file, this captures the URL of that file and sets it as a variable with the name specified. If this attribute is not specified and an on-the-fly file is written, the URL of that file will be output to the current pageContext output (most likely the resulting page).
scope
java.lang.String no yes page
Indicates the scope for the variable specified by the 'var' attribute. Acceptable scopes are: page, request, session, application.

 
scale

Scales the image to the specified size. This tag has two modes of operation: stretch, or preserve aspect-ratio. If both a width and height are specified, the current aspect-ratio of the image is ignored and the image is forced to conform to the aspect-ratio between the width and height specified.

If only one or the other of the width and height are specified, the aspect-ratio will be maintained and the missing side will be calculated.

If neither the width nor the height is specified, the image will be scaled to 0 by 0.

The 'scale' tag must be nested in an 'image' tag.

Attribute Class Required? EL? Default
Description
width
java.lang.Integer no yes
Indicates the width to which the current image will be scaled.
height
java.lang.Integer no yes
Indicates the height to which the current image will be scaled.
fit
java.lang.String no yes 'exact'
Indicates how stringently the specified width and height attributes should be enforced on images with different aspect ratios. The possibilities are:
  • exact   The given width and height are used exactly as specified.
  • short   The shorter edge of the source image will be scaled and the longer edge will be calculated based on the images aspect ratio. For example, if an image is 10 width by 20 height and a scale with 50 width by 50 height and fit 'short' is given, the resulting image will be 50 width by 100 height.
  • long   The longer edge of the source image will be scaled and the shorter edge will be calculated based on the images aspect ratio. For example, if an image is 10 width by 20 height and a scale with 50 width by 50 height and fit 'long' is given, the resulting image will be 25 width by 50 height.

 
crop

Crops the image according to the directions given. This tag has two modes of operation: square, or exact. If the 'square' attribute is set, all coordinate attributes are ignored and the image is squared. That is, the longest side is truncated to match the length of the shortest side.

Otherwise, all the coordinate attributes ('x', 'y', 'width', 'height') indicate the exact specifications for the cropping procedure to use. For any coordinate attribute that is not specified the edge of the image will be used. (So, if 'x' is not specified, "0" will be used; if 'width' is not specified, the right edge of the image will be used; etc.)

If the target area for the cropping is larger than the current image, the image space will be expanded to comply but the image will not be altered. It will be snugged into the top left corner unless the 'center' attribute is used. The background color of the expanded area will be black unless something is specified using the 'bgcolor' attribute.

The 'crop' tag must be nested in an 'image' tag.

Attribute Class Required? EL? Default
Description
x
java.lang.Integer no yes 0
Indicates the x-coordinate from which the current image will be cropped.
y
java.lang.Integer no yes 0
Indicates the y-coordinate from which the current image will be cropped.
width
java.lang.Integer no yes right edge of image
Indicates the width to which the current image will be cropped.
height
java.lang.Integer no yes bottom edge of image
Indicates the height to which the current image will be cropped.
square
java.lang.Boolean no yes false
Indicates that the image should be squared. The tags 'x', 'y', 'width', and 'height' will be ignored if this is set to 'true'.
center
java.lang.Boolean no yes false
Indicates that when the specified crop area is larger than the image, the image should be centered within that area.
bgcolor
java.lang.String no yes #000000
Specifies the color in RGB Color Component notation to paint the area of the specified crop area that is larger than the image. This is the same string representation used in HTML and CSS syntax. A color is represented by a triplet of hexadecimal values concatentated together, red, green, blue, respectively. The whole thing is prefixed by a pound. "#RRGGBB"

 
mask

Blends a given image with the current image. The specified mask image will be scaled to fit the current image. The specified composite determines how the two images will be blended together. See the section Composite Drawing Tags for more info on the possible composite settings.

The 'mask' tag must be nested in an 'image' tag.

Attribute Class Required? EL? Default
Description
maskFile
java.lang.File or
java.lang.String
if no 'maskUrl' yes
Provides the image to blend with the current image in the form of either a File object or a full path name. The magical prefix '~' (tilde) is supported to refer to the currently served path.
maskUrl
java.lang.String if no 'maskFile' yes
Provides the image to blend with the current image in the form of either an absolute or relative URL. If an absolute URL is provided, it can be of any protocol supported by the JVM. However, caution should be used when accessing other servers, as failure to load the URL will cause a JspTagException to be thrown.
composite
java.lang.String yes yes
Indicates the composite method to use to blend the two images together. See the section Composite Drawing Tags for more info on the possible composite settings.

 
drawText

Draws given text onto the current image. The specified font face, size and color determine how the glyphs will be drawn. The specified composite determines how the text and the image will be blended together. See the section Composite Drawing Tags for more info on the possible composite settings.

The 'drawText' tag must be nested in an 'image' tag.

Attribute Class Required? EL? Default
Description
face
java.lang.String no yes SansSerif
Specifies the font face that will be used to draw the text.
size
java.lang.Integer or
java.lang.String
no yes 12
Specifies the point size that the text will be drawn in.
color
java.lang.String no yes #000000
Specifies the color in RGB Color Component notation to draw the text in. This is the same string representation used in HTML and CSS syntax. A color is represented by a triplet of hexadecimal values concatentated together, red, green, blue, respectively. The whole thing is prefixed by a pound. "#RRGGBB"
x
java.lang.Integer or
java.lang.String
no yes 0
Specifies the x position to begin drawing the the text.
y
java.lang.Integer or
java.lang.String
no yes 0
Specifies the y position to begin drawing the the text.
composite
java.lang.String yes yes srcOver
Indicates the composite method to use to blend the text onto the image. See the section Composite Drawing Tags for more info on the possible composite settings.

 
width

Determines and reports the width of the image.

The 'width' tag must be nested in an 'image' tag.

Attribute Class Required? EL? Default
Description
var
java.lang.String no yes
Indicates the name of the variable that the resulting width information should be stored as. If this attribute is not specified, the information will be output to the current pageContext output (most likely the resulting page).
scope
java.lang.String no yes page
Indicates the scope for the variable specified by the 'var' attribute. Acceptable scopes are: page, request, session, application.

 
height

Determines and reports the height of the image.

The 'height' tag must be nested in an 'image' tag.

Attribute Class Required? EL? Default
Description
var
java.lang.String no yes
Indicates the name of the variable that the resulting height information should be stored as. If this attribute is not specified, the information will be output to the current pageContext output (most likely the resulting page).
scope
java.lang.String no yes page
Indicates the scope for the variable specified by the 'var' attribute. Acceptable scopes are: page, request, session, application.

 
Composite Drawing Tags

In version 0.1, there are two types of composite methods available: Alpha and Color-Math. In all cases, the current image encapsulated by the 'image' tag is the destination image, and the drawing, text or image defined by the compositing tag is the source image.

Alpha Compositing

The functionality of Alpha is provided by the AlphaComposite class built into Java. The rules implemented by this class are the set of Porter-Duff rules described in T. Porter and T. Duff, "Compositing Digital Images", SIGGRAPH 84, 253-259.

These compositing rules decide how the images will be blended together based on the alpha-channel of the image. If any input does not have an alpha channel, an alpha value of 1.0, which is completely opaque, is assumed for all pixels. A constant alpha value can also be specified to be multiplied with the alpha value of the source pixels.

The following abbreviations are used in the description of the rules:

  • Cs = one of the color components of the source pixel.
  • Cd = one of the color components of the destination pixel.
  • As = alpha component of the source pixel.
  • Ad = alpha component of the destination pixel.
  • Fs = fraction of the source pixel that contributes to the output.
  • Fd = fraction of the input destination pixel that contributes to the output.

The color and alpha components produced by the compositing operation are calculated as follows:

    Cd = Cs * Fs + Cd * Fd
    Ad = As * Fs + Ad * Fd

where Fs and Fd are specified by each rule. The above equations assume that both source and destination pixels have the color components premultiplied by the alpha component. Similarly, the equations expressed in the definitions of compositing rules below assume premultiplied alpha.

The alpha resulting from the compositing operation is stored in the destination if the destination has an alpha channel. Otherwise, the resulting color is divided by the resulting alpha before being stored in the destination and the alpha is discarded. If the alpha value is 0.0, the color values are set to 0.0.

Composite Description
clear Nothing will be drawn in the combined image.
src Only the source image will be in the combined image.
dst Only the destination image will be in the combined image.
srcOver The source image will be drawn over the destination image.
dstOver The destination image will be drawn over the source image.
srcIn Only the part of the source image that overlaps the destination image will be drawn.
dstIn Only the part of the destination image that overlaps the source image will be drawn.
srcOut Only the part of the source image that doesn't overlap the destination image will be drawn.
dstOut Only the part of the destination image that doesn't overlap the source image will be drawn.
srcAtop The part of the source image that overlaps the destination image will be drawn with the part of the destination image that doesn't overlap the source image.
dstAtop The part of the destination image that overlaps the source image will be drawn with the part of the source image that doesn't overlap the destination image.
xor The part of the source image that doesn't overlap the destination image will be drawn with the part of the destination image that doesn't overlap the source image.

 
Color-Math Compositing

The functionality of Color-Math is provided by a simple MathComposite class internal to the tag library. The rules implemented by this class are commonly available in many modern paint programs. (If I find definitive source information on them, I'll post that here.)

These compositing rules use simple arithmetic on each individual color channel to blend the images together. In these cases the alpha channel is treated in exactly the same fashion as the color channels.

The arithmetic functions are applied to each pixel for each color or alpha channel. The channels are considered distinctly from each other. Overflows and underflows in each channel result in the maximum and minimum values for those channels respectively.

Composite Description
add The source image will be added to the destination image.
sub The source image will be subtracted from the destination image.
avg The sum of the source and destination images will be averaged.