Reputation: 51
I try to show an 500 MB Tif File in an Java GUI.
My problem is: Dimensions (width=65687 height=70562) are too large
I'm already using the JAI Libary (Codec 1.1.3 & Core 1.1.3) to load the file.
static Image load(byte[] data) throws Exception {
Image image = null;
SeekableStream stream = new ByteArraySeekableStream(data);
String[] names = ImageCodec.getDecoderNames(stream);
ImageDecoder dec = ImageCodec.createImageDecoder(names[0], stream, null);
RenderedImage im = dec.decodeAsRenderedImage();
image = PlanarImage.wrapRenderedImage(im).getAsBufferedImage();
return image;
}
public static void main(String[] args) throws Exception{
String path;
if (args.length==0) {
path = JOptionPane.showInputDialog(null, "Image Path",
"c:/applications/sidebar.tif");
}
else {
path = args[0];
}
FileInputStream in = new FileInputStream(path);
FileChannel channel = in.getChannel();
ByteBuffer buffer = ByteBuffer.allocate((int)channel.size());
channel.read(buffer);
Image image = load(buffer.array());
// make sure that the image is not too big
// scale with a width of 500
Image imageScaled =
image.getScaledInstance(500, -1, Image.SCALE_SMOOTH);
//
System.out.println("image: " + path + "\n" + image);
//
JOptionPane.showMessageDialog(null, new JLabel(
new ImageIcon( imageScaled )) );
}
I just want to see the whole Image in a Frame.
UPDATE
I'm using JAVA 11 now.
But i got an new problem
java.lang.IllegalArgumentException: width*height > Integer.MAX_VALUE!
at java.desktop/javax.imageio.ImageReader.getDestination(ImageReader.java:2821)
at java.desktop/com.sun.imageio.plugins.tiff.TIFFImageReader.read(TIFFImageReader.java:1141)
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1468)
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1420)
at list.ImageView.<init>(ImageView.java:26)
at gui.GUI_Cut.<init>(GUI_Cut.java:61)
at gui.GUI_Main$3$1.run(GUI_Main.java:139)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:313)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
My Code:
image = ImageIO.read(getClass().getResource("/images/" + filename));
I'm loading the large tif image.
Upvotes: 3
Views: 432
Reputation: 44414
ImageIO is able to read some images one rectangular sub-area at a time. Each such rectangle is known as a tile.
I experimented with a few TIFF images, and found that ImageIO was willing to read each of them as tiles. I don’t know whether this is guaranteed to be the case for every TIFF image.
We can create the less memory-hungry scaled image (using the ColorModel and Raster format of the first tile we encounter), then draw each tile directly into that scaled image:
public BufferedImage readLargeImage(File file,
int desiredWidth)
throws IOException {
BufferedImage scaledImage = null;
Graphics2D scaledImageGraphics = null;
ImageReader tiffReader =
ImageIO.getImageReadersByFormatName("TIFF").next();
try (ImageInputStream stream = ImageIO.createImageInputStream(file)) {
tiffReader.setInput(stream);
int width = tiffReader.getWidth(0);
int height = tiffReader.getHeight(0);
int tileWidth = tiffReader.getTileWidth(0);
int tileHeight = tiffReader.getTileHeight(0);
int scaledWidth = desiredWidth;
float scale = (float) scaledWidth / width;
for (int tileY = 0; tileY * tileHeight < height; tileY++) {
for (int tileX = 0; tileX * tileWidth < width; tileX++) {
BufferedImage tile = tiffReader.readTile(0, tileX, tileY);
if (scaledImage == null) {
scaledImage = new BufferedImage(
tile.getColorModel(),
tile.getRaster().createCompatibleWritableRaster(
scaledWidth,
(int) (scale * height)),
false, new Properties());
scaledImageGraphics = scaledImage.createGraphics();
// Optional: better scaling
scaledImageGraphics.setRenderingHint(
RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
scaledImageGraphics.setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
}
scaledImageGraphics.drawImage(tile,
(int) (scale * tileX * tileWidth),
(int) (scale * tileY * tileHeight),
(int) (scale * tileWidth),
(int) (scale * tileHeight),
null);
}
}
}
scaledImageGraphics.dispose();
return scaledImage;
}
Upvotes: 1