0

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?

Community
  • 1
  • 1
Forseth11
  • 1,418
  • 1
  • 12
  • 21
  • Simply put: because `outputFile` may not exist yet. It would be better if you explained what you are trying to do and we can tell where to change your solution. – biziclop May 27 '15 at 21:04
  • 1
    It will also help if you use more modules in your code. – MaxZoom May 27 '15 at 21:19

3 Answers3

2

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);
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
Ahmet Karakaya
  • 9,899
  • 23
  • 86
  • 141
  • Thank you, but it turns out the problem was that I did not understand the code I was using and I was trying to read a file when I only wanted to write one. – Forseth11 May 27 '15 at 21:27
  • ImageIO.write(image, string, outputfile); ImageInputStream iis = ImageIO.createImageInputStream(outputfile); Iterator readers = ImageIO.getImageReaders(iis); – Ahmet Karakaya May 28 '15 at 04:50
0

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.

jatal
  • 790
  • 1
  • 10
  • 19
  • Thank you for your answer @jatal. It turns out that the problem this whole time was that I did not understand the code I was using and it was apparently trying to read a file when I only wanted it to write one. – Forseth11 May 27 '15 at 21:28
0

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();
    }
Forseth11
  • 1,418
  • 1
  • 12
  • 21