How do you clone a BufferedImage

62,942

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;
}
Share:
62,942
f1wade
Author by

f1wade

Updated on March 11, 2021

Comments

  • f1wade
    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
    Daniel Kats about 12 years
    I'm also borrowing this in my program =)
  • mishka
    mishka over 10 years
    have issue with this method on copying subimage
  • HaydenStudios
    HaydenStudios almost 10 years
    While 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
    HaydenStudios almost 10 years
    return new BufferedImage(cm, raster, isAlphaPremultiplied, null).getSubimage(0, 0, bi.getWidth(), bi.getHeight());
  • user1050755
    user1050755 over 9 years
    copyData(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
    Utku Ufuk over 9 years
    @f1wade @BlackSheep @HaydenStudios @user1050755 Is there a way to alter the size of the BufferedImage after cloning it?
  • WVrock
    WVrock about 9 years
    This looks pretty simple. Why this is n't the best answer? Is there a flaw that I'm not aware of?
  • Mgamerz
    Mgamerz almost 9 years
    Should have a null check on bi (e.g. if you're using this in a copy constructor) shouldn't there?
  • Tilman Hausherr
    Tilman Hausherr about 8 years
    @WVrock It doesn't work if the image type is 0 (custom)
  • f1wade
    f1wade over 7 years
    I 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
    Nadir over 7 years
    replace Graphics g = b.getGraphics(); by Graphics2D g = b.createGraphics(); and it is perfect
  • rococo
    rococo almost 6 years
    Thank you, I was getting an offset error trying to clone a subimage. This version is exactly what I needed.
  • Kröw
    Kröw almost 6 years
    This 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, not BufferedImage.
  • thekevshow
    thekevshow over 5 years
    I 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
    clic about 3 years
    BufferedImage is not serializable, which makes this alternative hard to use ..
  • José Roberto Araújo Júnior
    José Roberto Araújo Júnior over 2 years
    May fail: java Exception in thread "DefaultDispatcher-worker-1" java.lang.IllegalArgumentException: Unknown image type 0 at java.desktop/java.awt.image.BufferedImage.<init>(BufferedIma‌​ge.java:501)
  • clic
    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
    clic over 2 years
    @JoséRobertoAraújoJúnior try to replace "source.getType()" with "source.getType()==0?5:source.getType()"