Scripting Fractals for Oxidizer

by ralf • Sunday November 16th, 2008
Posted in Lua Scripts, Oxidizer Blog

This tutorial introduces Lua scripting for Oxidizer (>0.5.5), along with some hopefully useful (but not strictly required) peripherals. This text is intended for absolute beginners with no prior experience with Lua scripting, Xcode or the Terminal command line, although a modicum of familiarity with Oxidizer is assumed.

Oxidizer is a Mac OS X (10.4-10.5) software for generating fractal images and animations. From version 0.4, Lua scripting was added to Oxidizer. Two principal benefits of scripting are:

  1. Efficiency. Scripting can immensely simplify mechanical and repetitive tasks, like e.g. changing a genome parameter value sinusoidally over 200 frames for an animation. Or if you have a standard image/rendering setting that you often use, you can program it into a script instead of changing many parameters every time you want that setting.
  2. Capability. Did you know that Oxidizer has a color map rotator? A similarity-transform genome randomizer? Or a beat-syncing sequencer? Well with scripting it does.

Scripting is, in my opinion, one of the most powerful new meta-features of Oxidizer, because it is an enabling technology. It opens up possibilities for the user to be creative and invent tricks and methods the developer might not have thought of, or which would be too much work to program into Oxidizer as standard features.

Download tutorial. Includes PDF document, example scripts, genomes, and animations.


  1. Yoshiyahu
         November 16, 2008

    Woo hoo! Thank you so much– this is going to be very helpful.

  2. Capitaine Haddock
         November 17, 2008

    Cool thanks ! ;-)

  3. Don Larson
         November 17, 2008

    Thank you.


  4. ralf
         November 17, 2008

    I hope it can be of some help – if you have questions you can post them here or in the forum topic on Lua scripting.


  5. Pharmagician
         November 21, 2008

    Thanks for this, Ralf! I’ve been bending and twisting your scripts so much recently and having this tutorial will be a great help!

  6. ralf
         November 21, 2008

    Hey pharmagician – good to see some sign of life, I tried emailing you a while ago but the message bounced (there was some email exchange on scripting related issues that I cc’d you on). Well anyway – the gist of it was, there’s a new version of simil3 out, with some new features, you can grab it from my site.

  7. pharmagician
         November 21, 2008

    Hi Ralf – dropped the old email address when I moved house and am now at gmail. Thanks for new version – I love it already! Check out results from previous versions on my dA page – I’ve been tweaking the scripts like crazy, breeding and mutating the results like crazy and I’m really happy with some of them. :-)

    How possible would it be to separate out the randomisations for each transform? IE tell T1 to do thing “x” by degree “between y and z”, tell T2 to do it by more, T3 not at all etc etc? Or does it do that already and I am just too dumb to see it in the script?

    At any rate your work on this (and Dave’s on getting to a very stable version with 0.5.5) is MUCH appreciated!


  8. ralf
         November 21, 2008

    In the latest version I’ve already started adding keywords to do the things you suggest, like e.g. for the xform weight, color and symmetry. In principle there should be no problem to add more keywords like that for any particular feature that you want to have more control over. Feel free to put the specifics in an email and I can take a stab at it.

  9. ralf
         November 23, 2008

    Quick update – here’s a better version of the color map randomizer (Example 3 in the tutorial): cmap_rnd.lua. This one fixes the issue that the color map preview on the Oxi Colour tab would look messed up because the indices were not sorted. Also, it adds some saturation and lightness controls, and some generic RGB HSL conversion functions that might be useful.

  10. Valentin
         November 30, 2008

    Great stuff… can you give any example(s) of how the mod script is used? I get that there are a number of functions in there.. but I can’t quite get my head around how/when to call them, and where to derive the calling parameters. Seems very different from the parameters you have in the utils script. Maybe a quick recipe or calling script that you used for the beat synced animation on your website? (Just as a starting point) oh… pretty please?.. lol Thanks!

  11. ralf
         November 30, 2008

    The functions in mods.lua are various types of Xform modulations that were intended to be used just like in Example 2 or Example 5 in the tutorial — look for instance at Example 5 how it uses “affine_Prot” and other functions. Typically, the first input argument is the genome, which is modified in-place so there’s no return value from calling the function. The second argument is the number of the Xform to apply the modulation to, and the third argument is the modulation value, for instance a phase angle in degrees or a scale factor.

    Regarding the beat-syncing stuff, oh man, that’s a whole science in its own right. I’ll link the codes for you, but it’s all prototyping stuff, no handrails..

    The main sequencer is seq6.lua, and some example input scripts are lin1.lua, beat1.lua and beat4.lua. You have to edit seq6 to give it the right path to the utils and mods files, and also the input file. The rest of the scripting is done in the input file, where you have to define the “mdef” (modulation definition) and “cp” (control points) tables. beat4.lua was the actual input file for the random walk beat-syncing clip on my front page, but you should probably look at lin1 and beat1 first to get an idea of how it works when done manually.

  12. Valentin
         December 1, 2008

    Thanks so much for posting all that :-) I’m looking thru pretty much get the idea. I did change the path in seq6.lua to reflect my setup, and when I try to run to pull-in beat4.lua etc. it does nothing. Is it possible that there are other path refs or etc. that are missing or need to be changed? All I need is one good working example, and I can tweak from there for sure. This doesn’t seem to work at all… hmmmmm :-/ (beat1.lua doesn’t work either.. but all your examples from the tutorial work fine once path is properly set.)

  13. ralf
         December 1, 2008

    Alack, I discovered that for the last run (beat4) I had added a new morphing feature (the padding) which apparently wasn’t backwards compatible, so lin1 and beat1 are not going to work (I will fix that later), sorry about that. Also, there have been some changes in Oxi/flam3: motion_exponent is now called temporal_filter_exp, and one has to set temporal_filter_type=’Exponent’ to use it. Well that’s the cost of playing with development versions :-)

    Other possible points of failure: beat4 originally (with nm=64) expected 15 genomes in oxidizer for its morph sequence, and in the definition of the modulation channels (the “mdef” table) you can see that it also expects each genome to have at least 4 Xforms, and to use a color map. If you had less than 15 genomes or less than 4 Xforms, or used a palette, the script will probably crash.

    But beat4 was a pretty long sequence, you can shorten it by setting nm=16 or nm=8 (“nm” is the number of measures of 4/4 beats), and then it will only require 4 or 2 genomes. I have uploaded a new version of seq6.lua that fixes the motion_exponent issue, and a shortened form of beat4 that only requires 4 genomes, and here’s a test genome you can try it on: seq6-test1.flam3 (not very pretty, but just for testing). I just tested this setup and it ran fine, so you should be able to get this to work (it produced this:

    For grappling with developmental codes like this it is convenient to run Oxidizer via Xcode, because the seq6 script will print tons of information to the debugger console, so if something goes wrong you have a better chance of diagnosing the problem.

  14. ralf
         January 5, 2009

    Quick update: I started on a new animation scripting page, which contains some updates of the animation scripts talked about above (now called seq7). Enjoy :-)

  15. ekdor
         October 11, 2009

    Hi Ralf,
    Looking forward to learning to put together some basic scripts. Or at least use existing script to my own ends.

    I have started going through the tutorial and encountered an issue. Perhaps it is just me. Anyway you state that this is for a total new comer (that’s me), which pleased me since I haven’t scripted before. I have got up to “2. First Encounter” when I encountered an oversight (no pun intended). You say to have Oxidisation running with a flame loaded and a script editor (I’m using text edit until I decide if the LUA script is manageable for me). But then you leap right into an example, “Change Background Colour” with no explanation of how I go about doing this.

    I assumed I have to save the script text file, add .lua extension, which doesn’t seem to behave like an extension, and then load it into Oxidisation menu by clicking on the LUA tool-bar button and locating the script.

    I figured this after I realised that I’m missing all the resource files since I came to access the tutorial via a link I found else where on Rampant Mac which only linked directly to the tutorial and not to the archive containing all the examples etc. Where I looked at an example and made my assumption which worked. But I’d recommend that you insert some information to this effect for others like me.

    Looking forward to the remaining tutorial.


  16. ekdor
         October 11, 2009

    Ok, Been reading and playing around a bit. I have to admit most of that went a bit blurry but I got the gist of it. Doubt I would be able to do much.

    I did manage to get it to adjust the size as per my parameter and have it automatically keep the scale/height ratio matching. As though I had checked the “Lock to Height” check-box and then adjusted the size.

    oh1 = oxidizer_genomes[1].height
    os1 = oxidizer_genomes[1].scale
    oxidizer_genomes[1].width = 1680
    oxidizer_genomes[1].height = 1050
    oxidizer_genomes[1].scale = os1*oxidizer_genomes[1].height/oh1

    Perhaps there is an easier way but it’s my first proper script and I have a use for it!

    I do have a specific reason for commenting and it’s not to pat myself on the back for my tiny victory! No, no, no, I would like to know if there is an easy way to have it apply this to all genomes in the list, however many there are? A symbol for example to substitute [1] with?


  17. ekdor
         October 11, 2009

    Sure I’m using up valuable real-estate here but I figured out what I wanted to know in my comment above. I studied an example you provided and figured out how it worked. My complete render setting for all genomes bellow. Before I leave off, if there are improvements to be made could you let me know so I can learn? I decided to have a render settings script for the first genome (single) and one for all (which is the one bellow).


    — CHECK

    if #oxidizer_genomes==0 then
    oxidizer_status[“action”] = “error”
    oxidizer_status.message = “This script requires a genome to be in the list.”


    no_genome = #oxidizer_genomes
    for no=1, no_genome do

    oh1 = oxidizer_genomes[no].height
    os1 = oxidizer_genomes[no].scale
    oxidizer_genomes[no].width = 1680
    oxidizer_genomes[no].height = 1050
    oxidizer_genomes[no].scale = os1*oxidizer_genomes[no].height/oh1

    oxidizer_genomes[no].oversample = 1
    oxidizer_genomes[no].filter = 0.6
    oxidizer_genomes[no].filter_shape = “Gaussian”
    oxidizer_genomes[no].quality = 100
    oxidizer_genomes[no].estimator_radius = 10
    oxidizer_genomes[no].estimator_minimum = 0
    oxidizer_genomes[no].estimator_curve = 0.75


  18. Scott Chitwood
         October 11, 2009

    Nice work Ekdor!  I think we’ve got a great little community here, having your voice in the mix is a pleasure.

    If you like to see how my genomes are constructed for dimensions and quality settings you can grab a download in this post.

  19. ekdor
         October 20, 2009

    Oh thanks Scott!

    Just checking it out now. I’ve learnt heaps about constructing images with the program since I last posted above. Almost ready to upload my first image. It’s fairly simple, but it’s constructed from scratch in a semi planned fashion. That is as best I can with so many options at hand. No breeding done to produce it/them (have two but might not upload both.


  20. ekdor
         October 20, 2009

    Yea it’s me again!

    Just wanted to say the line:

    oxidizer_genomes[1].oversample = 1

    Doesn’t seem to work for me.


Sorry, comments for this entry are closed at this time.