如何将一个图像的一部分复制到另一个图像?

时间:2010-12-06 13:59:47

标签: java image graphics graphics2d image-clipping

我想将一个图像的一部分复制到另一个较小的图像中:换句话说,复制一个子矩形。

我有一个 Graphics2D 对象,我可以为目标创建一个,我知道 targetGraphics2D.drawImage(Image img,....) ,但如何从 sourceGraphics2D 中获取 img


答案(根据aioobe):源需要是图像而不是 Graphics2D

Image.subImage()是获取源的相关部分的方法。

4 个答案:

答案 0 :(得分:3)

正如Aioobe所说,你不会单独从Graphics2D获取图像。但是如果你的sourceGraphics2D来自Swing组件,你可以尝试用你自己的Graphics2D实例调用它的paint方法。从那里你可以复制有趣的子区域。

这是一种黑客行为,但假设您正在使用Swing对象,它应该可以正常工作。

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);
       }
}

答案 1 :(得分:3)

简短回答:是的,你可以

已在缓冲的Image 上创建的Graphics2D对象知道图像但不愿意将其交还给您。如果你不介意使用反射,你可以偷回它(反射)。以下代码演示了该方法:

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();
   }
}

注意:这取决于某些Sun / Oracle类,并且可能无法与所有Java VM一起使用。至少它显示了一种方法,你可能必须检查实际的类来获取字段。

答案 2 :(得分:1)

如果我理解正确,W3Schools有代码可以将图像的一部分放在画布上。如果您需要它作为另一个图像,您可以从该画布中获取它。

我有一个20高200宽的PNG图像,有10个“细胞或帧” - 我用于动画并使用下面的方法:

context.drawImage( img, sx, sy, swidth, sheight, x, y, width, height );

答案 3 :(得分:0)

首先,关于Andreas_D的一些注释在下面回答:

  • 他的代码依赖于sun.java2d.SunGraphics2D,这是一个内部和未记录的OpenJDK类。这意味着,虽然它可能在您的计算机上编译并运行,但如果您将代码分发给其他人,可能可能会中断。有关详细讨论,请参阅official statement有关此内容。

  • 代码依赖于反射来撬开内部类打开,这本身就是代码味道。

  • 总而言之,他的方法是异常糟糕的练习的一个例子(无论是编程风格还是帮助其他程序员正确使用API​​)

  • p>

  

如何从sourceGraphics2D获取img?

我怀疑你误解了Graphics2D班的责任。

您使用Graphics2D类来绘制某些内容。它能够绘制BufferedImage(如果您从缓冲图像中获取图形对象),屏幕(如果您将其作为paintComponent方法的参数)或甚至是打印机。换句话说,给定Graphics2D个对象,甚至可能没有图像!

因此,正如您可能理解的那样,Graphics2D API不提供获取底层图像的方法。 (这种方法没有意义,图形对象可能正在传递线条和文本被绘制到打印机!)

要掌握子图像,您需要掌握给定图形对象所依据的底层图像。