2013-10-25 26 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);