我有一个BufferedImage对象,我想将其编码为BMP格式并将其保存到磁盘.
我该怎么做呢?
在JPEG它没关系:
BufferedImage img; //here is an image ready to be recorded into the hard disk
FileOutputStream fout = new FileOutputStream("image.jpg");
JPEGImageEncoder jencoder = JPEGCodec.createJPEGEncoder(fout);
JPEGEncodeParam enParam = jencoder.getDefaultJPEGEncodeParam(img);
enParam.setQuality(1.0F, true);
jencoder.setJPEGEncodeParam(enParam);
jencoder.encode(img);
fout.close();
Run Code Online (Sandbox Code Playgroud) 我在保存大型(12 000 x 9 000)图像方面遇到了问题.
我正在开发一个图形编辑软件(类似于简单的Photoshop),用户显然必须能够保存图像.
让我们说我想将图像保存为.png.JAVA总是需要使用BufferedImage来保存绘制的东西吗?
我知道图像大小的等式是:Xsize*Ysize*4(红色,绿色,蓝色,alpha)所以在这种情况下,我们得到超过400 MB.
我知道我可以将图像保存在部分(图块)中,但用户必须以某种方式合并它们.
有没有其他方法可以在不使用BufferedImage的情况下保存这么大的图像?
保存图片的代码:
public static void SavePanel() {
BufferedImage image = null;
image = new BufferedImage(
(int) (Main.scale * sizeX ),
(int) (Main.scale * sizeY ),
BufferedImage.TYPE_INT_RGB);
g2 = image.createGraphics();
panel.paint(g2);
try {
ImageIO.write(image, "png", new File(FactoryDialog.ProjectNameTxt.getText() + ".png"));
} catch (IOException e) {
}
}
Run Code Online (Sandbox Code Playgroud)
先感谢您 !
我已经看过这个问题,但它似乎没有真正回答我的问题.我有一个图像文件,可能是任何分辨率.我需要以BufferedImage特定分辨率将该图像加载到对象中(例如,对于此示例,800x800).我知道Image类可以getScaledInstance()用来将图像缩放到一个新的大小,但我无法弄清楚如何将它恢复到一个新的大小BufferedImage.有没有一种简单的方法可以将缓冲图像缩放到特定大小?
注意 II不希望按特定因子缩放图像,我想拍摄图像并制作特定尺寸.
我正在使用这里JScrollNavigator描述的组件,以便为我嵌入的大型"画布式"CAD组件提供导航窗口.JScrollPane
我已经尝试调整JScrollNavigator绘制画布的缩略图以向用户提供一些额外的上下文.但是,执行此操作会导致应用程序主框架的呈现损坏.具体来说,它是调用paint(Graphics)视口组件(即我的主画布)的动作,传入由此Graphics创建的对象BufferedImage导致后续显示损坏; 如果我评论这一行,一切正常.
以下是JScrollNavigator被覆盖的paintComponent方法:
@Override
protected void paintComponent(Graphics g) {
Component view = jScrollPane.getViewport().getView();
BufferedImage img = new BufferedImage(view.getWidth(), view.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
// Paint JScrollPane view to off-screen image and then scale.
// It is this action that causes the display corruption!
view.paint(g2d);
g2d.drawImage(img, 0, 0, null);
Image scaled = img.getScaledInstance(getWidth(), getHeight(), 0);
super.paintComponent(g);
g.drawImage(scaled, 0, 0, null);
}
Run Code Online (Sandbox Code Playgroud)
有没有人对腐败的原因有任何建议?我原本以为绘画到幕外图像应该对现有的绘画操作没有影响.
编辑 …
我想得到一个缓冲图像的缩放实例,我做了:
public void analyzePosition(BufferedImage img, int x, int y){
img = (BufferedImage) img.getScaledInstance(getWidth(), getHeight(), Image.SCALE_SMOOTH);
....
}
Run Code Online (Sandbox Code Playgroud)
但我得到一个例外:
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: sun.awt.image.ToolkitImage cannot be cast to java.awt.image.BufferedImage
at ImagePanel.analyzePosition(ImagePanel.java:43)
Run Code Online (Sandbox Code Playgroud)
然后我想要转换为ToolkitImage使用getBufferedImage我在其他文章中读到的方法.问题是没有类,例如sun.awt.image.ToolkitImage我无法投射它,因为Eclipse甚至没有看到这个类.我用Java 1.7和jre1.7.

在我的代码中,我有一个像ImageIO类一样加载的BufferedImage,如下所示:
BufferedImage image = ImageIO.read(new File (filePath);
Run Code Online (Sandbox Code Playgroud)
后来,我想将它保存为一个字节数组,但ImageIO.write方法需要我来接的GIF,PNG,或JPG格式来写我的图像(如本教程中介绍这里).
我想选择与原始图像相同的文件类型.如果图像最初是GIF,我不希望将其保存为PNG的额外开销.但如果图像最初是PNG,我不想失去半透明性,并将其保存为JPG或GIF.有没有办法可以从BufferedImage中确定原始文件格式是什么?
我知道我可以简单地解析文件路径,当我加载图像以找到扩展名并将其保存以供日后使用时,但理想情况下我喜欢直接从BufferedImage执行此操作.
我有以下代码用于创建光栅图像.
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
Graphics g = img.getGraphics();
g.setColor(backgroundColour);
g.fillRect(0, 0, width, height);
Run Code Online (Sandbox Code Playgroud)
这在我的Windows机器和本地Ubuntu机器上运行,但是当转移到服务器时尝试调用X11服务器,显示堆栈跟踪.我怎么能阻止这个?
Exception in thread "main" java.lang.InternalError: Can't connect to X11
window server using 'localhost:10.0' as the value of the DISPLAY variable.
at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)
at
sun.awt.X11GraphicsEnvironment.access$200(X11GraphicsEnvironment.java:62)
at
sun.awt.X11GraphicsEnvironment$1.run(X11GraphicsEnvironment.java:178)
at java.security.AccessController.doPrivileged(Native Method)
at
sun.awt.X11GraphicsEnvironment.<clinit>(X11GraphicsEnvironment.java:142)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:190)
at
java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:82)
at
java.awt.image.BufferedImage.createGraphics(BufferedImage.java:1164)
at java.awt.image.BufferedImage.getGraphics(BufferedImage.java:1154)
at
org.xmlcml.cml.converters.molecule.fragments.Cml2PngTool.renderMolecule(Cml2PngTool.java:94)
at
org.xmlcml.cml.converters.molecule.fragments.Cml2PngTool.renderMolecule(Cml2PngTool.java:61)
at
org.xmlcml.cml.converters.molecule.fragments.FragmentGenerator.add2DCoordsAndRender(FragmentGenerator.java:180)
at
org.xmlcml.cml.converters.molecule.fragments.FragmentGenerator.write2dImage(FragmentGenerator.java:169)
at
org.xmlcml.cml.converters.molecule.fragments.FragmentGenerator.output2dImages(FragmentGenerator.java:486)
at
org.xmlcml.cml.converters.molecule.fragments.FragmentGenerator.generateMoieties(FragmentGenerator.java:443)
at
org.xmlcml.cml.converters.molecule.fragments.FragmentGenerator.createMoietiesAndFragments(FragmentGenerator.java:125)
at
org.xmlcml.cml.converters.molecule.fragments.CML2FragmentConverter.convert(CML2FragmentConverter.java:47)
at
org.xmlcml.cml.converters.AbstractConverter.process(AbstractConverter.java:1067)
at …Run Code Online (Sandbox Code Playgroud) (使用java 8)鉴于图像用户需要能够以像素为单位指定最小/最大图像大小,并且还需要以kbs为单位指定已保存图像的最大大小,图像将保存为jpg.
所以我通过调整缓冲图像的大小来完成第一个工作:
public static BufferedImage resizeUsingImageIO(Image srcImage, int size)
{
int w = srcImage.getWidth(null);
int h = srcImage.getHeight(null);
// Determine the scaling required to get desired result.
float scaleW = (float) size / (float) w;
float scaleH = (float) size / (float) h;
MainWindow.logger.finest("Image Resizing to size:" + size + " w:" + w + ":h:" + h + ":scaleW:" + scaleW + ":scaleH" + scaleH);
//Create an image buffer in which to paint on, create as an opaque …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用OpenCV Java API创建一个辅助函数,该函数将处理输入图像并返回输出字节数组.输入图像是保存在计算机中的jpg文件.输入和输出图像使用Swing显示在Java UI中.
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// Load image from file
Mat rgba = Highgui.imread(filePath);
Imgproc.cvtColor(rgba, rgba, Imgproc.COLOR_RGB2GRAY, 0);
// Convert back to byte[] and return
byte[] return_buff = new byte[(int) (rgba.total() * rgba.channels())];
rgba.get(0, 0, return_buff);
return return_buff;
Run Code Online (Sandbox Code Playgroud)
当return_buff返回并转换为BufferedImage时,我得到NULL.当我注释掉该Imgproc.cvtColor函数时,它return_buff被正确转换为我可以显示的BufferedImage.好像Imgproc.cvtColor是返回一个我无法在Java中显示的Mat对象.
这是我从byte []转换为BufferedImage的代码:
InputStream in = new ByteArrayInputStream(inputByteArray);
BufferedImage outputImage = ImageIO.read(in);
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,outputImage为NULL
有人有任何建议或想法吗?
我正在开发一个程序,它接受一个字符串,将字符串的每个字符变成一种颜色,然后在图像上从左到右,从上到下绘制颜色.然后可以使用相同的程序对图像进行解码以获得原始消息.举个例子,这里clojure.core编码为图像:
我把它写成一个玩具,但我注意到它产生的图像有一个有趣的属性:它们比原始信息的文本要小.对于clojure.core,它是259kb作为文本,但只有88.9kb作为图像(上图)(两个值都是"磁盘上的大小").为了确保数据不会丢失,我解码了图像,然后收回原始消息.
这怎么可能?我认为图像(png格式)会有标题和其他额外的信息,这会增加大小.
整个clojure.core包含265486个字符(根据Notepad ++),这意味着每个字符基本上占用一个字节.
从使用BufferedImage类(Java),看起来好像颜色存储为4字节整数,所以不应该每个像素需要大约4倍的内存?
以下是它的编码方式:
弹出字符串的第一个字符
通过获取它的ASCII值,将其乘以一个大数字(因此它更好地覆盖可能的颜色范围),然后将该数字转换为3位数,基数为256的数字([123 100 200]),将其转换为颜色.
每个数字被视为红色,绿色和蓝色信道,其被给予BufferedImage的setRGB方法.
所述position指示器前进,下一个字符被弹出,并重复该过程,直到整个消息进行编码.
这个算法现在有点复杂.@Thumbnail在Code Review上提出了一个更好的方法,但我还没有实现它.由于结果是相同的,这不应该对问题产生影响.