PNG到JPEC转换问题

时间:2015-06-30 03:19:48

标签: java image png jpeg draw

我有这个png文件并将其转换为jpg图像。

png image

如您所见,圆圈周围的某些像素不像png图像中的圆圈那么平滑。

jpg image

我有这个代码将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);

2 个答案:

答案 0 :(得分:1)

Jpeg使用有损压缩算法,这意味着修改了物理图像数据以减小图像大小。

您可以通过ImageIO设置压缩级别,它有点乱,但它应该为您提供所需的控制。

基于Setting jpg compression level with ImageIO in Java的答案,您可以执行以下操作:

Compared

左边是原始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。