Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I copy part of one image to another?

I want to copy part of one image into another smaller one: in other words, copy a subrectangle.

I have a Graphics2D object for the source, I can make one for the target, and I know about targetGraphics2D.drawImage(Image img,....) , but how do I get that img from the sourceGraphics2D?


Answer (per aioobe): The source needs to be an Image rather than a Graphics2D.

Image.subImage() is the method for getting the relevant part of the source.

like image 961
Joshua Fox Avatar asked Dec 06 '10 13:12

Joshua Fox


2 Answers

As Aioobe said, you're not going to get the image from the Graphics2D alone. But if your sourceGraphics2D is coming from a Swing component you could try invoking its paint methods with your own Graphics2D instance. From there you can copy the interesting sub-region.

This is kind of a hack but it should work assuming you're using Swing objects.

class CopySwingPaintingSubRegion extends TheSourceType
{
       private BufferedImage bufImg;

       public CopySwingPaintingSubRegion()
       {
          bufImg = new BufferedImage(...);

          //Draw the original image into our bufImg for copying
          super.paintComponent(bufImg.createGraphics());
       }

       public BufferedImage getSubImage(int x, int y, int w, int h)
       {
          return bufImg.getSubImage(x,y,w,h);
       }
}
like image 118
Tansir1 Avatar answered Oct 06 '22 00:10

Tansir1


Short answer: Yes, you can

A Graphics2D object that has been created on a buffered Image knows the image but isn't willing to hand it back to you. If you don't mind using reflection, you can steal it back (reflection). The following code demonstrates the approach:

public class Graphics2DReflector {

   public static void main(String[] args) {
     // prepare the Graphics2D - note, we don't keep a ref to the image!
     final Graphics2D g2d = 
          new BufferedImage(100,100,BufferedImage.TYPE_INT_RGB).createGraphics();
     g2d.drawString("Reflected", 10, 50);


     JFrame frame = new JFrame("Reflected Image");
     // one Panel to show the image only known by g2d
     frame.getContentPane().add(new Panel() {
       @Overwrite
       public void paint(Graphics g) {
         try {
           SurfaceData data = ((SunGraphics2D) g2d).surfaceData;
           Field bufImg = BufImgSurfaceData.class.getDeclaredField("bufImg");
           bufImg.setAccessible(true);
           BufferedImage image = (BufferedImage) bufImg.get(data);
           g.drawImage(image,0,0,null);
         } catch (Exception oops) {
           oops.printStackTrace();
         }
       }
     });
     frame.setSize(200,200);
     frame.setVisible();
   }
}

Note: this depends on some Sun/Oracle classes and may not work with all Java VMs. At least it shows an approach and you may have to inspect the actual classes to get the fields.

like image 22
Andreas Dolk Avatar answered Oct 06 '22 00:10

Andreas Dolk