2013-10-25 25 views
6

我有一个10000x10000 BufferedImage,我希望只是其中的一部分绘制到一个Canvas,是有办法做到这一点使用ARGS如:如何绘制大型BufferedImage的一部分?

x, y, width, height?因此,例如,drawImage(img,x,y,width,height)会从图像(x,y)开始绘制一个矩形,并将(宽度,高度)作为尺寸来绘制矩形。

编辑:

我会重新字这个问题:

我有一个10000x10000形象,我只是想显示在屏幕上的部分,只抵消它的问题由x和y表示,当整个图像被渲染时,这仍然会造成滞后,而其中大部分都是在画布之外。我如何基本上做到这一点,使整个图像呈现,但我可以滚动它,而不会导致画布滞后?

+0

我编辑了答案并回答了您的问题。 – Sage

回答

17

我有一个10000x10000的BufferedImage,我希望只是其中的一部分 画到画布,是有办法做到这一点使用ARGS如:

  1. 在java中不要使用画布进行自定义绘画。改为使用JComponentJPanel。它有一个很好的功能paintComponent(Graphics g),覆盖它并用g.drawImage(x, y, width, height, observer)在内部绘制图像;

  2. 摆动图形有​​在绘制图像之前绑定要绘制的区域矩形。

编辑(在回答你的问题编辑):

第一种方法是使用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(); 
      } 
     }); 
    } 
} 
0
+0

我相信这种方法实际上重新缩放图像,以适应指定的矩形内,这不是我正在寻找的。 –

+0

是的,你是对的,用它代替:http://docs.oracle.com/javase/6/docs/api/java/awt/Graphics.html#drawImage(java.awt.Image,int,int,int, int,int,int,int,int,java.awt.Color,java.awt.image.ImageObserver) –

0

您可以缩放或使用绘制图像的一部分Graphics.drawImage如另外提到的a根据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);