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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4367108/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 06:03:44  来源:igfitidea点击:

How do I copy part of one image to another?

javaimagegraphicsgraphics2dimage-clipping

提问by Joshua Fox

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

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

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

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



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

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

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

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

采纳答案by aioobe

First, some notes regarding Andreas_D answer below:

首先,关于 Andreas_D 答案的一些说明如下:

  • His code relies on sun.java2d.SunGraphics2Dwhich is an internal and undocumented OpenJDK class. This means that, while it might compile and run on your computer, it mightwill probably break if you distribute the code to other people. For a detailed discussion, see the official statementregarding 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)

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

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

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



how do I get that img from the sourceGraphics2D?

我如何从 img 中获取该 img sourceGraphics2D

I suspect you misunderstood the responsibility of the Graphics2Dclass.

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

You use the Graphics2Dclass 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 paintComponentmethod) or even a printer. So in other words, given a Graphics2Dobjects, there might not even exist an image!

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

So, as you probably understand, the Graphics2DAPI 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!)

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

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

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

回答by Tansir1

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.

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

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

这是一种技巧,但假设您使用的是 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);
       }
}

回答by Andreas Dolk

Short answer: Yes, you can

简短回答:是的,你可以

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

已在缓冲图像上创建的 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();
   }
}

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.

注意:这取决于某些 Sun/Oracle 类,并且可能不适用于所有 Java VM。至少它显示了一种方法,您可能必须检查实际类才能获取字段。

回答by kumado

If I understand it right, W3Schoolshas 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.

如果我理解正确的话,W3Schools有代码可以将图像的一部分放到画布上。如果你需要它作为另一个图像,你可以从那个画布上得到它。

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:

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

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