-2

The code is being modified a bit . I added a button to the Jpanel whose action event save the image on the disk .

Source Code

    package ImageResize;

    import java.awt.image.BufferedImage;

        import java.awt.*;
    import java.awt.event.*;
    import java.awt.image.RenderedImage;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.swing.*;
    import javax.swing.event.*;
    import javax.imageio.*;
    import java.io.*;
    import javax.imageio.stream.ImageOutputStream;
    import javax.imageio.plugins.jpeg.JPEGImageWriteParam;


     import java.util.Locale;
        import javax.swing.filechooser.FileNameExtensionFilter;

    class ImageCompressionDemo {

        private BufferedImage originalImage;
        private BufferedImage textImage;

        private JPanel gui;

        private JCheckBox antialiasing;
        private 

JCheckBox rendering;
    private JCheckBox fractionalMetrics;
    private JCheckBox strokeControl;
    private JCheckBox colorRendering;
    private JCheckBox dithering;

    private JComboBox textAntialiasing;
    private JComboBox textLcdContrast;

    private JLabel jpegLabel;
    private JLabel pngLabel;

    private JTextArea output;

    private JSlider quality;
    private JButton saveButton;

    private int pngSize;
    private int jpgSize;

    final static Object[] VALUES_TEXT_ANTIALIASING = {
        RenderingHints.VALUE_TEXT_ANTIALIAS_OFF,
        RenderingHints.VALUE_TEXT_ANTIALIAS_ON,
        RenderingHints.VALUE_TEXT_ANTIALIAS_GASP,
        RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR,
        RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB,
        RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR,
        RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB
    };

        final static Object[] VALUES_TEXT_LCD_CONTRAST = {
            new Integer(100),
            new Integer(150),
            new Integer(200),
            new Integer(250)
        };

        ImageCompressionDemo(BufferedImage inputImage) {
            int width = 280;
            int height = 100;

            gui = new JPanel(new BorderLayout(3,4));
            gui.setPreferredSize(new Dimension(400, 600));
            quality = new JSlider(JSlider.VERTICAL, 0, 100, 50);
            quality.setSnapToTicks(true);
            quality.setPaintTicks(true);
            quality.setPaintLabels(true);
            quality.setMajorTickSpacing(10);
            quality.setMinorTickSpacing(1);

            quality.addChangeListener( new ChangeListener(){
                public void stateChanged(ChangeEvent ce) {
                    updateImages();
                }
            } );
            gui.add(quality, BorderLayout.WEST);
             originalImage = inputImage;
               textImage =inputImage;

            JPanel controls = new JPanel(new GridLayout(0,1,0,0));
            antialiasing = new JCheckBox("Anti-aliasing", false);
            rendering = new JCheckBox("Rendering - Quality", true);
            fractionalMetrics = new JCheckBox("Fractional Metrics", true);
            strokeControl = new JCheckBox("Stroke Control - Pure", false);
            colorRendering = new JCheckBox("Color Rendering - Quality", true);
            dithering = new JCheckBox("Dithering", false);
            saveButton =new JButton("Save Image");



    saveButton.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
                    try {

                     BufferedImage img = (BufferedImage)getJpegCompressedImage(originalImage);
                        File outputfile = new File("C:/Users/uday/Desktop/newImage.jpg");
                           ImageIO.write(img, "jpg", outputfile);
                    } catch (IOException ex) {
                        Logger.getLogger(ImageCompressionDemo.class.getName()).log(Level.SEVERE, null, ex);
                    }
        } });


        controls.add(antialiasing);

        controls.add(fractionalMetrics);

        textLcdContrast = new JComboBox(VALUES_TEXT_LCD_CONTRAST);
        JPanel lcdContrastPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        lcdContrastPanel.add(textLcdContrast);
        lcdContrastPanel.add(new JLabel("Text LCD Contrast"));
        controls.add(lcdContrastPanel);

        textAntialiasing = new JComboBox(VALUES_TEXT_ANTIALIASING);
        controls.add(textAntialiasing);

        controls.add(dithering);
        controls.add(rendering);
        controls.add(colorRendering);
        controls.add(strokeControl);


        ItemListener itemListener = new ItemListener(){
            public void itemStateChanged(ItemEvent e) {
                updateImages();
            }
        };
        antialiasing.addItemListener(itemListener);
        rendering.addItemListener(itemListener);
        fractionalMetrics.addItemListener(itemListener);
        strokeControl.addItemListener(itemListener);
        colorRendering.addItemListener(itemListener);
        dithering.addItemListener(itemListener);

        textAntialiasing.addItemListener(itemListener);
        textLcdContrast.addItemListener(itemListener);

        Graphics2D g2d = originalImage.createGraphics();

        gui.add(controls, BorderLayout.EAST);

           gui.add(saveButton,BorderLayout.BEFORE_FIRST_LINE);




           JPanel images = new JPanel(new GridLayout(0,1,2,2));
        images.add(new JLabel(new ImageIcon(textImage)));



        try {
            pngLabel = new JLabel(new ImageIcon(getPngCompressedImage(textImage)));
            images.add(pngLabel);
            jpegLabel = new JLabel(new ImageIcon(getJpegCompressedImage(textImage)));
            images.add(jpegLabel);
        } catch(IOException ioe) {
        }

        gui.add(images, BorderLayout.CENTER);
        output = new JTextArea(4,40);
        output.setEditable(false);
        gui.add(new JScrollPane(output), BorderLayout.SOUTH);

        updateImages();

        JOptionPane.showMessageDialog(null, gui);
    }

    private Image getPngCompressedImage(BufferedImage image) throws IOException {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        ImageIO.write( image, "png", outStream );

        pngSize = outStream.toByteArray().length;

        BufferedImage compressedImage =
            ImageIO.read(new ByteArrayInputStream(outStream.toByteArray()));

        return compressedImage;
    }

    private Image getJpegCompressedImage(BufferedImage image) throws IOException {
        float qualityFloat = (float)quality.getValue()/100f;
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();

        ImageWriter imgWriter = ImageIO.getImageWritersByFormatName( "jpg" ).next();
        ImageOutputStream ioStream = ImageIO.createImageOutputStream( outStream );
        imgWriter.setOutput( ioStream );

        JPEGImageWriteParam jpegParams = new JPEGImageWriteParam( Locale.getDefault() );
        jpegParams.setCompressionMode( ImageWriteParam.MODE_EXPLICIT );
        jpegParams.setCompressionQuality( qualityFloat );

        imgWriter.write( null, new IIOImage( image, null, null ), jpegParams );

        ioStream.flush();
        ioStream.close();
        imgWriter.dispose();

        jpgSize = outStream.toByteArray().length;

        BufferedImage compressedImage = ImageIO.read(new ByteArrayInputStream(outStream.toByteArray()));
        return compressedImage;
    }

    private void updateText() {
        StringBuilder builder = new StringBuilder();

        builder.append("Fractional Metrics: \t");
        builder.append( fractionalMetrics.isSelected() );
        builder.append("\n");
        builder.append( textAntialiasing.getSelectedItem() );
        builder.append("\nPNG size: \t");
        builder.append(pngSize);
        builder.append(" bytes\n");
        builder.append("JPG size: \t");
        builder.append(jpgSize);
        builder.append(" bytes \tquality: ");
        builder.append(quality.getValue());

        output.setText(builder.toString());
    }

    private void updateImages() {
        int width = originalImage.getWidth();
        int height = originalImage.getHeight();

        Graphics2D g2dText = textImage.createGraphics();

        if (antialiasing.isSelected()) {
            g2dText.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        } else {
            g2dText.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_OFF);
        }

        if (rendering.isSelected()) {
            g2dText.setRenderingHint(RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);
        } else {
            g2dText.setRenderingHint(RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_SPEED);
        }

        if (fractionalMetrics.isSelected()) {
            g2dText.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
                RenderingHints.VALUE_FRACTIONALMETRICS_ON);
        } else {
            g2dText.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
                RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
        }

        if (strokeControl.isSelected()) {
            g2dText.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
                RenderingHints.VALUE_STROKE_NORMALIZE);
        } else {
            g2dText.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
                RenderingHints.VALUE_STROKE_PURE);
        }

        if (dithering.isSelected()) {
            g2dText.setRenderingHint(RenderingHints.KEY_DITHERING,
                RenderingHints.VALUE_DITHER_ENABLE);
        } else {
            g2dText.setRenderingHint(RenderingHints.KEY_DITHERING,
                RenderingHints.VALUE_DITHER_DISABLE);
        }

        if (colorRendering.isSelected()) {
            g2dText.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
                RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        } else {
            g2dText.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
                RenderingHints.VALUE_COLOR_RENDER_SPEED);
        }

        g2dText.setRenderingHint(RenderingHints.KEY_TEXT_LCD_CONTRAST,
            textLcdContrast.getSelectedItem());

        g2dText.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
            textAntialiasing.getSelectedItem());

        g2dText.drawImage(originalImage, 0,0, null);

        try {
            jpegLabel.setIcon(new ImageIcon(getJpegCompressedImage(textImage)));
            pngLabel.setIcon(new ImageIcon(getPngCompressedImage(textImage)));
        } catch(IOException ioe) {
        }

        gui.repaint();
        updateText();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater( new Runnable() {
            public void run() {
                try {
                    FileNameExtensionFilter  filter = new FileNameExtensionFilter("Pictures","jpg","png");
                     JFileChooser fc = new JFileChooser();
                     fc.setFileFilter(filter);
                       int returnVal = fc.showOpenDialog(null);
                        if (returnVal == JFileChooser.APPROVE_OPTION) {
                             File file = fc.getSelectedFile();
                              String Path = file.getPath();
                              BufferedImage originalImage = ImageIO.read(new File(Path));
                    ImageCompressionDemo iwt = new ImageCompressionDemo(originalImage);
                        }

                } catch (IOException ex) {
                    Logger.getLogger(ImageCompressionDemo.class.getName()).log(Level.SEVERE, null, ex);
                }

            }
        } );
    }
}

Here the Image size displayed in jpegLabel label variable is different from what is being saved on the disk . I want the size of the image saved on the disk to be of same size which is being displayed . Reference to the Question : Need Java function that takes image and imagesize(in Kb) as input and return an image

Community
  • 1
  • 1
UDAY KUMAR
  • 65
  • 1
  • 1
  • 7
  • 2
    cut down you code so that it just shows the relevant portion. Personally I can not be stuffed reading through this monolith of code. – Scary Wombat Sep 04 '14 at 02:10
  • @ScaryWombat I don't have sufficient reputation to post the image for better explanation of question so I am afraid to cut down the code . – UDAY KUMAR Sep 04 '14 at 02:30
  • 1
    be more afraid of getting the question bumped off the front page and/or closed –  Sep 04 '14 at 03:22

1 Answers1

1

The problem is here:

BufferedImage img = (BufferedImage)getJpegCompressedImage(originalImage);
File outputfile = new File("C:/Users/uday/Desktop/newImage.jpg");
ImageIO.write(img, "jpg", outputfile);

..when using the ImageIO class that way, it ignores whatever compression has been applied to the image and saves it using standard compression! The trick to saving the compressed image is to change the getJpegCompressedImage method to saveJpegCompressedImage, and instead of returning an Image it should declare void and save the byte[] directly to disk (using standard I/O).

E.G. as seen in this example:

Original image (unknown compression)


As seen in Example images for code and mark-up Q&As.

Saved as quality .2 (6,327 bytes)

enter image description here

Saved as quality .8 (18,702 bytes)

enter image description here

Code

import java.awt.Desktop;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.Locale;
import javax.imageio.*;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.ImageOutputStream;

public class CompressImage {

    /** TODO: This method has terrible handling of I/O.  
     Rewrite for production use. BNI. */
    static public void saveJpegCompressedImage(
            BufferedImage image,
            float quality,
            File file) throws Exception {
        OutputStream outStream = new FileOutputStream(
                new File(file, "Image-" + quality + ".jpg"));

        ImageWriter imgWriter = ImageIO.
                getImageWritersByFormatName("jpg").next();
        ImageOutputStream ioStream = 
                ImageIO.createImageOutputStream(outStream);
        imgWriter.setOutput(ioStream);

        JPEGImageWriteParam jpegParams = new JPEGImageWriteParam(
                Locale.getDefault());
        jpegParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        jpegParams.setCompressionQuality(quality);

        imgWriter.write(null, new IIOImage(image, null, null), jpegParams);

        ioStream.flush();
        ioStream.close();
        imgWriter.dispose();
    }

    public static void main(String[] args) throws Exception {
        URL url = new URL("https://i.stack.imgur.com/7bI1Y.jpg");
        File f = new File(System.getProperty("user.home"));
        BufferedImage bi = ImageIO.read(url);
        for (float q = 0.2f; q < .9f; q += .2f) {
            saveJpegCompressedImage(bi, q, f);
        }
        Desktop.getDesktop().open(f);
    }
}
Community
  • 1
  • 1
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433