Image Format Properties | ||||||||
---|---|---|---|---|---|---|---|---|
format | compact | lossy | trans | variable trans | photos | animation | wide support | notes |
gif | Oldest. Many variants. Patent has expired. | |||||||
jpg | Specialised for photos | |||||||
png | Creates feathered smooth transition to a background. Good for logos and icons. | |||||||
svg | It is a very compact vector format. Like PostScript, it is a set of mathematical descriptions of the picture which can be perfectly scaled to any size. | |||||||
WebP | either | Actually a suite of techniques bundled under one format. |
Technically WebP would be the best format for HTML use because of its excellent compression, 30% better than jpg. The catch is, browser makers and Java, have conspired against it because it Google created it. Compression is very important because it translates into snappier response since less has to be transmitted. Snappier response means happier visitors.
Just to confuse matters, there is also the Icon interface that ImageIcon implements. Whenever you see a method taking a Icon, you can feed it an ImageIcon.
ImageIcon.getImage will convert an ImageIcon to an Image. The constructor new ImageIcon( Image image ) will convert an Image to an ImageIcon.
The ImageIcon class and the Icon interface have nothing whatsoever to do with Windows *.ico icon format that supports multiple resolutions in one file. Java ImageIcons don’t have to be magic sizes. They don’t have to be square. They can be *.png, *.gif or *.jpg just like Images.
You can think of the scheme as like an assembly line. At each stage, the image consumer asks the previous stage image producer for a chunk of the partly processed image to work on. The producer gives it as much as it can and the consumer then asks again later for the remaining bits. With this scheme, you do not have to wait until all the image has completely arrived before getting on with the later stages of processing, e.g. getting at least part of the image up there on the screen. The details of how it all works are mind boggling, but surprisingly, you can write code even if you have only the vaguest understanding of how they work.
You can just close you eyes to those complexities at first, but you will have to understand them once you start fine tuning your apps when you want to get rid of strange behaviours and flicker.
The Image class is abstract. You can’t instantiate an Image with a constructor. Part of the problem is Image is associated with some very platform dependent code. Besides the terrifying ways of dealing with ImageProducers, ImageConsumers and ImageObservers, there are some simple techniques to create an Image.
Saving an image in gif or jpg format is referred to as encoding.
Another easy way to get an Image from the local hard disk is with, surprise,
It works with *.gif, *.jpg and in Java 1.4+, *.png files.
Class.getResource makes these changes to the resource name: if the resource name starts with /, it is unchanged; otherwise, the package name is prepended to the resource name after converting . to /. This allows you to use either dots or slashes to separate the components of the name. The name is case-sensitive. Double check the case by studying your jar files with WinZip.
Toolkit.getDefaultToolkit().createImage( rawByteArray , start, length );
There is no Component in Java version 1.6 or later that simply displays an Image. I have written one here called ImageViewer which is a greatly simplified version of the one that ships with Café. The component automatically sizes itself to fit the size of the Image you feed it. You can attach a standard MouseListener to it to trigger some action when somebody clicks it. Here is the source
You can download the latest source and a fancier one called ResizingImageViewer as part of the Canadian Mind Products Business package
Without Swing, you have to handle double buffering yourself. With Swing, all you need is Component.setDoubleBuffered( true ). If you don’t use double buffering you paint directly to the screen. Double buffering is not always faster. In Java version 1.2 or later Swing components, double buffering is applied by default. Sometimes you have to turn double buffering off to avoid strange ghosting effects. A simple offscreen drawing technique works like this:
I have experimented with Component.createImage( width, height). It is a tricky mechanism. It behaves differently in different JVMs (Java Virtual Machines) and different browsers. The problem is it uses the current Component’s (e.g. the Applet’s) peer object to create the offscreen Image object. createImage is an instance method of the current Component, not an independent static method as you might expect. That is how it finds the Component’s peer object in the native GUI (Graphic User Interface) that knows the details of the image format used by the particular video card we are using.
That peer does not get created until the last minute when Component.setVisible ( true ). Since you are presumably using createImage to eventually create that screen image, you have a minor catch-22. You can’t create the Image well ahead of time. You somehow must postpone any use of createImage until the Component’s addNotify method has been called assigning it a peer object in the native GUI that knows the native format for images on that particular video card. Hooking your code into the addNotify is an essay in itself.
In Java version 1.2 Component.isDisplayAble was introduced that lets you know if the peer object is ready yet for createImage to work. It definitely won’t work in static init. It sometimes works in init. Best to put it in an overriding addNotify method which is used to create the peer object. When it returns from super.addNotify is the earliest possible time you can use the peer.
public void addNotify() { super.addNotify(); offScreenImage = createImage ( width, height ); }
png format bypasses the patent problem, but it is not as widely supported. Java did not support it until version 1.4. The easiest way is to use an external screen capture utility such as PaintShop Pro. if you want to do it under java program control, you have to look for third party image-savers. See Peter van der Linden’s FAQ for some options. You can, of course, serialize the Image, but you can’t reconstitute it on a different platform because the format of the pickled (serialized) Image is platform-dependent. For speed, Images are stored in a ColorModel (internal format) matching or closely matching the local video card.
See the source code for Cropper to see how to load, crop, scale and save a *.png, *.jpg or *.gif file.
Don’t try to send serialized Images over RMI (Remote Method Invocation) either for the same reason. One way to do it is to use uk.co.demon.windsong.image.ZipImage to convert the Image to a device Independent GZIPOutputStream and the companion uk.co.demon.windsong.image.ImageProducer to reconstitute it.
When you want animation speed/smoothness, look into VolatileImage available since Java version 1.4 which is implemented where possible inside the video hardware. BitBlts on such images would be done with the 128-bit GPU (Graphics Processing Unit) (graphics processing unit) which is much better designed than the CPU (Central Processing Unit) for shovelling misaligned bits around. You build your images in the offscreen part of the hardware video REGEN buffer. Then when you blast them to the screen, they go instantaneously, since the BitBlt video hardware moves it without having to cross the blood-brain boundary to the video hardware memory buffer. It is a high speed double buffering technique.
In your AWT paint method or equivalent Swing paintComponent method you use you use the drawImage method typically with code like
What is all this?
g is the Graphics object. It represents the place where we are painting to, usually the screen, but it could be printer or offscreen image. It knows what sort of image format the video card likes. It is passed as a parameter to your paint or paintComponent method.
image is the usually-MediaTracked image more or less ready to draw. It may be part way through the conversion process to internal format.
x,y is where on screen you want to paint the Image.
width, height is how much of the Image you want to copy, usually the whole thing.
this is the Canvas or other Component we are painting on. It is used to reschedule work that cannot be completed now.
done is true if drawImage was able to complete the work.
If done is false then things get interesting. The work is left unfinished and your paint method completes.
When more of the Image is ready, the ImageProducer will use the Component’s ImageObserver interface to call its default Component.updateImage method. That method then calls repaint with a clip region describing the uncompleted part of the work.
repaint schedules a repaint event, which eventually ends up calling your paint or paintComponent again, but this time with Graphics object with a reduced clip region so you don’t have to bother redoing the completed work if you are clever.
This process repeats until eventually drawImage returns true.
The key point to understand is that your paint or paintComponent method may be called several times to complete the drawing from an initial repaint request. You can write your paint method oblivious to this madness. The Graphics object automatically clips everything you draw to the uncompleted region. However, ideally you should avoid excessive painting outside the clip region.
Image Processing Tools | |
---|---|
Class or Method | Purpose |
BufferedImage | A subclass of Image, that gives you additional ability to study and manipulate its bits. With ImageIO you can efficiently create them from images or disk or in RAM. You can actually instantiate an BufferedImage, unlike an abstract Image. You can examine and set individual bits with getRGB and setRGB. When you create a BufferedImage you decide the ColorModel it will use, e.g. how will pack the image and its colours into bits. BufferedImage is only available in Java version 1.2 or later. |
Class.getResource | get file in jar. |
ColorModel | abstract class that describes an internal bit map format. It is merely a set of methods for unpacking a single pixel coded as an int into alpha, red, green and blue. It does not know how to pack it up again. They are used by ImageConsumers to unpack the raw bytes and raw ints that ImageProducers throw at them. |
Component.createImage | creates empty Image, or creates an Image given any ImageProducer. Cannot be used until after addNotify. Similar to Toolkit.createImage. |
Component.prepareImage | starts the file loading, but does not ensure completion. |
Component.updateImage | ImageObserver interface to reschedule incomplete drawing. The ImageProducer notifies of the progress in preparing the Image by repeatedly calling Component.updateImage. |
Graphics.drawImage | copies bits from an Image to the screen or to another Image. |
Image | abstract class for plugging ImageProducers and ImageConsumers together. Much to my surprise, I discovered Image objects do not actually contain any bits of the picture. Image objects contain a reference to the ImageProducer, but not the ImageConsumer. The ImageProducers track all their ImageConsumers. getScaledInstance can be used to create a larger or smaller version of an image in one step. There are two concrete implement ions of the Image abstract class: BufferedImage and VolatileImage. |
ImageConsumer | interface capable of accepting image bits in one of Java’s standard internal formats (ColorModels) It may not necessarily receive them at once, or even in order. Graphics objects have ImageConsumers. They accept bits and convert them to the native GUI format for the video card. Other Graphics objects created by offscreen Image.getGraphics simply store the bits fed them in RAM somewhere, usually in one of Java’s standard formats. A VolatileImage.createGraphics stores its bits in native video card format right inside the video card’s private memory. ImageConsumers passively accept whatever bits the ImageProducers send to them. I don’t even see a way they can provide a clip region to the ImageProducer. On the other hand they are just passed the address of the bits. They are not obligated to copy any of them, so ImageConsumerss can do their own clipping fairly efficiently. You can write ImageFilters that act both as ImageConsumer and ImageProducer. They could clip, change colors, change ColorModels etc. |
ImageIcon | a wrapper class consisting of a reference an Image, a built-in MediaTracker and a text description. It is a convenient way to package an Image to hand to a JComponent such as a JButton to decorate it. |
ImageProducer | interface capable of providing image bits in one of Java’s standard internal formats. It does not have to provide them all at once, or even in order. It might be a method like URL.getContent that can fetch files off disk or the Internet and decompress the jpg format into standard Java internal bitmap format. Whenever it has more bits prepared, it hands them off to the ImageConsumer via ImageConsumer.setPixels. |
ImageObserver | interface used to reschedule incomplete painting. It gets notified of progress in preparing the Image via its ImageObserver.imageUpdate method. |
MediaTracker | Ensures a group of Images are fully loaded in RAM. |
PixelGrabber | captures pixels from any ImageProducer and converts them into an array of pixel ints. It gives you direct access to the raw bits behind an Image for bulk import/export. You can change individual bits more easily with BufferedImage. getRGB and BufferedImage. setRGB. Pixels are stored in arrays and are subject to the Integer. MAX_VALUE addressing limit. This limit will bite you sooner than you think. The biggest square of pixels you can address is 46,340 × 46,340. |
ToolKit.createImage | create an image Image out of raw bytes, an URL a file or any ImageProducer. Similar to Component.createImage. |
ToolKit.getImage | get an Image from local hard disk. Beware. getImage caches results. Use createImage to bypass the caching. If you change the disk file of the image and refetch you will likely get the old version again. Where do you get your Toolkit? from Component.getToolkit or Toolkit.getDefaultToolkit. If you get it from a Component, it must have a peer, e.g. after super.addNotify has returned. However, this is preferable since the Component will be automatically repainted as parts of the Image dribble in. |
VolatileImage | A Image living on borrowed time inside the regen buffer — video card’s private offscreen memory, already converted to the video card’s native internal format. It can be copied to the onscreen part of the REGEN by the video card 128-bit hardware in a twinkling. |
WriteableRaster | Lets you modify individual pixels in a BufferedImage. |
This page is posted |
http://mindprod.com/jgloss/image.html | |
Optional Replicator mirror
|
J:\mindprod\jgloss\image.html | |
Please read the feedback from other visitors,
or send your own feedback about the site. Contact Roedy. Please feel free to link to this page without explicit permission. | ||
Canadian
Mind
Products
IP:[65.110.21.43] Your face IP:[18.117.104.30] |
| |
Feedback |
You are visitor number | |