保存在磁盘上的图像大小与显示的大小不同

时间:2014-09-04 02:06:57

标签: java image image-processing

代码正在被修改一下。我在Jpanel上添加了一个按钮,其动作事件将图像保存在磁盘上。

源代码

    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);
                }

            }
        } );
    }
}

此处jpegLabel标签变量中显示的图像大小与磁盘上保存的图像大小不同。我希望保存在磁盘上的图像大小与显示的大小相同。 参考问题:Need Java function that takes image and imagesize(in Kb) as input and return an image

1 个答案:

答案 0 :(得分:1)

问题在于:

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

..当使用ImageIO类时,它会忽略对图像应用的压缩并使用标准压缩保存它! 保存 压缩图片的技巧是将getJpegCompressedImage方法更改为saveJpegCompressedImage,而不是返回Image它应该声明void并将byte[]直接保存到磁盘(使用标准I / O)。

E.G。如本例所示:

原始图像(未知压缩)


Example images for code and mark-up Q&As所示。

保存为质量.2(6,327字节)

enter image description here

保存为质量.8(18,702字节)

enter image description here

代码

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("http://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);
    }
}