|
Replies:
13
-
Last Post:
Oct 19, 2007 10:56 AM
by: b06
|
|
|
|
|
|
|
using JAI to create a thumbnail as a JPEG
Posted:
May 6, 2007 7:51 PM
|
|
|
I'm trying to use JAI to create a thumbnail of a JPEG and no matter what I do, I keep getting the following stack trace:
exception
javax.servlet.ServletException: All factories fail for the operation "encode" org.apache.struts.action.RequestProcessor.processException(RequestProcessor.java:523) org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:421) org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:224) org.apache.struts.action.ActionServlet.process(ActionServlet.java:1194) org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432) javax.servlet.http.HttpServlet.service(HttpServlet.java:709) javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
root cause
javax.media.jai.util.ImagingException: All factories fail for the operation "encode" javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1687) javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473) javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332) javax.media.jai.RenderedOp.createInstance(RenderedOp.java:819) javax.media.jai.RenderedOp.createRendering(RenderedOp.java:867) javax.media.jai.RenderedOp.getRendering(RenderedOp.java:888) javax.media.jai.JAI.createNS(JAI.java:1099) javax.media.jai.JAI.create(JAI.java:973) javax.media.jai.JAI.create(JAI.java:1395) UploadAction.resizeImage(UploadAction.java:111) UploadAction.execute(UploadAction.java:71) org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:419) org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:224) org.apache.struts.action.ActionServlet.process(ActionServlet.java:1194) org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432) javax.servlet.http.HttpServlet.service(HttpServlet.java:709) javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
root cause
java.io.IOException: reading encoded JPEG Stream sun.awt.image.codec.JPEGImageEncoderImpl.writeJPEGStream(Native Method) sun.awt.image.codec.JPEGImageEncoderImpl.encode(JPEGImageEncoderImpl.java:472) sun.awt.image.codec.JPEGImageEncoderImpl.encode(JPEGImageEncoderImpl.java:228) com.sun.media.jai.codecimpl.JPEGImageEncoder.encode(JPEGImageEncoder.java:277) com.sun.media.jai.opimage.EncodeRIF.create(EncodeRIF.java:70) sun.reflect.GeneratedMethodAccessor51.invoke(Unknown Source) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) java.lang.reflect.Method.invoke(Method.java:585) javax.media.jai.FactoryCache.invoke(FactoryCache.java:122) javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674) javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473) javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332) javax.media.jai.RenderedOp.createInstance(RenderedOp.java:819) javax.media.jai.RenderedOp.createRendering(RenderedOp.java:867) javax.media.jai.RenderedOp.getRendering(RenderedOp.java:888) javax.media.jai.JAI.createNS(JAI.java:1099) javax.media.jai.JAI.create(JAI.java:973) javax.media.jai.JAI.create(JAI.java:1395) UploadAction.resizeImage(UploadAction.java:111) UploadAction.execute(UploadAction.java:71) org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:419) org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:224) org.apache.struts.action.ActionServlet.process(ActionServlet.java:1194) org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432) javax.servlet.http.HttpServlet.service(HttpServlet.java:709) javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
The code I'm using is cobbled together from several examples and clearly I'm not doing something right. Here's what I've got so far:
import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.awt.image.renderable.ParameterBlock; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;
import javax.media.jai.Interpolation; import javax.media.jai.JAI; import javax.media.jai.OpImage; import javax.media.jai.RenderedOp; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping;
import com.sun.media.jai.codec.JPEGEncodeParam; import com.sun.media.jai.codec.PNGEncodeParam; import com.sun.media.jai.codec.SeekableStream;
public class UploadAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException {
String basePath = "C:\\Program Files\\Apache Software Foundation\\Tomcat 5.5\\webapps\\strutsTest\\";
UploadForm upload = (UploadForm) form;
if (upload.getFile() != null) { /* * * * * * */
// open input stream from uploaded file and copy into byte array InputStream is = new BufferedInputStream(upload.getFile().getInputStream()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); int bytesRead = 0; byte[] buffer = new byte[8192]; while ((bytesRead = is.read(buffer, 0, 8192)) != -1) { bos.write(buffer, 0, bytesRead); } bos.close(); is.close(); byte[] image = bos.toByteArray();
// write original (unresized) file OutputStream os = new BufferedOutputStream(new FileOutputStream(basePath + upload.getFile().getFileName())); ByteArrayInputStream bis = new ByteArrayInputStream(image); bytesRead = 0; buffer = new byte[8192]; while ((bytesRead = bis.read(buffer, 0, 8192)) != -1) { os.write(buffer, 0, bytesRead); } os.close();
// resize image bis.reset(); OutputStream osThumb = new BufferedOutputStream(new FileOutputStream(basePath + "THUMB_" + upload.getFile().getFileName())); resizeImage(bis, os, 150, 150); osThumb.close();
// close input stream bis.close();
}
return mapping.findForward("success");
}
// based on code examples from http://www.iproving.ca/space/Technologies/Java+Advanced+Imaging, http://forums.java.net/jive/thread.jspa?messageID=64672 and http://archives.java.sun.com/cgi-bin/wa?A2=ind0208&L=java-imageio-interest&P=242 private void resizeImage(InputStream is, OutputStream os, int width, int height) {
// read in the original image from an input stream SeekableStream s = SeekableStream.wrapInputStream(is, true); RenderedOp image = JAI.create("stream", s); ((OpImage) image.getRendering()).setTileCache(null);
// now resize the image double hRatio = ((double) height) / ((double) image.getHeight()); double wRatio = ((double) width) / ((double) image.getWidth()); double scale = Math.min(hRatio, wRatio); ParameterBlock pb = new ParameterBlock(); pb.addSource(image).add(scale).add(scale); pb.add(Interpolation.getInstance(Interpolation.INTERP_BICUBIC)); RenderingHints qualityHints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); RenderedOp resizedImage = JAI.create("SubsampleAverage", pb, qualityHints);
// lastly, write the newly-resized image to an // output stream, in a specific encoding pb = new ParameterBlock(); BufferedImage bi = resizedImage.getAsBufferedImage(); pb.addSource(bi); pb.add(os); pb.add("jpeg"); JPEGEncodeParam ep = new JPEGEncodeParam(); ep.setQuality(0.75f); pb.add(ep); JAI.create("encode", pb);
}
}
Any suggestions? I'm baffled.
Thanks
|
|
|
|
|
|
|
Re: [JAI] using JAI to create a thumbnail as a JPEG
Posted:
Jun 6, 2007 6:15 PM
in response to: mlevin
|
|
|
I'm not sure it will work, but maybe let the JPEGCodec automatically create the codec and params for you:
final JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder( os ); final JPEGEncodeParam ep = encoder.getDefaultJPEGEncodeParam( bi );
ep.setQuality( 0.75f , false );
jai-interest wrote: > > I'm trying to use JAI to create a thumbnail of a JPEG and no matter what I > do, I keep getting the following stack trace: > > exception > > javax.servlet.ServletException: All factories fail for the operation > "encode" > > org.apache.struts.action.RequestProcessor.processException(RequestProcessor.java:523) > > org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:421) > > org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:224) > org.apache.struts.action.ActionServlet.process(ActionServlet.java:1194) > org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432) > javax.servlet.http.HttpServlet.service(HttpServlet.java:709) > javax.servlet.http.HttpServlet.service(HttpServlet.java:802) > > root cause > > javax.media.jai.util.ImagingException: All factories fail for the > operation "encode" > > javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1687) > > javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473) > javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332) > javax.media.jai.RenderedOp.createInstance(RenderedOp.java:819) > javax.media.jai.RenderedOp.createRendering(RenderedOp.java:867) > javax.media.jai.RenderedOp.getRendering(RenderedOp.java:888) > javax.media.jai.JAI.createNS(JAI.java:1099) > javax.media.jai.JAI.create(JAI.java:973) > javax.media.jai.JAI.create(JAI.java:1395) > UploadAction.resizeImage(UploadAction.java:111) > UploadAction.execute(UploadAction.java:71) > > org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:419) > > org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:224) > org.apache.struts.action.ActionServlet.process(ActionServlet.java:1194) > org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432) > javax.servlet.http.HttpServlet.service(HttpServlet.java:709) > javax.servlet.http.HttpServlet.service(HttpServlet.java:802) > > root cause > > java.io.IOException: reading encoded JPEG Stream > sun.awt.image.codec.JPEGImageEncoderImpl.writeJPEGStream(Native > Method) > > sun.awt.image.codec.JPEGImageEncoderImpl.encode(JPEGImageEncoderImpl.java:472) > > sun.awt.image.codec.JPEGImageEncoderImpl.encode(JPEGImageEncoderImpl.java:228) > > com.sun.media.jai.codecimpl.JPEGImageEncoder.encode(JPEGImageEncoder.java:277) > com.sun.media.jai.opimage.EncodeRIF.create(EncodeRIF.java:70) > sun.reflect.GeneratedMethodAccessor51.invoke(Unknown Source) > > sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) > java.lang.reflect.Method.invoke(Method.java:585) > javax.media.jai.FactoryCache.invoke(FactoryCache.java:122) > > javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674) > > javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473) > javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332) > javax.media.jai.RenderedOp.createInstance(RenderedOp.java:819) > javax.media.jai.RenderedOp.createRendering(RenderedOp.java:867) > javax.media.jai.RenderedOp.getRendering(RenderedOp.java:888) > javax.media.jai.JAI.createNS(JAI.java:1099) > javax.media.jai.JAI.create(JAI.java:973) > javax.media.jai.JAI.create(JAI.java:1395) > UploadAction.resizeImage(UploadAction.java:111) > UploadAction.execute(UploadAction.java:71) > > org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:419) > > org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:224) > org.apache.struts.action.ActionServlet.process(ActionServlet.java:1194) > org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432) > javax.servlet.http.HttpServlet.service(HttpServlet.java:709) > javax.servlet.http.HttpServlet.service(HttpServlet.java:802) > > The code I'm using is cobbled together from several examples and clearly > I'm not doing something right. Here's what I've got so far: > > import java.awt.RenderingHints; > import java.awt.image.BufferedImage; > import java.awt.image.renderable.ParameterBlock; > import java.io.BufferedInputStream; > import java.io.BufferedOutputStream; > import java.io.ByteArrayInputStream; > import java.io.ByteArrayOutputStream; > import java.io.FileOutputStream; > import java.io.IOException; > import java.io.InputStream; > import java.io.OutputStream; > > import javax.media.jai.Interpolation; > import javax.media.jai.JAI; > import javax.media.jai.OpImage; > import javax.media.jai.RenderedOp; > import javax.servlet.http.HttpServletRequest; > import javax.servlet.http.HttpServletResponse; > > import org.apache.struts.action.Action; > import org.apache.struts.action.ActionForm; > import org.apache.struts.action.ActionForward; > import org.apache.struts.action.ActionMapping; > > import com.sun.media.jai.codec.JPEGEncodeParam; > import com.sun.media.jai.codec.PNGEncodeParam; > import com.sun.media.jai.codec.SeekableStream; > > public class UploadAction extends Action { > > public ActionForward execute(ActionMapping mapping, ActionForm form, > HttpServletRequest request, HttpServletResponse response) throws > IOException { > > String basePath = "C:\\Program Files\\Apache Software Foundation\\Tomcat > 5.5\\webapps\\strutsTest\\"; > > UploadForm upload = (UploadForm) form; > > if (upload.getFile() != null) { > /* > * > * > * > * > * > */ > > // open input stream from uploaded file and copy into byte array > InputStream is = new > BufferedInputStream(upload.getFile().getInputStream()); > ByteArrayOutputStream bos = new ByteArrayOutputStream(); > int bytesRead = 0; > byte[] buffer = new byte[8192]; > while ((bytesRead = is.read(buffer, 0, 8192)) != -1) { > bos.write(buffer, 0, bytesRead); > } > bos.close(); > is.close(); > byte[] image = bos.toByteArray(); > > // write original (unresized) file > OutputStream os = new BufferedOutputStream(new > FileOutputStream(basePath + upload.getFile().getFileName())); > ByteArrayInputStream bis = new ByteArrayInputStream(image); > bytesRead = 0; > buffer = new byte[8192]; > while ((bytesRead = bis.read(buffer, 0, 8192)) != -1) { > os.write(buffer, 0, bytesRead); > } > os.close(); > > // resize image > bis.reset(); > OutputStream osThumb = new BufferedOutputStream(new > FileOutputStream(basePath + "THUMB_" + > upload.getFile().getFileName())); > resizeImage(bis, os, 150, 150); > osThumb.close(); > > // close input stream > bis.close(); > > } > > return mapping.findForward("success"); > > } > > // based on code examples from > http://www.iproving.ca/space/Technologies/Java+Advanced+Imaging, > http://forums.java.net/jive/thread.jspa?messageID=64672 and > http://archives.java.sun.com/cgi-bin/wa?A2=ind0208&L=java-imageio-interest&P=242 > private void resizeImage(InputStream is, OutputStream os, int width, > int height) { > > // read in the original image from an input stream > SeekableStream s = SeekableStream.wrapInputStream(is, true); > RenderedOp image = JAI.create("stream", s); > ((OpImage) image.getRendering()).setTileCache(null); > > // now resize the image > double hRatio = ((double) height) / ((double) image.getHeight()); > double wRatio = ((double) width) / ((double) image.getWidth()); > double scale = Math.min(hRatio, wRatio); > ParameterBlock pb = new ParameterBlock(); > pb.addSource(image).add(scale).add(scale); > pb.add(Interpolation.getInstance(Interpolation.INTERP_BICUBIC)); > RenderingHints qualityHints = new > RenderingHints(RenderingHints.KEY_RENDERING, > RenderingHints.VALUE_RENDER_QUALITY); > RenderedOp resizedImage = JAI.create("SubsampleAverage", pb, > qualityHints); > > // lastly, write the newly-resized image to an > // output stream, in a specific encoding > pb = new ParameterBlock(); > BufferedImage bi = resizedImage.getAsBufferedImage(); > pb.addSource(bi); > pb.add(os); > pb.add("jpeg"); > JPEGEncodeParam ep = new JPEGEncodeParam(); > ep.setQuality(0.75f); > pb.add(ep); > JAI.create("encode", pb); > > } > > } > > Any suggestions? I'm baffled. > > Thanks > [Message sent by forum member 'mlevin' (mlevin)] > > http://forums.java.net/jive/thread.jspa?messageID=215776 > > --------------------------------------------------------------------- > To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net > For additional commands, e-mail: interest-help@jai.dev.java.net > > >
-- View this message in context: http://www.nabble.com/using-JAI-to-create-a-thumbnail-as-a-JPEG-tf3701670.html#a11000310 Sent from the JAI Projects - Interest mailing list archive at Nabble.com.
--------------------------------------------------------------------- To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net For additional commands, e-mail: interest-help@jai.dev.java.net
|
|
|
|
|
|
|
|
Re: [JAI] using JAI to create a thumbnail as a JPEG
Posted:
Jun 9, 2007 10:28 AM
in response to: mlevin
|
|
|
Give it up! I tried and tried to find a way to create a thumbnail using JAI and there seems to be a fundamental flaw with JAI - there doesn't seem to be a way to perform any JAI operations that don't attempt to load the entire image into memory, requiring ridiculous amounts of memory. Every JAI operation that I could think of or could find reference to causes the image to be loaded. On the Sun Java forums for JAI they recommend setting the TileCache memory via TileCache.setMemoryCapacity and TileCach.setMemoryThreshold. all to no avail. So I finally gave up on using JAI to create thumbnails.
I found that the same thing occurs with the Java AWT image classes, which cause the entire image to be loaded in order to even get the image dimension information such as width and height, which you need in order to figure out how to scale or subsample the original image in order to be able to generate a smaller version. As I was researching this, I found some advice in a Sun Java forum and came up with the code below which uses ImageIO to create thumbnails. Using ImageIO you can get the image dimension information without having to render the image in memory. With that information you can subsample the image data, yielding a much smaller rendered image! The code below demonstrates this. I hope this helps someone, it's taken me days to figure this out.
My approach involves using an ImageIO ImageReader to get the dimension information so I can compute how to subsample the source image. I subsample a slightly larger number (25%) of pixels into an intermediate thumbnail image that is slightly larger than the desired thumbnail size so I can use interpolation in order to get a better quality thumbnail image. From the intermediate thumbnail image I render down to the final thumbnail image and store it in a file.
This worked with a 40MB PNG file and a 7MB JPG file. I also tried TIFF but there doesn't seem to be an image reader for TIFF in the 1.4.2 Java that I am working with. I'm assuming there is a way to add TIFF support, but I don't really need to support TIFF.
import java.awt.Frame; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream;
import javax.imageio.ImageIO; import javax.imageio.ImageReadParam; import javax.imageio.ImageReader; import javax.imageio.stream.ImageInputStream;
import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGEncodeParam; import com.sun.image.codec.jpeg.JPEGImageEncoder;
/* * Created on Jun 9, 2007 */
public class TestIIOthumbnails {
private final static String[] knownFormats;
static { knownFormats = ImageIO.getReaderFormatNames(); for ( int x = 0 ; x < knownFormats.length ; x++ ) { knownFormats[x] =]]]] 1.0d ) { thumbnailHeight = (int) ( thumbnailDimension / imageRatio ); } else { thumbnailWidth = (int) ( thumbnailDimension * imageRatio ); }
int longEdge = ( Math.max( imgHeight , imgWidth ) ); int tempThumbnailEdge = (int) ( (float) thumbnailDimension * 1.25f ); int subSample = (int) ( (float) longEdge / (float) tempThumbnailEdge );
final ImageReadParam readParam = imgReader.getDefaultReadParam(); if ( subSample > 1 ) { readParam.setSourceSubsampling( subSample , subSample , 0 , 0 ); }
final BufferedImage tempThumbnailImage = imgReader.read( 0 , readParam );
final BufferedImage thumbnailImage = new BufferedImage( thumbnailWidth , thumbnailHeight , BufferedImage.TYPE_INT_RGB ); final Graphics2D graphics2D = thumbnailImage.createGraphics(); graphics2D .setRenderingHint( RenderingHints.KEY_INTERPOLATION , RenderingHints.VALUE_INTERPOLATION_BILINEAR ); graphics2D.drawImage( tempThumbnailImage , 0 , 0 , thumbnailWidth , thumbnailHeight , frame );
final String thumbnailFileName = getThumbnailFileName( inputFile.getCanonicalPath() ); final File thumbnailFile = new File( thumbnailFileName ); final BufferedOutputStream thumbnailOut = new BufferedOutputStream( ( new FileOutputStream( thumbnailFile ) ) , 4092 ); final JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder( thumbnailOut ); final JPEGEncodeParam encoderParam = encoder.getDefaultJPEGEncodeParam( thumbnailImage ); encoderParam.setQuality( thumbnailQuality , false ); encoder.setJPEGEncodeParam( encoderParam ); encoder.encode( thumbnailImage ); thumbnailOut.close();
// Dispose of AWT components graphics2D.dispose(); frame.dispose();
response = thumbnailFile; } catch( Exception e ) { e.printStackTrace(); } return response; }
private static boolean isKnownFormat( String fileName ) { boolean response = false;
if ( fileName == null || fileName.length() == 0 ) { return response; } int extensionPosition = fileName.lastIndexOf( '.' );
if ( extensionPosition == -1 ) return response;
final String extension = knownAliases( fileName.substring( extensionPosition ).toLowerCase() );
for ( int x = 0 ; x < knownFormats.length ; x++ ) { if ( extension.equals( knownFormats[x] ) ) { return true; } }
return response; }
private static String knownAliases( String fileName ) { final String extension = fileName.substring( fileName.lastIndexOf( '.' ) ).toLowerCase(); if ( extension.equals( ".jpg" ) ) return ".jpeg"; if ( extension.equals( ".jpe" ) ) return ".jpeg"; if ( extension.equals( ".tif" ) ) return ".tiff"; return extension; }
private static String getThumbnailFileName( String attachmentName ) { String result = null; int dotIndex = 0;
//
|
|
|
|
|
|
|
|
Re: [JAI] using JAI to create a thumbnail as a JPEG
Posted:
Jun 9, 2007 8:36 PM
in response to: martinrleon
|
|
|
Did you try the imageread operator in JAI, which wraps around Image I/O?
The problems you cite are not the fault of JAI per se, but of the jpeg reader. If the reader is capable of tiling the image, then JAI will make use of it. Unfortunately the old-style codec-based jpeg reader that is supplied with JAI is incapable of tiling the image on read, thus the problems you saw.
So try "imageread" instead of "fileload" to use the new IIO plugin, and see if that works easier.
-Bob
-----------cut here-----------clip & save-----------valuable coupon-----------
On Jun 9, 2007, at 10:28 AM, martinrleon wrote:
> > Give it up! I tried and tried to find a way to create a thumbnail > using JAI > and there seems to be a fundamental flaw with JAI - there doesn't > seem to be > a way to perform any JAI operations that don't attempt to load the > entire > image into memory, requiring ridiculous amounts of memory. Every JAI > operation that I could think of or could find reference to causes > the image > to be loaded. On the Sun Java forums for JAI they recommend > setting the > TileCache memory via TileCache.setMemoryCapacity and > TileCach.setMemoryThreshold. all to no avail. So I finally gave up > on using > JAI to create thumbnails. > > I found that the same thing occurs with the Java AWT image classes, > which > cause the entire image to be loaded in order to even get the image > dimension > information such as width and height, which you need in order to > figure out > how to scale or subsample the original image in order to be able to > generate > a smaller version. As I was researching this, I found some advice > in a Sun > Java forum and came up with the code below which uses ImageIO to > create > thumbnails. Using ImageIO you can get the image dimension information > without having to render the image in memory. With that > information you can > subsample the image data, yielding a much smaller rendered image! > The code > below demonstrates this. I hope this helps someone, it's taken me > days to > figure this out. > > My approach involves using an ImageIO ImageReader to get the dimension > information so I can compute how to subsample the source image. I > subsample > a slightly larger number (25%) of pixels into an intermediate > thumbnail > image that is slightly larger than the desired thumbnail size so I > can use > interpolation in order to get a better quality thumbnail image. > From the > intermediate thumbnail image I render down to the final thumbnail > image and > store it in a file. > > This worked with a 40MB PNG file and a 7MB JPG file. I also tried > TIFF but > there doesn't seem to be an image reader for TIFF in the 1.4.2 Java > that I > am working with. I'm assuming there is a way to add TIFF support, > but I > don't really need to support TIFF. > > import java.awt.Frame; > import java.awt.Graphics2D; > import java.awt.RenderingHints; > import java.awt.image.BufferedImage; > import java.io.BufferedInputStream; > import java.io.BufferedOutputStream; > import java.io.File; > import java.io.FileInputStream; > import java.io.FileOutputStream; > > import javax.imageio.ImageIO; > import javax.imageio.ImageReadParam; > import javax.imageio.ImageReader; > import javax.imageio.stream.ImageInputStream; > > import com.sun.image.codec.jpeg.JPEGCodec; > import com.sun.image.codec.jpeg.JPEGEncodeParam; > import com.sun.image.codec.jpeg.JPEGImageEncoder; > > /* > * Created on Jun 9, 2007 > */ > > public class TestIIOthumbnails { > > private final static String[] knownFormats; > > static { > knownFormats = ImageIO.getReaderFormatNames(); > for ( int x = 0 ; x < knownFormats.length ; x++ ) { > knownFormats[x] = '.' + knownFormats[x].toLowerCase(); > } > } > > public static void main( String[] args ) { > int thumbnailDimension = 300; > float thumbnailQuality = 0.5f; > > try { > > String[] fileNames = { "PIA03231.JPG" , "PIA03241.JPG" , > "PIA08814.JPG" , "PIA09201.JPG" , "PIA09202.JPG" , > "PIA09203.JPG" , "PIA09205.JPG" , "PIA09207.JPG" , > "PIA09259.JPG" , "large4.png" , "large3.png" , > "large2.png" , "large.png" , "marbles.tif" , > "xing_t24.tif" }; > > for ( int x = 0 ; x < fileNames.length ; x++ ) { > final File inputFile = new File( fileNames[x] ); > if ( !inputFile.exists() ) { > System.out.println( "Unable to locate file: " + > inputFile.getCanonicalPath() ); > continue; > } > > final File thumbnailFile = makeThumbnailFile > ( inputFile , > thumbnailDimension , thumbnailQuality ); > if ( thumbnailFile != null && thumbnailFile.exists > () ) { > System.out.println > ( thumbnailFile.getCanonicalPath() + " > succesfully created" ); > } > else { > System.out.println( "Unable to create thumbnail > for " + > inputFile.getCanonicalPath() ); > } > } > System.out.println( "Done." ); > } > catch( Exception e ) { > CommonLib.logException( e , CommonLib.notOnServer() ); > } > } > > private static File makeThumbnailFile( File inputFile , int > thumbnailDimension , float thumbnailQuality ) { > > File response = null; > > try { > if ( inputFile == null ) { > System.out.println( "Input file is null" ); > return response; > } > if ( !inputFile.exists() ) { > System.out.println( "Input file does not exist: " + > inputFile.getName() ); > return response; > } > if ( !isKnownFormat( inputFile.toString() ) ) { > System.out.println( "Unsupported file format: " + > inputFile.getName() ); > return response; > } > > final Frame frame = new Frame(); > frame.addNotify(); > > final String fileSuffix = knownAliases > ( inputFile.getName() > ).substring( 1 ); > > final ImageReader imgReader = (ImageReader) > ImageIO.getImageReadersBySuffix( fileSuffix ).next(); > > final ImageInputStream bufferedInput = > ImageIO.createImageInputStream( new BufferedInputStream( > new FileInputStream( inputFile ) ) ); > > imgReader.setInput( bufferedInput ); > > int imgHeight = imgReader.getHeight( 0 ); > int imgWidth = imgReader.getWidth( 0 ); > > double imageRatio = (double) imgWidth / (double) > imgHeight; > int thumbnailHeight = thumbnailDimension; > int thumbnailWidth = thumbnailDimension; > > if ( imageRatio > 1.0d ) { > thumbnailHeight = (int) ( thumbnailDimension / > imageRatio ); > } > else { > thumbnailWidth = (int) ( thumbnailDimension * > imageRatio ); > } > > int longEdge = ( Math.max( imgHeight , imgWidth ) ); > int tempThumbnailEdge = (int) ( (float) > thumbnailDimension * > 1.25f ); > int subSample = (int) ( (float) longEdge / (float) > tempThumbnailEdge ); > > final ImageReadParam readParam = > imgReader.getDefaultReadParam(); > if ( subSample > 1 ) { > readParam.setSourceSubsampling( subSample , > subSample , 0 , > 0 ); > } > > final BufferedImage tempThumbnailImage = imgReader.read > ( 0 , > readParam ); > > final BufferedImage thumbnailImage = new BufferedImage( > thumbnailWidth , thumbnailHeight , > BufferedImage.TYPE_INT_RGB ); > final Graphics2D graphics2D = > thumbnailImage.createGraphics(); > graphics2D > .setRenderingHint > ( RenderingHints.KEY_INTERPOLATION , > RenderingHints.VALUE_INTERPOLATION_BILINEAR ); > graphics2D.drawImage( tempThumbnailImage , 0 , 0 , > thumbnailWidth , thumbnailHeight , frame ); > > final String thumbnailFileName = getThumbnailFileName( > inputFile.getCanonicalPath() ); > final File thumbnailFile = new File( thumbnailFileName ); > final BufferedOutputStream thumbnailOut = new > BufferedOutputStream( > ( new FileOutputStream( thumbnailFile ) ) , > 4092 ); > final JPEGImageEncoder encoder = > JPEGCodec.createJPEGEncoder( > thumbnailOut ); > final JPEGEncodeParam encoderParam = > encoder.getDefaultJPEGEncodeParam( thumbnailImage ); > encoderParam.setQuality( thumbnailQuality , false ); > encoder.setJPEGEncodeParam( encoderParam ); > encoder.encode( thumbnailImage ); > thumbnailOut.close(); > > // Dispose of AWT components > graphics2D.dispose(); > frame.dispose(); > > response = thumbnailFile; > } > catch( Exception e ) { > e.printStackTrace(); > } > return response; > } > > private static boolean isKnownFormat( String fileName ) { > boolean response = false; > > if ( fileName == null || fileName.length() == 0 ) { > return response; > } > int extensionPosition = fileName.lastIndexOf( '.' ); > > if ( extensionPosition == -1 ) return response; > > final String extension = knownAliases( fileName.substring( > extensionPosition ).toLowerCase() ); > > for ( int x = 0 ; x < knownFormats.length ; x++ ) { > if ( extension.equals( knownFormats[x] ) ) { > return true; > } > } > > return response; > } > > private static String knownAliases( String fileName ) { > final String extension = fileName.substring > ( fileName.lastIndexOf( > '.' ) ).toLowerCase(); > if ( extension.equals( ".jpg" ) ) return ".jpeg"; > if ( extension.equals( ".jpe" ) ) return ".jpeg"; > if ( extension.equals( ".tif" ) ) return ".tiff"; > return extension; > } > > private static String getThumbnailFileName( String > attachmentName ) { > String result = null; > int dotIndex = 0; > > // Get the position of the . before the extension > dotIndex = attachmentName.lastIndexOf( "." ); > // Get the extension of the current file > final String extension = attachmentName.substring( dotIndex > + 1 ); > // Get the file name without the extension > result = attachmentName.substring( 0 , dotIndex ); > // Build the thumbnail file name > result = result + "_thumb_" + extension + ".jpg"; > > return result; > } > } > > -- > View this message in context: http://www.nabble.com/using-JAI-to- > create-a-thumbnail-as-a-JPEG-tf3701670.html#a11042093 > Sent from the JAI Projects - Interest mailing list archive at > Nabble.com. > > --------------------------------------------------------------------- > To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net > For additional commands, e-mail: interest-help@jai.dev.java.net >
--------------------------------------------------------------------- To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net For additional commands, e-mail: interest-help@jai.dev.java.net
|
|
|
|
|
|
|
|
Re: [JAI] using JAI to create a thumbnail as a JPEG
Posted:
Jun 10, 2007 2:11 AM
in response to: Bob Deen
|
|
|
Thanks for your response.
I can't find any documentation for the "imageread" operator. Is it bundled with the standard 1.4 SE distribution or is it something I have to add? If so, how do I add the ImageIO plugin to my JAI configuration and where can I find documentation for it?
Thanks again for your response, I was incredulous about a newer API (JAI) not being able to do what an older one could do (ImageIO) - I figured they didn't want to make the effort when another API could already provide the functionality.
Bob Deen wrote: > > Did you try the imageread operator in JAI, which wraps around Image I/O? > > The problems you cite are not the fault of JAI per se, but of the jpeg > reader. If the reader is capable of tiling the image, then JAI will > make > use of it. Unfortunately the old-style codec-based jpeg reader that > is supplied with JAI is incapable of tiling the image on read, thus the > problems you saw. > > So try "imageread" instead of "fileload" to use the new IIO plugin, and > see if that works easier. > > -Bob > > -----------cut here-----------clip & save-----------valuable > coupon----------- > > On Jun 9, 2007, at 10:28 AM, martinrleon wrote: > >> >> Give it up! I tried and tried to find a way to create a thumbnail >> using JAI >> and there seems to be a fundamental flaw with JAI - there doesn't >> seem to be >> a way to perform any JAI operations that don't attempt to load the >> entire >> image into memory, requiring ridiculous amounts of memory. Every JAI >> operation that I could think of or could find reference to causes >> the image >> to be loaded. On the Sun Java forums for JAI they recommend >> setting the >> TileCache memory via TileCache.setMemoryCapacity and >> TileCach.setMemoryThreshold. all to no avail. So I finally gave up >> on using >> JAI to create thumbnails. >> >> I found that the same thing occurs with the Java AWT image classes, >> which >> cause the entire image to be loaded in order to even get the image >> dimension >> information such as width and height, which you need in order to >> figure out >> how to scale or subsample the original image in order to be able to >> generate >> a smaller version. As I was researching this, I found some advice >> in a Sun >> Java forum and came up with the code below which uses ImageIO to >> create >> thumbnails. Using ImageIO you can get the image dimension information >> without having to render the image in memory. With that >> information you can >> subsample the image data, yielding a much smaller rendered image! >> The code >> below demonstrates this. I hope this helps someone, it's taken me >> days to >> figure this out. >> >> My approach involves using an ImageIO ImageReader to get the dimension >> information so I can compute how to subsample the source image. I >> subsample >> a slightly larger number (25%) of pixels into an intermediate >> thumbnail >> image that is slightly larger than the desired thumbnail size so I >> can use >> interpolation in order to get a better quality thumbnail image. >> From the >> intermediate thumbnail image I render down to the final thumbnail >> image and >> store it in a file. >> >> This worked with a 40MB PNG file and a 7MB JPG file. I also tried >> TIFF but >> there doesn't seem to be an image reader for TIFF in the 1.4.2 Java >> that I >> am working with. I'm assuming there is a way to add TIFF support, >> but I >> don't really need to support TIFF. >> >> import java.awt.Frame; >> import java.awt.Graphics2D; >> import java.awt.RenderingHints; >> import java.awt.image.BufferedImage; >> import java.io.BufferedInputStream; >> import java.io.BufferedOutputStream; >> import java.io.File; >> import java.io.FileInputStream; >> import java.io.FileOutputStream; >> >> import javax.imageio.ImageIO; >> import javax.imageio.ImageReadParam; >> import javax.imageio.ImageReader; >> import javax.imageio.stream.ImageInputStream; >> >> import com.sun.image.codec.jpeg.JPEGCodec; >> import com.sun.image.codec.jpeg.JPEGEncodeParam; >> import com.sun.image.codec.jpeg.JPEGImageEncoder; >> >> /* >> * Created on Jun 9, 2007 >> */ >> >> public class TestIIOthumbnails { >> >> private final static String[] knownFormats; >> >> static { >> knownFormats = ImageIO.getReaderFormatNames(); >> for ( int x = 0 ; x < knownFormats.length ; x++ ) { >> knownFormats[x] = '.' + knownFormats[x].toLowerCase(); >> } >> } >> >> public static void main( String[] args ) { >> int thumbnailDimension = 300; >> float thumbnailQuality = 0.5f; >> >> try { >> >> String[] fileNames = { "PIA03231.JPG" , "PIA03241.JPG" , >> "PIA08814.JPG" , "PIA09201.JPG" , "PIA09202.JPG" , >> "PIA09203.JPG" , "PIA09205.JPG" , "PIA09207.JPG" , >> "PIA09259.JPG" , "large4.png" , "large3.png" , >> "large2.png" , "large.png" , "marbles.tif" , >> "xing_t24.tif" }; >> >> for ( int x = 0 ; x < fileNames.length ; x++ ) { >> final File inputFile = new File( fileNames[x] ); >> if ( !inputFile.exists() ) { >> System.out.println( "Unable to locate file: " + >> inputFile.getCanonicalPath() ); >> continue; >> } >> >> final File thumbnailFile = makeThumbnailFile >> ( inputFile , >> thumbnailDimension , thumbnailQuality ); >> if ( thumbnailFile != null && thumbnailFile.exists >> () ) { >> System.out.println >> ( thumbnailFile.getCanonicalPath() + " >> succesfully created" ); >> } >> else { >> System.out.println( "Unable to create thumbnail >> for " + >> inputFile.getCanonicalPath() ); >> } >> } >> System.out.println( "Done." ); >> } >> catch( Exception e ) { >> CommonLib.logException( e , CommonLib.notOnServer() ); >> } >> } >> >> private static File makeThumbnailFile( File inputFile , int >> thumbnailDimension , float thumbnailQuality ) { >> >> File response = null; >> >> try { >> if ( inputFile == null ) { >> System.out.println( "Input file is null" ); >> return response; >> } >> if ( !inputFile.exists() ) { >> System.out.println( "Input file does not exist: " + >> inputFile.getName() ); >> return response; >> } >> if ( !isKnownFormat( inputFile.toString() ) ) { >> System.out.println( "Unsupported file format: " + >> inputFile.getName() ); >> return response; >> } >> >> final Frame frame = new Frame(); >> frame.addNotify(); >> >> final String fileSuffix = knownAliases >> ( inputFile.getName() >> ).substring( 1 ); >> >> final ImageReader imgReader = (ImageReader) >> ImageIO.getImageReadersBySuffix( fileSuffix ).next(); >> >> final ImageInputStream bufferedInput = >> ImageIO.createImageInputStream( new BufferedInputStream( >> new FileInputStream( inputFile ) ) ); >> >> imgReader.setInput( bufferedInput ); >> >> int imgHeight = imgReader.getHeight( 0 ); >> int imgWidth = imgReader.getWidth( 0 ); >> >> double imageRatio = (double) imgWidth / (double) >> imgHeight; >> int thumbnailHeight = thumbnailDimension; >> int thumbnailWidth = thumbnailDimension; >> >> if ( imageRatio > 1.0d ) { >> thumbnailHeight = (int) ( thumbnailDimension / >> imageRatio ); >> } >> else { >> thumbnailWidth = (int) ( thumbnailDimension * >> imageRatio ); >> } >> >> int longEdge = ( Math.max( imgHeight , imgWidth ) ); >> int tempThumbnailEdge = (int) ( (float) >> thumbnailDimension * >> 1.25f ); >> int subSample = (int) ( (float) longEdge / (float) >> tempThumbnailEdge ); >> >> final ImageReadParam readParam = >> imgReader.getDefaultReadParam(); >> if ( subSample > 1 ) { >> readParam.setSourceSubsampling( subSample , >> subSample , 0 , >> 0 ); >> } >> >> final BufferedImage tempThumbnailImage = imgReader.read >> ( 0 , >> readParam ); >> >> final BufferedImage thumbnailImage = new BufferedImage( >> thumbnailWidth , thumbnailHeight , >> BufferedImage.TYPE_INT_RGB ); >> final Graphics2D graphics2D = >> thumbnailImage.createGraphics(); >> graphics2D >> .setRenderingHint >> ( RenderingHints.KEY_INTERPOLATION , >> RenderingHints.VALUE_INTERPOLATION_BILINEAR ); >> graphics2D.drawImage( tempThumbnailImage , 0 , 0 , >> thumbnailWidth , thumbnailHeight , frame ); >> >> final String thumbnailFileName = getThumbnailFileName( >> inputFile.getCanonicalPath() ); >> final File thumbnailFile = new File( thumbnailFileName ); >> final BufferedOutputStream thumbnailOut = new >> BufferedOutputStream( >> ( new FileOutputStream( thumbnailFile ) ) , >> 4092 ); >> final JPEGImageEncoder encoder = >> JPEGCodec.createJPEGEncoder( >> thumbnailOut ); >> final JPEGEncodeParam encoderParam = >> encoder.getDefaultJPEGEncodeParam( thumbnailImage ); >> encoderParam.setQuality( thumbnailQuality , false ); >> encoder.setJPEGEncodeParam( encoderParam ); >> encoder.encode( thumbnailImage ); >> thumbnailOut.close(); >> >> // Dispose of AWT components >> graphics2D.dispose(); >> frame.dispose(); >> >> response = thumbnailFile; >> } >> catch( Exception e ) { >> e.printStackTrace(); >> } >> return response; >> } >> >> private static boolean isKnownFormat( String fileName ) { >> boolean response = false; >> >> if ( fileName == null || fileName.length() == 0 ) { >> return response; >> } >> int extensionPosition = fileName.lastIndexOf( '.' ); >> >> if ( extensionPosition == -1 ) return response; >> >> final String extension = knownAliases( fileName.substring( >> extensionPosition ).toLowerCase() ); >> >> for ( int x = 0 ; x < knownFormats.length ; x++ ) { >> if ( extension.equals( knownFormats[x] ) ) { >> return true; >> } >> } >> >> return response; >> } >> >> private static String knownAliases( String fileName ) { >> final String extension = fileName.substring >> ( fileName.lastIndexOf( >> '.' ) ).toLowerCase(); >> if ( extension.equals( ".jpg" ) ) return ".jpeg"; >> if ( extension.equals( ".jpe" ) ) return ".jpeg"; >> if ( extension.equals( ".tif" ) ) return ".tiff"; >> return extension; >> } >> >> private static String getThumbnailFileName( String >> attachmentName ) { >> String result = null; >> int dotIndex = 0; >> >> // Get the position of the . before the extension >> dotIndex = attachmentName.lastIndexOf( "." ); >> // Get the extension of the current file >> final String extension = attachmentName.substring( dotIndex >> + 1 ); >> // Get the file name without the extension >> result = attachmentName.substring( 0 , dotIndex ); >> // Build the thumbnail file name >> result = result + "_thumb_" + extension + ".jpg"; >> >> return result; >> } >> } >> >> -- >> View this message in context: http://www.nabble.com/using-JAI-to- >> create-a-thumbnail-as-a-JPEG-tf3701670.html#a11042093 >> Sent from the JAI Projects - Interest mailing list archive at >> Nabble.com. >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net >> For additional commands, e-mail: interest-help@jai.dev.java.net >> > > --------------------------------------------------------------------- > To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net > For additional commands, e-mail: interest-help@jai.dev.java.net > > >
-- View this message in context: http://www.nabble.com/using-JAI-to-create-a-thumbnail-as-a-JPEG-tf3701670.html#a11046982 Sent from the JAI Projects - Interest mailing list archive at Nabble.com.
--------------------------------------------------------------------- To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net For additional commands, e-mail: interest-help@jai.dev.java.net
|
|
|
|
|
|
|
|
RE: [JAI] using JAI to create a thumbnail as a JPEG
Posted:
Jun 11, 2007 6:00 AM
in response to: martinrleon
|
|
|
the "imageread" operator is a way to use a JAI operator to wrap the functionality of the ImageIO API. It is included in the JAI ImageIO tools package (http://jai-imageio.dev.java.net).
JAI is not strictly a "newer" API than ImageIO, in fact JAI was around before ImageIO was a part of the J2SE distribution (1.4). JAI is really an image processing framework, whereas ImageIO is for reading and writing images. You can read an image with ImageIO, process it with JAI, and write it again with ImageIO.
Now the JAI ImageIO Tools libraries are perhaps newer than ImageIO. These are a set of plugins to provide the functionality that is also provided in the JAI codecs, but accessible through the standard ImageIO API. Check the link above for more info; it might be that the JPEG reader in the JAI ImageIO Tools bundle works better for what you want. However, it might also not be the case.
The bottom line is if you are reading a large image to generate a thumbnail of it, and the reader is incapable of reading the image in manageable chunks, then you will run into the memory problems you encountered. At that point, you may need to find a new image reader.
Mike
> -----Original Message----- > From: martinrleon [mailto:martinrleon@yahoo.com] > Sent: Sunday, June 10, 2007 5:11 AM > To: interest@jai.dev.java.net > Subject: Re: [JAI] using JAI to create a thumbnail as a JPEG > > > Thanks for your response. > > I can't find any documentation for the "imageread" operator. > Is it bundled with the standard 1.4 SE distribution or is it > something I have to add? If so, how do I add the ImageIO > plugin to my JAI configuration and where can I find > documentation for it? > > Thanks again for your response, I was incredulous about a > newer API (JAI) not being able to do what an older one could > do (ImageIO) - I figured they didn't want to make the effort > when another API could already provide the functionality. > > > Bob Deen wrote: > > > > Did you try the imageread operator in JAI, which wraps > around Image I/O? > > > > The problems you cite are not the fault of JAI per se, but > of the jpeg > > reader. If the reader is capable of tiling the image, then > JAI will > > make use of it. Unfortunately the old-style codec-based > jpeg reader > > that is supplied with JAI is incapable of tiling the image on read, > > thus the problems you saw. > > > > So try "imageread" instead of "fileload" to use the new IIO plugin, > > and see if that works easier. > > > > -Bob > > > > -----------cut here-----------clip & save-----------valuable > > coupon----------- > > > > On Jun 9, 2007, at 10:28 AM, martinrleon wrote: > > > >> > >> Give it up! I tried and tried to find a way to create a thumbnail > >> using JAI and there seems to be a fundamental flaw with > JAI - there > >> doesn't seem to be a way to perform any JAI operations that don't > >> attempt to load the entire image into memory, requiring ridiculous > >> amounts of memory. Every JAI operation that I could think of or > >> could find reference to causes the image to be loaded. On the Sun > >> Java forums for JAI they recommend setting the TileCache > memory via > >> TileCache.setMemoryCapacity and > TileCach.setMemoryThreshold. all to > >> no avail. So I finally gave up on using JAI to create thumbnails. > >> > >> I found that the same thing occurs with the Java AWT image > classes, > >> which cause the entire image to be loaded in order to even get the > >> image dimension information such as width and height, > which you need > >> in order to figure out how to scale or subsample the > original image > >> in order to be able to generate a smaller version. As I was > >> researching this, I found some advice in a Sun Java forum > and came up > >> with the code below which uses ImageIO to create > thumbnails. Using > >> ImageIO you can get the image dimension information > without having to > >> render the image in memory. With that information you can > >> subsample the image data, yielding a much smaller rendered > image! > >> The code > >> below demonstrates this. I hope this helps someone, it's taken me > >> days to figure this out. > >> > >> My approach involves using an ImageIO ImageReader to get the > >> dimension information so I can compute how to subsample the source > >> image. I subsample a slightly larger number (25%) of > pixels into an > >> intermediate thumbnail image that is slightly larger than > the desired > >> thumbnail size so I can use > >> interpolation in order to get a better quality thumbnail image. > >> From the > >> intermediate thumbnail image I render down to the final thumbnail > >> image and store it in a file. > >> > >> This worked with a 40MB PNG file and a 7MB JPG file. I also tried > >> TIFF but there doesn't seem to be an image reader for TIFF in the > >> 1.4.2 Java that I am working with. I'm assuming there is a way to > >> add TIFF support, but I don't really need to support TIFF. > >> > >> import java.awt.Frame; > >> import java.awt.Graphics2D; > >> import java.awt.RenderingHints; > >> import java.awt.image.BufferedImage; > >> import java.io.BufferedInputStream; > >> import java.io.BufferedOutputStream; > >> import java.io.File; > >> import java.io.FileInputStream; > >> import java.io.FileOutputStream; > >> > >> import javax.imageio.ImageIO; > >> import javax.imageio.ImageReadParam; > >> import javax.imageio.ImageReader; > >> import javax.imageio.stream.ImageInputStream; > >> > >> import com.sun.image.codec.jpeg.JPEGCodec; > >> import com.sun.image.codec.jpeg.JPEGEncodeParam; > >> import com.sun.image.codec.jpeg.JPEGImageEncoder; > >> > >> /* > >> * Created on Jun 9, 2007 > >> */ > >> > >> public class TestIIOthumbnails { > >> > >> private final static String[] knownFormats; > >> > >> static { > >> knownFormats = ImageIO.getReaderFormatNames(); > >> for ( int x = 0 ; x < knownFormats.length ; x++ ) { > >> knownFormats[x] = '.' + knownFormats[x].toLowerCase(); > >> } > >> } > >> > >> public static void main( String[] args ) { > >> int thumbnailDimension = 300; > >> float thumbnailQuality = 0.5f; > >> > >> try { > >> > >> String[] fileNames = { "PIA03231.JPG" , > "PIA03241.JPG" , > >> "PIA08814.JPG" , "PIA09201.JPG" , "PIA09202.JPG" , > >> "PIA09203.JPG" , "PIA09205.JPG" , > "PIA09207.JPG" > >> , "PIA09259.JPG" , "large4.png" , "large3.png" , > >> "large2.png" , "large.png" , "marbles.tif" , > >> "xing_t24.tif" }; > >> > >> for ( int x = 0 ; x < fileNames.length ; x++ ) { > >> final File inputFile = new File( fileNames[x] ); > >> if ( !inputFile.exists() ) { > >> System.out.println( "Unable to locate file: " + > >> inputFile.getCanonicalPath() ); > >> continue; > >> } > >> > >> final File thumbnailFile = makeThumbnailFile ( > >> inputFile , thumbnailDimension , thumbnailQuality ); > >> if ( thumbnailFile != null && thumbnailFile.exists > >> () ) { > >> System.out.println ( > >> thumbnailFile.getCanonicalPath() + " > >> succesfully created" ); > >> } > >> else { > >> System.out.println( "Unable to create > thumbnail > >> for " + > >> inputFile.getCanonicalPath() ); > >> } > >> } > >> System.out.println( "Done." ); > >> } > >> catch( Exception e ) { > >> CommonLib.logException( e , CommonLib.notOnServer() ); > >> } > >> } > >> > >> private static File makeThumbnailFile( File inputFile , int > >> thumbnailDimension , float thumbnailQuality ) { > >> > >> File response = null; > >> > >> try { > >> if ( inputFile == null ) { > >> System.out.println( "Input file is null" ); > >> return response; > >> } > >> if ( !inputFile.exists() ) { > >> System.out.println( "Input file does not exist: " + > >> inputFile.getName() ); > >> return response; > >> } > >> if ( !isKnownFormat( inputFile.toString() ) ) { > >> System.out.println( "Unsupported file format: " + > >> inputFile.getName() ); > >> return response; > >> } > >> > >> final Frame frame = new Frame(); > >> frame.addNotify(); > >> > >> final String fileSuffix = knownAliases ( > >> inputFile.getName() ).substring( 1 ); > >> > >> final ImageReader imgReader = (ImageReader) > >> ImageIO.getImageReadersBySuffix( fileSuffix ).next(); > >> > >> final ImageInputStream bufferedInput = > >> ImageIO.createImageInputStream( new BufferedInputStream( > >> new FileInputStream( inputFile ) ) ); > >> > >> imgReader.setInput( bufferedInput ); > >> > >> int imgHeight = imgReader.getHeight( 0 ); > >> int imgWidth = imgReader.getWidth( 0 ); > >> > >> double imageRatio = (double) imgWidth / (double) > >> imgHeight; > >> int thumbnailHeight = thumbnailDimension; > >> int thumbnailWidth = thumbnailDimension; > >> > >> if ( imageRatio > 1.0d ) { > >> thumbnailHeight = (int) ( thumbnailDimension / > >> imageRatio ); > >> } > >> else { > >> thumbnailWidth = (int) ( thumbnailDimension * > >> imageRatio ); > >> } > >> > >> int longEdge = ( Math.max( imgHeight , imgWidth ) ); > >> int tempThumbnailEdge = (int) ( (float) > >> thumbnailDimension * 1.25f ); > >> int subSample = (int) ( (float) longEdge / (float) > >> tempThumbnailEdge ); > >> > >> final ImageReadParam readParam = > >> imgReader.getDefaultReadParam(); > >> if ( subSample > 1 ) { > >> readParam.setSourceSubsampling( subSample > , subSample > >> , 0 , 0 ); > >> } > >> > >> final BufferedImage tempThumbnailImage = > imgReader.read ( > >> 0 , readParam ); > >> > >> final BufferedImage thumbnailImage = new > BufferedImage( > >> thumbnailWidth , thumbnailHeight , > >> BufferedImage.TYPE_INT_RGB ); > >> final Graphics2D graphics2D = > >> thumbnailImage.createGraphics(); > >> graphics2D > >> .setRenderingHint ( > >> RenderingHints.KEY_INTERPOLATION , > >> RenderingHints.VALUE_INTERPOLATION_BILINEAR ); > >> graphics2D.drawImage( tempThumbnailImage , 0 , 0 , > >> thumbnailWidth , thumbnailHeight , frame ); > >> > >> final String thumbnailFileName = getThumbnailFileName( > >> inputFile.getCanonicalPath() ); > >> final File thumbnailFile = new File( > thumbnailFileName ); > >> final BufferedOutputStream thumbnailOut = new > >> BufferedOutputStream( > >> ( new FileOutputStream( thumbnailFile ) ) , > >> 4092 ); > >> final JPEGImageEncoder encoder = > >> JPEGCodec.createJPEGEncoder( thumbnailOut ); > >> final JPEGEncodeParam encoderParam = > >> encoder.getDefaultJPEGEncodeParam( thumbnailImage ); > >> encoderParam.setQuality( thumbnailQuality , false ); > >> encoder.setJPEGEncodeParam( encoderParam ); > >> encoder.encode( thumbnailImage ); > >> thumbnailOut.close(); > >> > >> // Dispose of AWT components > >> graphics2D.dispose(); > >> frame.dispose(); > >> > >> response = thumbnailFile; > >> } > >> catch( Exception e ) { > >> e.printStackTrace(); > >> } > >> return response; > >> } > >> > >> private static boolean isKnownFormat( String fileName ) { > >> boolean response = false; > >> > >> if ( fileName == null || fileName.length() == 0 ) { > >> return response; > >> } > >> int extensionPosition = fileName.lastIndexOf( '.' ); > >> > >> if ( extensionPosition == -1 ) return response; > >> > >> final String extension = knownAliases( fileName.substring( > >> extensionPosition ).toLowerCase() ); > >> > >> for ( int x = 0 ; x < knownFormats.length ; x++ ) { > >> if ( extension.equals( knownFormats[x] ) ) { > >> return true; > >> } > >> } > >> > >> return response; > >> } > >> > >> private static String knownAliases( String fileName ) { > >> final String extension = fileName.substring ( > >> fileName.lastIndexOf( '.' ) ).toLowerCase(); > >> if ( extension.equals( ".jpg" ) ) return ".jpeg"; > >> if ( extension.equals( ".jpe" ) ) return ".jpeg"; > >> if ( extension.equals( ".tif" ) ) return ".tiff"; > >> return extension; > >> } > >> > >> private static String getThumbnailFileName( String > attachmentName > >> ) { > >> String result = null; > >> int dotIndex = 0; > >> > >> // Get the position of the . before the extension > >> dotIndex = attachmentName.lastIndexOf( "." ); > >> // Get the extension of the current file > >> final String extension = attachmentName.substring( dotIndex > >> + 1 ); > >> // Get the file name without the extension > >> result = attachmentName.substring( 0 , dotIndex ); > >> // Build the thumbnail file name > >> result = result + "_thumb_" + extension + ".jpg"; > >> > >> return result; > >> } > >> } > >> > >> -- > >> View this message in context: http://www.nabble.com/using-JAI-to- > >> create-a-thumbnail-as-a-JPEG-tf3701670.html#a11042093 > >> Sent from the JAI Projects - Interest mailing list archive at > >> Nabble.com. > >> > >> > --------------------------------------------------------------------- > >> To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net > >> For additional commands, e-mail: interest-help@jai.dev.java.net > >> > > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net > > For additional commands, e-mail: interest-help@jai.dev.java.net > > > > > > > > -- > View this message in context: > http://www.nabble.com/using-JAI-to-create-a-thumbnail-as-a-JPE > G-tf3701670.html#a11046982 > Sent from the JAI Projects - Interest mailing list archive at > Nabble.com. > > --------------------------------------------------------------------- > To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net > For additional commands, e-mail: interest-help@jai.dev.java.net > >
--------------------------------------------------------------------- To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net For additional commands, e-mail: interest-help@jai.dev.java.net
|
|
|
|
|
|
|
|
Re: RE: [JAI] using JAI to create a thumbnail as a JPEG
Posted:
Jun 11, 2007 6:24 AM
in response to: Nidel, Mike
|
|
|
Try using the ImageIO reader sub sampling feature. This instructs the readers to only read every x pixels horzontally or y pixels vertically. For making thumbnails this would seem the obvious answer. If you set the x and y subsampling to 2 then the returned image will be half-size in each dimension (so 1/4 of the memory). This is done during the decode, it is not a scaling operation done afterwards so it should reduce the memory requirements a lot. You can set the subsampling in the ImageReadParam for the decoder.
|
|
|
|
|
|
|
|
Re: RE: [JAI] using JAI to create a thumbnail as a JPEG
Posted:
Jun 11, 2007 5:41 PM
in response to: fred34
|
|
|
If the JAI Image I/O Tools JPEG reader is bsing used this won't help. Per the javadoc with respect to JPEG and PNG:
"All subsampling and sub-banding is performed in memory, however, so if either is required, use of the core JPEG plug-in might be preferable."
On Mon, 11 Jun 2007, jai-interest@javadesktop.org wrote:
> Try using the ImageIO reader sub sampling feature. This instructs the readers to only read every x pixels horzontally or y pixels vertically. For making thumbnails this would seem the obvious answer. If you set the x and y subsampling to 2 then the returned image will be half-size in each dimension (so 1/4 of the memory). This is done during the decode, it is not a scaling operation done afterwards so it should reduce the memory requirements a lot. You can set the subsampling in the ImageReadParam for the decoder. > [Message sent by forum member 'fred34' (fred34)] > > http://forums.java.net/jive/thread.jspa?messageID=221478 > > --------------------------------------------------------------------- > To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net > For additional commands, e-mail: interest-help@jai.dev.java.net > >
---------------- Brian Burkhalter Java Media, Imaging, and Graphics Sun Microsystems, Inc.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This email message is for the sole use of the intended recipient(s) and may contain confidential and privileged information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--------------------------------------------------------------------- To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net For additional commands, e-mail: interest-help@jai.dev.java.net
|
|
|
|
|
|
|
|
[JAI] RE: using JAI to create a thumbnail as a JPEG
Posted:
Jun 11, 2007 7:15 PM
in response to: Nidel, Mike
|
|
|
Mike,
Thank you for the clarification and the URL.
I was able to accomplish what I needed to by using the ImageReader class in ImageIO but was curious whether JAI could do it, I guess not without relying on ImageIO.
Thanks to your URL reference I have a choice of going with JAI and adding support for additional file formats. I really appreciate that.
Martin
Nidel, Mike wrote: > > the "imageread" operator is a way to use a JAI operator to wrap > the functionality of the ImageIO API. It is included in the JAI > ImageIO tools package (http://jai-imageio.dev.java.net). > > JAI is not strictly a "newer" API than ImageIO, in fact JAI was > around before ImageIO was a part of the J2SE distribution (1.4). > JAI is really an image processing framework, whereas ImageIO is > for reading and writing images. You can read an image with ImageIO, > process it with JAI, and write it again with ImageIO. > > Now the JAI ImageIO Tools libraries are perhaps newer than ImageIO. > These are a set of plugins to provide the functionality that is > also provided in the JAI codecs, but accessible through the standard > ImageIO API. Check the link above for more info; it might be that > the JPEG reader in the JAI ImageIO Tools bundle works better for what > you want. However, it might also not be the case. > > The bottom line is if you are reading a large image to generate > a thumbnail of it, and the reader is incapable of reading the image > in manageable chunks, then you will run into the memory problems > you encountered. At that point, you may need to find a new image > reader. > > Mike > >
-- View this message in context: http://www.nabble.com/using-JAI-to-create-a-thumbnail-as-a-JPEG-tf3701670.html#a11071881 Sent from the JAI Projects - Interest mailing list archive at Nabble.com.
--------------------------------------------------------------------- To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net For additional commands, e-mail: interest-help@jai.dev.java.net
|
|
|
|
|
|
|
|
Re: [JAI] RE: using JAI to create a thumbnail as a JPEG
Posted:
Jun 11, 2007 9:19 PM
in response to: martinrleon
|
|
|
The codecs in JAI were provided as a convenience to users and were never a formal API. JAI is an API for image processing. Image I/O is an API for just that. JAI Image I/O Tools provides support for formats not handled by Java SE Image I/O.
Brian
On Mon, 11 Jun 2007, martinrleon wrote:
> > Mike, > > Thank you for the clarification and the URL. > > I was able to accomplish what I needed to by using the ImageReader class in > ImageIO but was curious whether JAI could do it, I guess not without relying > on ImageIO. > > Thanks to your URL reference I have a choice of going with JAI and adding > support for additional file formats. I really appreciate that. > > Martin > > > Nidel, Mike wrote: >> >> the "imageread" operator is a way to use a JAI operator to wrap >> the functionality of the ImageIO API. It is included in the JAI >> ImageIO tools package (http://jai-imageio.dev.java.net). >> >> JAI is not strictly a "newer" API than ImageIO, in fact JAI was >> around before ImageIO was a part of the J2SE distribution (1.4). >> JAI is really an image processing framework, whereas ImageIO is >> for reading and writing images. You can read an image with ImageIO, >> process it with JAI, and write it again with ImageIO. >> >> Now the JAI ImageIO Tools libraries are perhaps newer than ImageIO. >> These are a set of plugins to provide the functionality that is >> also provided in the JAI codecs, but accessible through the standard >> ImageIO API. Check the link above for more info; it might be that >> the JPEG reader in the JAI ImageIO Tools bundle works better for what >> you want. However, it might also not be the case. >> >> The bottom line is if you are reading a large image to generate >> a thumbnail of it, and the reader is incapable of reading the image >> in manageable chunks, then you will run into the memory problems >> you encountered. At that point, you may need to find a new image >> reader. >> >> Mike >> >> > > -- > View this message in context: http://www.nabble.com/using-JAI-to-create-a-thumbnail-as-a-JPEG-tf3701670.html#a11071881 > Sent from the JAI Projects - Interest mailing list archive at Nabble.com. > > --------------------------------------------------------------------- > To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net > For additional commands, e-mail: interest-help@jai.dev.java.net > >
---------------- Brian Burkhalter Java Media, Imaging, and Graphics Sun Microsystems, Inc.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This email message is for the sole use of the intended recipient(s) and may contain confidential and privileged information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--------------------------------------------------------------------- To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net For additional commands, e-mail: interest-help@jai.dev.java.net
|
|
|
|
|
|
|
|
Re: [JAI] using JAI to create a thumbnail as a JPEG
Posted:
Jun 11, 2007 5:46 PM
in response to: martinrleon
|
|
|
As Mike pointed out the JAI operations have nothing to do with this. Operations use whatever layout you happen to have and if the decoder or reader can only return an untiled image then that is what is used.
Note also that subsampling will give a lousy result if the image has any significant high frequency content as the subsampling will induce aliasing. In terms of quality what seems to produce the best result is SubsampleAverage. But as mentioned if the source image can only be decoded monolithically then you have to have the memory to handle it.
On Sat, 9 Jun 2007, martinrleon wrote:
> Give it up! I tried and tried to find a way to create a thumbnail using JAI > and there seems to be a fundamental flaw with JAI - there doesn't seem to be > a way to perform any JAI operations that don't attempt to load the entire > image into memory, requiring ridiculous amounts of memory. Every JAI > operation that I could think of or could find reference to causes the image > to be loaded. On the Sun Java forums for JAI they recommend setting the > TileCache memory via TileCache.setMemoryCapacity and > TileCach.setMemoryThreshold. all to no avail. So I finally gave up on using > JAI to create thumbnails. > > I found that the same thing occurs with the Java AWT image classes, which > cause the entire image to be loaded in order to even get the image dimension > information such as width and height, which you need in order to figure out > how to scale or subsample the original image in order to be able to generate > a smaller version. As I was researching this, I found some advice in a Sun > Java forum and came up with the code below which uses ImageIO to create > thumbnails. Using ImageIO you can get the image dimension information > without having to render the image in memory. With that information you can > subsample the image data, yielding a much smaller rendered image! The code > below demonstrates this. I hope this helps someone, it's taken me days to > figure this out. > > My approach involves using an ImageIO ImageReader to get the dimension > information so I can compute how to subsample the source image. I subsample > a slightly larger number (25%) of pixels into an intermediate thumbnail > image that is slightly larger than the desired thumbnail size so I can use > interpolation in order to get a better quality thumbnail image. From the > intermediate thumbnail image I render down to the final thumbnail image and > store it in a file. > > This worked with a 40MB PNG file and a 7MB JPG file. I also tried TIFF but > there doesn't seem to be an image reader for TIFF in the 1.4.2 Java that I > am working with. I'm assuming there is a way to add TIFF support, but I > don't really need to support TIFF. > > import java.awt.Frame; > import java.awt.Graphics2D; > import java.awt.RenderingHints; > import java.awt.image.BufferedImage; > import java.io.BufferedInputStream; > import java.io.BufferedOutputStream; > import java.io.File; > import java.io.FileInputStream; > import java.io.FileOutputStream; > > import javax.imageio.ImageIO; > import javax.imageio.ImageReadParam; > import javax.imageio.ImageReader; > import javax.imageio.stream.ImageInputStream; > > import com.sun.image.codec.jpeg.JPEGCodec; > import com.sun.image.codec.jpeg.JPEGEncodeParam; > import com.sun.image.codec.jpeg.JPEGImageEncoder; > > /* > * Created on Jun 9, 2007 > */ > > public class TestIIOthumbnails { > > private final static String[] knownFormats; > > static { > knownFormats = ImageIO.getReaderFormatNames(); > for ( int x = 0 ; x < knownFormats.length ; x++ ) { > knownFormats[x] = '.' + knownFormats[x].toLowerCase(); > } > } > > public static void main( String[] args ) { > int thumbnailDimension = 300; > float thumbnailQuality = 0.5f; > > try { > > String[] fileNames = { "PIA03231.JPG" , "PIA03241.JPG" , > "PIA08814.JPG" , "PIA09201.JPG" , "PIA09202.JPG" , > "PIA09203.JPG" , "PIA09205.JPG" , "PIA09207.JPG" , > "PIA09259.JPG" , "large4.png" , "large3.png" , > "large2.png" , "large.png" , "marbles.tif" , > "xing_t24.tif" }; > > for ( int x = 0 ; x < fileNames.length ; x++ ) { > final File inputFile = new File( fileNames[x] ); > if ( !inputFile.exists() ) { > System.out.println( "Unable to locate file: " + > inputFile.getCanonicalPath() ); > continue; > } > > final File thumbnailFile = makeThumbnailFile( inputFile , > thumbnailDimension , thumbnailQuality ); > if ( thumbnailFile != null && thumbnailFile.exists() ) { > System.out.println( thumbnailFile.getCanonicalPath() + " > succesfully created" ); > } > else { > System.out.println( "Unable to create thumbnail for " + > inputFile.getCanonicalPath() ); > } > } > System.out.println( "Done." ); > } > catch( Exception e ) { > CommonLib.logException( e , CommonLib.notOnServer() ); > } > } > > private static File makeThumbnailFile( File inputFile , int > thumbnailDimension , float thumbnailQuality ) { > > File response = null; > > try { > if ( inputFile == null ) { > System.out.println( "Input file is null" ); > return response; > } > if ( !inputFile.exists() ) { > System.out.println( "Input file does not exist: " + > inputFile.getName() ); > return response; > } > if ( !isKnownFormat( inputFile.toString() ) ) { > System.out.println( "Unsupported file format: " + > inputFile.getName() ); > return response; > } > > final Frame frame = new Frame(); > frame.addNotify(); > > final String fileSuffix = knownAliases( inputFile.getName() > ).substring( 1 ); > > final ImageReader imgReader = (ImageReader) > ImageIO.getImageReadersBySuffix( fileSuffix ).next(); > > final ImageInputStream bufferedInput = > ImageIO.createImageInputStream( new BufferedInputStream( > new FileInputStream( inputFile ) ) ); > > imgReader.setInput( bufferedInput ); > > int imgHeight = imgReader.getHeight( 0 ); > int imgWidth = imgReader.getWidth( 0 ); > > double imageRatio = (double) imgWidth / (double) imgHeight; > int thumbnailHeight = thumbnailDimension; > int thumbnailWidth = thumbnailDimension; > > if ( imageRatio > 1.0d ) { > thumbnailHeight = (int) ( thumbnailDimension / imageRatio ); > } > else { > thumbnailWidth = (int) ( thumbnailDimension * imageRatio ); > } > > int longEdge = ( Math.max( imgHeight , imgWidth ) ); > int tempThumbnailEdge = (int) ( (float) thumbnailDimension * > 1.25f ); > int subSample = (int) ( (float) longEdge / (float) > tempThumbnailEdge ); > > final ImageReadParam readParam = > imgReader.getDefaultReadParam(); > if ( subSample > 1 ) { > readParam.setSourceSubsampling( subSample , subSample , 0 , > 0 ); > } > > final BufferedImage tempThumbnailImage = imgReader.read( 0 , > readParam ); > > final BufferedImage thumbnailImage = new BufferedImage( > thumbnailWidth , thumbnailHeight , > BufferedImage.TYPE_INT_RGB ); > final Graphics2D graphics2D = thumbnailImage.createGraphics(); > graphics2D > .setRenderingHint( RenderingHints.KEY_INTERPOLATION , > RenderingHints.VALUE_INTERPOLATION_BILINEAR ); > graphics2D.drawImage( tempThumbnailImage , 0 , 0 , > thumbnailWidth , thumbnailHeight , frame ); > > final String thumbnailFileName = getThumbnailFileName( > inputFile.getCanonicalPath() ); > final File thumbnailFile = new File( thumbnailFileName ); > final BufferedOutputStream thumbnailOut = new > BufferedOutputStream( > ( new FileOutputStream( thumbnailFile ) ) , 4092 ); > final JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder( > thumbnailOut ); > final JPEGEncodeParam encoderParam = > encoder.getDefaultJPEGEncodeParam( thumbnailImage ); > encoderParam.setQuality( thumbnailQuality , false ); > encoder.setJPEGEncodeParam( encoderParam ); > encoder.encode( thumbnailImage ); > thumbnailOut.close(); > > // Dispose of AWT components > graphics2D.dispose(); > frame.dispose(); > > response = thumbnailFile; > } > catch( Exception e ) { > e.printStackTrace(); > } > return response; > } > > private static boolean isKnownFormat( String fileName ) { > boolean response = false; > > if ( fileName == null || fileName.length() == 0 ) { > return response; > } > int extensionPosition = fileName.lastIndexOf( '.' ); > > if ( extensionPosition == -1 ) return response; > > final String extension = knownAliases( fileName.substring( > extensionPosition ).toLowerCase() ); > > for ( int x = 0 ; x < knownFormats.length ; x++ ) { > if ( extension.equals( knownFormats[x] ) ) { > return true; > } > } > > return response; > } > > private static String knownAliases( String fileName ) { > final String extension = fileName.substring( fileName.lastIndexOf( > '.' ) ).toLowerCase(); > if ( extension.equals( ".jpg" ) ) return ".jpeg"; > if ( extension.equals( ".jpe" ) ) return ".jpeg"; > if ( extension.equals( ".tif" ) ) return ".tiff"; > return extension; > } > > private static String getThumbnailFileName( String attachmentName ) { > String result = null; > int dotIndex = 0; > > // Get the position of the . before the extension > dotIndex = attachmentName.lastIndexOf( "." ); > // Get the extension of the current file > final String extension = attachmentName.substring( dotIndex + 1 ); > // Get the file name without the extension > result = attachmentName.substring( 0 , dotIndex ); > // Build the thumbnail file name > result = result + "_thumb_" + extension + ".jpg"; > > return result; > } > } > > -- > View this message in context: http://www.nabble.com/using-JAI-to-create-a-thumbnail-as-a-JPEG-tf3701670.html#a11042093 > Sent from the JAI Projects - Interest mailing list archive at Nabble.com. > > --------------------------------------------------------------------- > To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net > For additional commands, e-mail: interest-help@jai.dev.java.net > >
---------------- Brian Burkhalter Java Media, Imaging, and Graphics Sun Microsystems, Inc.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This email message is for the sole use of the intended recipient(s) and may contain confidential and privileged information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--------------------------------------------------------------------- To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net For additional commands, e-mail: interest-help@jai.dev.java.net
|
|
|
|
|
|
|
|
Re: using JAI to create a thumbnail as a JPEG
Posted:
Jun 22, 2007 1:05 PM
in response to: mlevin
|
|
|
Folks, I am new to using the java imaging APIs. I am trying to use java to create thumbnail images mainly for jpeg and gifs, and am not sure how to proceed. Ideally, the APIs shouldnt force me to materialize the full image in memory before scaling.
By reading this thread, it seems like there are 2 options: (1) Use JAI APIs (2) Use Java ImageIO APIs (by using the ImageReadParam)
Which of these is recommended?
Also, it was mentioned that the underlying decoder/reader used is what really matters and the decoder packaged with sun's java will read the entire image in memory. If thats true, can someone recommended other decoders (preferably free/open source, but commerical is also ok), that offer better performance (in terms of memory consumption).
Thanks much Srinivas
|
|
|
|
|
|
|
|
Re: [JAI] Re: using JAI to create a thumbnail as a JPEG
Posted:
Jun 22, 2007 2:36 PM
in response to: snsf
|
|
|
On Fri, 22 Jun 2007, jai-interest@javadesktop.org wrote:
> Folks, > I am new to using the java imaging APIs. I am trying to use java to create thumbnail images mainly for jpeg and gifs,
For thumbnail generation I recommend the SubsampleAverage operation:
http://download.java.net/media/jai/javadoc/1.1.3/jai-apidocs/javax/media/jai/operator/SubsampleAverageDescriptor.html
Note that for a palette color image such as GIF this operation will not work directly. For palette color imagery you need either to expand the image to three-band RGB before applying the geometric operation or you need to use an operation which does not interpolate the source image gray levels such as nearest neighbor downsampling. Note that the negative side effect of the latter approach is that you cannot apply low pass filtering at least by the standard methods which implies that your thumbnail will suffer aliasing.
> and am not sure how to proceed. Ideally, the APIs shouldnt force me to > materialize the full image in memory before scaling.
The APIs don't force this but for better or worse the JPEG and GIF implementations can only load the entire image into memory. Formats which support tiling such as TIFF and JPEG2000 do not have this drawback. Neither of these formats really supports partial reading all that well anyway except perhaps for JPEGs which include RSTn markers.
> By reading this thread, it seems like there are 2 options: > (1) Use JAI APIs > (2) Use Java ImageIO APIs (by using the ImageReadParam) > > Which of these is recommended?
The second. The JAI codecs pre-date the Java Image I/O Framework APIs and were provided as a user convenience.
> Also, it was mentioned that the underlying decoder/reader used is what really matters and the decoder packaged with sun's java will read the entire image in memory. If thats true, can someone recommended other decoders (preferably free/open source, but commerical is also ok), that offer better performance (in terms of memory consumption).
If you find one please let us know where it is.
Thanks,
Brian
---------------- Brian Burkhalter Java Media, Imaging, and Graphics Sun Microsystems, Inc.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This email message is for the sole use of the intended recipient(s) and may contain confidential and privileged information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--------------------------------------------------------------------- To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net For additional commands, e-mail: interest-help@jai.dev.java.net
|
|
|
|
|
|
|