Load & Decode a GIF Image The GifDecoder java class lets programmers load and decode gif images from a gif file formatted input stream with a single method call. The next methods to load and decode gif images are available: public static final GifImage decode(InputStream inputStream) throws IOException public static final GifImage decode(File input) throws IOException public static final GifImage decode(URL input) throws IOException Note: If you load GIF images for displaying purposes (for example to display as image icons within a swing application) then you should use the standard Java API: java.awt.Toolkit#getImage, java.awt.Toolkit#createImage or javax.swing.ImageIcon.
Java Example: Load a GIF Image and Extract GIF File Format Meta Info import com.gif4j.GifDecoder; import com.gif4j.GifFrame; import com.gif4j.GifImage; import java.awt.*; import java.awt.image.BufferedImage; import java.awt.image.IndexColorModel; import java.io.File; import java.io.IOException; import java.util.Iterator; // ... public GifImage loadGifImageAndExtractMetaInfo(File file) throws IOException { // load and decode gif image from the file GifImage gifImage = GifDecoder.decode(file); // print general GIF image info System.out.println("gif image format version: " + gifImage.getVersion()); System.out.println("gif image logic screen width: " + gifImage.getScreenWidth()); System.out.println("gif image logic screen height: " + gifImage.getScreenHeight()); // check if one or more comments present if (gifImage.getNumberOfComments() > 0) { // get iterator over gif image textual comments Iterator commentsIterator = gifImage.comments();
while (commentsIterator.hasNext()) System.out.println(commentsIterator.next()); // print comments } System.out.println("number of frames: " + gifImage.getNumberOfFrames()); // below we iterate frames in loop // but it can also be done using Iterator instance: gifImage.frames() for (int i = 0; i < gifImage.getNumberOfFrames(); i++) { System.out.println("------frame(" + (i + 1) + ")---------"); GifFrame frame = gifImage.getFrame(i); System.out.println("width: " + frame.getWidth()); System.out.println("height: " + frame.getHeight()); System.out.println("position: " + frame.getX() + "," + frame.getY()); System.out.println("disposal method: " + frame.getDisposalMethod()); System.out.println("delay time: " + frame.getDelay()); System.out.println("is interlaced: " + frame.isInterlaced()); // get frame's color model IndexColorModel frameColorModel = frame.getColorModel(); System.out.println("number of colors: " + frameColorModel.getMapSize()); System.out.println("is transparent: " + frameColorModel.hasAlpha()); System.out.println("transparent index: " + frameColorModel.getTransparentPixel()); //get frame's representation as an Image Image image = frame.getAsImage(); //get frame's representation as a BufferedImage BufferedImage bufferedImage = frame.getAsBufferedImage(); } return gifImage; }
Construct a GIF Image The GifImage java class is used to represent a gif image as a sequence of one or more frames and to aggregate and encode some general gif image specific parameters including GIF image logic screen size, GIF file format version, loop information and ASCII textual comments. The GifImage class has the next constructors: public GifImage(); public GifImage(int resizeStrategy); public GifImage(int width, int height); public GifImage(int width, int height, int resizeStrategy); The first two constructors create GifImage with indefinite general gif image width and height these parameters will be taken from the first added frame. Hint: You can always get the current gif image width/height using the next methods: public int getCurrentLogicWidth() public int getCurrentLogicHeight()
Resize Strategies Gif4J PRO undertakes to control general image size (take into consideration all internal frames' size and their positions) using one of the predefined resize strategies: Crop to Fit Image Size, Scale to Fit Image Size and Extend to Current. First two strategies allows to fix the general gif image size (logical screen size). The last extends logical screen size to fit all added gif frames. Below examples demostrate all strategies (see examples/ResizeStrategies):
crop to fit image size (predefined size: 150x150)
scale to fit image size (predefined size: 150x150)
extend to current (extended size: 200x200)
GIF Image Looping Animated gif images can have a Looping Application Extension Block that tells Encoder to loop the entire GIF file. Based on the Gif89a specification you can set number of iterations between 0 and 65535 where 0 means indefinite (infinite) looping. The next method should be used: public void setLoopNumber(int number) Note: By default a new GifImage doesn't contain a Looping Application Extension Block at all which is equal to 1 iteration. To set, for example, infinite looping you should call gifImage.setLoopNumber(0). Note: A lot of gif encoders and viewers (including Microsoft IE browser) ignore number of iterations more than 1 and iterate an animated gif image indefinitely. Hint: You can set default delay time between frames. This delay is automatically applied to adding frames without delay parameter set. The next method should be used: public void setDefaultDelay(int delay)
Note: Any delay parameter is set in 1/100 (centiseconds) - value 100 means delay in 1 second. Default delay between frames is set to 200 (2 seconds).
Extract, Add and Remove GIF Image Comments The GIF Image Comment Extension contains textual information which is not part of the actual graphics in the GIF Data Stream. It is suitable for including comments about the graphics, credits, descriptions or any other type of non-control and non-graphic data. The next methods should be used to add, get and remove comments (please consult GifImage API for more info): public void addComment(String comment); public String getComment(int index); public void removeComment(int index); public int getNumberOfComments(); public Iterator comments();
Gif4J PRO Java Example: Add a comment to a GIF image import com.gif4j.GifDecoder; import com.gif4j.GifEncoder; import com.gif4j.GifImage; import java.io.File; import java.io.IOException; // ... public void addCommentToGifImage(File file, String comment) throws IOException { //read gif image from the file GifImage gifImage = GifDecoder.decode(file); // add comment gifImage.addComment(comment); // write commented gif image to the same file GifEncoder.encode(gifImage, file); }
Access GIF Image Frames
You can get a number of already added frames, get an iterator over the frames or access frames in the random order using the next methods (please consult GifImage API for more info): public GifFrame getFrame(int index); public GifFrame getLastFrame(); public int getNumberOfFrames(); public Iterator frames();
Gif4J PRO Java Example: Double the total GIF animation time import com.gif4j.GifImage; import com.gif4j.GifFrame; import java.util.Iterator; // ... public GifImage doubleAnimationTime(GifImage gifImage) { // iterate frames for (Iterator framesIterator = gifImage.frames(); framesIterator.hasNext();) { // get the next frame GifFrame frame = (GifFrame) framesIterator.next(); // double frame's delay frame.setDelay(frame.getDelay() * 2); } return gifImage; }
Construct a GIF Frame The GifFrame java class is used as a container to aggregate and encode the gif format specific information about a single gif image frame. GifFrame constructors can be divided into 2 types according to the desired frame position (absolute or relative). "absolute positioning" costructors contain Point parameter and "relative positioning" constructors contain layout constraint parameter. Note: If you use "relative positioning" then the final position is calculated according to one of the predifined layout constraint before the final encoding process starts.
Absolute and Relative Internal GIF Frame Positioning Below examples demostrate relative positioning and how you can use it (see examples/FramePositioning):
(size: 300x300, every frame size: 100x100)
(size: 200x200, every frame size: 100x100)
image tour (size: 300x240, every frame is scaled down using ImageUtils to 150x130)
Get Frame's Position and Size You can get frame's position and size using the next methods: public int getX(); public int getY(); public int getWidth(); public int getHeight();
Disposal Methods & Delay Time Disposal Method - indicates the way in which the graphic is to be treated after being displayed. According to Gif89a format specification there are 4 disposal methods: Not Specified, Do Not Dispose, Restore To Background Color and Restore To Previous. You can set disposal method through corresponding GifFrame constructors or using the next
method: public void setDisposalMethod(int disposalMethod) You can get disposal method using the next method: public int getDisposalMethod() Delay Time - If not 0, this field specifies the number of hundredths (1/100) of a second to wait before continuing with the processing of the Data Stream. The clock starts ticking immediately after the graphic is rendered. You can set delay time through corresponding GifFrame constructors or using the next method: public void setDelay(int delay) You can get frame's delay time using the next method: public int getDelay()
Adding GIF Frames to a GIF Image To add GifFrame(s) to GifImage(s) you can use the next methods (please consult GifFrame API for more information): public GifImage addGifFrame(GifFrame frame); public GifImage addGifFrame(GifFrame frame, MorphingFilter filter); public GifImage addGifFrame(GifFrame frame, Watermark watermark); public GifImage addGifFrame(GifFrame frame, MorphingFilter filter, Watermark watermark) ;
Retrieve Frame's Image Data and Color Model To retrieve a copy of the frame's image data as an instance of Image or BufferedImage java classes you should use the next methods: public Image getAsImage(); public BufferedImage getAsBufferedImage();
To retrieve a copy of the frame's image color model as an instance of IndexColorModel the next method can be used: public IndexColorModel getColorModel(); Hint: You can use a copy of the frame's image color model to get frame's transparency information through IndexColorModel methods: hasAlpha(), getTransparency(), getTransparentPixel() etc.
Transform a GIF Image The GifTransformer class is the helper java class containing static methods to affine transform animated and non-animated GIF images represented by GifImage objects including resize, scale, rotate and flip gif image transform operations. The next methods to transform gif images are available (please consult the Gif4J PRO Java API for more info): public static final GifImage rotate(GifImage gifImage, double theta, boolean smooth); public static final GifImage rotate90Left(GifImage gifImage); public static final GifImage rotate90Right(GifImage gifImage); public static final GifImage rotate180(GifImage gifImage); public static final GifImage scale(GifImage gifImage, double xscale, double yscale, boolean smooth); public static final GifImage resize(GifImage gifImage, int width, int height, boolean smooth); public static final GifImage flipHorizontal(GifImage gifImage); public static final GifImage flipVertical(GifImage gifImage); Note: smooth parameter (if presents) lets Java developers choose a gif image processing algorithm: if 'true' then the higher priority is given to a gif image smoothness than processing speed. But on the other hand it can bring about sizeable increase of the transformed GIF image size.
Gif4J PRO Java Example: Resize a GIF image using GifTransformer // ... // resize gif image to the width=100px // with maintaining the aspect ratio of the original gif image dimension GifImage resizedGifImage1 = GifTransformer.resize(gifImage, 100, -1, false); // the same but smoothly GifImage resizedGifImage1_smooth = GifTransformer.resize(gifImage, 100, -1, true); // resize gif image to the width=100px and height=60px GifImage resizedGifImage2 = GifTransformer.resize(gifImage, 100, 60, false); // the same but smoothly GifImage resizedGifImage2_smooth = GifTransformer.resize(gifImage, 100, 60, true); // ...
Encode and Save a GIF Image The GifEncoder java class lets programmers encode and save images out to a file or output stream using the GIF file format (GIF89a version) with a single method call. The next methods to encode and save images as GIFs are available (please consult the Gif4J PRO Java API for more info): public static final void encode(BufferedImage image, DataOutput dataOutput) throws IOException; public static final void encode(BufferedImage image, File output) throws IOException; public static final void encode(BufferedImage image, OutputStream outputStream) throws IOException; public static final void encode(GifImage gifImage, File output) throws IOException; public static final void encode(GifImage gifImage, File output, boolean forceGlobalColorTableUsage) throws IOException; public static final void encode(GifImage gifImage, OutputStream outputStream) throws IOException; public static final void encode(GifImage gifImage, OutputStream outputStream, boolean forceGlobalColorTableUsage) throws IOException; The first three methods can be used to encode BufferedImage(s) directly to non-animated (consists of one frame) gif image files. If the specified BufferedImage contains more than 256 unique colors then it'll be automatically quantized using the Gif4J Java Color Quantizer. Parameter forceGlobalColorTableUsage forces Global Color Table use. If this parameter is set to true then Local Color Tables from all frames will be union to one Global Color Table. It's useful to optimize final image size (every Local Color Table takes up to 768 bytes). Especially this option is recommended to set for encoding gif images with lots of internal frames (for example, after applying Morphing Filters).
Gif4J PRO Java Example: Save Image as a GIF to a file import com.gif4j.ImageUtils; import com.gif4j.GifEncoder; import import import import
java.awt.Image; java.awt.image.BufferedImage; java.io.File; java.io.IOException;
// ... public void saveImageAsGif(Image image, File fileToSave) throws IOException { // convert Image to the BufferedImage BufferedImage bufferedImage = ImageUtils.toBufferedImage(image); // save image GifEncoder.encode(bufferedImage, fileToSave); }
Gif4J PRO Java Example: Save array of images as an animated GIF to a file import com.gif4j.GifEncoder; import com.gif4j.GifFrame; import com.gif4j.GifImage; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; // ... public void saveImageArrayAsAnimatedGif(BufferedImage[] images, File fileToSa ve) throws IOException { // create new GifImage instance GifImage gifImage = new GifImage(); // set default delay between gif frames gifImage.setDefaultDelay(500); // add comment to gif image gifImage.addComment("Animated GIF image example");
// add images wrapped by GifFrame for (int i = 0; i < images.length; i++) gifImage.addGifFrame(new GifFrame(images[i])); // save animated gif image GifEncoder.encode(gifImage, fileToSave); }
Write GIF Images with Java ImageIO You can find more infomation about the Java Image I/O API here. Just one quotation: "The Java Image I/O API provides a pluggable architecture for working with images stored in files and accessed across the network. It offers substantially more flexibility and power than the previously available APIs for loading and saving images." To enable ImageIO support by the Gif4J PRO you just need to add library jar file to the CLASSPATH. The Java Image I/O API should automatically resolve the Gif4J library as a plugin, load the Gif4J service provider classes, and registers the Gif4J service provider instance. The next code checks that the Gif4J PRO has been resolved correctly: Iterator iterator = ImageIO.getImageWritersByFormatName("gif"); while (iterator.hasNext()) { ImageWriter imageWriter = (ImageWriter) iterator.next(); ImageWriterSpi spi = imageWriter.getOriginatingProvider(); System.out.println("Vendor: "+spi.getVendorName()); System.out.println("Format description: " + imageWriter.getOriginatingProvider().getDescription(null)+"\n"); } The output should contain something like this: Vendor: Gif4J Software, http://www.gif4j.com/ Format description: GRAPHICS INTERCHANGE FORMAT(sm) Version 89a If nothing has been found then you should call ImageIO.scanForPlugins() method to force the ImageIO scans the application class path for plug-ins. If the Gif4J service provider has been detected and loaded then an image Writing in the gif format is equally simple: BufferedImage bi = null; // skip image initialization try { File f = new File("c:\\images\\myimage.gif");
ImageIO.write(bi, "gif", f); } catch (IOException e) { }
Construct a Watermark The Watermark java class is used to prepare and apply (paint with the specified transparency) images as watermarks to the whole gif images, separate gif image frames and BufferedImage(s). Absolute and relative (layout constraint based) positioning are supported. The Watermark class constructors can be divided into 2 types according to the desired position type (absolute or relative): "absolute positioning" costructors contain Point parameter and "relative positioning" constructors contain layout constraint parameter. Also you can specify watermark's transparency parameter which is represented by float value between 0 (absolutely transparent) and 1 (absolutely opaque). Default is 0.5f. Below examples demostrate positioning and transparency opportunities (see examples/Watermarks and examples/ImageTour1):
(size: 150x150, 5 frames - each with different relative position and the last with "cover consecutively" watermark)
Note: If you load GIF images for displaying purposes (for example to display as image icons within a swing application) then you should use the standard Java API: java.awt.Toolkit#getImage, java.awt.Toolkit#createImage or javax.swing.ImageIcon.
Apply a Watermark to a BufferedImage Below example demostrates creating and adding a text watermark to a BufferedImage:
Gif4J PRO Java Example: Add text watermark to a BufferedImage import com.gif4j.Watermark; import com.gif4j.TextPainter; import java.awt.image.BufferedImage; import java.awt.*; public BufferedImage addTextWatermarkToImage(BufferedImage image, String te xt) { //create new TextPainter TextPainter textPainter = new TextPainter(new Font("Verdana", Font.BOLD, 10)) ; textPainter.setOutlinePaint(Color.WHITE); //render the specified text outlined BufferedImage renderedWatermarkText = textPainter.renderString(text,true); //create new Watermark Watermark watermark = new Watermark(renderedWatermarkText, Watermark.LAYOUT_BOTTOM_RI GHT); //apply watermark to the specified image and return the result return watermark.apply(image); }
Apply a Watermark to a GIF image Below example demostrates creating and adding a text watermark to a GifImage:
Gif4J PRO Java Example: Add text watermark to a GifImage import com.gif4j.Watermark; import com.gif4j.TextPainter; import com.gif4j.GifImage; import java.awt.image.BufferedImage; import java.awt.*; public GifImage addTextWatermarkToGifImage(GifImage gifImage, String text) { //create new TextPainter TextPainter textPainter = new TextPainter(new Font("Verdana", Font.BOLD, 10) );
textPainter.setOutlinePaint(Color.WHITE); //render the specified text outlined BufferedImage renderedWatermarkText = textPainter.renderString(text, true); //create new Watermark Watermark watermark = new Watermark(renderedWatermarkText, Watermark.LAYOUT_BOTTOM_RI GHT); //apply watermark to the specified gif image and return the result return watermark.apply(gifImage, true); }
GIF Image Morphing Filters Morphing filters are the unique feature of the Gif4J PRO which lets you to create amazing GIF animations, image tours and banners without any additional coding. There are 7 base morphing filters with more than 20 morphing options. To apply the specified filter to a gif frame you just need to create an instance (or use already created - you can apply one filter's instance to any number of gif frames) of the selected filter (please consult Morphing Filters Java API for more information) and add a GifFrame to a GifImage using one of the next methods: public GifImage addGifFrame(GifFrame frame, MorphingFilter filter) public GifImage addGifFrame(GifFrame frame, MorphingFilter filter, Watermark watermark) Below examples demostrate morphing filters in action (see examples/MorphingFilters and examples/MorphingImageTours):
(CellFilter)
(CurtainFilter)
(MillFilter)
(RadarFilter)
(MozaicFilter)
(TunnelFilter)
(SnakeFilter)
(Cell and Curtain filters have been used)
(Mill, Mozaic and Tunnel filters have been used)
(Snake filter with different options has been used) Note: For every filter you can specify 'delay time between frames' parameter (in 1/100 seconds). Default delay is equal to 10. To do a gif animation smoother please specify this parameter small but note that some gif viewers and browsers (including Microsoft IE) can ignore very small delay between frames. Experience has shown that, for example, Microsoft Internet Explorer ignores delay between frames less than 6 and in this case uses own default delay. So if you want to get the fastest gif animation then set the delay to 6. Note: Morphing filtering is based on fragmentation one gif frame to several and it increases the total number of gif frames greatly. As you know by default every output gif frame has own local color table which can take up to 768 bytes in the result file. To prevent this process encode the GifImage with "force global color table usage" option (see GifEncoder class API for more information).
Text Rendering The TextPainter java class is intended for drawing a text across the single or multiple lines on the BufferedImage(s). It can be very convenient for adding some text information to images, creation text-based watermarks etc. The TextPainter class in its basis uses Java 2D lays and supports some Java 2D API concepts such as Paint etc. This java class actually represents a small superstructure above Java2D and uses only a small part of Java2D functionality. The TextPainter context contains the next attributes: font (instance of java.awt.Font), foreground paint (instance of java.awt.Color, java.awt.GradientPaint or java.awt.TexturePaint), backgroung color (instance of java.awt.Color), outline paint (instance of java.awt.Color, java.awt.GradientPaint or java.awt.TexturePaint) and antialiasing (on/off). You can get and set these attributes using the corresponding constructors and getter/setter methods. There are 2 main rendering methods (please consult TextPainter Java API for more options): public BufferedImage renderString(String str); public BufferedImage renderText(String text, int width, boolean outline, boolean centralized); The first method renders single string using the specified attributes from the TextPainter context. Size of the returned BufferedImage object is equal to visual bounds of the specified string to render. The second method renders line-wraped to the specified width text using the specified attributes from the TextPainter context. Width of the returned BufferedImage object is equal to the specified width. Height is automatically extended to contain all text lines. Below examples demostrate some TextPainter features (see examples/TextRendering, examples/TextBanner, examples/ProductIcon1 and examples/ProductIcon2):
Hint: To render outlined text with better quality use BOLD font instances. Hint: It is no secret that any published on a site text information are not protected and can be easily grabbed by special scripts or even by copy/paste. You can prevent the grabbing of any privacy information (passwords, e-mails, price lists, financial reports etc.) by publishing such information as gif images. With the help of the Gif4J PRO for Java such functionality can be added easily for short time. Note: Sometimes you can get ugly rendered text on the other platform while on your own platform text is rendered well. Such problems are usually connected with failing one or another font. You can get all supported fonts on the exact platform by calling getAllFonts() method of the GraphicsEnvironment class: GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); Font[] allfonts = ge.getAllFonts();