如何绘制大型BufferedImage的一部分?

时间:2013-10-25 23:47:08

标签: java graphics rendering bufferedimage

我有一个10000x10000 BufferedImage而且我只想将其中的一部分绘制到Canvas,有没有办法使用args执行此操作,例如:

x, y, width, height

例如,drawImage(img,x,y,width,height)会从图像开始绘制一个矩形,从(x,y)开始,并以(width,height)为维度?

编辑:

我要重新提出这个问题:

我有一个10000x10000的图像,我只想在屏幕上显示它的一部分,只是用x和y偏移它的问题是,这仍然会导致整个图像渲染时出现延迟,只是大部分时间画布。我怎么能基本上这样做才能渲染整个图像,但我可以滚动它而不会导致画布滞后?

3 个答案:

答案 0 :(得分:19)

  

我有10000x10000 BufferedImage,我只想画一部分   对于Canvas来说,有没有办法使用args这样做:

  1. 不要在java中使用canvas进行自定义绘制。请改用JComponentJPanel。它有一个很好的函数paintComponent(Graphics g),覆盖它并用g.drawImage(x, y, width, height, observer)绘制你的图像;

  2. 在绘制图像之前,摆动图形具有Graphics.clipRect(int x, int y, int width, int height)以限制您想要绘制的区域矩形。

  3. 编辑(针对您编辑过的问题):

    第一种方法是使用BufferedImage..getSubimage(x, y, width, height)来获取具有指定矩形区域的子图像。它更快。

        BufferedImage img = ImageIO.read(new File("file")); 
        img = img.getSubimage(50, 50, 500, 500); // 500 x 500
    

    此功能将为您提供使用您指定的原始图像rectangle(x, y, width, height)裁剪的新图像。使用返回的图像在组件上绘制。

    教程资源: Clipping the Drawing Region


    演示:使用动画演示裁剪图像:

    enter image description here

    import java.awt.*;
    import java.awt.event.*;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.net.URL;
    import java.util.*;
    import java.util.logging.*;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    import javax.swing.Timer;
    
    class MyCanvas extends JPanel implements ActionListener
    {
      public BufferedImage buffImg;
      public Rectangle rectangle;
      Random random;
      long lastTimeChanged;
      int dirX = 1, dirY = 1;
      volatile static boolean imageLoading = true; 
        public MyCanvas() {
            random = new Random();
            rectangle = new Rectangle(50, 50, 250, 250);
            lastTimeChanged = System.currentTimeMillis();
            setBackground(Color.WHITE);
        }
    
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g); 
    
            if(imageLoading)
            {
                showWaitForLoading(g);
                return;
            }
    
            g.clipRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
            g.drawImage(buffImg, 0, 0, getWidth(), getHeight(), this);
    
        }
    
    
        public void showWaitForLoading(Graphics g)
        {
            Graphics2D g2d = (Graphics2D)g.create();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setColor(Color.DARK_GRAY);
            g2d.fillRoundRect(getWidth()/2-100, getHeight()/2-15, 200, 30, 30, 30);
            g2d.setColor(Color.WHITE);
            g2d.drawString("Loading image...", getWidth()/2 - 45, getHeight()/2 + 3 );
            g2d.dispose();
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
    
            long endTime = System.currentTimeMillis();
            if(endTime - lastTimeChanged > 500)
            {
                dirX = random.nextInt(2) == 0 ? -1 : 1;
                dirY = random.nextInt(2) == 0 ? -1 : 1;
                lastTimeChanged = endTime;
            }
    
            if(rectangle.x < 0)dirX = 1;
            else if(rectangle.x + rectangle.width > getWidth())dirX = -1;
    
            if(rectangle.y < 0)dirY = 1;
            else if(rectangle.y + rectangle.height > getHeight())dirY = -1;
    
            rectangle.x = rectangle.x + dirX * 10;
            rectangle.y = rectangle.y + dirY * 10;;
    
            repaint();
        }
    
    }
    public class CustomPainting {
    
    
        public static void main(String[] args) throws IOException {
    
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                   final MyCanvas canvas = new MyCanvas();
                   JFrame frame = new JFrame();
                  frame.setSize(new Dimension(500, 500));
                  frame.add(canvas);
                  frame.setVisible(true);
                  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
                  Timer timer = new Timer(200, canvas);
                  timer.start();
                  new Thread()
                  {
                      public void run()
                      {
                          try {
                              canvas.buffImg = ImageIO.read(new URL("http://images6.fanpop.com/image/photos/33400000/Cute-Panda-beautiful-pictures-33434826-500-500.jpg"));
                              MyCanvas.imageLoading = false;
                          } catch (IOException ex) {
                              Logger.getLogger(CustomPainting.class.getName()).log(Level.SEVERE, null, ex);
                          }
                      }
                  }.start();
                }
            });
        }
    }
    

答案 1 :(得分:0)

答案 2 :(得分:0)

您可以使用Graphics.drawImage缩放或绘制图像的一部分,如另一个答案所述,根据Java文档,BufferedImage不需要ImageObserver参数,因此您只能传递null。

http://docs.oracle.com/javase/7/docs/api/java/awt/Graphics.html

但是,我的选择将是图像的剪切绘图区域。 以下是您可以尝试的示例:

Graphics2D g = BufferedImage.getGraphics;
g.setClip(x, y, width, height);
g.drawImage(sx, sy, x - sx, y - sy, null );