Как скопировать часть одного изображения в другое? - PullRequest
5 голосов
/ 06 декабря 2010

Я хочу скопировать часть одного изображения в другое, меньшее: другими словами, скопировать прямоугольник.

У меня есть Graphics2D объект для источника, я могу сделать его для цели, и я знаю о targetGraphics2D.drawImage (Image img, ....) , но как мне получить этот img от sourceGraphics2D ?


Ответ (за aioobe): Источник должен быть Изображение, а не Graphics2D .

Image.subImage () - метод получения соответствующей части источника.

Ответы [ 4 ]

3 голосов
/ 06 декабря 2010

Как сказал Aioobe, вы не получите изображение только от Graphics2D.Но если ваш sourceGraphics2D исходит из компонента Swing, вы можете попробовать вызвать его методы рисования с вашим собственным экземпляром Graphics2D.Оттуда вы можете скопировать интересный субрегион.

Это своего рода хак, но он должен работать, если вы используете объекты 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);
       }
}
3 голосов
/ 06 декабря 2010

Краткий ответ: Да, вы можете

Объект 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. По крайней мере, это показывает подход, и вам, возможно, придется проверить фактические классы, чтобы получить поля.

1 голос
/ 07 ноября 2013

Если я правильно понимаю, W3Schools имеет код, чтобы получить часть изображения для размещения на холсте. Если вам нужно это как другое изображение, вы можете получить его из этого холста.

У меня есть одно PNG-изображение высотой 20 на 200, которое имеет 10 "ячеек или кадров" - я использую для анимации и использую метод ниже:

context.drawImage( img, sx, sy, swidth, sheight, x, y, width, height );
0 голосов
/ 06 декабря 2010

Во-первых, некоторые примечания относительно ответа Andreas_D ниже:

  • Его код опирается на sun.java2d.SunGraphics2D, который является внутренним и недокументированным классом OpenJDK.Это означает, что, хотя он может компилироваться и запускаться на вашем компьютере, он может , вероятно, сломается, если вы передадите код другим людям.Подробное обсуждение см. В официальном заявлении относительно этого.

  • Код основан на рефлексии, чтобы вырвать открытый внутренний класс, который сам по себе является запахом кода.

  • В целом его подход является примером исключительно плохой практики (как в том, что касается стиля программирования, так и в том, что касается помощи другим программистам в использованииAPI правильно)


как мне получить это изображение от sourceGraphics2D?

Я подозреваю, что вы неправильно поняли ответственностьGraphics2D класс.

Вы используете класс Graphics2D для рисования чего-либо.Он способен рисовать на BufferedImage (если вы получили графический объект из буферизованного изображения), на экране (если вы получили его в качестве аргумента для вашего paintComponent метода) или даже на принтере.Другими словами, с учетом Graphics2D объектов изображение может даже не существовать!

Итак, как вы, наверное, понимаете, API Graphics2D не предоставляет методов для получения базового изображения.(Такой метод не имеет смысла, графический объект может передаваться по линиям, а текст выводится на принтер!)

Чтобы получить изображение, вам нужно получить изображение, лежащее в основе данного изображения.графический объект опирается на.

...