PROJECT: FomoFoto


Overview

My team and I were tasked with enhancing a basic command line addressbook for our Software Engineering project. We decided to morph the project into a image editor.

FomoFoto is a robust yet simple image-editing tool. Users interact with the application through worded commands from their keyboard, and receive visual feedback from it through the displayed image on the application.

Unlike other heavy image editors, FomoFoto has a very gentle learning curve as it abstracts out clutter by providing the more essential features (complex editing can still be done with special commands). The features and implementations are well documented in guides for users and developers respectively.

In addition, FomoFoto is well maintained with high reliability and code quality as it is covered by rigorous tests and checks.

Summary of contributions

This section provides a summary of my coding, documentation and other contributions to FomoFoto, our team project.

  • Major enhancement 1: added the ability to undo/redo transformations on an image

    • What it does: allows the user to undo previous transformations one at a time. Preceding undone transformations can be reversed by using the redo command.

    • Justification: This feature improves the product significantly because a user can make mistakes by applying incorrect transformations and the app should provide a convenient way to rectify them.

    • Highlights: Transformation history is stored as a list of commands so it takes up minimal space on the user’s PC.

  • Major enhancement 2: added the ability to export images to the user’s PC

    • What it does: allows the user to export an image in the album to a specified directory.

    • Justification: This feature improves the product significantly because the user can save his images outside of the application.

  • Code contributed:

  • Other contributions:

    • Documentation:

      • Wrote detailed documentation on undo/redo command in developer guide: #138

      • Wrote detailed documentation on export command in developer’s guide: #216

    • Community:

      • PRs merged (with non-trivial review comments): #141 #57

Contributions to the User Guide

Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users.

Undo Edit Steps : undo

Goes back to the previous state of the image.
Format: undo

Undoable commands: those commands that modify the image (rotate, crop, resize, brightness, contrast, wm and bw).

Redo Edit Steps : redo

Returns to a previously undone state.
Format: redo

Redoable commands: those commands that modify the image (rotate, crop, resize, brightness, contrast and bw).

Examples:

  • rotate 180
    brightness
    undo (reverses the brightness command)
    redo (runs brightness again)

  • contrast 0.3
    crop 2 3 500 500
    undo (reverses the crop 2 3 500 500 command
    undo (reverses the contrast 0.3)
    redo (runs contrast 0.3 command again)
    redo (runs crop 2 3 500 500 command again)

Upcoming Features (in v2.0)

Layer

Format: layer add (layer name) → Creates a new layer for the user to work on.

Example:

  • layer add BW-layer adds a new layer with name BW-layer.

Format: layer select (layer name) → Selects the layer the user wants to work on.

Example:

  • layer select BW-layer selects the BW-layer.

Format: layer delete (layer name) → deletes the layer with input name.

Example:

  • layer delete (BW-layer) → deletes the BW-layer

This command is not undo-able and transformations on each layer do not affect other layers.

Ruler

Format: ruler [ON|OFF] → Toggles a ruler that surrounds the displayed image. This will help you in estimating the number of pixels to move when using crop or resizing objects.

Contributions to the Developer Guide

Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project.

Undo/Redo feature

Current Implementation

The undo/redo mechanism is facilitated by Image. It contains a list of commands applied to the current image. Additionally, it implements the following operations:

  • Image#addHistory() — Saves the current edit command into commandHistory list and increments index.

  • Image#setUndo() — Decreases index by 1.

  • Image#setRedo() — Increases index by 1.

  • Image#getHistory() — Returns commandHistory as List.

  • Image#getSubHistory() — Returns commandHistory sublist using index to track which commands should be included.

  • Image#canUndo() — Returns true if index > 0.

  • Image#canRedo() — Returns true if index < CommandHistory.size().

These operations are exposed in the CurrentEdit interface as CurrentEdit#addCommand(), CurrentEdit#setUndoTemp(), CurrentEdit#setRedoTemp(), CurrentEdit#getHistoryTemp(), CurrentEdit#getSubHistoryTemp(), CurrentEdit#canUndoTemp() and CurrentEdit#canRedoTemp() respectively.

Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.

Step 1. The user opens an image. The Image will be initialized with an empty commandHistory List.

UndoRedoStartingStateListDiagram
Figure 1. State list diagram for undo/redo

Step 2. The user executes a series of transformations on the image. These transformations are stored in the commandHistory list and for each transformation stored, the index is incremented by 1 to point to that transformation.

UndoRedoNewCommand1StateListDiagram
Figure 2. First Transformation
UndoRedoNewCommand2StateListDiagram
Figure 3. Second Transformation

Step 3. The user wants to undo the previous transformation by using the undo command. It will call CurrentEdit#replaceTempWithOriginal() which will replace the edited image in temp folder with the original image. It will then call CurrentEdit#setUndoTemp() to set the index in tempImage to the required index and retrieve the list with CurrentEdit#getHistoryTemp(). Using the list, it will apply the commands onto the original image until it reaches the command just before the set index.

UndoRedoNewCommand3StateListDiagram
Figure 4. Undo transformation
If a command fails its execution, it will return the image before undo was called and produce an error message.

Step 4. After executing Undo, index will be less than the size of commandHistory. If redo is not executed before a new command is added, all commands in the list after index will be deleted.

For redo, it will call setRedo and retrieve that command to apply it on the current image.

UndoRedoExecuteUndoStateListDiagram
Figure 5. State List diagram
If the Image#index is 0, pointing to the initial image, then there are no previous commands to restore. The undo command uses CurrentEdit#canUndoTemp() to check if this is the case. If so, it will return an error to the user rather than attempting to perform the undo.

The following sequence diagram shows how the undo operation works:

UndoSeqTEMP
Figure 6. Sequence Diagram

The redo command does the opposite — it calls CurrentEdit#setRedoTemp(), which shifts the index once to the right, pointing to the previously undone command, and executes that command to perform the transformation.

If the index is at index commandHistory.size(), pointing to the latest image state, then there is no undone transformation to restore. The redo command uses CurrentEdit#canRedoTemp() to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.

Step 5. The user executes saves, which calls CurrentEdit#saveToAssets(). This replaces the original image with the temp image since a name is not specified. When this happens, the user can no longer call undo as there is no original image to work on. The command history is also cleared.

Design Considerations

Aspect: How undo & redo executes
  • Alternative 1: Saves each transformation as a separate image.

    • Pros: Easy to implement.

    • Cons: May have performance issues in terms of memory usage.

  • Alternative 2(current choice): Save all transformation in a list and apply them when undo/redo is called. We chose this method as we do not want our application to take up too much space in the PC.

    • Pros: Will use less memory

    • Cons: We must ensure that the implementation of each individual command is correct.

Aspect: Data structure to support the undo/redo commands
  • Alternative 1 (current choice): Use a list to store the history of commands. We chose this so as to preserve good object-oriented programming principles.

    • Pros: Easy for new computer science student undergraduates to understand, who are likely to be the new incoming developers of our project.

    • Cons: Logic is duplicated twice. For example, when a new command is executed, we must remember to update both HistoryManager and Image.

  • Alternative 2: Use HistoryManager for undo/redo

    • Pros: We do not need to maintain a separate list, and just reuse what is already in the codebase.

    • Cons: Requires dealing with commands that have already been undone: We must remember to skip these commands. Violates single responsibility principle and separation of concerns as HistoryManager now needs to do two different things.

PROJECT: PowerPointLabs