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

发布于 2024-10-05 22:27:58 字数 319 浏览 0 评论 0原文

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

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


答案(根据 aioobe):源必须是Image,而不是Graphics2D

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

妄断弥空 2024-10-12 22:27:58

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

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);
       }
}
你列表最软的妹 2024-10-12 22:27:58

简短的回答:是的,您可以

在缓冲图像上创建的 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。至少它显示了一种方法,您可能必须检查实际的类才能获取字段。

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.

苦笑流年记忆 2024-10-12 22:27:58

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

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

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

If I understand it right, W3Schools has code to get part of an image to put on a canvas. If you need it as another image you could get it from that canvas.

I have one PNG image 20 tall by 200 wide that has 10 "cells or frames" - I use for animation and use the method below:

context.drawImage( img, sx, sy, swidth, sheight, x, y, width, height );
晚雾 2024-10-12 22:27:58

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

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

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

  • ,他的方法是极其糟糕的实践的一个例子(无论是在编程风格方面还是在帮助其他程序员正确使用 API 方面)


如何从 sourceGraphics2D 获取该 img?

我怀疑您误解了 Graphics2D 类的职责。

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

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

要获取子图像,您需要获取给定图形对象所绘制的底层图像。

First, some notes regarding Andreas_D answer below:

  • His code relies on sun.java2d.SunGraphics2D which is an internal and undocumented OpenJDK class. This means that, while it might compile and run on your computer, it might will probably break if you distribute the code to other people. For a detailed discussion, see the official statement regarding this.

  • The code relies on reflection to pry the internal class open which is a code smell in it self.

  • All in all, his approach is an example of exceptionally bad practice (both when it comes to programming style and when it comes to helping fellow programmers to use the API correctly)


how do I get that img from the sourceGraphics2D?

I suspect you misunderstood the responsibility of the Graphics2D class.

You use the Graphics2D class to draw on something. It is capable of drawing on a BufferedImage (if you got the graphics object from a buffered image), the screen (if you got it as an argument to your paintComponent method) or even a printer. So in other words, given a Graphics2D objects, there might not even exist an image!

So, as you probably understand, the Graphics2D API does not provide methods for getting hold of the underlying image. (Such method wouldn't make sense, the graphics object might be passing on lines and text being drawn to a printer!)

To get hold of a subimage you need to get hold of the underlying image which the given graphics object draws upon.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文