PNG 到 JPG 的转换问题
PNG to JPEC conversion issues
我有这个 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);
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);
}
}
您需要确保正确管理您的资源,在使用完后关闭或处置它们
您看到的是非照片图像中 JPEG 压缩的自然结果。 JPEG 依赖于人们无法注意到摄影图像中的小刻度。当从一种颜色突然变为另一种颜色时,您会看到伪影。
您可以通过量化 table 选择(大多数编码器中的质量设置)并且不以低于 Y 的速率对 Cb 和 Cr 分量进行采样来减少这种影响。
但是,对于您所展示的图像,您最好坚持使用 PNG。
我有这个 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);
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);
}
}
您需要确保正确管理您的资源,在使用完后关闭或处置它们
您看到的是非照片图像中 JPEG 压缩的自然结果。 JPEG 依赖于人们无法注意到摄影图像中的小刻度。当从一种颜色突然变为另一种颜色时,您会看到伪影。
您可以通过量化 table 选择(大多数编码器中的质量设置)并且不以低于 Y 的速率对 Cb 和 Cr 分量进行采样来减少这种影响。
但是,对于您所展示的图像,您最好坚持使用 PNG。