Solved

Quality of reduced images

Posted on 2004-04-21
26
390 Views
Last Modified: 2010-08-05
Hi,

I am loading TIF images, and showing them reduced in my app. The quality really suffers. I am displaying original text images, and even at small reduction I can not read them anymore.

On the other hand, when MS Paint reduces images, they are still readable.

I am using Jimi to load image (which shoud not matter), and Graphics.drawImage to display it.

Should I look at image processing techniques, the word dithering comes to mind, or should it be anything else?

Thank you.
0
Comment
Question by:kerzner
[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
  • 9
  • 8
  • 8
  • +1
26 Comments
 
LVL 9

Expert Comment

by:mmuruganandam
ID: 10879272
Is the exact image is  same size as the displayed one.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 10879273
I don't know Jimi but you will probably find there are parameters you can pass to such a transformation, say about interpolation techniques and that sort of thing, that may offer some control over the quality of the outcome
0
 
LVL 1

Author Comment

by:kerzner
ID: 10879566
That is probably what I am looking for, something like this advice

http://mail.python.org/pipermail/image-sig/2002-March/001762.html

but for my answer I need a real instruction, more than general pointer
0
What Is Transaction Monitoring and who needs it?

Synthetic Transaction Monitoring that you need for the day to day, which ensures your business website keeps running optimally, and that there is no downtime to impact your customer experience.

 
LVL 92

Accepted Solution

by:
objects earned 250 total points
ID: 10883528
AffineTransform scale = AffineTransform.getScaleInstance(ratio, ratio);
BufferedImage scaled = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g = scaled.createGraphics();
g.setTransform(scale);
g.drawImage(i, 0, 0, null);
0
 
LVL 1

Author Comment

by:kerzner
ID: 10883656
Thank you, that looks very enticing, but produced blank images in my app. Could you please give more exlanation?

Here is how I used your code in my app

                double ratio = 1;
                AffineTransform scale = AffineTransform.getScaleInstance(ratio, ratio);
                BufferedImage scaled = new BufferedImage(r.width, r.height, BufferedImage.TYPE_INT_RGB);
                Graphics2D g2 = scaled.createGraphics();
                g2.setTransform(scale);
                g2.drawImage(image, r.x, r.y, r.width, r.height, this);

Thank you.
0
 
LVL 92

Expert Comment

by:objects
ID: 10883719
> Could you please give more exlanation?

Creates a new image and paints a scaled version of an image onto the new image.

> double ratio = 1;

that won't do any scaling :)

> g2.drawImage(image, r.x, r.y, r.width, r.height, this);

why do u do that?
whats r?
0
 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 250 total points
ID: 10884133
You should set rendering hints if you're going to use the standard api or you'll end up with precisely the same deterioration:



    graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
      RenderingHints.VALUE_INTERPOLATION_BILINEAR);
   
That's taken from an example of producing a thumbnail at http://www.geocities.com/marcoschmidt.geo/java-save-jpeg-thumbnail.html

If you're going to save the image again you can use ImageIO.write rather than that JPEGEncoder stuff nowadays
0
 
LVL 92

Expert Comment

by:objects
ID: 10884211
>   graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
>      RenderingHints.VALUE_INTERPOLATION_BILINEAR);

Thats not necessary with the approach suggested above.

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 10884233
It's not necessary if you're not interested in the quality of the result
0
 
LVL 92

Expert Comment

by:objects
ID: 10884274

Have you actually ever scaled an image???

kerzner,

The code I posted above will produce excellent quality scaling, but you don't need to specify the size to draw the image in the drawImage() call as that is already handled by the transformation.
Just paint the image whereever you need it.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 10884289
>>Have you actually ever scaled an image???

I most certainly have. The results are usually lousy. They improve somewhat with hints
0
 
LVL 92

Expert Comment

by:objects
ID: 10884310
you better start using my code then :D
0
 
LVL 1

Author Comment

by:kerzner
ID: 10885142
Guys, thank you, I am going to try all that early tomorrow morning
0
 
LVL 1

Author Comment

by:kerzner
ID: 10889501
Ok, good morning.

Dear Objects:

Here is what I am doing now, and I still do not see the image, just empty space

                    double ratio = .1;
                    AffineTransform scale = AffineTransform.getScaleInstance(ratio, ratio);
                    int w = image.getWidth(null);
                    int h = image.getHeight(null);
                    BufferedImage scaled = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
                    Graphics2D g2 = scaled.createGraphics();
                    g2.setTransform(scale);
                    g2.drawImage(image, 0, 0, null);
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 10889524
You have created an empty image, that's why. Do you want to read one from a file? Where's it meant to come from?
0
 
LVL 1

Author Comment

by:kerzner
ID: 10889701
I read the image from a tif file using Jimi. When I use regular graphics, I see it. Here is my complete code

if (whichGraphics == 1) {
                    // regular graphics
                    g.drawImage(image, r.x, r.y, r.width, r.height, this);
                }
                else if (whichGraphics == 2) {
                    // using Graphics2D with hints
                    Graphics2D g2 = (Graphics2D) g;
                    RenderingHints hints = new RenderingHints(null);
                    hints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                    g2.setRenderingHints(hints);
                    g2.drawImage(image, r.x, r.y, r.width, r.height, this);
                }
                else if (whichGraphics == 3) {
                    // exp exchange advice
                    double ratio = .1;
                    AffineTransform scale = AffineTransform.getScaleInstance(ratio, ratio);
                    int w = image.getWidth(null);
                    int h = image.getHeight(null);
                    BufferedImage scaled = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
                    Graphics2D g2 = scaled.createGraphics();
                    g2.setTransform(scale);
                    g2.drawImage(image, 0, 0, null);
                }
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 10889799
>>else if (whichGraphics == 2)

Is that block working?
0
 
LVL 1

Author Comment

by:kerzner
ID: 10889935
yes, block else if (whichGraphics == 2) is working fine. The quality is only slightly better, almost no difference. I know, that is what you would expect. It also takes a lot of memory and processing.
0
 
LVL 92

Expert Comment

by:objects
ID: 10894587
what color model is the original image using?
0
 
LVL 1

Author Comment

by:kerzner
ID: 10900025
it is a black and white image
0
 
LVL 1

Author Comment

by:kerzner
ID: 10900260
I found that this call does the job very well

Image scaledImage = image.getScaledInstance(r.width, r.height, Image.SCALE_SMOOTH);

It runs a bit slow, but produced a very good quality. What would you say?
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 10904720
>>What would you say?

Go for it! ;-)
0
 
LVL 92

Expert Comment

by:objects
ID: 10904748
> it is a black and white image

Thats possiblty why option 3 was creating empty image as you werre painting to a rgb image.
0
 
LVL 92

Expert Comment

by:objects
ID: 10904772
actually the other options paint the iamge to (i assume) the screen whereas that one paints to another image. Compare it with this:

               else if (whichGraphics == 3) {
                    // exp exchange advice
                    double ratio = .1;
                    AffineTransform scale = AffineTransform.getScaleInstance(ratio, ratio);
                    Graphics2D g2 = (Graphics2D) g;
                    g2.setTransform(scale);
                    g2.drawImage(image, 0, 0, null);
                }
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 10904891
8-)
0
 
LVL 92

Expert Comment

by:objects
ID: 10905063
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

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 about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:

688 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