Useful stuff for your blog-reading pleasure.
All | General

20070823 Thursday August 23, 2007

Cool Apple-Like Photo Animations With POV-Ray, ImageMagick and Solaris

A GIF Animation Showing Popular Sun ProductsOne of the features I like most about Apple's iPhoto application is the transition effect in slideshows where the whole screen becomes a cube that rotates into the next photograph. The same effect is also used when switching users, etc.

Recently we took a team photograph for an internal web page. I wanted that effect and I love the open source raytracer POV-Ray so I wrote a script that renders the same animation effect and creates an animated GIF using ImageMagick. You can see an example output to the right featuring photos of some popular Sun products. BTW, check out photos.sun.com for free, high-quality access to Sun product photography.

To create your own photocubes, you just need POV-Ray and ImageMagick in your path and the photocube.sh script. Being open source, all run on Solaris but also on Linux, NetBSD or any other operating system that can run open source software. I'd love to try this script out on a Niagara 2 system with its 8 cores, 16 pipelines, 64 threads and 8 FPUs. Hmmm, all rendering frames in parallel :).

There are already precompiled distributions of POVRay and ImageMagick on Blastwave that you can install very easily onto your Solaris machine if you don't have them already.

Just call the script with 6 URLs or pathnames. It will then automatically read in the images, render the animation frames and then combine them all into an animated GIF:

-bash-3.00$ ../photocube.sh *.jpg
Converting images to be quadratic...
Fetching and processing 721_DRIVE-open.1024x768.jpg
Fetching and processing 773_FrtAbv-78L-PWR-FAN.1024x768.jpg
Fetching and processing 915_Lside-plexiOFF.1024x768.jpg
Fetching and processing IMG_4551.1024x768.jpg
Fetching and processing blackbox_wind_turbine.1024x768.jpg
Fetching and processing ultra_cool_combo.1024x768.jpg
Rendering animation frames...
Creating animated gif file...
-bash-3.00$ ls
721_DRIVE-open.1024x768.jpg          blackbox_wind_turbine.1024x768.jpg
773_FrtAbv-78L-PWR-FAN.1024x768.jpg  photocube.gif
915_Lside-plexiOFF.1024x768.jpg      ultra_cool_combo.1024x768.jpg
IMG_4551.1024x768.jpg
-bash-3.00$

The script uses ImageMagick to make the pictures quadratic and to limit their size to 1200x1200 pictures if necessary. Since the -extent switch is fairly new, you'll need to use a newer distribution of ImageMagick, the one on the Solaris Companion CD is sadly not new enough. The POVRay source (embedded in the script) uses an S-curve to turn the cube which produces a natural and smooth acceleration/decelleration effect. It would have been more efficient to let POVRay output PNG files rather than TGA but for some reason some of the PNG files that POVRay produces were not compatible with ImageMagick.

Feel free to modify this script to your needs. You may want to experiment with other ways of animating the cube or other image transition effects. Maybe you want to use ffmpeg to create real video files instead of animated GIFs. Be careful when cranking up the number of frames while using ImageMagick to create animated GIFs, ImageMagick wants to suck in all frames into memory before creating the animated GIF and so you may end up using a lot of memory. If someone has a more elegant, scriptable animated GIF creator, please leave me a comment.

I hope you enjoy this little exercise in raytracing and animation. Let me know if you have suggestions or other ideas to improve this script!

"Cool Apple-Like Photo Animations With POV-Ray, ImageMagick and Solaris" has been brought to you by Constantin's Blooog.
This entry was created on 2007-08-23 13:20:47.0 PST and is associated with the following tags:

You're welcome to use this Permalink , add a comment below or send your feedback to constantin at sun dot com.
Comments [4]


20070816 Thursday August 16, 2007

ZFS Snapshot Replication Script

One of the OpenSolaris' ZFS filesystem's greatest features are its snapshots. You can easily create a snapshot by saying zfs create pool/filesystem@snapshot and then replicate that snapshot by saying something like zfs send pool/filesystem@snapshot | zfs receive newpool/some_other_filesystem. So far, so great.

Now let's say you have a nice pool and have been creating snapshots on a regular basis. After a few months, you decide to remodel your pool layout or migrate some of your filesystems over to a new pool for whatever reason. Then, you're facing a lot of those zfs send and receive commands. Especially, if you're like Chris and do snapshots on a per-minute basis. That's why the ZFS community is now waiting for 6421958: A zfs send -r option.

I had to migrate quite a few filesystems and many snapshots (thanks to Tim's excellent ZFS Snapshot SMF Service) lately when I set up a new pool strategy for my home server so I wrote myself a script to do the replication job. Since it may take some time for the send -r feature to be implemented, I turned it into a more generic utility.

Disclaimer: Please be advised that this script has only been tested a couple of times and it is provided to you completely on an "as-is" basis. Please have a look at the script to understand how it works and try it out on some non-risky pools and filesystems before you do real stuff with it. Run a backup before using this script and don't shoot me if something goes wrong.

Ok, what can this script do for you? First of all, check out its -h flag to see what options it provides:

# zfs-replicate -h
usage: zfs-replicate [-h] [-F ] [-n] [-s] [-v]
[-m [-c "FMRI|pattern[ FMRI|pattern]...]" ]
source dest

where source and dest is a ZFS filesystem, snapshot or volume.

Options:
-h: Print this help.
-F: Force a rollback of the destination filesystem to the most recent
snapshot before replicating a snapshot. This is equivalent to the -F
option of zfs receive.
-n: Don't actually replicate anything, just print what would be done.
This will only print the next step but nothing dependent on that step
since it won't actually be executed. For instance, -ns will print the
snapshot command but not print the subsequent send/receive command as it
depends on the snapshot actually being taken.
-s: After sending existing snapshots, make a final one and replicate it as well.
This option requires that the source be a filesystem and not a snapshot.
-m: After sending all snapshots, migrate the source to the dest filesystem by
unmounting the source filesystem and changing the new filesystem's
mountpoint to that of the source one. This option includes -s.
-c: A space delimited list of SMF services in quotes to be temporarily disabled
before unmounting the source, then re-enable after changing the mountpoint
of the destination. Requires -m.
-v: Be verbose.

Great, let's try it out. Here's a pool with some data and some snapshots as well as another, empty pool:


# zfs list -r piscina
NAME                            USED  AVAIL  REFER  MOUNTPOINT
piscina                         384M  87.6M    19K  /piscina
piscina/ficheros                384M  87.6M   384M  /piscina/ficheros
piscina/ficheros@instantanea1    17K      -   128M  -
piscina/ficheros@instantanea2    17K      -   256M  -
piscina/ficheros@instantanea3      0      -   384M  -
# zfs list -r lago
NAME   USED  AVAIL  REFER  MOUNTPOINT
lago   105K   472M    18K  /lago

Now, let's copy the ficheros filesystem along with all its snapshots in one go:


# zfs-replicate -v piscina/ficheros lago
Sending piscina/ficheros@instantanea1 to lago.
Sending piscina/ficheros@instantanea2 to lago.
(incremental to piscina/ficheros@instantanea1.)
Sending piscina/ficheros@instantanea3 to lago.
(incremental to piscina/ficheros@instantanea2.)
# zfs list -r lago
NAME                         USED  AVAIL  REFER  MOUNTPOINT
lago                         384M  87.6M    20K  /lago
lago/ficheros                384M  87.6M   384M  /lago/ficheros
lago/ficheros@instantanea1    17K      -   128M  -
lago/ficheros@instantanea2    17K      -   256M  -
lago/ficheros@instantanea3      0      -   384M  - 

It works. And it automatically used incremental snapshots as well to save space, too!

If we now add another snapshot to our original pool piscina and then run zfs-replicate again, it will skip already replicated snapshots and just copy those that are additional:


# zfs snapshot piscina/ficheros@instantanea4 
# zfs-replicate -v piscina/ficheros lago
Sending piscina/ficheros@instantanea4 to lago.
(incremental to piscina/ficheros@instantanea3.)
# zfs list -r lago
NAME                         USED  AVAIL  REFER  MOUNTPOINT
lago                         384M  87.6M    20K  /lago
lago/ficheros                384M  87.6M   384M  /lago/ficheros
lago/ficheros@instantanea1    17K      -   128M  -
lago/ficheros@instantanea2    17K      -   256M  -
lago/ficheros@instantanea3      0      -   384M  -
lago/ficheros@instantanea4      0      -   384M  -

This is useful because you can now run this script on regularly basis to have one pool automatically backed up to another pool. In fact, the -s option will first make sure all existing snapshots are copied over, then create a new snapshot for you and copy that one over as well, all in one command.

Sometimes, the destination filesystem gets touched, or otherwise acted upon and then zfs receive to it will no longer work. In that case, you can use the -F switch which will force a rollback of the destination filesystem to its latest snapshot and then you'll be back in business.

Finally, another scenario is file system migration: You have a filesystem in one pool and want to migrate it with all it's snapshots to another pool, with minimal downtime. This can be done using the -m option: First copy all existing snapshots while the source file system is still live, then unmount it, create a final snapshot, copy that one over to the destination file system as well, set the destination filesystem's mountpoint to be the same as the source filesystem's one and remount the destination file system. (Please note that the script might appear frozen when unmounting while it's waiting for some open files to be closed, etc.).

If you're worried about some daemons depending on your filesystem's availability (like Samba), you can use the -c option to provide their names. zfs-replicate will then bring down the matching SMF services right before unmounting and restart them automatically after re-mounting the migrated filesystem. Again, you might need to wait until the SMF service is really down (Read: The last Samba connection has closed).

I hope this script is useful to you and again, I assume you know what you're doing and do some testing before using it in production. I'm sure there are still some bugs and shortcomings so please send me email to constantin (dot) gonzalez (at) sun (dot) com or leave a comment and I'll try to make the script better for you.

Many thanks to Chris Gerhard, whose backup script was an inspiration for me in hacking together this utility. Also, many thanks to Tim Foster for some code-review and initial feedback (Sorry, I haven't managed to implement some locking yet...). Let me know when you're in Munich and you'll get some well-deserved beer!

"ZFS Snapshot Replication Script" has been brought to you by Constantin's Blooog.
This entry was created on 2007-08-16 13:41:02.0 PST and is associated with the following tags:

You're welcome to use this Permalink , add a comment below or send your feedback to constantin at sun dot com.



« Previous page | Main
Archives
Subscribe to This Blog!
Most Popular Entries
Watch videos of Constantin
About this site
Links
Get in Touch!
This is Sun employee Constantin Gonzalez' personal blog.
All opinions expressed herein are solely of the author and do not necessarily reflect those of his employer.
If you want to contact the author, please send email to constantin (dot) gonzalez (at) sun (dot) com.
Thank you for reading this blog!