Solved

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

Posted on 2007-04-02
7
1,665 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Delete Android all or certain applications data programmatically 9 153
Desingning Refactoring existing code 2 46
String array comparison 4 58
printf performancy 11 105
INTRODUCTION Working with files is a moderately common task in Java.  For most projects hard coding the file names, using parameters in configuration files, or using command-line arguments is sufficient.   However, when your application has vi…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
Viewers learn about the “for” loop and how it works in Java. By comparing it to the while loop learned before, viewers can make the transition easily. You will learn about the formatting of the for loop as we write a program that prints even numbers…
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…
Suggested Courses

751 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