1

Is there no way, using a reference to an instance of type Image, to force the loading of the corresponding image's data so that e.g. Image.getWidth(ImageObserver) returns valid data? — For example:

Image image = getImageFromSomewhereElse();
image.load(); // This method doesn't exist but it would be wonderful if it did
Image otherImage = getImageFromYetAnotherPlace();
otherImage.load();
// "compareImages" from <https://stackoverflow.com/a/29886786/1391325>
// "toBufferedImage" from <https://stackoverflow.com/a/13605411/1391325>
if (compareImages(toBufferedImage(image), toBufferedImage(otherImage))){
    System.out.println("Yay! Images are the same!");
}

Background

In an existing application, I now need to test if two references to objects of Image are actually the "same" picture (however that best can be accomplished): In order to do that, I'm trying to do a pixel-by-pixel comparison as suggested in an answer to a related question. In order to do this with the provided solution, however, I need to convert the Image instances I've got into BufferedImage instances, e.g. by constructing a new BufferedImage and then drawing the other image's data onto it as suggested in another post. However, corresponding with acomment posted to the linked answer, this is not possible in my case due to the fact that the images in question have not been loaded yet:

...

Caused by: java.lang.IllegalArgumentException: Width (-1) and height (-1) cannot be <= 0

at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1016)

java.awt.image.BufferedImage.(BufferedImage.java:333)

...

Unfortunately, the code which creates the Image instances is quite complicated, so I'm reluctant to start refactoring in order to e.g. instead check if the data used to create the Image instances is equivalent. Therefore, it would be easiest to simply ensure somehow that each image is loaded before doing the pixel-by-pixel check.

Community
  • 1
  • 1
errantlinguist
  • 3,658
  • 4
  • 18
  • 41

2 Answers2

3

There is a wonderful class

MediaTracker mt=new MediaTracker(this);
mt.addImage(image, 0);
try {
  mt.waitForID(0);
}
catch (InterruptedException me) { System.out.println("error); }

and then you can use any of the error methods in MediaTracker.html to check for possible errors/misloading.

gpasch
  • 2,672
  • 3
  • 10
  • 12
  • 1
    **Note for posterity:** [The constructor of `MediaTracker`](https://docs.oracle.com/javase/8/docs/api/java/awt/MediaTracker.html#MediaTracker-java.awt.Component-) requires a non-null reference to a `Component`, but you don't need to "plug in" an actual GUI object to the instance: If you just create a plain `new Container()` and pass it to the constructor `new MediaTracker(new Container())`, the new instance can be used in a standalone manner. – errantlinguist Feb 26 '17 at 12:06
3

Using Toolkit#get/createImage or java.awt.Image uses a background thread to load the image, you can use ImageObserver (through MediaTracker) to monitor the image's loading state or you could just use ImageIO.read instead, which loads the image fully before returning

See Reading/Loading an image for more details

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Since the question has not been downvote and no new close votes have been added, I can assume there is nothing wrong with the question. In what ways does it not answer the question? In what ways could it be improved? Since no new answers have been provided, I can assume you don't have a better idea of how to solve the problem, which begs the question how you know it won't work? Since no other answers have been voted against I can only assume you have a personal issue with me helping people – MadProgrammer Feb 23 '17 at 00:00