Command Pattern for undo/redo in paint application - java

I would like to implement undo/redo in a small paint application. It seems the Command Pattern fits the use nicely, but I am unsure how to best implement it.
As I understand the pattern, it is necessary to include in each command:
The details of the paint operation for purposes of redo (e.g. Line -> start & end points, free form line -> GeneralPath)
The state of the component prior to the change for undo. In this case, that will be a small snapshot image of the area affected by the command.
My understanding based on that is that each command needs to be 'atomic' or self contained, with all the information needed for undo/redo that operation.
Unfortunately that would require storing more information than I'd first anticipated. For a line we must also account for things like the Color, Stroke and RenderingHints used to draw it initially. This turns my 'simple little commands' into something ..more bulky in memory, and with more boiler-plate code to churn out (each will be a serializable bean1).
For reasons of memory conservation (mostly) I was wanting to 'cheat' on the specification of the commands. Perhaps take a backup of the entire drawing area every 100th update, but otherwise store no part of the changed image, and simply rebuild the last (up to) 100 commands for each new paint operation. But that seems problematic to ensure that the state of the Graphics object is right before painting each part - this part might require a line, but the RenderingHints were changed 4 commands ago, the Color was changed 98 commands ago, while the Stroke has remained the same for the last 227 commands.
Pursuing a more memory efficient command seems to throw the pattern right out the window in terms of being 'atomic'. That in turn leads to difficulties in determining the earliest command that might affect the rendering.
Should I:
Look for a new pattern?
Attempt to implement my peculiar needs by tweaking the pattern?
Toss all this in the waste bin as premature optimization and code it in the simplest (and most memory consuming) way that sticks to the command pattern as defined?
Update
"each will be a serializable bean" On 2nd thoughts, no. I did dome checks to find that a Graphics2D (which neatly encapsulates many parameters used when drawing) is not serializable. Further, a BasicStroke is serializable, but the thickness of the stroke is not stored. I could create serializable versions of many of the attributes but it seems to make for a lot more code, so I'm going to abandon that spec. as well. I will only attempt to store a reference to a BufferedImage at run-time.

I would stick with command pattern and first try a naive solution (=the most memory-hungry). For some graphical operations it may be even necessary to keep a copy of the entire image in the command object (eg. think of filters). This is a common problem also in professional image editing applications, they often have a memory or step limit of last commands that are remembered. And if the memory consumption is really large you may think of swapping the oldest entries in command-history to file system. I think user will not mind waiting a second until the change is undone.

Maybe, it would be better not to store copy of entire image in command, but store only copy of area, which is changing by command. Of course, this is not a panacea

Related

Large amount of data deletion

I have a program with GUI with segment that can be large and contain a lot of objects. One of the features of my program is to "close" that segment and create a new one.
This whole segment is attached to the program by only one JPanel and an ArrayList. If I dispose of/set those two to null there should be no way to access the any of the JPanels childen (one of which are complex object extending GUI components, but also containing a lot of variables).
If I'm correct, all of JPanels childeren will be collected by garbage collector.
However, what happens to the children of the children? I have some "families" that go up to 5-6 "generations". Will they be deleted only upon GC's 5th (or 6th) pass, or will it detect the whole "family" as unacessible and collect it all at once (or upon it's first pass)?
EDIT: Another minor question: Is there a method for swing component that will remove all of it's children?
For an empirical approach, exercise your program repeatedly and look for the pattern shown here, in which the memory consumed fails to return to baseline.
In contrast, this example returns to the baseline after each cycle.
The comments to your question do a good job of addressing the deletion issue. But, if you're still curious about removing a component's children without removing the component, the answer is no, as seen in the JComponent documentation (I'm assuming you're on Java 7, if not you can easily change to the proper version of Java). If you want to quickly and easily remove just the children from a component without removing the component itself, I recommend just re-initializing the component.

How to adjust the volume of a Line without using Controls

I'm new to using the javax.sound.sampled package, the reason I chose to to use the package was to have more control over the audio I was using than some simpler sound solutions such as AudioClip.
I've read through: Oracle's Sound Tutorial
(or at least as much as I could grasp) but I don't see a method of modulating the level/volume of playback on a Line using the Clip interface they seemed to give these kinds of options in the portions of the package that allow you to create sound, but I can't find any way of making these adjustments be it through my Line, or my AudioInputStream.
I found [this] page with the text,
Float controls, on the other hand, are well suited to represent continuously variable controls, such as pan, balance, or volume.
but no Lines on my computer return any Controls (using Line.getControls())
(I tried to force the line to accept the FloatControl.Type.VOLUME similar to this but I get an "unsupported control type exception")
Is the only way to modify the volume/level on a Line (using the Clip interface) through use of the Line's controls? Or is it possible to modify the volume of an AudioInputStream?
Alternatively is there a method of adding Controls to an existing Line?
Instead of using FloatControl.Type.VOLUME use FloatControl.Type.MASTER_GAIN.
There is at least one other way, besides using lines. (I was also having trouble getting a control line, and found that a Master line worked, as recommended by Travis Meyers. I'm giving him a + vote.) Not sure if you want to go there, but it is possible to multiply EVERY frame's audio values by a volume factor. The Java Tutorial makes a passing reference to this technique, but like much else in that document, they don't provide explicit examples.
Thus, when you acquire a buffer of bytes, you have to loop through the buffer, assembling the bytes to get the audio values. Then, multiply by your volume factor (often a float from 0 to 1.0), then dissassemble the audio value back into bytes.
It works. I do it in a crude Java Theremin you can try out. I also manipulate my pitches on a per frame basis in that program. But there are still issues with the program! I'm working right now on improving the way I pipe GUI event data to the audio loop. Also, I'm responding to changes on a per-frame basis rather than via per-buffer basis. But for most uses, per-buffer is fine.
That said, something to listen for is to take care about sending in changes in volume that cause discontinuities, which can cause loud clicks. The amount that causes the click can vary in the different volume ranges. Also, volume doesn't exactly drop off in a linear fashion, as you go from 0 to 1.0 with your volume factor.

Understanding Java Swing screen buffer memory usage (reading materials would be welcome)

So I need to understand how swing allocates memory for buffering screen rendering. Obviously there are duplicates if you have double/tripple/etc buffering. However I would need to know when swing allocates memory and how much of it. Very helpful to know if I have multiple windows open (launched from the same jvm) how much memory is needed depending on windows being maximized to one screen, multiple screens (I need it to go up to 6 screens), etc.
Does anyone know of any good readings or maybe have answers for how Java Swing/AWT allocate memory for rendering buffers.
End of the day, I am looking for a definitive formula so that if I have a number of windows opened, number of buffers in each window, location of windows, and size of each window I can get an exact byte count required to render the application (just the buffering part, the rest of the memory is another problem)
I was assuming it was (single buffered) x by y of each window = 1 buffer, add those together and you have all memory requirements, but profiling the data this appears to be far from the truth, some buffers are weak/soft references, some strong, and I cannot determine the way to calculate (yet :)).
Edit: I am using JFrame objects (for better or worse) to do my top-level stuff.
Double buffering is a convenient feature of JPanel, but there will always be a significant platform-dependent contribution: Every visible JComponent belongs to a heavyweight peer whose memory is otherwise inaccessible to the JVM.
If you're trying to avoid running out of memory, pick a reasonable value for the startup parameters and instruct the user how to change them. ImageJ is a good example.
I'd recommend JConsole and the Swing Source code fro this kind of precision.
I assume you realize this will be extremely tedious to calculate since you have to consider every object created somewhere in the process, which of course will depend on the controls involved in the UI.
I am not aware of any automatic screen buffering support in Swing. If you need double buffering, you need to implement it yourself in which case you will know better how to calculate memory requirements :-)
See this answer: Java: how to do double-buffering in Swing? for more information and good pointers.

How is userinput kept independent of FPS when using for example Java Slick 2D or .NET XNA framework?

I have written a few 2D games in the past using libraries such as LWJGL (with a Slick2D wrapper) and the XNA framework, but one thing i have never been able to grasp (or have the need to) is how the user input is kept constant, eq not dependent on FPS.
I'm looking for a more generic answer rather than framework specific. I understand it has something to do with time measured between frame updates ?
Thank you
I can't speak for some of those other frameworks, but I know that XNA basically lets you poll the current input state (are the buttons up or down?) whenever you like. You usually do it each frame.
What this means is, if your player happens to be a ninja and can hit keys faster than 60FPS, it is possible that they may hit a key (or mouse button) between pollings and you miss it. In practice it is almost never an issue.
If it does bother you, the solution to this problem is to hook the Windows message pump and receive keyboard up/down events.
For general gameplay it is really not worth the effort. Usually the only time where you really must capture every keystroke is when the user is typing text. So rather than capture key up/down events, you capture character events (WM_CHAR). This means you won't miss a keypress. But the more important problem that this solves is that it offloads key-to-character translation to Windows - allowing it to handle key-repeat, keyboard layout, shifted characters, etc, for you - allowing your game to behave like any other Windows application.
(Of course, if you can get away with just using the polling-based framework input stuff - go with that - it's much easier to implement and less platform-specific.)
The above only matters when you are detecting distinct key presses (eg: tap to fire this gun), as opposed to holding keys down (eg: accelerate this vehicle).
The alternate interpretation of your question is you are suggesting that a key may come up half way through a frame - how do you account for that, in a game with a discrete time-step?
Generally you don't worry about it. Just as 60 frames per second is fast enough to discretely calculate your game state and appear smooth and continuous to a human, it's fast enough to accept input.
But what happens if you're not running at 60FPS? If you're running at 30FPS (as you might on a mobile platform), then it can make your inputs - particularly analogue inputs - feel much smoother if you poll them at 60FPS. The easiest way to do this is to simply do two Updates for each Draw - if your Update is not too taxing on the CPU.

Efficient undo/redo for Photoshop-like mobile app

I'm trying to write a painting app for a mobile device (Android) that will have a bit more functionality than MS Paint (e.g. various brushes and brush settings, selections, layers) but won't be as complex as Photoshop. I need my app to have a decent undo/redo feature. Unlimited undo/redo is probably not possible. I'd be happy with being able to undo about the last minute worth of user actions (maybe about 20 actions).
The main approaches I know of for undo/redo is:
save the whole state or just the bits that changed after each operation. Undoing involves updating the state by restoring snapshots. Pros: simple to implement Cons: memory intensive.
use the command pattern where each command has a "do action" and "undo action" method. To undo, you just call the undo action of the previous commands. Pros: memory efficient, Cons: much more complex to implement.
My pathological undo/redo scenarios I have to consider is:
the user paints over the whole canvas in one go, where you would want this whole operation to be undone when the user clicks undo. With option 1, we'd need to store a bitmap the size of the whole canvas.
the user draws something, imports image 1.jpg onto the canvas, does some more drawing, 1.jpg is then deleted/modified at some point by another application and then the user wants to undo then redo all their actions in the paint application. I'm really not sure how to undo correctly here without saving a copy of any imported image while it's on the undo stack.
Can anyone give any recommendations about how best to implement undo/redo on a mobile device where memory and processor speed are low? I like the simplicity of 1 and 3 but it seems like the only realistic option is 2. I'm not sure how to cope with my second pathological example with this option though.
On the iPhone, Core Data has built in support for undo and redo. Just make your data model reflect the objects drawn and you can easily roll it back and forward between saves. Usually you would save the procedures and objects used to create the graphic instead of the graphic itself.
Edit:
OK, but this is just a little API
support for implementing number 2 and
won't help with the examples I gave.
The key idea to making this work is that you don't configure your data model to modal and persist the graphical output of the program, you configure it to modal and persist the process of creating the graphical output.
The naive way of creating a graphical program would be to set up the data flow like:
Input_UI-->Display_UI-->Data_Model
The user manipulates the Input_UI which directly alters the onscreen graphics of the Display_UI. Only when the user saved would the Data_Model come into play. This type of data flow makes undo/redo (and other things) very hard to implement especially in a painting e.g. compositing program. Every single operation has to know how to undo itself and has to be able operate on the altered graphic.
The better way is to set up a data flow like this:
Input_UI-->Data_Model-->Display_UI
The user manipulates the Input_UI which communicates to the Data_Model which manipulations the user chose. The Data_Model records the process e.g. "add file jpg.1 at rect {0,0,100,100}". A change to the Data_Model sends a notification to the Display_UI which reads the changed data and implements the process described.
The Data_Model rolls itself back and the Display_UI simply draws what the Data_Model tells it to. The Display_UI doesn't have to understand the undo process at all.
In a drawing program you would create logical layers of individual graphical objects so that redoing is just a matter of removing layers in the reverse order they were added. For painting/composition programs, you have to start at the last save point and recreate the graphic going forward until the last-1 step.
So, in your examples for a compositing program:
The Data_Model stores the coordinates of the selected area (the entire canvas) which is still just "rect {0,0,canvas.width,canvas.height}" and then the operation "fill with black". For undo, the Display_UI whips the image back to the last save point and then invisibly applies the changes made up to last-1.
You just need to save a cache of the image up until the next save. At that point, the Data_Modal commits all the changes and exports the composition to a file. The next time the app starts, it begins with the image from the last time. If you want infinite undo, then yes you have to save the imported image permanently.
The way to approach this is to ignore the GUI and instead think about how you would design an app to be run from the command line with out any GUI input or output. The Data_Modal would work just the same. It would save the text commands and the data (e.g. imported images) for creating the output image, not just a snapshot of the image on screen.
I like the simplicity of 1 and 3 but
it seems like the only realistic
option is 2.
I'm not sure what "3" is, since you only appear to have two options in your question.
With respect to the memory consumption of #1, it's only an issue if you use memory. Only hold onto history in memory for as long as it takes an AsyncTask (or possibly a regular background thread working off a LinkedBlockingQueue) to write them to the SD card. No SD card -- no undo/redo. On an undo, if your history has already written it to disk, reload it from disk. Just be sure to clean up the SD card (delete history on a clean exit, delete all lingering files on next startup).
Bear in mind that I have never written a painting application, let alone on Android, and so there may yet be performance problems (e.g., undo may take a second to load the bitmap off of the SD card).

Categories

Resources