-
Notifications
You must be signed in to change notification settings - Fork 1
Images
image.h provides a Color class and an Image class. Images can
be loaded from file or created. Users may access and set per-pixel color data. Image can be modified
by manipulating them at the pixel level, as well as by drawing lines, circles, rectangles and text.
Images can be displayed and saved as bitmaps (an uncompressed format).
image_event.h provides a MouseEvent and a MouseEventListener interface. Extend the MouseEventListener interface and implement OnMouseEvent. To begin receiving mouse events, use Image::AddMouseEventListener to register for mouse events, and enter the event loop with Image::ShowUntilClosed. Note you will need to use Image::Flush (and cout::flush) to ensure updates are noted after calling Image::ShowUntilClosed.
image.cc is backed by CImg, an open-source C++ image processing library. To update CImg.h
to the latest, run make update_cimg in graphics/.
It would be possible to back image.cc with some other implementation, for example Skia or OpenGL. CImg was chosen because it is relatively light-weight, as all the implementation is contained within the CImg.h header.
Graphical assignments can vary between instructors handling all the drawing / animation / event handling logic in starter code to having students implement the entire thing. The more graphical work the instructor's starter code does, the less unit tests need to concern themselves with checking the image.
- Instructor code handles graphical component:
- Pixel manipulation
- Drawing shapes
- Animation
- Mouse events
Make a new repository from the cppaudit-graphics-template to get a template lab, including a copy of cpputils, example unittest, and a github action to test the unittest is working.
Writing testable graphical assignments:
- Try to avoid floating-point math that could impact graphical layout or coloring. For example, a recursive fractal tree might have floating point math that impacts how it is drawn many iterations deep, while a recursive sierpinski's carpet will not have that issue over an image that's sized to a power of 3. Future work may include improving unit testing to check for "almost-equal" images, but that is not currently available.
- Unit tests cannot view the image in a window, but they can look at a .bmp file. I've tended to include a method
graphics::Image& GetImageForTesting()to allow unit tests to inspect the image without saving it. - If
Image::ShowUntilClosedis called it will cause the unit tests to hang. EnsureImage::ShowUntilClosedis only called by the main program but not unit tests. This might require separating anInitializefrom aStartmethod. - Use
graphics::AnimationEventListenerinstead ofImage::ShowForto create animations. This allows mock animation events to be sent.
graphics::Color has equality and inequality operator overrides so you can do the following, as expected, in gtest:
graphics::Color red(255, 0, 0);
ASSERT_EQ(image.GetColor(0, 0), red);If you want to test image equality use methods from image_test_utils.h in cpputils/graphics/test. These generate a expected vs actual image file using overlay or side-by-side, or highlighting differing pixels in red.
You must call Image::Show before generating mouse or animation events, and tests must be run on a machine with an x server. If running on a headless server you can use the following steps to get an X server for unit testing:
sudo apt-get install xvfb
Xvfb :99 &
export DISPLAY=:99
Animation: use TestEventGenerator in cpputils/graphics/test to SendAnimationEvent as many times as desired.
Mouse: use TestEventGenerator in cpputils/graphics/test to move the mouse, click it, drag it, and release it.