2013-10-25 15 views
6

Tôi có một 10000x10000 BufferedImage và tôi đang tìm để vẽ chỉ là một phần của nó vào một Canvas, là có một cách để làm điều này bằng args như:Làm cách nào để vẽ một phần của BufferedImage lớn?

x, y, width, height?

Ví dụ: drawImage (img, x, y, chiều rộng, chiều cao) sẽ vẽ hình chữ nhật từ hình ảnh bắt đầu tại (x, y) và có (chiều rộng, chiều cao) làm thứ nguyên?

EDIT:

Tôi sẽ để lại lời câu hỏi này:

Tôi có một hình ảnh 10000x10000 và tôi chỉ muốn hiển thị một phần của nó trên màn hình, vấn đề chỉ với bù đắp nó bởi x và y là điều này vẫn gây ra độ trễ khi toàn bộ hình ảnh đang được hiển thị, hầu hết trong số đó là tắt canvas. Làm thế nào về cơ bản tôi có thể làm cho nó để toàn bộ hình ảnh được trả lại nhưng tôi có thể di chuyển xung quanh nó mà không gây ra các canvas để tụt hậu?

+0

Tôi đã chỉnh sửa câu trả lời với câu trả lời cho câu hỏi của bạn. – Sage

Trả lời

17

Tôi có một 10000x10000 BufferedImage và tôi đang tìm để vẽ chỉ là một phần của nó vào một Canvas, là có một cách để làm điều này bằng args như:

  1. Không sử dụng canvas để sơn tùy chỉnh trong java. sử dụng JComponent hoặc JPanel thay thế. Nó có một chức năng tốt đẹp paintComponent(Graphics g), ghi đè lên nó và vẽ hình ảnh của bạn bên trong với g.drawImage(x, y, width, height, observer);

  2. Đồ họa xoay có Graphics.clipRect(int x, int y, int width, int height) để gắn hình chữ nhật khu vực mà bạn muốn vẽ trước khi vẽ hình ảnh.

Chỉnh sửa (Trả lời câu hỏi đã chỉnh sửa của bạn):

phương pháp đầu tiên là sử dụng BufferedImage..getSubimage(x, y, width, height) để có được một hình ảnh phụ với khu vực hình chữ nhật xác định. Nó nhanh hơn.

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

Chức năng này sẽ cung cấp cho bạn một hình ảnh mới được cắt với rectangle(x, y, width, height) của hình ảnh gốc bạn đã chỉ định. Sử dụng hình ảnh được trả về để vẽ trên thành phần của bạn.

tài nguyên Hướng dẫn:Clipping the Drawing Region


Demo: Thể hiện cắt hình ảnh với Animation:

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

Tôi tin rằng phương pháp này thực sự tái tỷ lệ hình ảnh để vừa với hình chữ nhật được chỉ định, đó không phải là những gì tôi đang tìm kiếm. –

+0

Có bạn đã đúng, hãy sử dụng thay vào đó: 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

Bạn có thể mở rộng hoặc vẽ một phần của một hình ảnh sử dụng Graphics.drawImage như đã đề cập khác nswer và theo tài liệu Java, đối số ImageObserver là không cần thiết cho BufferedImage, do đó bạn chỉ có thể vượt qua null.

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

Tuy nhiên, sự lựa chọn của tôi sẽ là clipping vẽ khu vực của hình ảnh để thay thế. Dưới đây là ví dụ bạn có thể thử:

Graphics2D g = BufferedImage.getGraphics; 
g.setClip(x, y, width, height); 
g.drawImage(sx, sy, x - sx, y - sy, null); 
Các vấn đề liên quan