我有这个png文件并将其转换为jpg图像。
如您所见,圆圈周围的某些像素不像png图像中的圆圈那么平滑。
我有这个代码将png转换为jpeg。如何更新代码,以便消除圆圈周围的噪音。
BufferedImage bufferedJpgImage = new BufferedImage(inputPngImage.getWidth(null),
inputPngImage.getHeight(null),
BufferedImage.TYPE_INT_RGB);
Graphics2D g = bufferedImage.createGraphics();
g.drawImage(inputPngImage, 0, 0, bufferedJpgImage.getWidth(), bufferedJpgImage.getHeight(), Color.WHITE, null);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(bufferedJpgImage, "jpg", out);
答案 0 :(得分:1)
Jpeg使用有损压缩算法,这意味着修改了物理图像数据以减小图像大小。
您可以通过ImageIO
设置压缩级别,它有点乱,但它应该为您提供所需的控制。
基于Setting jpg compression level with ImageIO in Java的答案,您可以执行以下操作:
左边是原始BufferedImage
,右边是生成的JPEG
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.spi.ServiceRegistry;
import javax.imageio.stream.FileImageOutputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
try {
BufferedImage original = ImageIO.read(...);
BufferedImage bufferedJpgImage = new BufferedImage(original.getWidth(null),
original.getHeight(null),
BufferedImage.TYPE_INT_RGB);
Graphics2D g = bufferedJpgImage.createGraphics();
g.drawImage(original, 0, 0, original.getWidth(), original.getHeight(), Color.WHITE, null);
g.dispose();
File jpg = new File("tmp.jpg");
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
write(bufferedJpgImage, baos);
try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray())) {
BufferedImage image = ImageIO.read(bais);
JPanel panel = new JPanel();
panel.add(new JLabel(new ImageIcon(original)));
panel.add(new JLabel(new ImageIcon(image)));
JOptionPane.showMessageDialog(null, panel);
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static void write(BufferedImage capture, OutputStream to) throws IOException {
// use IIORegistry to get the available services
IIORegistry registry = IIORegistry.getDefaultInstance();
// return an iterator for the available ImageWriterSpi for jpeg images
Iterator<ImageWriterSpi> services = registry.getServiceProviders(ImageWriterSpi.class,
new ServiceRegistry.Filter() {
@Override
public boolean filter(Object provider) {
if (!(provider instanceof ImageWriterSpi)) {
return false;
}
ImageWriterSpi writerSPI = (ImageWriterSpi) provider;
String[] formatNames = writerSPI.getFormatNames();
for (int i = 0; i < formatNames.length; i++) {
if (formatNames[i].equalsIgnoreCase("JPEG")) {
return true;
}
}
return false;
}
},
true);
//...assuming that servies.hasNext() == true, I get the first available service.
ImageWriterSpi writerSpi = services.next();
ImageWriter writer = writerSpi.createWriterInstance();
// specifies where the jpg image has to be written
writer.setOutput(ImageIO.createImageOutputStream(to));
JPEGImageWriteParam jpegParams = new JPEGImageWriteParam(null);
jpegParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
jpegParams.setCompressionQuality(1f);
// writes the file with given compression level
// from your JPEGImageWriteParam instance
writer.write(null, new IIOImage(capture, null, null), jpegParams);
}
}
您需要确保正确管理资源,在完成资源后关闭或处理资源
答案 1 :(得分:0)
您所看到的是非摄影图像中JPEG压缩的自然结果。 JPEG依赖于人们无法注意到摄影图像中的小刻度。当从一种颜色到另一种颜色发生突然变化时,就会看到你看到的文物。
您可以通过量化表选择(大多数编码器中的质量设置)减少此效果,而不是以低于Y的速率对Cb和Cr分量进行采样。
然而,对于像你所展示的图像,你最好坚持使用PNG。