Reputation: 1438
I have a method which I am making to save an image and show its progress while saving. Overall the method seems to work, but if I call it more than once it sometimes gives me a IllegalArgumentException error.
This is the stack trace:
java.lang.IllegalArgumentException: input == null!
at javax.imageio.ImageIO.getImageReaders(ImageIO.java:641)
at com.forseth11.ColorEncoder.Encoder.saveImage(Encoder.java:308)
at com.forseth11.ColorEncoder.Encoder.encode(Encoder.java:82)
at com.forseth11.ColorEncoder.Encoder$3.run(Encoder.java:376)
at java.lang.Thread.run(Thread.java:745)
I don't know why I get this error or how to fix it. I need to be able to call this method multiple times to save multiple images in a row.
Here is the method:
private void saveImage(final BufferedImage image, final String string, final File outputfile) throws IOException, InterruptedException {
Thread thread = new Thread(new Runnable(){
public void run() {
try {
ImageIO.write(image, string, outputfile);
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
try {
ImageInputStream iis = ImageIO.createImageInputStream(outputfile);
Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
if (readers.hasNext()) {
ImageReader reader = readers.next();
reader.setInput(iis);
try {
BufferedImage img = reader.read(0);
ByteArrayOutputStream baos = new ByteArrayOutputStream();//This is the line the error is pointing to.
try {
ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("png");
if (writers.hasNext()) {
ImageWriter writer = writers.next();
writer.addIIOWriteProgressListener(new IIOWriteProgressListener() {
public void imageStarted(ImageWriter source, int imageIndex) {
}
public void imageProgress(ImageWriter source, float percentageDone) {
System.out.println("UPDATE: " + percentageDone);//TODO
}
public void imageComplete(ImageWriter source) {
}
public void thumbnailStarted(ImageWriter source, int imageIndex, int thumbnailIndex) {
}
public void thumbnailProgress(ImageWriter source, float percentageDone) {
}
public void thumbnailComplete(ImageWriter source) {
}
public void writeAborted(ImageWriter source) {
}
});
writer.setOutput(ios);
try {
writer.write(img);
} finally {
writer.removeAllIIOWriteProgressListeners();
}
}
} finally {
reader.removeAllIIOReadProgressListeners();
}
} finally {
reader.removeAllIIOReadProgressListeners();
}
}
} catch (IOException exp) {
exp.printStackTrace();
}
thread.join();//I added this so it will not leave the method until the image is saved.
}
I got the code for getting the percentage the image is saved from here. I modified it a bit.
How can I make this method to save an image and print its percentage saved without getting an error? Also why does it not always give me an error when I call the method two times in a row?
Upvotes: 0
Views: 416
Reputation: 1438
It turns out that I did not understand the code I was using. Apparently it was trying to read a file when I only wanted to write to own.
Here is my new method which seems to work in case anyone has a similar problem:
private void saveImage(final BufferedImage image, final String string, final File outputfile) throws IOException, InterruptedException {
Thread thread = new Thread(new Runnable(){
public void run() {
try {
ImageIO.write(image, string, outputfile);
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(string);
if (writers.hasNext()) {
ImageWriter writer = writers.next();
writer.addIIOWriteProgressListener(new IIOWriteProgressListener() {
public void imageStarted(ImageWriter source, int imageIndex) {
}
public void imageProgress(ImageWriter source, float percentageDone) {
System.out.println("UPDATE: " + percentageDone);//TODO
}
public void imageComplete(ImageWriter source) {
}
public void thumbnailStarted(ImageWriter source, int imageIndex, int thumbnailIndex) {
}
public void thumbnailProgress(ImageWriter source, float percentageDone) {
}
public void thumbnailComplete(ImageWriter source) {
}
public void writeAborted(ImageWriter source) {
}
});
writer.setOutput(ios);
try {
writer.write(image);
} finally {
writer.removeAllIIOWriteProgressListeners();
}
}
thread.join();
}
Upvotes: 0
Reputation: 840
The error is a result of these lines, per the stack trace, so your:
ImageInputStream iis = ImageIO.createImageInputStream(outputfile);
Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
I googled for the ImageIO source code and found it here: ImageIO source on GrepCode
The source code snippet throwing the exception is:
public static Iterator<ImageReader> More ...getImageReaders(Object input) {
640 if (input == null) {
641 throw new IllegalArgumentException("input == null!");
642 }
643 Iterator iter;
644 // Ensure category is present
645 try {
646 iter = theRegistry.getServiceProviders(ImageReaderSpi.class,
647 new CanDecodeInputFilter(input),
648 true);
649 } catch (IllegalArgumentException e) {
650 return Collections.emptyIterator();
651 }
652
653 return new ImageReaderIterator(iter);
654 }
There are multiple cases from the "ImageIO.createImageInputStream(outputfile)" method call that can cause issues, based on looking at the source: Either the call to the registry for service providers is throwing an exception, or the returned service providers iterator has no members. In both cases, you get null return.
I would suggest downloading the jar code local and setting a conditional breakpoint in this source so you can see exactly which case is happening.
Hope that helps get to the source of the issue.
Upvotes: 0
Reputation: 10147
do not use following thread
Thread thread = new Thread(new Runnable(){
public void run() {
try {
ImageIO.write(image, string, outputfile);
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
Since when outputfile is not ready you continue with following code
ImageInputStream iis = ImageIO.createImageInputStream(outputfile);
Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
Upvotes: 2