2013-10-25 29 views
6

mam 10000x10000 BufferedImage i szukam zwrócić tylko część jej do Canvas, czy istnieje sposób to zrobić przy użyciu argumenty takie jak:Jak narysować część dużego obrazu BufferedImage?

x, y, width, height?

Na przykład drawImage (img, x, y, width, height) narysuje prostokąt od obrazu zaczynającego się na (x, y) i mającego (szerokość, wysokość) jako wymiary?

EDIT:

zamierzam ponownie słowo to pytanie:

Mam 10000x10000 obraz i chcę tylko, aby wyświetlić jego część na ekranie, problem z wyrównaniem tylko go przez x i y jest to, że nadal powoduje opóźnienie, gdy renderowany jest cały obraz, po prostu większość poza płótnem. Jak zasadniczo mogę zrobić tak, aby cały obraz był renderowany, ale mogę go przewijać bez powodowania opóźnienia obszaru roboczego?

+0

Edytowałem odpowiedź, odpowiadając na twoje pytanie. – Sage

Odpowiedz

17

mam 10000x10000 BufferedImage i szukam zwrócić tylko część go na płótnie, czy istnieje sposób to zrobić przy użyciu argumenty takie jak:

  1. Nie używaj płótna do niestandardowego malowania w Javie. zamiast tego użyj JComponent lub JPanel. Ma ładną funkcję paintComponent(Graphics g), nadpisuje ją i maluje obraz wewnątrz za pomocą g.drawImage(x, y, width, height, observer);

  2. Grafiki obrotowe mają Graphics.clipRect(int x, int y, int width, int height), aby związać prostokąt obszaru, który chcesz narysować przed rysowaniem obrazu.

Edit (W odpowiedzi na pytanie edytowanego):

pierwsze podejście jest użycie BufferedImage..getSubimage(x, y, width, height) dostać sub obraz z określonego regionu prostokąta. To jest szybsze.

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

Funkcja ta daje nowy obraz przycięty z rectangle(x, y, width, height) z oryginalnego obrazu, który określony. Użyj zwróconego obrazu, aby narysować swój komponent.

Tutorial zasób:Clipping the Drawing Region


Demo: Wykazanie wycinek obrazu z animacji:

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

Wierzę, że ta metoda w rzeczywistości powoduje skalowanie obrazu, aby zmieścił się wewnątrz określonego prostokąta, co nie jest tym, czego szukam. –

+0

Tak, masz rację, użyj tego zamiast: 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

można skalować lub narysować część obrazu za pomocą Graphics.drawImage jak wspomniano inny a nswer i zgodnie z dokumentacją Java argument ImageObserver nie jest potrzebny dla BufferedImage, więc możesz po prostu przekazać wartość null.

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

Jednak mój wybór byłby do strzyżenia rysunek region zamiast obrazu. Oto przykład, który możesz wypróbować:

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