-1

I have this png file and converted it to jpg image.

png image

As you can see, some pixels around the circles are not as smooth as the circles in the png image.

jpg image

I have this code to convert png to jpeg. How do I update the code so that I can remove the noise around the circles.

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);
codereviewanskquestions
  • 13,460
  • 29
  • 98
  • 167
  • 1
    jpeg is lossy see http://stackoverflow.com/questions/13204432/java-how-to-set-jpg-quality – BevynQ Jun 30 '15 at 03:22
  • 1. `dispose` of the `Graphics` context when you're done with it. 2. JPEG uses a lossy compression algorithm, meaning it will "merge" pixels in order to reduce the file size. You could have a look at [this](http://stackoverflow.com/questions/17108234/setting-jpg-compression-level-with-imageio-in-java) question for details about how to change the compression level – MadProgrammer Jun 30 '15 at 03:23

2 Answers2

1

Jpeg uses a lossy compression algorithm, this means that the physical image data is modified in order to reduce the image size.

You can set the compression level through ImageIO, it's a little messy, but it should provide you the control you need.

So based the answer from Setting jpg compression level with ImageIO in Java, you could do something like:

Compared

The left is the original BufferedImage and the right is the resulting 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);
    }

}

You need to make sure you're managing your resources properly, closing or disposing of them when you have finished with them

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0

What you are seeing is a natural consequence of JPEG compression in non-photographic images. JPEG relies on people not being able to notice small graduations in photographic images. When there is an abrupt change from one color to another, you get the artifacts you see.

You can reduce this effect by quantization table selection (quality settings in most encoders) and not sampling the Cb and Cr components at a lower rate than Y.

However, for an image like what you are showing, you are better off sticking with PNG.

user3344003
  • 20,574
  • 3
  • 26
  • 62