0

Intention: Get BufferedImage from resource (be it in IDE or running JAR).

Problem: Getting an Image always works, converting to BufferedImage requires knowledge of size, but size always returns -1, even after waiting with MediaTracker. In IDE, size after MediaTracker is proper, before it is -1. Waiting with while-loop until size >-1 seems to never end in running JAR. (Tried with code language level 6 and 8 using JDK/JRE 8.)

Output of SSCCE in IDE:

IMAGE: sun.awt.image.ToolkitImage@15975490

WIDTH: -1

DURATION: 38 ms

WIDTH: 32

BUFFEREDIMAGE: BufferedImage@6adede5: type = 1 DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=0 IntegerInterleavedRaster: width = 32 height = 32 #Bands = 3 xOff = 0 yOff = 0 dataOffset[0] 0

EDIT: MediaTracker's "isErrorAny()" returns false.

Output of SSCCE in running JAR:

IMAGE: sun.awt.image.ToolkitImage@2a84aee7

WIDTH: -1

DURATION: 23 ms

WIDTH: -1

Exception in thread "main" java.lang.IllegalArgumentException: Width (-1) and height (-1) cannot be <= 0 at java.awt.image.DirectColorModel.createCompatibleWritableRaster(Unknown Source) at java.awt.image.BufferedImage.(Unknown Source) at ImageSizeProblem.createBufferedImageFromImage(ImageSizeProblem.java:82) at ImageSizeProblem.main(ImageSizeProblem.java:26)

EDIT: MediaTracker's "isErrorAny()" returns true. But I have no way of finding out what the error is - also, the image does load properly, since it can be successfully used in an JToolBar via making an ImageIcon from it. (I already tried abusing ImageIcon's getIconWidth() or getImage() methods - they bring no improvement at all.)

SSCCE:

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.net.URL;

public class ImageSizeProblem {

    public static void main(final String[] args) {

        final Image img = createImageFromResource("test.png");

        System.out.println("IMAGE: " + img);
        System.out.println("WIDTH: " + img.getWidth(null));

        final long startTime = System.currentTimeMillis();
        waitForImage(img);
        final long duration = System.currentTimeMillis() - startTime;
        System.out.println("\nDURATION: " + duration + " ms");

        System.out.println("\nWIDTH: " + img.getWidth(null));

        final BufferedImage buffImg = createBufferedImageFromImage(img, false);
        System.out.println("\nBUFFEREDIMAGE: " + buffImg);

        System.exit(0);
    }

    private static Image createImageFromResource(final String resourceFileName_dontForgetToAddItsFolderToClasspath) {

        final Toolkit kit = Toolkit.getDefaultToolkit();
        final URL url = ClassLoader.getSystemResource(resourceFileName_dontForgetToAddItsFolderToClasspath);
        if (url != null) {
            final Image img = kit.createImage(url);
            if (img == null) {
                System.err.println("Image resource could not be loaded.");
                return null;
            }
            return img;
        } else {
            System.err.println("Image resource not found.");
            return null;
        }
    }

    private static boolean waitForImage(final Image img) {
        final MediaTracker mediaTracker = new MediaTracker(new JPanel());
        mediaTracker.addImage(img, 1);
        try {
            mediaTracker.waitForID(1);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
        return !mediaTracker.isErrorAny();
    }


    // improved version of http://stackoverflow.com/a/13605411/3500521
    private static BufferedImage createBufferedImageFromImage(final Image img, final boolean withTransparency) {

        if (img instanceof BufferedImage) {
            return (BufferedImage) img;
        } else if (img == null) {
            return null;
        }

        final int w = img.getWidth(null);
        final int h = img.getWidth(null);

        final BufferedImage bufferedImage;
        if (withTransparency) {
            bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        } else {
            bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        }

        final Graphics2D g = bufferedImage.createGraphics();
        g.drawImage(img, 0, 0, null);
        g.dispose();
        return bufferedImage;
    }
}

Note that the image used for testing was loaded and used successfully in another application via new ImageIcon(image) in a JToolBar. Getting the size from the ImageIcon also returns -1, also from the image returned by ImageIcon.getImage().

Dreamspace President
  • 1,060
  • 13
  • 33
  • You are ignoring the return value of `waitForImage` (i.e. `mediaTacker.isErrorAny()`). Is this intentional? Maybe it can tell you something? – Harald K Dec 01 '14 at 16:11
  • @haraldK: Thanks for the reply. Yes, I should probably have mentioned that (fought with the problem 5 hours yesterday from all angles, so maybe lost sight a little). In the IDE, isErrorAny returns false, but returns true in the JAR. But there seems to be no way to find out what error is happening during the completion of the image loading process kit.createImage performs. – Dreamspace President Dec 02 '14 at 07:12
  • The problem debugging the `Image` and the `Toolkit` image API is that it is lazy-loading. You never know if there's a problem, before it's too late.. Have you tried just reading the image using `ImageIO.read(...)`, if for nothing else, to see what error message you get? – Harald K Dec 02 '14 at 11:44
  • @haraldK: That's sadly useless, because I have never gotten it to work in the JAR, it throws a FileNotFoundException with a text closely like "(Access denied)". The approach above, however, at least gives me a working Image. – Dreamspace President Dec 02 '14 at 15:12
  • That's very unlikely, as both approaches has to read from the same file system eventually. But there might be details I don't know about. Anyway, the "access denied" exception is likely the real problem. Of course, feel free to ignore that advice. ;-) – Harald K Dec 02 '14 at 15:18
  • @haraldK: I have no choice but to ignore it, since I get an image with one method, and no (buffered)image with the other, hence I can't assume that the error message is relevant. But thanks for trying to help, anyway. – Dreamspace President Dec 02 '14 at 15:56

1 Answers1

0

The problem was path depth.

I also tried Avira, because the problem is technically a program accessing its own file, which could well seem suspicious, but while Avira was uninstalling, I tried the executables in a different location with a shorter path, and everything worked like a charm.

Dada
  • 6,313
  • 7
  • 24
  • 43
Dreamspace President
  • 1,060
  • 13
  • 33