Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Quality of reduced images

Posted on 2004-04-21
26
Medium Priority
?
392 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
Independent Software Vendors: 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 1000 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 1000 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

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

Question has a verified solution.

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

Java contains several comparison operators (e.g., <, <=, >, >=, ==, !=) that allow you to compare primitive values. However, these operators cannot be used to compare the contents of objects. Interface Comparable is used to allow objects of a cl…
Java functions are among the best things for programmers to work with as Java sites can be very easy to read and prepare. Java especially simplifies many processes in the coding industry as it helps integrate many forms of technology and different d…
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…
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.
Suggested Courses

597 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