
tds
|
Documente-toi la dessus (javadoc) et tu t'épargneras un sérieux calvaire :p ==> ConvolveOp <==
CECI EST EN PLUS PARCE JE SUIS COOL CE MATIN: *****************************************
Core Java Technologies Tech Tips
Tips, Techniques, and Sample Code
Welcome to the Core Java Technologies Tech Tips for February 17, 2004. Here you'll get tips on using core Java technologies and APIs, such as those in Java 2 Platform, Standard Edition (J2SE).
This issue covers:
* Loading and Saving Images with the Image I/O Library * Reflecting JavaBeans Components These tips were developed using Java 2 SDK, Standard Edition, v 1.4.2.
This issue of the Core Java Technologies Tech Tips is written by John Zukowski, president of JZ Ventures, Inc. (http://www.jzventures.com).
You can view this issue of the Tech Tips on the Web at http://java.sun.com/developer/JDCTechTips/2004/tt0217.html
See the Subscribe/Unsubscribe note at the end of this newsletter to subscribe to Tech Tips that focus on technologies and products in other Java platforms.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LOADING AND SAVING IMAGES WITH THE IMAGE I/O LIBRARY
Introduced in J2SE 1.4, the javax.imageio package is the primary package for the Java Image I/O API. As its name implies, this package helps you read and write image files. You might wonder what's so important about this package. The fact is that you could read images with the getImage method of various classes like Toolkit and Applet since the initial release of the Java platform. But there is more to the javax.imageio package than simply reading images. One important point is that there was no writeImage or putImage previous to the Image I/O library. Now there is a way to write images. Also, you can now set properties such as compression level when you save images.
The first question many people ask when working with the Image I/O libraries is what formats are supported? With Sun's reference implementation, you get a specific set. However, the API is flexible enough so that you can install your own formats by extending the necessary classes in the javax.imageio.spi library. For the moment, let's put that aspect of the library aside. To discover the installed set of readers and writers, you simply ask the ImageIO class through its getReaderFormatNames() and getWriterFormatNames() methods (or getReaderMIMETypes() and getWriterMIMETypes() if you want to work directly with MIME types). Here's an example:
import javax.imageio.*;
public class GetList { public static void main(String args[]) { String readerNames[] = ImageIO.getReaderFormatNames(); printlist(readerNames, "Reader names:"); String readerMimes[] = ImageIO.getReaderMIMETypes(); printlist(readerMimes, "Reader MIME types:"); String writerNames[] = ImageIO.getWriterFormatNames(); printlist(writerNames, "Writer names:"); String writerMimes[] = ImageIO.getWriterMIMETypes(); printlist(writerMimes, "Writer MIME types:"); } private static void printlist(String names[], String title) { System.out.println(title); for (int i=0, n=names.length; i<n; i++) { System.out.println("\t" + names[i]); } } }
If you run the GetList program with Sun's reference implementation (and no custom providers installed), you should see the following output:
Reader names: jpeg gif JPG png jpg JPEG Reader MIME types: image/png image/jpeg image/x-png image/gif Writer names: jpeg JPG png jpg PNG JPEG Writer MIME types: image/png image/jpeg
Basically, you get support for reading GIF, JPEG, and PNG formatted images, and for writing JPEG and PNGs. There is no GIF writer provided.
As you work with the Image I/O libraries, you might notice that almost all the work is requested through the static methods of the ImageIO class. For basic usage, these static methods are all you need. For example, to read an image, you pass the location to one of the following read methods of ImageIO:
o read(File input) o read(ImageInputStream stream) o read(InputStream input) o read(URL input)
The ImageInputStream is an interface of the javax.imageio.stream package that is seekable, and so it's potentially faster than a regular InputStream. Instead of getting an InputStream from a FileInputStream, and passing that InputStream into the read method, it's more efficient to pass the File object to be read, or to create a FileImageInputStream from the File. More specifically, instead of:
InputStream is = new InputStream("myimage.jpg"); ImageIO.read(is);
use either:
File file = new File("myimage.jpg"); ImageIO.read(file);
or File file = new File("myimage.jpg"); FileImageInputStream fiis = new FileImageInputStream(file); ImageIO.read(fiis);
The read method (in all cases) returns a BufferedImage object. You can then draw this image with the drawImage method of Graphics, or you can filter it with something like a ConvolveOp from the java.awt.image package.
The following program, ReadSharp, demonstrates reading and displaying an image. The program also applies a sharpness filter.
import java.awt.image.*; import javax.imageio.*; import java.io.*; import java.awt.*; import javax.swing.*; public class ReadSharp { private static class FrameShower implements Runnable { final Frame frame; public FrameShower(Frame frame) { this.frame = frame; } public void run() { frame.show(); } } public static void main(String args[]) throws IOException { if (args.length != 1) { System.err.println( "Please include image filename on command line"); System.exit(-1); } // Read File file = new File(args[0]); BufferedImage input = ImageIO.read(file); // Convert Kernel sharpKernel = new Kernel(3, 3, new float[] { 0.0f, -1.0f, 0.0f, -1.0f, 5.0f, -1.0f, 0.0f, -1.0f, 0.0f }); ConvolveOp convolveOp = new ConvolveOp( sharpKernel, ConvolveOp.EDGE_NO_OP, null); int width = input.getWidth(); int height = input.getHeight(); BufferedImage output = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB); convolveOp.filter(input, output); // Make screen Icon icon = new ImageIcon(output); JLabel label = new JLabel(icon); JFrame frame = new JFrame("Sharp Image"); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE); frame.getContentPane().add( label, BorderLayout.CENTER); frame.pack(); // Show Runnable runner = new FrameShower(frame); EventQueue.invokeLater(runner); } } When you run the ReadSharp program, specify an image name on the command line. For example, let's use one of the images from the February 10, 2004 Tech Tip titled "Styling Digital Images with ConvolveOp" (http://java.sun.com/developer/JDCTechTips/2004/tt0210.html):
java ReadSharp BrightnessChanger.jpg
As ReadSharp demonstrates, you don't have to specify the image format when reading an image. Typically, the system will determine the correct reader based on the first few bytes of the stream (typically referred to as the magic number).
Writing images can be just as easy as reading them, though you can also specify metadata if you need more control. For basic support, there are the three forms of the write method:
o write(RenderedImage im, String formatName, File output) o write(RenderedImage im, String formatName, ImageOutputStream output) o write(RenderedImage im, String formatName, OutputStream output)
All three method forms of the write method return a boolean. This indicates whether an appropriate writer object is available in the system. For example, asking for a GIF writer will return false because there is no GIF writer in the system.
BufferedImage is a type of RenderedImage, so you only need to pass to the write method the BufferedImage returned by the read method. This makes it easy to do simple transformations, such as from GIF to PNG:
File inputFile = new File("image.gif"); BufferedImage input = ImageIO.read(inputFile); File outputFile = new File("image.png"); ImageIO.write(input, "PNG", outputFile);
Notice that the format name passed to the write method is one of those returned by getWriterFormatNames().
When you write an image, you can configure various writing parameter metadata, such as compression level. However, you can't do that directly with the write method of ImageIO. Instead, you must use some of the other Image I/O classes (and packages). More on how to specify this metadata through the ImageWriteParam class shortly.
It is possible to have more than one Reader or Writer provider for a specific format. Because of that, methods such as getImageWritersByFormatName of ImageIO return an Iterator. To customize output compression levels, you could examine all the installed providers and find the maximum compression level supported. Or you could simply use the first one and work with it. Let's take the simpler approach here:
Iterator iter = ImageIO.getImageWritersByFormatName("JPG"); if (iter.hasNext()) { ImageWriter writer = (ImageWriter)iter.next(); ... }
You can get the default writing parameters for a specific ImageWriter through its getDefaultWriteParam method. The method returns an ImageWriteParam object. For JPEGs, this is an instance of javax.imageio.plugins.jpeg.JPEGImageWriteParam (though you don't need to know this). To change the compression level, you need to tell the ImageWriteParam object that you want to set the compression mode explicitly:
iwp.setCompressionMode( ImageWriteParam.MODE_EXPLICIT);
You then set the compression quality with:
iwp.setCompressionQuality(floatLevel);
Instead of picking a value at random, you can ask the writer what compression quality values it supports (or how much it will compress things):
float values[] = iwp.getCompressionQualityValues();
Here's a program, Compress, that converts any image that can be read through the Image I/O library. The program reads the image, and writes an image for each supported compression format. The Sun-provided JPEG encoder returns the values of 5%, 75%, and 95% from getCompressionQualityValues. Notice that the program writes directly with the ImageWriter object, not with the ImageIO object.
Because the output parameters are being customized, you must use an IIOImage object (IIO stands for Image IO) to represent the image to be written. You can't use a plain BufferedImage. The BufferedImage can be directly converted to an IIOImage as an extra step.
import java.awt.image.*; import javax.imageio.*; import javax.imageio.stream.*; import java.io.*; import java.util.Iterator; public class Compress { public static void main(String args[]) throws IOException { if (args.length != 1) { System.err.println( "Please include image filename on command line"); System.exit(-1); } // Read String name = args[0]; File file = new File(name); BufferedImage input = ImageIO.read(file); // Get Writer and set compression Iterator iter = ImageIO.getImageWritersByFormatName("JPG"); if (iter.hasNext()) { ImageWriter writer = (ImageWriter)iter.next(); ImageWriteParam iwp = writer.getDefaultWriteParam(); iwp.setCompressionMode( ImageWriteParam.MODE_EXPLICIT); float values[] = iwp.getCompressionQualityValues(); // Write one for each compression values for (int i=0, n=values.length; i<n; i++) { iwp.setCompressionQuality(values[i]); String newName = i + name; if (!newName.endsWith(".jpg")) { newName += ".jpg"; } File outFile = new File(newName); FileImageOutputStream output = new FileImageOutputStream(outFile); writer.setOutput(output); IIOImage image = new IIOImage(input, null, null); System.out.println( "Writing " + values[i] + "%"); writer.write(null, image, iwp); } } } }
B@ron {EU.BELGIUM}
|