为啥加入小缓冲图像的 Java 代码不起作用?
Posted
技术标签:
【中文标题】为啥加入小缓冲图像的 Java 代码不起作用?【英文标题】:Why Java code to join small buffered images does not work?为什么加入小缓冲图像的 Java 代码不起作用? 【发布时间】:2021-10-10 09:17:48 【问题描述】:我创建了 4 个缓冲图像对象并用不同的颜色填充它们。然后创建一个更大的 bufferedimage 对象并将之前创建的所有四个 buff.image 绘制到其中以创建更大的图像。然后我将大图像保存到带有 gif 扩展名的文件中。虽然大小正确,但 gif 文件不包含颜色。为什么 ?我的错在哪里?
import java.awt.HeadlessException;
import java.awt.*;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class MainFrame extends JFrame implements Runnable
public MainFrame() throws HeadlessException
ImagePanel ip=new ImagePanel(this);
add(ip,"Center");
public static void main(String[] args)
MainFrame mf=new MainFrame();
mf.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
mf.setSize(new Dimension(800,600));
mf.setLocationRelativeTo(null);
mf.setVisible(true);
class ImagePanel extends JPanel
public ImagePanel(MainFrame jf)
ImageJoiner imj=new ImageJoiner();
class ImageJoiner
// this will joing four buffered images together to construct bigger image as buffered image and save it as gif file
public ImageJoiner()
createImages();
public void createImages()
imtl=new BufferedImage(PW, PH, BufferedImage.TYPE_INT_RGB);
imtr=new BufferedImage(PW, PH, BufferedImage.TYPE_INT_RGB);
imbl=new BufferedImage(PW, PH, BufferedImage.TYPE_INT_RGB);
imbr=new BufferedImage(PW, PH, BufferedImage.TYPE_INT_RGB);
bigW=PW*2;
bigH=PH*2;
bigmap=new BufferedImage(bigW, bigH, BufferedImage.TYPE_INT_RGB);
imtl.createGraphics().setColor(Color.blue);
imtl.createGraphics().fillRect(0,0, PW, PH);
imtr.getGraphics().setColor(Color.red);
imtr.getGraphics().fillRect(0, 0, PW, PH);
imbl.getGraphics().setColor(Color.green);
imbl.getGraphics().fillRect(0, 0, PW, PH);
imbr.getGraphics().setColor(Color.yellow);
imbr.getGraphics().fillRect(0, 0, PW, PH);
bigmap.getGraphics().drawImage(imtl, 0, 0,PW,PH,null);
bigmap.getGraphics().drawImage(imtr, PW, 0,PW,PH,null);
bigmap.getGraphics().drawImage(imbl, 0, PH, PW,PH,null);
bigmap.getGraphics().drawImage(imbr, PW, PH,PW,PH,null);
writeBufferedImageToFile(bigmap);
private void writeBufferedImageToFile(BufferedImage bim)
File file = new File("images/out.gif");
try
ImageIO.write(bim, "gif", file);
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();
static final int PW =1000;
static final int PH =1000;
static int bigW,bigH;
BufferedImage imtl,imtr,imbl,imbr;
BufferedImage bigmap;
【问题讨论】:
请注意,即使存储imtl
而不是bigmap
也会产生一个白色文件,而JFrame
是不必要的,因此您仍然可以将这个示例剪掉很多。跨度>
【参考方案1】:
您正在随意创建 Graphics 对象,设置一个对象的颜色,使用另一个对象进行绘图,这可能行不通。以更好的方式创建并使用您的 Graphics 对象,例如:
public static void createImages()
imtl = new BufferedImage(PW, PH, BufferedImage.TYPE_INT_RGB);
imtr = new BufferedImage(PW, PH, BufferedImage.TYPE_INT_RGB);
imbl = new BufferedImage(PW, PH, BufferedImage.TYPE_INT_RGB);
imbr = new BufferedImage(PW, PH, BufferedImage.TYPE_INT_RGB);
int bigW = PW * 2;
int bigH = PH * 2;
BufferedImage bigmap = new BufferedImage(bigW, bigH, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = imtl.createGraphics();
g2d.setColor(Color.BLUE);
g2d.fillRect(0,0, PW, PH);
g2d.dispose();
g2d = imtr.createGraphics();
g2d.setColor(Color.RED);
g2d.fillRect(0,0, PW, PH);
g2d.dispose();
g2d = imbl.createGraphics();
g2d.setColor(Color.GREEN);
g2d.fillRect(0,0, PW, PH);
g2d.dispose();
g2d = imbr.createGraphics();
g2d.setColor(Color.YELLOW);
g2d.fillRect(0,0, PW, PH);
g2d.dispose();
g2d = bigmap.createGraphics();
g2d.drawImage(imtl, 0, 0,PW,PH,null);
g2d.drawImage(imtr, PW, 0,PW,PH,null);
g2d.drawImage(imbl, 0, PH, PW,PH,null);
g2d.drawImage(imbr, PW, PH,PW,PH,null);
g2d.dispose();
writeBufferedImageToFile(bigmap);
代码经过测试,可以正常工作
你也问过:
我仍然很好奇,为什么
BufferedImage#getGraphics().fillRect()
不起作用?它只有你定义一个图形对象然后分配它才有效?为什么不能直接使用?
当BufferedImage#getGraphics()
或BufferedImage#createGraphics()
创建一个新 Graphics2D 实例时,该实例与之前创建的任何实例都没有关系。
例如,您可以通过调用来测试:
BufferedImage img = new BufferedImage(20, 20, BufferedImage.TYPE_INT_RGB);
Graphics ga = img.getGraphics();
Graphics gb = img.getGraphics();
System.out.println("ga: " + ga.hashCode());
System.out.println("gb: " + gb.hashCode());
ga.dispose(); // always dispose of resources that *you* create
gb.dispose();
运行这个程序,你会看到两个不同的 hashCodes被打印出来,证明ga和gb实例是不同的。如果您调用.createGraphics()
,将出现相同的相对输出。
所以,当你这样做时:
imtl.createGraphics().setColor(Color.blue);
imtl.createGraphics().fillRect(0,0, PW, PH);
您正在设置一个 Graphics 实例的颜色,然后使用另一个独特的新实例进行绘制。由于第二个实例的颜色没有设置,它会使用默认颜色进行绘制,所有图像都将保持黑色。
【讨论】:
呃......我已经很久没有做过任何 AWT 或 Swing,但那是非常不直观的,特别是因为该方法被称为getGraphics
:假设总是返回相同的 Graphics
,但这不是它指定要做的事情。
@JoachimSauer 始终使用createGraphics()
。它做同样的事情,但有一个更好的名字,你不需要转换为Graphics2D
。 ?
谢谢,它起作用了,但我仍然很好奇,为什么 以上是关于为啥加入小缓冲图像的 Java 代码不起作用?的主要内容,如果未能解决你的问题,请参考以下文章