Skip to main content

[JAVA2D] Image rendering and speed.

10 replies [Last post]
Anonymous

Hello,

I am displaying a BufferedImage in a JPanel and have some questions on
performance.

I use the AffineTransform to scale and translate the BufferedImage in
the panel.

I also allow the user to draw on top of the image by dragging the mouse
(something like a paint program). So as the user draws on top of the
image, I need to keep calling repaint() on the panel to update the image
and the user's drawing.

What I find is this:

A. When my panel is relatively small (for example an 8th of total screen
area) and when the image is not scaled up (fits entirely within the
panel), I get good performance. That is, the user's drawing keeps up
with the motion of the mouse in the panel.

B. When the panel is relatively large (say half as large as the screen
itself) and when the image is scaled way up so that it does not fit
within panel (say five times the size of the panel itself), performance
is very poor. By this I mean that the user's drawing on top of the image
lags significantly behind the movement of the mouse.

All of my rendering is done inside of the panel's paintComponent(...)
method.

This is how I draw the image:

g2d.drawImage(theImage.getBufferedImage(), 0, 0, null);

Also, I am not setting a clipping area.

At this point I'm looking for some general advice on how to improve
performance. I'm guessing that this would involve setting a clipping
region.

If so can some one give some specific pointers on how to set the proper
clipping region when AffineTransform has been used to scale and pan the
image so that the image is much larger than the panel itself.

Thank you,

Ted Hill

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".
[att1.html]

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Augusto Sellhorn

Thanks for the reply, but I don't want to clip the string, I just want
to make it fit within a bounding box. Or find the "best" font size, that
given a bounging box and a string, will make the string fit in the box ...

Augusto

Rosenstrauch, David wrote:

>You can set a "clipping region" on the graphics context before painting the
>string. Anything that would be painted outside this region gets "clipped" -
>i.e., chopped off. That should effectively set a maximum size on the area you
>paint the text in.
>
>See java.awt.Graphics.setClip()
>
>HTH,
>
>DR
>
>
>
>>-----Original Message-----
>>From: Discussion list for Java 2D API
>>[mailto:JAVA2D-INTEREST@JAVA.SUN.COM]On Behalf Of Augusto Sellhorn
>>Sent: Thursday, August 26, 2004 7:55 PM
>>To: JAVA2D-INTEREST@JAVA.SUN.COM
>>Subject: [JAVA2D] Drawing text inside of a bounding box
>>
>>
>>I have a situation where users are editing a vector drawing
>>in a program
>>where the font doesn't match what I display in my renderer. In their
>>editing program, all that is saved is a world "height" for
>>the text, so
>>I can use that to scale and match the font once I draw it.
>>
>>Now, the font they use in the editing program is monospaced,
>>so based on
>>the height, i can calculate a "maximum width". Saying that, I'm trying
>>to find a way to simply draw a string saying and make sure it doesn't
>>exceed this bounding box (height and calculated width).
>>
>>Is there any easy and fast way to do this?
>>
>>What I have now tries to match the height, and it does, but
>>then when it
>>goes for the width it has to decrement the size until the width is not
>>greater than the calculated width. There are some cases where
>>this takes
>>too many iterations and is slow.
>>
>>So if anybody has any idea what I'm talking about :-), what's a good
>>idea to just say, draw this string and don't exceed these bounds?
>>
>>Thanks
>>
>>Augusto
>>
>>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Knight, Jon

Font.deriveFont ( AffineTransform trans ); Pass it a transform of the
correct scale.

Jon Knight
Senior Database Analyst
2525 Horizon Lake Drive, Suite 120
Memphis, TN 38133
JKnight@concordefs.com
901.371.8000 - Phone
800.238.7675 - Phone
901.380.8336 - Fax
www.FirstData.com
First Data's merger with Concord creates "One Company" with enhanced choice,
voice and innovation for all customers.

-----Original Message-----
From: Discussion list for Java 2D API
[mailto:JAVA2D-INTEREST@JAVA.SUN.COM] On Behalf Of Augusto Sellhorn
Sent: Friday, August 27, 2004 11:09 AM
To: JAVA2D-INTEREST@JAVA.SUN.COM
Subject: Re: [JAVA2D] Drawing text inside of a bounding box

Thanks for the reply, but I don't want to clip the string, I just want
to make it fit within a bounding box. Or find the "best" font size, that
given a bounging box and a string, will make the string fit in the box ...

Augusto

Rosenstrauch, David wrote:

>You can set a "clipping region" on the graphics context before painting the
>string. Anything that would be painted outside this region gets "clipped"
-
>i.e., chopped off. That should effectively set a maximum size on the area
you
>paint the text in.
>
>See java.awt.Graphics.setClip()
>
>HTH,
>
>DR
>
>
>
>>-----Original Message-----
>>From: Discussion list for Java 2D API
>>[mailto:JAVA2D-INTEREST@JAVA.SUN.COM]On Behalf Of Augusto Sellhorn
>>Sent: Thursday, August 26, 2004 7:55 PM
>>To: JAVA2D-INTEREST@JAVA.SUN.COM
>>Subject: [JAVA2D] Drawing text inside of a bounding box
>>
>>
>>I have a situation where users are editing a vector drawing
>>in a program
>>where the font doesn't match what I display in my renderer. In their
>>editing program, all that is saved is a world "height" for
>>the text, so
>>I can use that to scale and match the font once I draw it.
>>
>>Now, the font they use in the editing program is monospaced,
>>so based on
>>the height, i can calculate a "maximum width". Saying that, I'm trying
>>to find a way to simply draw a string saying and make sure it doesn't
>>exceed this bounding box (height and calculated width).
>>
>>Is there any easy and fast way to do this?
>>
>>What I have now tries to match the height, and it does, but
>>then when it
>>goes for the width it has to decrement the size until the width is not
>>greater than the calculated width. There are some cases where
>>this takes
>>too many iterations and is slow.
>>
>>So if anybody has any idea what I'm talking about :-), what's a good
>>idea to just say, draw this string and don't exceed these bounds?
>>
>>Thanks
>>
>>Augusto
>>
>>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Rosenstrauch, David

You can set a "clipping region" on the graphics context before painting the
string. Anything that would be painted outside this region gets "clipped" -
i.e., chopped off. That should effectively set a maximum size on the area you
paint the text in.

See java.awt.Graphics.setClip()

HTH,

DR

> -----Original Message-----
> From: Discussion list for Java 2D API
> [mailto:JAVA2D-INTEREST@JAVA.SUN.COM]On Behalf Of Augusto Sellhorn
> Sent: Thursday, August 26, 2004 7:55 PM
> To: JAVA2D-INTEREST@JAVA.SUN.COM
> Subject: [JAVA2D] Drawing text inside of a bounding box
>
>
> I have a situation where users are editing a vector drawing
> in a program
> where the font doesn't match what I display in my renderer. In their
> editing program, all that is saved is a world "height" for
> the text, so
> I can use that to scale and match the font once I draw it.
>
> Now, the font they use in the editing program is monospaced,
> so based on
> the height, i can calculate a "maximum width". Saying that, I'm trying
> to find a way to simply draw a string saying and make sure it doesn't
> exceed this bounding box (height and calculated width).
>
> Is there any easy and fast way to do this?
>
> What I have now tries to match the height, and it does, but
> then when it
> goes for the width it has to decrement the size until the width is not
> greater than the calculated width. There are some cases where
> this takes
> too many iterations and is slow.
>
> So if anybody has any idea what I'm talking about :-), what's a good
> idea to just say, draw this string and don't exceed these bounds?
>
> Thanks
>
> Augusto

==============================================================================
This message is for the sole use of the intended recipient. If you received
this message in error please delete it and notify us. If this message was
misdirected, CSFB does not waive any confidentiality or privilege. CSFB
retains and monitors electronic communications sent through its network.
Instructions transmitted over this system are not binding on CSFB until they
are confirmed by us. Message transmission is not guaranteed to be secure.
==============================================================================

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

mgrev
Offline
Joined: 2003-08-12

I think he wants to "scale" the text with some smaller font to fit the width, if the text it's too wide.

Cheers,
Mikael

Jim

If you are drawing simple shape like squares, circles, etc. then drawing
in xor mode will speed things up. If you are drawing freehand, then that
might not look too good.

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Ted Hill

Chet,

Thanks for the quick feed back.

Can you elaborate a bit on "pre-scaling to an intermediate image" or
point me to more information on this idea.

Can you also point me to some resources that discuss your 2nd
suggestion: "repainting altered areas." I have the JDK documentation but
it would be nice to see some examples and read a discussion of different
ways to set clip areas.

Thanks again,

Ted Hill

-----Original Message-----
From: Chet Haase [mailto:Chet.Haase@Sun.COM]
Sent: Wednesday, August 25, 2004 9:44 AM
To: Ted Hill
Cc: JAVA2D-INTEREST@JAVA.SUN.COM
Subject: Re: [JAVA2D] Image rendering and speed.

Hi Ted,

There are two approaches I can think of off the top of my head that
might improve things for you:
intermediate images, and repainting only what you need to.

1) Intermediate images
There is no need to scale the image every time you paint it if it's the
same size for
some amount of time. Why not pre-scale that image to some intermediate
image
instead nad then simply call drawImage() from that temporary image?
This copy operation will,
in general, be way faster than a scaling operation (at least until we
support scaling
operations in hardware, which is only enabled in the non-default opengl
pipeline as of
jdk 5.0).

2) Repainting altered areas
There is no need to tell Swing to repaint the entire image area: you can

just tell it to
update the region that's changed (the difference between the last mouse
position and the current
one, presumably). Then you will get called with a Graphics for the
component with a clip
set appropriately and can draw only that changed region.

I think suggestion #1 above will have the biggest impact; if you don't
need to transform
on the fly, don't...

Chet.

Ted Hill wrote:

> Hello,
>
> I am displaying a BufferedImage in a JPanel and have some questions on
> performance.
>
> I use the AffineTransform to scale and translate the BufferedImage in
> the panel.
>
> I also allow the user to draw on top of the image by dragging the
> mouse (something like a paint program). So as the user draws on top of

> the image, I need to keep calling repaint() on the panel to update the

> image and the user's drawing.
>
> What I find is this:
>
> A. When my panel is relatively small (for example an 8th of total
> screen area) and when the image is not scaled up (fits entirely within

> the panel), I get good performance. That is, the user's drawing keeps
> up with the motion of the mouse in the panel.
>
> B. When the panel is relatively large (say half as large as the screen
> itself) and when the image is scaled way up so that it does not fit
> within panel (say five times the size of the panel itself),
> performance is very poor. By this I mean that the user's drawing on
> top of the image lags significantly behind the movement of the mouse.
>
> All of my rendering is done inside of the panel's paintComponent(...)
> method.
>
> This is how I draw the image:
>
> g2d.drawImage(theImage.getBufferedImage(), 0, 0, null);
>
> Also, I am not setting a clipping area.
>
> At this point I'm looking for some general advice on how to improve
> performance. I'm guessing that this would involve setting a clipping
> region.
>
> If so can some one give some specific pointers on how to set the
> proper clipping region when AffineTransform has been used to scale and

> pan the image so that the image is much larger than the panel itself.
>
> Thank you,
>
> Ted Hill
> ======================================================================
> =====
> To unsubscribe, send email to listserv@java.sun.com and include in the

> body of the message "signoff JAVA2D-INTEREST". For general help, send
> email to listserv@java.sun.com and include in the body of the message
> "help".

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Chet Haase

Hi Ted,

On intermediate images:

You might check out my blogs on the various image types on javadesktop.org.
They don't go over this method in detail, but they do mention in in various
contexts. I should write up a blog specifically about this technique since
it's kind of a useful tidbit to know and use.

Breifly, it's like this. Let's say you have an image of some size and you
want it to be scaled to 100x100 into the window. You could do this in
your paintComponent() method:
g.drawImage(img, 0, 0, 100, 100, null);
This will cause us to scale every time (assuming your original image is not
100x100).
You could, instead, use the Intermediate Image approach, where you create an
image of the appropriate size, scale the original image to that new
temporary
image, and then do a simple copy from that temporary image:
if (intermediateImage == null ||
intermediateImage.getWidth() != 100 ||
intermediateImage.getHeight() != 100)
{
intermediateImage = createImage(100, 100);
Graphics gImg = intermediateImage.getGraphics();
gImg.drawImage(img, 0, 0, 100, 100, null);
}
g.drawImage(intermediateImage, 0, 0, null);
Note here that we are only creating/rendering-to the intermediate image
whenever either the size of your scale has changed or when that intermediate
image has not yet been created. At all other times, we are simply
copying from
that image (make intermediateImage a class variable so that you are not
creating it anew every time through paintComponent()).

On repainting a specific region, I don't have an example off-hand, but
check out the docs on repaint(x, y, w, h).

Chet.

Ted Hill wrote:

>Chet,
>
>Thanks for the quick feed back.
>
>Can you elaborate a bit on "pre-scaling to an intermediate image" or
>point me to more information on this idea.
>
>Can you also point me to some resources that discuss your 2nd
>suggestion: "repainting altered areas." I have the JDK documentation but
>it would be nice to see some examples and read a discussion of different
>ways to set clip areas.
>
>Thanks again,
>
>Ted Hill
>
>
>
>
>-----Original Message-----
>From: Chet Haase [mailto:Chet.Haase@Sun.COM]
>Sent: Wednesday, August 25, 2004 9:44 AM
>To: Ted Hill
>Cc: JAVA2D-INTEREST@JAVA.SUN.COM
>Subject: Re: [JAVA2D] Image rendering and speed.
>
>
>
>Hi Ted,
>
>There are two approaches I can think of off the top of my head that
>might improve things for you:
>intermediate images, and repainting only what you need to.
>
>1) Intermediate images
>There is no need to scale the image every time you paint it if it's the
>same size for
>some amount of time. Why not pre-scale that image to some intermediate
>image
>instead nad then simply call drawImage() from that temporary image?
>This copy operation will,
>in general, be way faster than a scaling operation (at least until we
>support scaling
>operations in hardware, which is only enabled in the non-default opengl
>pipeline as of
>jdk 5.0).
>
>2) Repainting altered areas
>There is no need to tell Swing to repaint the entire image area: you can
>
>just tell it to
>update the region that's changed (the difference between the last mouse
>position and the current
>one, presumably). Then you will get called with a Graphics for the
>component with a clip
>set appropriately and can draw only that changed region.
>
>I think suggestion #1 above will have the biggest impact; if you don't
>need to transform
>on the fly, don't...
>
>Chet.
>
>
>Ted Hill wrote:
>
>
>
>>Hello,
>>
>>I am displaying a BufferedImage in a JPanel and have some questions on
>>performance.
>>
>>I use the AffineTransform to scale and translate the BufferedImage in
>>the panel.
>>
>>I also allow the user to draw on top of the image by dragging the
>>mouse (something like a paint program). So as the user draws on top of
>>
>>
>
>
>
>>the image, I need to keep calling repaint() on the panel to update the
>>
>>
>
>
>
>>image and the user's drawing.
>>
>>What I find is this:
>>
>>A. When my panel is relatively small (for example an 8th of total
>>screen area) and when the image is not scaled up (fits entirely within
>>
>>
>
>
>
>>the panel), I get good performance. That is, the user's drawing keeps
>>up with the motion of the mouse in the panel.
>>
>>B. When the panel is relatively large (say half as large as the screen
>>itself) and when the image is scaled way up so that it does not fit
>>within panel (say five times the size of the panel itself),
>>performance is very poor. By this I mean that the user's drawing on
>>top of the image lags significantly behind the movement of the mouse.
>>
>>All of my rendering is done inside of the panel's paintComponent(...)
>>method.
>>
>>This is how I draw the image:
>>
>>g2d.drawImage(theImage.getBufferedImage(), 0, 0, null);
>>
>>Also, I am not setting a clipping area.
>>
>>At this point I'm looking for some general advice on how to improve
>>performance. I'm guessing that this would involve setting a clipping
>>region.
>>
>>If so can some one give some specific pointers on how to set the
>>proper clipping region when AffineTransform has been used to scale and
>>
>>
>
>
>
>>pan the image so that the image is much larger than the panel itself.
>>
>>Thank you,
>>
>>Ted Hill
>>======================================================================
>>=====
>>To unsubscribe, send email to listserv@java.sun.com and include in the
>>
>>
>
>
>
>>body of the message "signoff JAVA2D-INTEREST". For general help, send
>>email to listserv@java.sun.com and include in the body of the message
>>"help".
>>
>>
>
>
>
>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

Augusto Sellhorn

I have a situation where users are editing a vector drawing in a program
where the font doesn't match what I display in my renderer. In their
editing program, all that is saved is a world "height" for the text, so
I can use that to scale and match the font once I draw it.

Now, the font they use in the editing program is monospaced, so based on
the height, i can calculate a "maximum width". Saying that, I'm trying
to find a way to simply draw a string saying and make sure it doesn't
exceed this bounding box (height and calculated width).

Is there any easy and fast way to do this?

What I have now tries to match the height, and it does, but then when it
goes for the width it has to decrement the size until the width is not
greater than the calculated width. There are some cases where this takes
too many iterations and is slow.

So if anybody has any idea what I'm talking about :-), what's a good
idea to just say, draw this string and don't exceed these bounds?

Thanks

Augusto

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

mgrev
Offline
Joined: 2003-08-12

Some pseudo code that [i]may[/i] do the thing. It's a predicting kind of "binary" search algorithm.

[code]
int targWidth = getWidthOfTarget();
int curWidth = getWidthOfString(text, font);
Font font = getTheFont();

while(isWidthCloseEnoughToEnd(curWidth, targWidth)) {
font = getResizedFontByPercentage(font, targWidth / curWidth);
curWidth = getWidthOfString(text, font);
}

g.setFont(font)
g.drawString(x, y, str);

[/code]

Cheers,
Mikael

Chet Haase

Hi Ted,

There are two approaches I can think of off the top of my head that
might improve things for you:
intermediate images, and repainting only what you need to.

1) Intermediate images
There is no need to scale the image every time you paint it if it's the
same size for
some amount of time. Why not pre-scale that image to some intermediate
image
instead nad then simply call drawImage() from that temporary image?
This copy operation will,
in general, be way faster than a scaling operation (at least until we
support scaling
operations in hardware, which is only enabled in the non-default opengl
pipeline as of
jdk 5.0).

2) Repainting altered areas
There is no need to tell Swing to repaint the entire image area: you can
just tell it to
update the region that's changed (the difference between the last mouse
position and the current
one, presumably). Then you will get called with a Graphics for the
component with a clip
set appropriately and can draw only that changed region.

I think suggestion #1 above will have the biggest impact; if you don't
need to transform
on the fly, don't...

Chet.

Ted Hill wrote:

> Hello,
>
> I am displaying a BufferedImage in a JPanel and have some questions on
> performance.
>
> I use the AffineTransform to scale and translate the BufferedImage in
> the panel.
>
> I also allow the user to draw on top of the image by dragging the
> mouse (something like a paint program). So as the user draws on top of
> the image, I need to keep calling repaint() on the panel to update the
> image and the user's drawing.
>
> What I find is this:
>
> A. When my panel is relatively small (for example an 8th of total
> screen area) and when the image is not scaled up (fits entirely within
> the panel), I get good performance. That is, the user's drawing keeps
> up with the motion of the mouse in the panel.
>
> B. When the panel is relatively large (say half as large as the screen
> itself) and when the image is scaled way up so that it does not fit
> within panel (say five times the size of the panel itself),
> performance is very poor. By this I mean that the user's drawing on
> top of the image lags significantly behind the movement of the mouse.
>
> All of my rendering is done inside of the panel's paintComponent(...)
> method.
>
> This is how I draw the image:
>
> g2d.drawImage(theImage.getBufferedImage(), 0, 0, null);
>
> Also, I am not setting a clipping area.
>
> At this point I'm looking for some general advice on how to improve
> performance. I'm guessing that this would involve setting a clipping
> region.
>
> If so can some one give some specific pointers on how to set the
> proper clipping region when AffineTransform has been used to scale and
> pan the image so that the image is much larger than the panel itself.
>
> Thank you,
>
> Ted Hill
> ===========================================================================
> To unsubscribe, send email to listserv@java.sun.com and include in the
> body of the message "signoff JAVA2D-INTEREST". For general help, send
> email to listserv@java.sun.com and include in the body of the message
> "help".

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".