• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Jeanne Boyarsky
  • Ron McLeod
Sheriffs:
  • Paul Clapham
  • Liutauras Vilda
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
Bartenders:

Image smoothing

 
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

I've written this applet into which the user can paste a screenshot and do various things with the pasted image. The problem i've encountered is that when the image is made to fit into the panel, its very illegible. Is there a way to make the image more smoother? I don't mind changing the resolution of the picture or whatever as long as the image is good enough to view.

thank you in advance
 
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
How are you resizing the image now? And are you making it smaller or bigger, and by how much?
 
Ziggy Kowalski
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
i'm simply drawing the image by calling the 'drawImage' method in the graphics class. By passing in the width and height of the panel, the image is automatically resized (by about half of the original size).
So, basically i'm squashing the image into a panel half its size.
[ February 06, 2006: Message edited by: zzdziarski zzdziarski ]
 
Jeff Albertson
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If you are making an image smaller, I suggest Image's getScaledInstance method, since it allows you to supply a hint for the scaling algorithm.

On the other hand, if you are making an image *bigger*, I suggest scaling AffineTransforms and setting RenderingHints.KEY_INTERPOLATION to either VALUE_INTERPOLATION_BILINEAR or
VALUE_INTERPOLATION_BICUBIC. I find this gives better results for larger images than the area averaging algorithm.

Again, the good news is that you only need to change one line of code. Take a look at this demo. A good place to compare the two images is around my glasses.
 
Ziggy Kowalski
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
works like a dream, thanks
 
Ziggy Kowalski
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Actually, i've hit a snag with the new code Jeff posted above. The problem is that getScaledInstance(...) returns an image whereas i require a BufferedImage object because i later cast the image to this class and convert it to a jpeg using the code below:

BufferedImage bimg = null;
int w = image.getWidth(null);
int h = image.getHeight(null);
System.out.println("w: "+w+" h: "+h);
int[] pixels = new int[w * h];
PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h, pixels, 0, w);
try {
pg.grabPixels();
} catch (InterruptedException ie) {
ie.printStackTrace();
}

bimg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
bimg.setRGB(0, 0, w, h, pixels, 0, w);

// Encode as a JPEG
ByteArrayOutputStream bout = new ByteArrayOutputStream();
try {
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bout);

encoder.encode((BufferedImage)image);
//bout.close();
}catch(Exception e){
System.err.println("An error occured while trying to convert img to jpg:"+e);
}
byte[] ba = bout.toByteArray();

I was actually surprised to see this code work in the first place because image was meant to be initially an Image object but the BufferedImage cast was allowed to occur and the code seemed to work. Now that i have this line in my code:
image = image.getScaledInstance(w, h, Image.SCALE_AREA_AVERAGING);
i get a classCastException.

so i guess my question is whether there's another way to convert an image object into a jpeg without having to use a BufferedImage.

For background info, my code is meant to do this:
grab a screenshot (using Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); etc)
scale it to fit into a panel and disply it
convert the image into a jpeg and then into base64 format

this is turning out to be much more difficult than i first expected...
 
Jeff Albertson
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Converting an image to a buffered image is easy, but you have to make sure the image's data has been loaded:

Loading an image requires a MediaTracker:

You are using JPEGCodec -- I'm not familiar with it -- what package is it from? I just use classes from J2SE to write images:

Whilst your program's encoding of a scaled version of a screen shot goes through several steps, every step is short, right?
[ February 08, 2006: Message edited by: Jeff Albertson ]
 
Ziggy Kowalski
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
JPEGCodec is from the com.sun.image.codec.jpeg.* package

Yes, all the steps taken in my applet require a few lines of code each.

I have one question however:
My program now works fine but the load(...) method keeps throwing an exception for me.
When i comment-out the if statement, everything works like a breeze. The code appears to have been correctly written so i can't for the life of me think why the exception is being thrown. The image is obvioulsy loaded else it wouldn't appear on my applet. If that's the case why is statusID returning 0 (assuming MediaTracker.COMPLETE = 1)?
 
Jeff Albertson
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Ziggy Kowalski:
JPEGCodec is from the com.sun.image.codec.jpeg.* package



You should read this page:

http://java.sun.com/products/jdk/faq/faq-sun-packages.html

On it, it states:

Why Developers Should Not Write Programs That Call 'sun' Packages

In general, packages such as sun.*, that are outside of the Java platform, can be different across OS platforms (Solaris, Windows, Linux, Macintosh, etc.) and can change at any time without notice with SDK versions (1.2, 1.2.1, 1.2.3, etc). Programs that contain direct calls to the sun.* packages are not 100% Pure Java. In other words: [...] The sun.* packages are not part of the supported, public interface. A Java program that directly calls into sun.* packages is not guaranteed to work on all Java-compatible platforms. In fact, such a program is not guaranteed to work even in future versions on the same platform.


> If that's the case why is statusID returning 0 (assuming MediaTracker.COMPLETE = 1)?

According to the API, COMPLETE is 8 Have you printed out the exact value statusID returns? Have you tried this with code that doesn't rely on the com.sun.image.codec.jpeg.* package?
 
Jeff Albertson
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I went back and tried my code and I think I'm having the same runtime error you are: statusID always return 2 (ABORTED), which doesn't make sense. And like you said, if I ignore the error, the image is there. In fact, I completely commented out my call to load() and it still works. This may be because getScaledInstance applied to a BufferedImage returns an image that is already "loaded", but I haven't read anything in the API to back that up.
 
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
as far as i know, you are going to get that exception. it will be thrown before the image is fully loaded in mem. there are posts aroudn the net on this specifically.

I am looking for a fast way to get high quality images resized and optimized and saved to disk as a jpeg. not in a jpanel. not low quality. not 256 color. yada yada. good output. i have gotten many examples to work from things all around the net, but they all produce the same poor albeit fast output.
for example, where light would highlight the texture of a leather, i get grainy harsh white pixels. yuck! here are three methods that all work.
the one that does a nice job takes 19s to convert from an image to a buffered image which is required to write as jpeg. does anyone know a way around this? unlike posts i have seen, Image resizedImg = bufImage.getScaledInstance( whatever) does not take long. it is the conversion from the returned Image to BufferedImage that takes so darn long.

any help would be appreciated. thanks.
-neil
 
neil up
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
sorry, i forgot to post the methods i said:


If anyone can help, thanks in advance. if anyone benefits from these examples great. lots of articles don't have the needed include statements and that sux. here they are for you as a jsp woudl need them:
 
Legend has it that if you rub the right tiny ad, a genie comes out.
Smokeless wood heat with a rocket mass heater
https://woodheat.net
reply
    Bookmark Topic Watch Topic
  • New Topic