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

我有一个10000×10000 BufferedImage ,我希望只将其中的一部分绘制到Canvas ,有没有办法使用args这样做:

x, y, width, height

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

编辑:

我要重新提出这个问题:

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

我有一个10000×10000 BufferedImage,我希望只将其中的一部分绘制到Canvas,有没有办法使用args这样做:

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

  2. Swing图形具有Graphics.clipRect(int x, int y, int width, int height) ,用于在绘制图像之前绑定要绘制的区域矩形。

编辑(回复您编辑的问题):

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

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

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

教程资源: 剪切绘图区域


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

在此处输入图像描述

 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(); } }); } } 

您可以使用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 ); 

是的有: drawImage(Image img, int x, int y, int width, int height, ImageObserver observer)