Sei sulla pagina 1di 6

J D C

T E C H

T I P S
TIPS, TECHNIQUES, AND SAMPLE CODE

WELCOME to the Java Developer Connection(sm) (JDC) Tech Tips,


October 21, 1999. This issue covers:
* Creating Image Thumbnails
* Capturing Standard Output in a Log File
This issue of the JDC Tech Tips is written by Patrick Chan,
author of "The Java(tm) Developers Almanac"
(http://www.amazon.com/exec/obidos/ASIN/0201432986/xeo).
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CREATING IMAGE THUMBNAILS
This tip demonstrates how you can create a small thumbnail version
of a larger image. This is especially important for web applications
that need to display a number of images on a page and do it in
a reasonable amount of time.
The tip applies to the Java(tm) 2 Platform, JDK(tm) v1.2 and uses
the com.sun.image.codec.jpeg package. Although this package is
currently included in JDK v1.2, it's not yet part of the Java 2
Platform APIs and so it might change or be deleted in the future.
The example program below illustrates how to create an image
thumbnail. The program takes any GIF or JPEG file and creates
a smaller JPEG file. The program shrinks the original image so that
it fits into a square whose size you specify. In other words, the
program maintains the aspect ratio, that is, the width-to-height
ratio, of the original image. It also ensures that the width and
height of the thumbnail are less than the size you specify.
Here's the code for the example program.
import
import
import
import
import
import
import
import
import
import

java.awt.Image;
java.awt.Graphics2D;
java.awt.geom.AffineTransform;
java.awt.image.BufferedImage;
java.io.IOException;
java.io.OutputStream;
java.io.FileOutputStream;
javax.swing.ImageIcon;
com.sun.image.codec.jpeg.JPEGCodec;
com.sun.image.codec.jpeg.JPEGImageEncoder;

class Thumbnail {
public static void main(String[] args) {
createThumbnail(args[0], args[1], Integer.parseInt(args[2]));
}
/**
* Reads an image in a file and creates a thumbnail in another file.
* @param orig The name of image file.
* @param thumb The name of thumbnail file. Will be created if necessary.

* @param maxDim The width and height of the thumbnail must


*
be maxDim pixels or less.
*/
public static void createThumbnail(String orig, String thumb, int maxDim) {
try {
// Get the image from a file.
Image inImage = new ImageIcon(orig).getImage();
// Determine the scale.
double scale = (double)maxDim/(double)inImage.getHeight(null);
if (inImage.getWidth(null) > inImage.getHeight(null)) {
scale = (double)maxDim/(double)inImage.getWidth(null);
}
// Determine size of new image. One of them
// should equal maxDim.
int scaledW = (int)(scale*inImage.getWidth(null));
int scaledH = (int)(scale*inImage.getHeight(null));
// Create an image buffer in which to paint on.
BufferedImage outImage = new BufferedImage(scaledW, scaledH,
BufferedImage.TYPE_INT_RGB);
// Set the scale.
AffineTransform tx = new AffineTransform();
// If the image is smaller than the desired image size,
// don't bother scaling.
if (scale < 1.0d) {
tx.scale(scale, scale);
}
// Paint image.
Graphics2D g2d = outImage.createGraphics();
g2d.drawImage(inImage, tx, null);
g2d.dispose();
// JPEG-encode the image and write to file.
OutputStream os = new FileOutputStream(thumb);
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(os);
encoder.encode(outImage);
os.close();
} catch (IOException e) {
e.printStackTrace();
}
System.exit(0);
}
}
You run the program like this:
java Thumbnail <original.{gif,jpg}> <thumbnail.jpg> <maxDim>
Notice that the program takes three parameters. The first parameter
is the name of the file for the source image. The second parameter
is the name of the file for the resulting image thumbnail. The third
parameter specifies the maximum number of pixels for the width and
height of the thumbnail. The width and height of the thumbnail will
be no larger than the value of maxDim. The width or height of the

thumbnail can be smaller than maxDim if the width or height of the


original image is smaller.
The program first loads the image file using the ImageIcon class.
This class differs from Toolkit.getImage() in that ImageIcon doesn't
return until the image is fully loaded. The image needs to be fully
loaded in order to immediately access its width and height.
With the width and height, the program can determine the scaling
factor. This means how much the image needs to be reduced so that it
can fit into a square of maxDim pixels. Both the width and height of
the image are scaled down by the same amount to maintain the aspect
ratio.
The program scales the image. It creates a transform
(AffineTransform) object to do the scaling and an image buffer
to hold the new scaled image. Using the scale factor, the program
can determine the exact size of the thumbnail image and the size of
an image buffer just large enough to hold it. The transform is set
with the scaling factor. However, no scaling takes place if the
original image is smaller than the thumbnail.
After scaling, the program paints the original image onto the new
image buffer. It does this by creating a graphic context on the
image buffer and then painting the original image using the
graphics context. Now the thumbnail is in image buffer.
The final step is to convert the image buffer into a JPEG stream
to be written to a file. This is done using the
JPEGImageEncoder.encode() method.
CAPTURING STANDARD OUTPUT IN A LOG FILE
This tip demonstrates how you can record in a log file everything you
print to standard out and standard error. This is especially useful
if you deploy an application and your users encounter problems. You
can have the users send you the log file for analysis.
The following example code demonstrates how to capture standard
output. You can include the example code, as is, in your program.
The example implements a class called SaveOutput, with two static
methods - start() and stop(). Calling start() creates a new log
file or empties an existing log file. It copies into the log file
characters printed to standard output and standard error. Calling
stop() closes the log file and restores the behavior of standard
output and standard error (that is, their behavior before start() was
called).
import java.io.*;
class Stdout {
public static void main(String[] args) {
try {
// Start capturing characters into the log file.
SaveOutput.start("log.txt");
// Test it.
System.out.println("Here's is some stuff to stdout.");
System.err.println("Here's is some stuff to stderr.");

System.out.println("Let's throw an exception...");


new Exception().printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
// Stop capturing characters into the log file
// and restore old setup.
SaveOutput.stop();
}
}
}
class SaveOutput extends PrintStream {
static OutputStream logfile;
static PrintStream oldStdout;
static PrintStream oldStderr;
SaveOutput(PrintStream ps) {
super(ps);
}
// Starts copying stdout and stderr to the file f.
public static void start(String f) throws IOException {
// Save old settings.
oldStdout = System.out;
oldStderr = System.err;
// Create/Open logfile.
logfile = new PrintStream(
new BufferedOutputStream(
new FileOutputStream(f)));
// Start redirecting the output.
System.setOut(new SaveOutput(System.out));
System.setErr(new SaveOutput(System.err));
}
// Restores the original settings.
public static void stop() {
System.setOut(oldStdout);
System.setErr(oldStderr);
try {
logfile.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// PrintStream override.
public void write(int b) {
try {
logfile.write(b);
} catch (Exception e) {
e.printStackTrace();
setError();
}
super.write(b);
}
// PrintStream override.
public void write(byte buf[], int off, int len) {

try {
logfile.write(buf, off, len);
} catch (Exception e) {
e.printStackTrace();
setError();
}
super.write(buf, off, len);
}
}
The start() method first saves the current standard output and
standard error print streams. These print streams will be restored
when stop() is called. Next, the log file is opened. If the log
file does not exist, it's created. Otherwise, the log file is
emptied. Finally, System.setOut() and System.setErr() are called
to replace the standard output and standard error print streams with
SaveOutput print streams.
The stop () method restores the original standard output and
standard error. It then closes the log file.
A SaveOutput object is a PrintStream object that acts like a tee.
Any characters it receives are forwarded to two places: the log file
and the underlying print streams. The underlying print streams in
the example are the original standard output and standard error
print streams; these are supplied to the SaveOutput constructor.
Although both standard output and standard error are written into the
same logfile, there is no need to synchronize this operation. The
reason is that the logfile output stream is itself a print stream
and write operations are synchronized.
To implement this tee behavior, the program needs to override the
two forms of the write method. These overrides simply write the
characters into the logfile and then to the underlying print stream
(by calling super.write()). The write() methods do not throw
exceptions. Instead, they set a flag in the print stream if some
problem occurs. They set the flag by calling setError(). If the client
of the print stream wants to check if an error occurred, it can call
checkError().
. . . . . . . . . . . . . . . . . . . . . . . .
- NOTE
The names on the JDC mailing list are used for internal Sun
Microsystems(tm) purposes only. To remove your name from the list,
see Subscribe/Unsubscribe below.
- FEEDBACK
Comments? Send your feedback on the JDC Tech Tips to:
jdc-webmaster@java.sun.com
- SUBSCRIBE/UNSUBSCRIBE
The JDC Tech Tips are sent to you because you elected to subscribe
when you registered as a JDC member. To unsubscribe from JDC Email,
go to the following address and enter the email address you wish to
remove from the mailing list:

http://developer.java.sun.com/unsubscribe.html
To become a JDC member and subscribe to this newsletter go to:
http://java.sun.com/jdc/
- ARCHIVES
You'll find the JDC Tech Tips archives at:
http://developer.java.sun.com/developer/TechTips/index.html
- COPYRIGHT
Copyright 1999 Sun Microsystems, Inc. All rights reserved.
901 San Antonio Road, Palo Alto, California 94303 USA.
This document is protected by copyright. For more information, see:
http://developer.java.sun.com/developer/copyright.html

JDC Tech Tips


October 21, 1999

Potrebbero piacerti anche