5

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

我有一个用于源的Graphics2D对象,我可以为目标制作一个对象,并且我知道targetGraphics2D.drawImage(Image img,....),但是如何从sourceGraphics2D获取该img


答案(按 aioobe):源需要是Image而不是Graphics2D

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

4

4 回答 4

3

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

这是一种 hack,但假设您使用的是 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);
       }
}
于 2010-12-06T14:57:27.337 回答
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。至少它显示了一种方法,您可能必须检查实际的类才能获取字段。

于 2010-12-06T15:04:44.003 回答
1

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

我有一个 20 高 x 200 宽的 PNG 图像,它有 10 个“单元格或框架” - 我用于动画并使用以下方法:

context.drawImage( img, sx, sy, swidth, sheight, x, y, width, height );
于 2013-11-07T13:44:17.323 回答
0

首先,关于 Andreas_D 答案的一些注释如下:

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

  • 该代码依靠反射来撬开内部类,这本身就是一种代码气味。

  • 总而言之,他的方法是一个非常糟糕的实践示例(无论是在编程风格方面还是在帮助其他程序员正确使用 API 方面)


我如何从那里得到那个img sourceGraphics2D

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

你使用这个Graphics2D类来绘制一些东西。它能够在BufferedImage(如果您从缓冲图像中获取图形对象)、屏幕(如果您将其作为paintComponent方法的参数)甚至打印机上绘图。所以换句话说,给定一个Graphics2D对象,甚至可能不存在图像!

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

要获取子图像,您需要获取给定图形对象绘制的基础图像。

于 2010-12-06T14:07:16.343 回答