How do you clone a BufferedImage
Solution 1
Something like this?
static BufferedImage deepCopy(BufferedImage bi) {
ColorModel cm = bi.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster = bi.copyData(null);
return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
}
Solution 2
I do this:
public static BufferedImage copyImage(BufferedImage source){
BufferedImage b = new BufferedImage(source.getWidth(), source.getHeight(), source.getType());
Graphics g = b.getGraphics();
g.drawImage(source, 0, 0, null);
g.dispose();
return b;
}
It works fairly well and it is simple to use.
Solution 3
The previously mentioned procedure fails when applied to sub images. Here is a more complete solution:
public static BufferedImage deepCopy(BufferedImage bi) {
ColorModel cm = bi.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster = bi.copyData(bi.getRaster().createCompatibleWritableRaster());
return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
}
Solution 4
I know that this question is pretty old, but for future visitors, here's the solution I'd use:
Image oldImage = getImage();
Image newImage = oldImage.getScaledInstance(oldImage.getWidth(null), oldImage.getHeight(null), Image.SCALE_DEFAULT);
Please correct me if changing the just obtained newImage
also affects the original image in any way.
--> Javadoc for getScaledInstance
--> Javadoc for SCALE_DEFAULT (the other constants are listed just below that one)
Solution 5
Another way is to use the Graphics2D
class to draw the image onto a new blank image. This doesn't really clone the image, but it results in a copy of the image being produced.
public static final BufferedImage clone(BufferedImage image) {
BufferedImage clone = new BufferedImage(image.getWidth(),
image.getHeight(), image.getType());
Graphics2D g2d = clone.createGraphics();
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
return clone;
}
f1wade
Updated on March 11, 2021Comments
-
f1wade about 3 years
I have an object which has many bufferedimages in it, I want to create a new object copying all the bufferedimages into the new object, but these new images may be altered and i don't want the original object images to be altered by altering the new objects images.
is that clear?
Is this possible to do and can anyone suggest a good way to do it please? I have thought of getSubImage but read somewhere that any changes to the subimage are relected back to the parent image.
I just want to be able to get a fresh entirely separate copy or clone of a BufferedImage
-
Daniel Kats about 12 yearsI'm also borrowing this in my program =)
-
mishka over 10 yearshave issue with this method on copying subimage
-
HaydenStudios almost 10 yearsWhile this works under most circumstances, it doesn't work properly when that BufferedImage has been cropped(it returns the whole image before it was cropped). A simple fix to this is to change that last line to:
-
HaydenStudios almost 10 yearsreturn new BufferedImage(cm, raster, isAlphaPremultiplied, null).getSubimage(0, 0, bi.getWidth(), bi.getHeight());
-
user1050755 over 9 yearscopyData(null) does not always work because it may work on a parent raster (ie. when the image is a sub image), see my modified answer
-
Utku Ufuk over 9 years@f1wade @BlackSheep @HaydenStudios @user1050755 Is there a way to alter the size of the
BufferedImage
after cloning it? -
WVrock about 9 yearsThis looks pretty simple. Why this is n't the best answer? Is there a flaw that I'm not aware of?
-
Mgamerz almost 9 yearsShould have a null check on bi (e.g. if you're using this in a copy constructor) shouldn't there?
-
Tilman Hausherr about 8 years@WVrock It doesn't work if the image type is 0 (custom)
-
f1wade over 7 yearsI think that would not actually copy the image,ie if you changed the original the scaled willalso change, but its been a while so ill let someone else say for sure.
-
Nadir over 7 yearsreplace Graphics g = b.getGraphics(); by Graphics2D g = b.createGraphics(); and it is perfect
-
rococo almost 6 yearsThank you, I was getting an offset error trying to clone a subimage. This version is exactly what I needed.
-
Kröw almost 6 yearsThis does actually copy the image, in that changes to the original will not change the copy. This answer is short and concise and isn't even limited to BufferedImages. The only issue is that it returns
Image
, notBufferedImage
. -
thekevshow over 5 yearsI think this is the cleanest answer. Although is there any performance difference between this and the accepted answer? I feel like negligible if any no? Could this be faster purely cause object creation is optimized in the jvm. Also using openjdk 11. If anyone can answer that question.
-
clic about 3 yearsBufferedImage is not serializable, which makes this alternative hard to use ..
-
José Roberto Araújo Júnior over 2 yearsMay fail:
java Exception in thread "DefaultDispatcher-worker-1" java.lang.IllegalArgumentException: Unknown image type 0 at java.desktop/java.awt.image.BufferedImage.<init>(BufferedImage.java:501)
-
clic over 2 years@JoséRobertoAraújoJúnior which image format, which Java version and which operating system are you using? There are some reported issues with PNG and TIFF. A hack exists where in case the image type is 0 it is manually set to 5...
-
clic over 2 years@JoséRobertoAraújoJúnior try to replace "source.getType()" with "source.getType()==0?5:source.getType()"