I've managed to pull off a number of helloworldlets:
The ones in large boldface appear in the
final production. Progressively sillier program names are a byproduct
of my homegrown version-control algorithm...
-
hc/lib/loadj.c
- Figuring out libjpeg well enough to read in a color jpeg image to
play with and displaying it with GL (writing too, now, and color or
grayscale)
- dd/dc.c
- drawing Dirichlet domains in GL (with z-buffered cones)
- dd/djt.c
- and making a mosaic out of an image and the DD's (anything to get
rid of the grid...)
-
hc/lib/color.c
- Color space conversion. Everything here was done in YIQ space.
-
hc/lib/wto.c
- wavelet-transforming images (DAUB4 and Haar wavelets)
- wav/jwdemo.c,
wav/sigrun.c
- Two (Daubechies-4) wavelet-compressing demos: in the
first, you can tweak thresholds for Y,I,Q coefficients (dreadful
glutMenuThing interface); the second shows the image reconstructed
from only its biggest coefficient, then adds the next largest,
...
- hc/lib/top.c
- Finding the top M of N
wavelet coefficients (cross between heap-select and index sort),
zeroing all the rest, and transforming back (99%+ can go away and look
all right, or far more and still be of some use). By the
way, it turns out that only rarely are more than two or three of the
top40 coeffs in the I or Q direction.
- hc/cropsqs.c
- Image cropping: as
many as can fit of as large as possible of 2n x
2n chunks; used for making the biggest tiles from random
jpegs.
- hc/lib/rez.c
- Image scaling: rescale a 2n x 2n image up or
down by factors of two, with no bicubic resampling or anything;
scaling used not for matching at different resolutions but only for
applying tiles at the right size (early revs use glRasterPos(),
glPixelZoom(), and glPixelDraw() to actually draw them on in the right
place at the right size, and then glReadPixels() to see what it is
that you've drawn: SLOW! -- now, just resize the pixel data with rez()
and write it into the right subsquare of the array).
- hc/lib/tile.h
- Repository of declarations of the data structures that crop up
throughout.
- hc/targa.c
- DAUB4 wavelet pyramid
scheme on a target image (top40 coefficients and average Y for
subsquares). The wavelet transform is run one level at a time, and
each intermediate stage is yanked out and translated into the wavelet
transforms of that level of subsquares. The datafile produced
contains a {filename, size, nnodes} structure followed by the an
nnodes-element array of {average subsquare luminance, top40 coeffs,
size} in "for (level), for(x), for(y)" order, 4-ary-tree order.
Result: matches() can match tiles against any subsquare in this
iceberg.
-
hc/tirade.c
- DAUB4 wavelets (top40 coefficients and average Y) for potential
tile images. Run it batchly on everything in a directory; run a
post-matches (snatches, sneetches) program snatches on the cat of any
individual tile.dat files you want to use. (Caveat: this currently
records only file basename, not path, so matches and triage need to be
run in the directory of the tiles and the tilefile, and not really on
the cat of tilefiles that refer to files in more than one directory.)
The approximation is that the wavelet coefficients of a
half-resolution (etc.) version of a tile are the low-frequency subset
of those for the full-res image, and that those for the
double-resolution version are the full-res ones plus a lot of zeroes.
With Haar wavelets, these are exact; with DAUB4's, you lose a factor
of twoish with each rescaling. The same matching algorithm
(find which tiles have the most coefficient sign matches
among their lists of top 40 coefficients) applies for any size tile
against any size target subsquare.
- hc/testtirade.c
- Shows how much information is left in those top40 coefficients:
does the inverse wavelet transform on an array in which everything but
them is zeroed and shows the picture.
- hc/testtarga.c
- Same thing, but given a target file it shows the inverse
transform for the whole target image, then each quarter, sixteenth,
etc., down to the resolution of the target data file, which has
typically been 16x16 pixel squares.
- hc/ttest.c
- Just turns a target or tile data file into readable ascii, for a
check.
- hc/tedit.c
- It was too close to due-hour to rebuild the database when I
realized the kids-in-tutus picture was a REALLY GOOD MATCH for a
certain chunk of target and WOULDN'T GO AWAY (same with that NASA
logo). Thus was conceived tedit.c, to which you pass any number of
filename prefixes, and it copies the database minus any res-sturctures
the filenames of which begin with those characters. Kids, Golf,
Ballet, Balloons: all gone.
- hc/matches.c
- Given a target data
file (with top-40 wavelet coefficients for 2m x
2m subsquares of the
target image down to some fine scale) and a tile data file (with
top-40 coeffs for each of many square potential tile images at their
original resolution), test each potential tile (at the appropriate
resolution, i.e. comparing only the wavelet coefficients that appear
at that res.) against each target subsquare, looking for the best
scoring match (using the harsh quantization algorithm of the
"Multiresolution Image Database Querying" article (let me find that
citation...), in which the score is simply the number of wavelet
coeffs that appear in the top40 of both tile and target with the same
sign(!!), plus a certain weighting of luminance agreement (completely
lost in the quantization)). So for each match of tile onto target
subsquare, the data recorded is {filename, exp = log2
(magnification), score}.
In the current version, the top two contenders are noted at all times;
any upstart that places in the top two is inserted in the right place,
ousting one of the previous contenders. A current best match may
match with a score of zero, so that there is always at least some
skanky match for any square, so triage doesn't freak out.
Look what I learned how to do: Since this takes a little while
to run, it's been adjusted to accept a "kill -SIGUSR1 pid" signal, on
which it writes the current best matches to a file usable by any
post-triage program and exits. It also tells you how many tiles it
got through, and can be restarted on the n+1st tile by invoking it in
the same manner as before only with that number as an additional
argument.
-
hc/treeage.c
- "triage.c" was The first shot at collage/montage/triage code. For
now, it just draws the tiles in the right place at the right
resolution, using GL, one layer over/obscuring another, getting the
exp=log_2(magnification) from the matches datafile and sending the
proper magnification to glPixelZoom(). Ridiculously enough, the
screen shots of the individual layers that appear on the results page
were obtained by running triage in gdb, with a breakpoint set at the
appropriate time. (triage.c itself (and matches.c, its partner in
crime) is out of date; their datafile structure has been changed.)
"treeage" is the same thing plus some optimizations regarding how much
data to store (next gen, different file structure). It grabs
(glReadPixels()) the pixel data from each layer and adds it (mod
modulation, which is also noted in a normalization array) into an
accumulation array.
-
hc/treeedge.c
- Another round of collage/montage/triage code. Attempts to
deemphasize edges using sin2(x)*sin2(y)
modulation (= near 0 around edges of that layer, so lower layers show
through more there). For example, at the center of the final image,
the only thing that shows well is the only layer that has no edge
there, the full-size single-tile lowest-frequency subsquare. This
produces the images where the tile content is most visible.
-
hc/troismenage.c
- More collage/montage/triage. Also weights by tile score, and
foreground/background-ness of image coordinates.
-
hc/trog.c
- At last, just try a straight average of the layers! Results are
embarrassingly similar to those from the score-weighting versions.
- hc/crwton.c
- Cluster-weighted modeling with expectation maximization: extension
of the class assignment to 2D.
-
hc/trwth.c
-
A triage-like program, incorporating CWM. Still buggy.
Trying out libjpeg
Drawing a random dirichlet-domain mosaic.
Drawing a dirichlet-domain mosaic based on a source
jpeg.
Wavelet compression demo 1: tweak thresholds
for Y,I,Q coefficients.
Wavelet compression demo 2: shows picture with
only its biggest coefficient, then adds the next largest, ...
c=Y: avg=6.043251, max=15844.109375, zeroed=58330
c=I: avg=0.866628, max=1391.290283, zeroed=56751
c=Q: avg=0.507719, max=103.790565, zeroed=52942
nonzeroed=28585
c=Y: avg=6.043251, max=15844.109375, zeroed=65401
c=I: avg=0.866628, max=1391.290283, zeroed=65514
c=Q: avg=0.507719, max=103.790565, zeroed=65531
nonzeroed=162
c=Y: avg=6.043251, max=15844.109375, zeroed=65468
c=I: avg=0.866628, max=1391.290283, zeroed=65519
c=Q: avg=0.507719, max=103.790565, zeroed=65536
nonzeroed=85
CWM in 2d using the full covariance matrix (4
clusters, gnuplot plot)
ebeth@media.mit.edu