David German - Engineering 26 Portfolio

Lab 1: Basic Image Manipulation

Bluescreen

A computer image is an array of discrete color elements called pixels. A pixel's color is customarily encoded in three channels, which specify the intensity of the primary additive colors - red, green, and blue - required to compose the pixel's color. In many conventional image formats, including all those used in this exercise, each channel is eight bits wide.

Algorithms to distinguish a monochromatic, primary-color backdrop from a scene staged in front of it are fairly intuitive, and straightforward to implement in software. Thus, a computer can be programmed to replace the backdrop pixels with an alternative image.

Procedure

Prof. Maxwell photographed each student in front of a bluescreen. I prepared my photo with the GNU Image Manipulation Program (GIMP), running the built-in blurring filter to remove noise, scaling the image down for convenience, and exporting it as a portable pixmap (PPM). The GIMP reported that the output image was 1458x1944 pixels.

The image libraries referenced in the laboratory instructions provide functions to read and write PPM files within a C program. I wrote a simple C program (ppm_whitesquare.c, appended) to find the coordinate origins of the PPM and TIFF formats. The origin of a PPM image is the top left corner; the image-viewing utility xv also follows this convention. The origin of a TIFF image, as Prof. Maxwell's tiffmain.c reveals, is the bottom left corner.

I wrote a C program (bluescreen.c, appended) to replace the bluescreen in my photo with the corresponding pixels from an identically-sized image. After a little tinkering, I decided to identify any pixel with a blue value larger than three-quarters of the red and green values summed as backdrop. Since I was wearing no blue clothing in the picture, this algorithm did not produce false positives despite its high sensitivity and context-unawareness. There are a few, barely-noticeable false negatives amid my hair and along my sleeves. Under more demanding circumstances, one might consider whether a pixel bordered other probable bluescreen pixels before judging it bluescreen.

Results

I used bluescreen.c to superimpose myself on a portion of an image of a thunderstorm taken by the Thuringer Landessternwarte Tautenburg institute in Tautenburg, Germany and found on its website. At Prof. Maxwell's suggestion, I extended the program to implement radial intensity shading so that I appear more illuminated nearer the lightning.

David and lighting
Image 1. Tropical Depression Ernesto was much less exciting than the storm in the background.

I then modified bluescreen.c to generate a new image featuring multiple instances of me, scaled, translated, layered, and colorized. I scaled without interpolation, simply replacing every square of four pixels with the top right pixel. Since my face contains little high-frequency information, this approach does not create noticeable artifacts. Layering generalizes the principle behind background insertion: higher-layer objects are added to the image before lower-layer objects, and each pixel of the object is added only if the destination pixel is still bluescreen. To translate the miniature Davids, I simply began attempting to insert their pixels at a constant-defined point.

David and his split conscience
Image 2. The gentleman on the right was cranky after a long walk in the rain. His counterpart, however, was thrilled to be attending e26 lab.

Fractals

The Mandelbrot set and the Julia sets are sets of sequences defined by the recurrence relation z(n+1) = z(n)^2 - c, where z and c are complex numbers. For a given Julia set, c is constant, and the set contains the sequence with initial condition z(0) = k for all points k on the complex plane. In the Mandelbrot set, z(0) = 0, and the set contains the sequence with c = k for all points k on the complex plane.

The Mandelbrot and Julia sets exhibit chaotic behavior. The sequences in each attract to infinity or zero, but the pattern relating points to attractors is infinitely complex, or fractal. Computer-generated visualizations of interesting regions within these fractals help clarify this concept. They are also aesthetically pleasing.

Procedure

I wrote two similar programs (mandelbrot.c and julia.c, appended) to generate fractal images. Each program expects bounds of the region of interest in the complex plane, and dimensions for the output image, as arguments; julia.c also expects the real and imaginary components of c.

Both programs iterate over the image space, mapping each pixel in that space to the corresponding point in the complex plane. They then compute an eight-bit intensity for that pixel; the intensity is the value n for which z(n) at that point exceeds 100 in magnitude, or 255 if it does not do so before it would overflow the eight-bit field. Thus, the more likely a point is to be zero-attracted, the greater the intensity at that point. Intensity is then converted to a graphic representation.

Since a pixel has non-zero area, the procedure just described actually applies the complex value for the upper left corner of a pixel to the entire area it covers. This aliases high-frequency information. Both my programs therefore contain code that samples a 4x4 grid of complex points within the pixel, computes intensity for each of them, and averages the results to generate the actual intensity applied to that pixel.

Results

With experimentation, I decided that greyscale fractals were more elegant than any colorization I could concoct.

Mandelbrot set w/o AA
Image 3. The Mandelbrot set from (-.5, i) to (2, -i).

Mandelbrot set w/AA
Image 4. The Mandelbrot set as above, with antialiasing.

Julia set w/o AA
Image 5. The Julia set for c = .7454054 + .1130063i, from (-1.5, i) to (1.5, -i).

Mandelbrot set w/AA
Image 6. The Julia set as above, with antialiasing.

Piece of a Julia set
Image 7. The Julia set for c = -.3 - .018i, from (-1.25, i) to (1.25, -i), with antialiasing.

Part of the Mandelbrot set
Image 8. The Mandelbrot set from (0, .64i) to (.1, .7i), with antialiasing.

Conclusion and Future Work

This project introduced useful tools for computer graphics work, including relevant features of the C language, the PPM and TIFF I/O libraries, and UNIX applications for both software engineering and image analysis. It also introduced key concepts, such as color itself, mappings between mathematical and image spaces, and aliasing.

In future work with bluescreens, I would put more effort into lighting, perspective, and other factors influencing plausibility: my images are not very convincing. In future work with both the Mandelbrot and Julia sets, I would like to quantify the effects of aliasing and antialiasing on the fractal signal.

As predictably happens in a time-pressured academic project, my code is not so well-engineered as I would like. It is not exhaustively documented. It contains a variety of unsafe procedures that could yield erratic behavior or segmentation faults given invalid input. Potential modularity is not fully exploited. Potential optimizations remain on the table. No formal, structured testing has been done. I will try to improve on these points as time permits. It would be helpful to be assigned a more structured, black-box specification for future projects.

Appendices

My code is available for download. To comply with course policy, however, it is encrypted with AES256, and I will only furnish the passphrase to Prof. Maxwell. Note that Prof. Maxwell's example code influenced the development of all my programs, and the makefile is mostly verbatim his.