It's been years since I've used Java2D, but last I remembered, BufferedImage is no different from any other Java class. It gets passed around by reference, not copy. Even if a BufferedImage did end up being copied, I'd imagine most of the time just the BufferedImage class gets copied and the underlying raster data is then refered to by more than one object.

I don't think you can make an immutable version of BufferedImage since it implements the WriteableRenderedImage interface. You could make your own extension of Image and have it implement RenderedImage, but as far as I can tell the graphics pipeline won't be able to do anything useful with it. (i.e. you can't pass it to Graphics#drawImage). The other alternative would be to extend BufferedImage and override all methods that modify the image so that they throw an UnsupportedOperationException. That also sounds like a bad idea though and might not even work in practice, since the BufferedImage constructors probably use some of these methods.It's probably easier to simlpy state in the javadoc that the returned image should not be modified and if you do, something might break or result in unexpected behaviour.

cloning the raster / wrapping an BufferedImage and thowing some UnsupportedOperationExceptions upon invoking methods that can cause the image to be altered(eg createGraphics() setRaster etc).

I suppose I could pass an uri/url around to the generator cach it the first time and make the cach inaccessible to outside the class. I'll recieve exceptions with reguard to reading the image later then I would have wanted but I gues I have to make a compromise somewhere.

I guess the best solution really depends on how you want to use these images. If you need them as Image/BufferedImage instances there's probably going to be a tradeoff somewhere. Passing URIs and getting errors a bit later sounds like a reasonable one.If you don't need BufferedImages you could hide the BufferedImage instances in another wrapper class. For instance

1 2 3 4 5 6 7 8 9 10 11

classImmutableImage {privatefinalBufferedImageimage;

publicDrawableImage(BufferedImageimage) {this.image = image; }

publicvoiddrawImage(Graphicsg) {g.drawImage(image, 0, 0, null); }}

The downside is that you have to provide methods for each operation that you want to do with the BufferedImage.

I guess the best solution really depends on how you want to use these images. If you need them as Image/BufferedImage instances there's probably going to be a tradeoff somewhere. Passing URIs and getting errors a bit later sounds like a reasonable one.If you don't need BufferedImages you could hide the BufferedImage instances in another wrapper class. For instance

1 2 3 4 5 6 7 8 9 10 11

classImmutableImage {privatefinalBufferedImageimage;

publicDrawableImage(BufferedImageimage) {this.image = image; }

publicvoiddrawImage(Graphicsg) {g.drawImage(image, 0, 0, null); }}

The downside is that you have to provide methods for each operation that you want to do with the BufferedImage.

I might be able to live with that downside, very interesting approach, thanks.

The suggested method wouldn't make the image immutable, because after running the constructor you can still have other references to the argument image outside and thus alter it. A more correct way would be to create a new BufferedImage inside the constructor which is a copy of the argument. This could still be altered if the user subclasses Graphics and overrides the drawImage method before passing it to the grawImage method of ImmutableImage, but this is getting pretty far out.

Your initial question, however, shows concern regarding "copying" of images. Do you have any other reason than that to want an immutable implementation?

I kind of had a factory in mind that creates the ImmutableImage instances. This factory would decode the images to BufferedImages and then return an ImmutableImage instead of the BufferedImage directly. In practice that would mean there's only one reference to the BufferedImage. Images tend to get large so copying them seemed like a waste of memory (albeit for a very short period of time) and cpu cycles to me. If it's really a concern then I agree that copying is the better solution of course.Given the BufferedImage interface and the restrictions made by the Graphics(2D) implemenation, I don't think a true immutable BufferedImage is possible. This probably isn't really a problem in his application though. It seems unlikely that the security or stability of an application would depend on this. To me it sounds more like an api design issue, where you don't want the images to be mutable in an obvious way.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org