drawing complex generated image in java 2d - java

I have a very large complicated diagram that needs to be drawn on the fly.
I am already using a double buffered technique to paint the image (from this answer: Using threads to paint panel in java) however, the generated image that is being painted is so large that it cant be painted as a single image (and the multiple images required to paint it cant be stored in memory all at the same time). For this reason, I paint the currently visible area of the view + some margin. As I scroll, I paint the area that is going to come next, and remove from memory the area we just came from. However, if the user then decides to change direction, they need to wait for this area to be painted again. My question is this:
If a single "frame" of the screen being painted is approximately 1000*1000 pixels, in which approximately 5000 lines/circles are drawn (nodes/edges of a graph) is it likely to be more efficient to repaint this image each time, or is there a way to affectively cache the image to hard disk (to avoid java heap limitations).
Ive already optimised the paint method as much as I can think of, but there are still several seconds of delay if a user scrolls to quickly (i.e. moves out of the painted area before the next set of "frames" are painted). So my second question is this: Will moving to OpenGL offer a large improvement, and will it require major changes to the infrastructure of the code? (I tried doing this a couple of days ago, and found it was not as simple as I thought - often led to the computer crashing).

Several things come to mind:
Profile to verify your working hypotheses; self-time the animation budget on your target platform for comparison, as shown in this AnimationTest.
Compare your approach to the example cited here; it scales into the 1000's and accommodates dragging selections into the hundreds.
If your frames have a suitable geometry, consider adopting the flyweight pattern for rendering; JTable rendering is an example; the underlying mechanism using CellRendererPane is examined here.

Related

Implementation of specfical region refresh with Java Swing

The number of models that my swing application needs to display is currently 2000 to 10000 images. After multiple zooming or using for a period of time, the memory continues to increase and will not decrease,How can I optimize it?
It is hard to recommend anything without knowing more about the environment, but I'll list some general tips:
You resize images every time you zoom in/out. This creates new images rapidly, especially if you zoom in using the mouse wheel or some other tool that fires events rapidly. Consider creating the image after the resizing has finished.
Don't hold references to unused images. This means you shouldn't store all the resized images, only the used ones.
Probably you don't need every image in every state of the
application - consider creating a loading screen which is shown while your application loads and resizes the used images, and discards the previous ones. (It does not have to be an actual loading screen or animation)
I've never seen a small or medium-scale project which needed 10k unrelated images. You might be storing animations per-frame, which is way less efficient than using video formats.
If you have many similar images, consider not loading them from file but instead paint them dynamically (you have a base image and paint over it using the component's Graphics).
Call the garbage collector. This should free up any unused space in the memory.

Java Swing heavy/slow paintComponent - any advice?

I'm making a scrolling 2D map/tile based game. Each tile (stored as tile[21][11] - 231 tiles total per map) can contain up to 21 values (stored as int[3][7]). While full-screen I see about 8 maps at once.
On average, each map takes about 0.03 seconds to draw (found with System.nanoTime). The problem is that as soon as more than 1 map is on the screen, the Swing event polling noticeably slows down.
Is there any solution to this? I can't draw the map a single time to save it as an image because it has transparency involving moving actors, so it changes too frequently. Also I don't think I can call a thread in paintComponent to draw the maps without it glitching out, but I'm not positive.
My Tiles aren't any type of JComponent, they're just data. I call their container the MapPane, which draws all of the tiles in its paintComponent.
Likewise, JTable cells are just data rendered inside a JComponent; the flyweight pattern, mentioned here, is still applicable: the goal is to omit any effort to render non-visible cells. Profile and self-time with a view toward optimizing the rendering; some approaches are examined in the KineticModel cited here.
A BufferedImage that needs no scaling is best. If you must scale, experiment with RenderingHints related to interpolation type. If composition is too expensive, construct maps in the background using SwingWorker; publish() them as they become available and process() them on the EDT, as shown here.

Canvas/Stage Size in Flash is too small and cannot show entire level

This isn't directly a programing problem but I feel it still can fall under the catagory, I am sorry if this is the wrong place. I am making a game in flash using box2d and I decided to draw the levels in flash as the level design would look better, The levels are very large ( this level is 10,000 pixels long) and the canvas in flash just won't display anything.
The preview in the library seems to be able to display the drawing longer than the one on the stage. How do I go about making the canvas longer? Should I try upgrading to a newer version of flash, does that version allow this?
You just don't put everything at once over your canvas, instead draw only those level primitives or parts that are visible right now. Or, if your level is basically a pretty simple shape, you can just change its X and Y so that the relevant part of the level is displayed on stage.
Don't use giant bitmaps - they use a lot of memory, and even if not all of the content is visible, they will degrade performance considerably. For this reason, Flash imposes a size limit of 4095x4095 pixels (or an equal amount of pixels in rectangular formats).
The way to deal with this is to tile your graphics into parts of equal size, preferably smaller than the stage (1/2 or 1/3 side length is a good measure). You then place them all as a grid into a larger Sprite or MovieClip and set visible=false; on each tile. Then, at runtime, your game loop must check for each frame, which of the tiles should actually appear on the stage - and only those should then be set to visible=true;. That way, you reduce the amount of pixels drawn to what is absolutely necessary, and keep screen memory usage to a minimum.

Heap overflow implementing Undo in Swing App

I am developing a scribble type app in java swing. It is in a rudimentary stage and is shown here.
I have implemented the undo feature which undoes the last drawn stroke upto. The undo feature can be done upto a maximum defined undo levels.
The undo feature works by copying the contents of the drawing canvas after each stroke in an Image array.
This array acts like a First-In-Last-Out Stack. When undo is clicked the stack is poped
and the obtained image is drawn on screen.
Now the problem I am facing is, the current method of implementation of undo takes up too much memory. At undo levels of 20, almost 70-80 MB of memory is used up, and at levels of 30, heap overflow occurs.
Is there a better way of implementing the undo feature ? Thanks.
EDIT : I found some useful information here which may be helpful.
You need to represent the steps in your drawing differently. In the current approach you are using, you save the Canvas each time anew as an uncompressed picture - and that is memory-greedy.
Try to refactor your code so that only the strokes being drawn on the Canvas are saved into the stack. This will put a little bit more overhead when rendering the picture (you would need to redraw the entire canvas each time a change occurs), but Java is designed to deal with that.
Having saved only shapes, the memory requirements should decrease significantly. Use the Shape class to represent the strokes on the canvas.

How to generate simple 2D graphics in real time?

For my internship on Brain-Computer Interfacing I need to generate some very fast flickering squares on a CRT monitor (flickering = alternating between two colors). The monitor's refresh rate is 85Hz and we would like this to be the bottleneck, which means that repainting all squares can take at most 1000/85 = 11ms.
My language of preference for GUI/graphics programming is Java, so I tried making a prototype with AWT, because it's synchronous (unlike Swing). I now seem to have two problems: the first is that time measurements show that the repainting of even 9 squares simply takes too long. My algorithm takes the desired frequency and calculates the times at which the system should repaint in advance and then uses a loop (with no sleep/wait delay) that checks everytime if the next 'time' was reached and if so, loops through all the squares to repaint them. The way I implemented it now is that the squares are Panels with background color A and are contained in another Panel with background color B and the flickering happens because the Panels' visibility is changed. I figured that this would be faster than one Panel that has to draw Rectangles all the time.
I don't have a decent profiling tool (can't get Eclipse TPTP or NetBeans profiler to work) so I can't be sure, but I have the feeling that the bottleneck is actually not in the repainting, but in the looping (with conditional checking etc.). Can you recommend anything about what I should do?
The second problem is that it seems like the squares are rendered top-to-bottom. It's like they unroll really fast, but still visibly. This is unacceptable. What I'm wondering though, is what causes this. Is it Java/AWT, or Windows, or just me writing a slow algorithm?
Can you recommend some things for me to try? I prefer to use Java, but I will use C (or something) if I must.
I would avoid any kind of high-level "components", like JPanels and the like. Try getting a Graphics2D representing the window's contents, and use its fillRect() method.
Failing that, you could probably do this easy enough in C and OpenGL. rasonly.c is a standard template program that sets up OpenGL to work as a "rasterizer" only, i.e. 2D mode. Using this as a starting point, you should be able to get something running that draws your desired "squares" without too much trouble.
You don't describe your desired scene very well, it sounds from that equation as if you want to draw 100 squares, each having a different color. For maximum performance in OpenGL, you should draw all squares of the same color together, to minimize the "state changes" between drawing calls. This is probably a purely theoretical point though, as drawing 100 2D squares at 85 Hz really shouldn't tax OpenGL.
UPDATE: Oh, so it's been a bunch of years, and nowadays you probably need to take the above with a grain of salt and read some modern tutorial. Things have changed. Look up the Vulkan API.
(I remember a demonstration of this using the BBC micro and palette switching, though that would be 50fps rather than 85, as it was a British domestic TV)
I'd switch to jogl and use display lists. They get very high fps rates in Java.

Categories