Image scaling in realtime

G

Gidion

Hi,

have someone a good hint ( lib or algorithm) to scale images on the
fly ?
I will write a programm that have to scale 100 images (200k per Image)
in 1 s.
The Programm have to be one prozess, so i have to use threads.

my first idea is, to write a Servlet that will du this with the java
imageio.

but maybe there are better libs and or solutions.

thanks for your Help.

k.r. Gidion
 
J

John B. Matthews

Gidion said:
have someone a good hint ( lib or algorithm) to scale images on the
fly ? I will write a programm that have to scale 100 images (200k per
Image) in 1 s. The Programm have to be one prozess, so i have to use
threads.

my first idea is, to write a Servlet that will du this with the java
imageio.

AffineTransformOp offers three common interpolation types:

<http://java.sun.com/javase/6/docs/api/java/awt/image/AffineTransformOp.h
tml>
 
B

blue indigo

AffineTransformOp offers three common interpolation types:

<http://java.sun.com/javase/6/docs/api/java/awt/image/AffineTransformOp.h
tml>

Depending on the quality you want and the hardware you can expect your
program to be run on, you may not be able to meet your real-time
requirements with this.

Look into the possibility of pre-scaling and caching. A while back I
worked on a project that, among other things, required a list control
displaying image thumbnails. It proved impossible to have the list control
responsive to scrolling and repaints and still have acceptable quality
thumbnails using on-the-fly scaling, but the images were static so it was
easy to work around this. The first revision pre-scaled the images and
created a thumbnail database on disk. The list was much more responsive,
but still sluggish enough to offend users during usability testing. Adding
an in-RAM cache of the last N thumbnails viewed proved crucial, with the
cache size at least equal to the maximum number the list control
could simultaneously display. This made repaints (if the list was covered
by another window and then uncovered, for instance) essentially
instantaneous and scrolling fast enough to satisfy test users.

Also important is to store images as TYPE_INT_RGB or TYPE_INT_BGR where
possible. Trying to display some oddball color model images is really slow
on every repaint. Internally converting them to TYPE_INT_RGB when they're
first loaded works wonders. There's a ColorConvertOp or similar in the
same place as AffineTransformOp that can be used for this purpose.
TYPE_INT_BGR has the added advantage that an ImageIO.write() in JPEG
format will DTRT with this format, useful for making that thumbnail cache
and for not having it gobble up too much disk space. (TYPE_INT_RGB saved
to JPEG seems to come out with the blue and red channels swapped.)

Furthermore, stay away from Image.getScaledInstance(). All of the filter
options have poor quality except SCALE_AREA_AVERAGING, which instead has
poor performance. To add insult to injury, Image.getScaledInstance()
apparently keeps a reference to the parent image rather like
String.substring() does with the parent string. This can quickly add up to
OOME if the parent images are large and you keep very many scaled
instances around, even if the scaled instances are tiny. So use an
AffineTransformOp on a BufferedImage instead, as John indicated.

For maximum quality, downsample by at most a factor of two; if you want a
bigger reduction, do repeated halvings and then a final step by some other
factor. In pseudocode, instead of:

scaleFactor = computeScaleFactor();
out = rescale(in, scaleFactor);

use

scaleFactor = computeScaleFactor();
assert scaleFactor > 0.0;
while (scaleFactor < 0.5) {
in = rescale(in, 0.5);
scaleFactor *= 2.0;
}
out = rescale(in, scaleFactor);

and you will get much better results, comparable to those from
Image.getScaledInstance() with SCALE_AREA_AVERAGING but faster and
without the internal reference to the parent image. Yes, faster, even with
the repeated halvings; if the size of the job for a one-shot rescale is 1,
the size for a repeated-halvings rescale is 1 + 1/4 + 1/16 + ...
which converges on 4/3, for a mere 33% increase in the amount of
computation done but a much more than 33% increase in the quality of the
results.

(See http://en.wikipedia.org/wiki/Geometric_series if you doubt the value
of 4/3. In fact, since there are a finite number of halvings, and the
partial sums are monotonic increasing, for any given actual job the
repeated-halving overhead will be strictly less than 33%, and in
particular is essentially zero if the image is shrunk by no more than a
factor of two.)

Last but not least, use

BufferedImage bi = new BufferedImage(scaledWidth, scaledHeight,
TYPE_INT_RGB);
scaleOp.filter(src, bi);

rather than

BufferedImage bi = scaleOp.filter(src, null);

in your rescale() because for some odd reason the latter is also prone to
causing OOMEs with large images. The OOMEs come from a
createCompatibleDestination() (or similarly-named) method in Sun's code,
which is called if you specify a null destination. I can only guess that
it does something a lot less efficient than "new
BufferedImage(scaledWidth, scaledheight, TYPE_INT_RGB)" for some reason.

See
http://tinyurl.com/2rverf
for some more on this.
 
L

Lars Enderin

blue indigo wrote:
Completely OT:
Why do you use charset=ISO-8859-13? Do you need to use Latvian characters?
 
B

blue indigo

blue indigo wrote:
Completely OT:
Why do you use charset=ISO-8859-13? Do you need to use Latvian characters?

That's odd, mate. I don't know how that happened. It didn't make my post
unreadable, did it? It looks normal over here. I was posting to a
multilingual group (that isn't carried very widely) the other day. Likely
I forgot to set it back.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,274
Latest member
JessMcMast

Latest Threads

Top