Log in

View Full Version : C# Help



Haruki-kun
2009-11-12, 08:42 PM
Usually, I don't like to start threads for this sort of thing, but I need a bit of homework help and Google has failed me.

Here's the thing.... We're creating a simple Paint application. It already works, it rotates the image, it's got eyedropper, creates circles and rectangles, etc. The problem is we still have several requirements to meet. We have to:

-Undo/Redo
-Smudge
-Invert Colours
-Bucket
-Select, Cut/Copy/Paste

I'm mainly in charge of finding out how to undo and redo, but if anyone has ideas on how to work the others, that would be appreciated.

My thoughts for the Undo/Redo tool are currently to create two stacks in which I'd save instances of the image, but I don't know how to do that.

RS14
2009-11-12, 09:14 PM
My thoughts for the Undo/Redo tool are currently to create two stacks in which I'd save instances of the image, but I don't know how to do that.

That would work. A doubly-linked list makes a bit more sense to me, but the differences would be minor. Either way, remember to delete your data properly to avoid memory leaks.

I'm not familiar with C#, honestly, but I imagine there is some library containing the relevant data structures.

Tirian
2009-11-12, 10:00 PM
You don't know how to do what? Create a collection of objects or implement a stack?

Haruki-kun
2009-11-12, 10:05 PM
You don't know how to do what? Create a collection of objects or implement a stack?

I know both of those. What I don't know is what object I can use to save the image into a stack. In other words, I know how to stack, but I don't know what to stack.

Tirian
2009-11-12, 10:38 PM
If you haven't already, you need to encapsulate whatever it is that you're displaying on the screen and make that an Image object. That object will be responsible for displaying itself on the screen (which would be a graphics context or whatever c# calls that that would be set in the initializer), and also sending some sort of persistent version of itself to the undo/redo stack (and the clipboard too, I suppose, when it comes time to implement cut and paste).

Delwugor
2009-11-13, 12:23 PM
Overall I would look at two possible approaches - the first is separate stacks for undo and redo. The other is a double list with a pointer to the current place in this list - anything "below" is an undo anything "above" is a redo.

The critical question as you said is what to save. I'd suggest saving the original image as the first thing added to the stack (or the list) and the rest would be the commands that change the image such as 'add a ellipse", 'fill this area'....

RS14
2009-11-13, 12:39 PM
The critical question as you said is what to save. I'd suggest saving the original image as the first thing added to the stack (or the list) and the rest would be the commands that change the image such as 'add a ellipse", 'fill this area'....

This is easy on memory, but will take longer to reconstruct it from the original image.

A reasonable hybrid mode would be to have a small rectangular sub-image with coordinates that is the xor of everything that changes. Thus you can easily go both forwards and backwards, and you don't need to store an entire copy of the image at each stage of construction.

For example, given

00000
00000
10101
11111

which is changed to

10000
10000
11101
11111

you would store (0,0) and (1,3) as the coordinates of the changed rectangle and

10
10
01
00

as the changed data. Then to reverse this, for example, xor the changed data over the applicable range.

Consider caching the history to disk when it gets large.

Delwugor
2009-11-13, 02:28 PM
This is easy on memory, but will take longer to reconstruct it from the original image.
That's why I wouldn't reconstruct the display image from the original except when absolutely necessary.


A reasonable hybrid mode would be to have a small rectangular sub-image with coordinates that is the xor of everything that changes. Thus you can easily go both forwards and backwards, and you don't need to store an entire copy of the image at each stage of construction.

For example, given

00000
00000
10101
11111

which is changed to

10000
10000
11101
11111

you would store (0,0) and (1,3) as the coordinates of the changed rectangle and

10
10
01
00

as the changed data. Then to reverse this, for example, xor the changed data over the applicable range.

That looks very workable as long as you add in the information for the area of the sub-images that the change occurs.
But I do note that this implements a undo/redo on the image but not one for actions on the image. Yes that is a subtle distinction but I think worthy to mention.