Friday, March 15, 2013

Compress Images on upload

Hi,


Recently i wanted to compress images when uploading using Postgresql and hibernate. I implemented below code :

Image compressor utility code below ::

package com.utils;

import java.awt.Graphics2D; 
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.renderable.ParameterBlock;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.MemoryCacheImageOutputStream;
import javax.media.jai.JAI;
import javax.media.jai.RenderedOp;

import com.sun.media.jai.codec.SeekableStream;

/**
 * 
 * @author Ujjwal Soni
 * 
 */

public class ImageCompressor {

    public byte[] compressFile(byte[] content, String fileName)
            throws FileNotFoundException {

        BufferedImage input = null;
        InputStream ips = null;
        ByteArrayOutputStream baout = new ByteArrayOutputStream();

        try {
            ips = new ByteArrayInputStream(content);
            

            if (fileName.endsWith(".jpg") || fileName.endsWith(".JPG") || fileName.endsWith(".jpeg") || fileName.endsWith(".JPEG")) {
                
                input = ImageIO.read(ips);

            } else if (fileName.endsWith(".gif") || fileName.endsWith(".GIF")) {

                input = ImageIO.read(ips);

            } else if (fileName.endsWith(".bmp") || fileName.endsWith(".BMP")) {

                // Wrap the InputStream in a SeekableStream.

                SeekableStream s = SeekableStream.wrapInputStream(ips, false);

                // Create the ParameterBlock and add the SeekableStream to it.
                ParameterBlock pb = new ParameterBlock();
                pb.add(s);

                // Perform the BMP operation
                RenderedOp img1 = JAI.create("BMP", pb);

                input = getBufferedImage(img1.getAsBufferedImage());
            } else if (fileName.endsWith(".png") || fileName.endsWith(".PNG")) {

                SeekableStream s = SeekableStream.wrapInputStream(ips, false);

                // Create the ParameterBlock and add the SeekableStream to it.
                ParameterBlock pb = new ParameterBlock();
                pb.add(s);

                // Perform the PNG operation
                RenderedOp img1 = JAI.create("PNG", pb);

                input = getBufferedImage(img1.getAsBufferedImage());
            }

            if (input == null)
                return null;

            // Get Writer and set compression
            Iterator iter = ImageIO.getImageWritersByFormatName("jpg");

            if (iter.hasNext()) {

                ImageWriter writer = (ImageWriter) iter.next();
                ImageWriteParam iwp = writer.getDefaultWriteParam();
                iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
                float values[] = iwp.getCompressionQualityValues();
                System.out.println("compression Quality >> "+values[2]);
                iwp.setCompressionQuality(0.2f);
                //BufferedImage image = ImageIO.read(ips);
                IIOImage image1 = new IIOImage(input, null, null);
                writer.setOutput(new MemoryCacheImageOutputStream(baout));
                // writer.write(null, new IIOImage(image, null, null), iwp);
                writer.write(null, image1, iwp);
                input.flush();
                writer.dispose();
                writer = null;
                image1 = null;
                input = null;

            }
        } catch (FileNotFoundException finfExcp) {
            System.out.println(finfExcp);
        } catch (IOException ioExcp) {
            System.out.println(ioExcp);
        }
        return baout.toByteArray();
    }

    private BufferedImage getBufferedImage(Image img) {

        // if the image is already a BufferedImage, cast and return it
        // if ((img instanceof BufferedImage)) {
        // return (BufferedImage) img;
        // }

        // otherwise, create a new BufferedImage and draw the original
        // image on it
        int w = img.getWidth(null);
        int h = img.getHeight(null);
        int thumbWidth = 330;
        int thumbHeight = 250;

        // if width is less than 330 keep the width as it is.
        if (w < thumbWidth)
            thumbWidth = w;

        // if height is less than 250 keep the height as it is.
        if (h < thumbHeight)
            thumbHeight = h;

        // if less than 330*250 then do not compress
        if (w > 330 || h > 250) {

            double imageRatio = (double) w / (double) h;
            double thumbRatio = (double) thumbWidth / (double) thumbWidth;

            if (thumbRatio < imageRatio) {
                thumbHeight = (int) (thumbWidth / imageRatio);
            } else {
                thumbWidth = (int) (thumbHeight * imageRatio);
            }
        }
        // draw original image to thumbnail image object and
        // scale it to the new size on-the-fly
        BufferedImage bi = new BufferedImage(thumbWidth, thumbHeight,
                BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = bi.createGraphics();
        g2d.drawImage(img, 0, 0, thumbWidth, thumbHeight, null);
        g2d.dispose();
        return bi;
    }
    
}

Now in your Upload Action, write below code

for(FileBean fileBean: fileList){
                    if(fileBean.getActualFile()!=null && fileBean.getActualFile().getFileSize()>0)
                    {
                        //byte[] bFile = new byte[ fileBean.getActualFile().getFileSize()];    
                        
                        byte[] bFile = fileBean.getFileContent();    
                        
                        
                        fileBean.getActualFile().getInputStream().read(bFile);        
                        MyDocumentImage mydocimage=new MyDocumentImage();
                        //MyDocumentImageId mydocimageId=new MyDocumentImageId();
                        mydocimage.setMyDocImage(new MyDocImageType(fileType));
                        
                        if (fileBean.getActualFile().getFileName().endsWith(".jpg") || fileBean.getActualFile().getFileName().endsWith(".JPG") || fileBean.getActualFile().getFileName().endsWith(".jpeg") || fileBean.getActualFile().getFileName().endsWith(".JPEG") || fileBean.getActualFile().getFileName().endsWith(".gif") || fileBean.getActualFile().getFileName().endsWith(".GIF") || fileBean.getActualFile().getFileName().endsWith(".bmp") || fileBean.getActualFile().getFileName().endsWith(".BMP") || fileBean.getActualFile().getFileName().endsWith(".png") || fileBean.getActualFile().getFileName().endsWith(".PNG") && fileBean.getActualFile().getFileSize()>300000)
                        {
                            mydocimage.setDocContent(img.compressFile(bFile, fileBean.getActualFile().getFileName()));
                        }
                        else
                        {
                            mydocimage.setDocContent(bFile);
                        }
                            
                        mydocimage.setDocCreatedBy(userId);
                        mydocimage.setDocCreatedDate(new Timestamp(System.currentTimeMillis()));
                        mydocimage.setSdocLatest(true);
                        mydocimage.setSdocMimeType(fileBean.getActualFile().getContentType());
                        mydocimage.setSdocFileName(fileBean.getActualFile().getFileName());
                        mydocimage.setDocActive("Y");
                        mydocimage.setDocVersion(1);
                        //String docSeq = commonDAO.getNextSequence("my_doc.seq");
                        //mydocimage.setSCode(Integer.valueOf(sdocSeq));
                        //mydocimage.setSdocDtlCode(fileType);
                        //mydocimage.setSMewCode(staStall.getId().getStaBusCode());
                        //mydocimage.setSCode(staStall.getId().getStaCode());
                        //mydocimage.setId(mydocimageId);
                        mydocimage.setDs(dStp);

                        myDocList.getMyDocumentImages().add(mydocimage);
                    }
                }



Thats it, above code will compress images of particular size. Email me if you need source code or guidance on this.

Cheers,

Ujjwal Soni


4 comments:

dung dungdung said...

Very cool entry and I so satisfied that I have found this useful information. I will definitely bookmark your site and visit this website again in the future. Thanks a lot for posting this valuable info for us. King regards! WOW gold

neead smith said...

I added this to my favorites menu. I want to take another look later. I agree on many points made in this article, but I would like to take time to think about some aspects.

aluminium signs

julia said...

Really I'm impressed out of this post…The one that created this post can be a genius and learns how to keep your readers connected..Thank you for sharing this with us. I uncovered it informative and interesting. Excited for much more updates. automaty hazardowe

neead smith said...

I really like your presentation
stainless steel signs