question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

IndexOutOfBoundsException in ImageReader.getImageMetadata(0)

See original GitHub issue

As you know from my ongoing saga in #586 I want to scale an image, modify metadata, and write the image to a file using Java Image I/O.

For the time being for certain images I have updated the code to maintain the existing metadata. I just need to do this:

IIOMetadata imageMetadata = imageReader.getImageMetadata(0);
IIOImage iioImage = new IIOImage(newImage, null, imageMetadata);

Unbelievably it works well, and Java Image I/O seems to keep all the Exif, IPTC and XMP metadata!

Note that I am assuming that the image I am processing is the first image, image 0. (This might not work on a JPEG image with no image metadata, but truly that is the last of my worries at the moment.)

Because of this approach I don’t even need to use Twelve Monkeys, so had taken it out altogether. I wanted to check one last thing, so I added back Twelve Monkeys 3.6.2 without changing any of my code, and I get this:

java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
	at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
	at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
	at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
	at java.base/java.util.Objects.checkIndex(Objects.java:372)
	at java.base/java.util.ArrayList.get(ArrayList.java:458)
	at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader.readSegments(JPEGImageReader.java:842)
	at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader.initHeader(JPEGImageReader.java:693)
	at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader.initHeader(JPEGImageReader.java:727)
	at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader.getImageMetadata(JPEGImageReader.java:1229)

I have no idea why Twelve Monkeys thinks that there are no images when calling ImageReader.getImageMetadata(0). It was working earlier when I was ignoring metadata altogether (and adding the last true argument in ImageReader.setInput(imageInputStream, true, true)).

As I mentioned this works fine with pure Java Image I/O; it’s only when I add Twelve Monkeys as a dependency that this breaks.

Because I wound up not needing Twelve Monkeys at the moment (and I have to deal with breaking bugs in Apache Commons Imaging such as IMAGING-281; and in metadata-extractor such as https://github.com/drewnoakes/metadata-extractor/issues/270 ) unfortunately I don’t time to investigate this further. Sorry. I hope you understand.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:13 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
garretwilsoncommented, Feb 15, 2021

I have excellent news!

I do spot a problem in your code though. … You cannot use the imageReader after it’s disposed!

Indeed, that was the problem! Thank you so much! Even though it wasn’t causing me any problems at the moment (as I wasn’t using Twelve Monkeys), it’s very good to have the code more robust and to remove a blatant error.

Here is what the code looks like now. I’ve restructured the code a bit to prevent this sort of problem the future:

final ImageInputStream imageInputStream = createImageInputStream(inputStream); //this stream will not be closed in this method, as it wraps a stream provided by the caller
if(imageInputStream == null) {
  throw new IOException("No suitable image input stream service provider found.");
}
final BufferedImage oldImage; //read the first of the images
final IIOMetadata oldImageMetadata;
final ImageWriter imageWriter; //get the writer while the reader is still valid
{ //use the reader in a separate scope to keep it from being accidentally used after it is disposed
  final ImageReader imageReader = findNext(getImageReaders(imageInputStream)) //use the first available image reader
      .orElseThrow(() -> new IOException("No service provider image reader available."));
  try {
    final ImageReadParam imageReadParam = imageReader.getDefaultReadParam();
    imageReader.setInput(imageInputStream, true, !keepMetadata); //tell the image reader to read from the image input stream, ignoring metadata if we shouldn't keep metadata
    oldImage = imageReader.read(imageIndex, imageReadParam); //tell the image reader to read the image
    oldImageMetadata = keepMetadata ? imageReader.getImageMetadata(imageIndex) : null; //get any metadata associated with the image if we have been asked to keep it
    imageWriter = getImageWriter(imageReader); //get an image writer that corresponds to the reader
  } finally {
    imageReader.dispose(); //tell the image reader we don't need it any more
  }
}

If this is the cause, you owe me a beer!

I now owe you several! Seriously, after the pandemic if I’m in the area I might just buy you one personally.

I’ll mark this ticket as closed. Feel free to add an “invalid” label or whatever to the bug report.

1reaction
garretwilsoncommented, Feb 15, 2021

@haraldk I sent you the original image via email. I’d rather not post it on GitHub. (It’s nothing secret, just a large, full-size version of one of my photography works. I prefer to distribute only the scaled versions, which is part of why I’m going to all the trouble to scale them to begin with.)

Yesterday I generated an entire set of photos with a milestone version of my static site generation with image scaling project. It worked just fine. To reproduce this problem, I merely added the following as a dependency as per your project instructions:

    <dependency>
        <groupId>com.twelvemonkeys.imageio</groupId>
        <artifactId>imageio-jpeg</artifactId>
        <version>3.6.2</version>
    </dependency>

Boom, it broke:

java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
	at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
	at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
	at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
	at java.base/java.util.Objects.checkIndex(Objects.java:372)
	at java.base/java.util.ArrayList.get(ArrayList.java:458)
	at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader.readSegments(JPEGImageReader.java:842)
	at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader.initHeader(JPEGImageReader.java:693)
	at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader.initHeader(JPEGImageReader.java:727)
	at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReader.getImageMetadata(JPEGImageReader.java:1229)
	at io.guise.mummy.mummify.image.DefaultImageMummifier.processImage(DefaultImageMummifier.java:249)
	at io.guise.mummy.mummify.image.DefaultImageMummifier.mummifyFile(DefaultImageMummifier.java:125)
	at io.guise.mummy.mummify.AbstractFileMummifier.mummify(AbstractFileMummifier.java:204)
	at io.guise.mummy.mummify.collection.DirectoryMummifier.mummify(DirectoryMummifier.java:366)
	at io.guise.mummy.mummify.collection.DirectoryMummifier.mummify(DirectoryMummifier.java:366)
	at io.guise.mummy.GuiseMummy.mummify(GuiseMummy.java:314)
	at io.guise.cli.GuiseCli.mummify(GuiseCli.java:204)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at picocli.CommandLine.executeUserObject(CommandLine.java:1872)
	at picocli.CommandLine.access$1100(CommandLine.java:145)
	at picocli.CommandLine$RunLast.executeUserObjectOfLastSubcommandWithSameParent(CommandLine.java:2255)
	at picocli.CommandLine$RunLast.handle(CommandLine.java:2249)
	at picocli.CommandLine$RunLast.handle(CommandLine.java:2213)
	at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:2080)
	at picocli.CommandLine.execute(CommandLine.java:1978)
	at com.globalmentor.application.BaseCliApplication.execute(BaseCliApplication.java:213)
	at com.globalmentor.application.AbstractApplication.start(AbstractApplication.java:118)
	at com.globalmentor.application.Application.start(Application.java:133)
	at io.guise.cli.GuiseCli.main(GuiseCli.java:88)

This is with commit 5525b5acc7aecfd1bba32824f1279cf28d0319dc as indicated above.

Read more comments on GitHub >

github_iconTop Results From Across the Web

ImageReader (Java Platform SE 7 ) - Oracle Help Center
An abstract superclass for parsing and decoding of images. This class must be subclassed by classes that read in images in the context...
Read more >
javax.imageio.ImageReader.getImageMetadata java code ...
public String readCustomData(byte[] imageData, String key) throws IOException{ ImageReader imageReader = ImageIO.getImageReadersByFormatName("png").next(); ...
Read more >
javax.imageio.ImageReader#getImageMetadata
This page shows Java code examples of javax.imageio.ImageReader#getImageMetadata.
Read more >
How to write simple Exif metadata to JPEG from scratch. #586
... Image I/O. It's works fine. I set my image reader to ignore re... ... IndexOutOfBoundsException in ImageReader.getImageMetadata(0) #587.
Read more >
Source for javax.imageio.ImageReader
Constantly 0 if 105: * seekForwardOnly is false, always increasing if ... if input is null 270: * @exception IndexOutOfBoundsException if the frame...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found