Solved

JPEGImageEncoder: Reducing the size of the JPEG without resizing the Image

Posted on 2007-04-02
7
1,628 Views
Last Modified: 2012-06-27
I am using JPEGImageEncoder in order to encode a BufferedImage into a JPEG file.
The problem is that I would like to restrict the files size to a maximum of 200KB, without affecting the height/widht of the image. So I guess that the only option that is left is quality.

The code I am using is something like:

BufferedImage thumbImage = new BufferedImage(
image.getWidth(),
image.getHeight(),
BufferedImage.TYPE_INT_RGB);

Graphics2D graphics2D = thumbImage.createGraphics();
graphics2D.setRenderingHint(
                 RenderingHints.KEY_INTERPOLATION,
                 RenderingHints.VALUE_INTERPOLATION_BILINEAR);
      graphics2D.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);

      imageOut = new FileOutputStream(yetAnOtherFile);
      out = new BufferedOutputStream(imageOut);
      encoder = JPEGCodec.createJPEGEncoder(imageOut);
      enparam = encoder.getDefaultJPEGEncodeParam(thumbImage);
      int quality = 100;
      enparam.setXDensity(100);
      enparam.setYDensity(100);

        enparam.setQuality( (float) quality / 100.0f, false);
        encoder.setJPEGEncodeParam(enparam);
        encoder.encode(thumbImage);


I also tried a do/while loop till the out file gets an accepted size, decreasing the quality in each step. It didn't work as expected. Is there an other solution to the problem ?
0
Comment
Question by:Nellios
  • 4
  • 3
7 Comments
 
LVL 92

Expert Comment

by:objects
ID: 18835109
that approach should work, what problem were u having?
btw, u probably should start quality at 80 max, theres no real value going any higher.
0
 
LVL 92

Expert Comment

by:objects
ID: 18835111
be better off wrting it to a ByteArrayOutputStream rather than a file.
0
 
LVL 10

Author Comment

by:Nellios
ID: 18835117
The problem was that I ended up in an infinite loop. I didn't like the approach anyway so I stoped working on it. If there isn't a better one, then I guess I will work on this one.
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 92

Accepted Solution

by:
objects earned 500 total points
ID: 18835128
can't think of one, the size of the file will depend on the actual contents of the image and how much it can be compressed.

the loop would be something like:

byte[] bytes = null;
int quality = 80;
while (bytes==null && quality>0)
{
   bytes = encode(image, quality);
   if (bytes.length>maxsize)
   {
       bytes = null;
   }
   else
   {
       quality -= 10;
   }
}
0
 
LVL 10

Author Comment

by:Nellios
ID: 18916802
I am accepting objects proposal as a solution to this, since its the only feasible way to solve the problem that I am aware of.

I am not very fond of that solution, neither I applied it to my problem yet. I will provide further feedback in this thread as soon as I do so.
0
 
LVL 10

Author Comment

by:Nellios
ID: 18945579
I promised you feedback didn't I?

So here's exactly what worked for me:

 int size = 1024000;
     for (int quality = 80; size > 921600; quality -= 2) {

        imageOut = new FileOutputStream(new File(tmpdir + "tmpImageName.jpg"));
        out = new BufferedOutputStream(imageOut);
        encoder = JPEGCodec.createJPEGEncoder(imageOut);
        enparam = encoder.getDefaultJPEGEncodeParam(thumbImage);

          enparam.setXDensity(100);
          enparam.setYDensity(100);
          enparam.setQuality( (float) quality / 100.0f, false);
          encoder.setJPEGEncodeParam(enparam);
          encoder.encode(thumbImage);
          out.close();
          imageIn = new FileInputStream(new File(tmpdir + "tmpImageName.jpg"));
          this.in = new BufferedInputStream(imageIn);
          size = in.available();
       }

with this for loop the image quality will gradually decrease till the output file is less than the maximum allowed size.

This is the implementation of my original idea influenced by Objects. Currently I am using temporary files to do so. It would also work with Piped Streams, though it would involve threads and would make things a bit more complicated :-D
0
 
LVL 92

Expert Comment

by:objects
ID: 18945596
you can avoid using a file by writing the image to a ByteArrayOutputStream.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Image decoding from Camera 3 72
thymeleaf natural templating vs JSP 2 65
varialbe initialization 11 30
How to convert String matching to regex in java 4 16
Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis. Java Flight Recorder is a profiling and event collectio…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.

932 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now