diff -Naur flam3-3.0.1/src/README.txt trunk/src/README.txt
--- flam3-3.0.1/src/README.txt	2010-12-30 01:04:10.000000000 +0100
+++ trunk/src/README.txt	2011-10-21 21:37:26.114170539 +0200
@@ -106,14 +106,13 @@
 enable_jpeg_comments  1         enables comments in the jpeg header (render and animate)
 enable_png_comments   1         enables comments in the png header (render and animate)
 
-New in 2.8:
-
 earlyclip       0               enables the early clipping of rgb values for better antialiasing and resizing
                                 defaults to 0 for backwards compatibility
 flam27          0               flam3 2.7 compatibility mode; ensures generated genomes can be used by flam3 2.7.18
 stagger         0               affects simultaneity of xform interpolation during genome interpolation.
                                 represents how 'separate' the xforms are interpolated.  set to 1 for each
                                 xform to be interpolated individually, fractions control interp overlap.
+apo_palette     0               set this to 1 to use only the first 255 elements of the palette (apophysis compatibility)
 
 for example:
 
diff -Naur flam3-3.0.1/src/docstring.c trunk/src/docstring.c
--- flam3-3.0.1/src/docstring.c	2010-10-04 13:04:45.000000000 +0200
+++ trunk/src/docstring.c	2011-10-21 21:37:26.084166726 +0200
@@ -103,13 +103,13 @@
 "enable_jpeg_comments   1    enables comments in the jpeg header (render and animate)\n"
 "enable_png_comments    1    enables comments in the png header (render and animate)\n"
 "\n"
-"New in 2.8:\n"
 "earlyclip       0               enables the early clipping of rgb values for better antialiasing and resizing\n"
 "                                defaults to 0 for backwards compatibility\n"
 "flam27          0               flam3 2.7 compatibility mode; ensures generated genomes can be used by flam3 2.7.18\n"
 "stagger         0               affects simultaneity of xform interpolation during genome interpolation.\n"
 "                                represents how 'separate' the xforms are interpolated.  set to 1 for each\n"
 "                                xform to be interpolated individually, fractions control interp overlap.\n"
+"apo_palette     0               set this to 1 to use only the first 255 elements of the palette (apophysis compatibility)\n"
 
 "\n"
 "for example:\n"
diff -Naur flam3-3.0.1/src/filters.h trunk/src/filters.h
--- flam3-3.0.1/src/filters.h	2010-04-19 21:52:20.000000000 +0200
+++ trunk/src/filters.h	2011-10-21 21:37:26.106169520 +0200
@@ -23,27 +23,6 @@
 
 #define DE_THRESH   100
 
-/* Spatial filter kernels */
-#define flam3_gaussian_kernel 0
-#define flam3_hermite_kernel 1
-#define flam3_box_kernel 2
-#define flam3_triangle_kernel 3
-#define flam3_bell_kernel 4
-#define flam3_b_spline_kernel 5
-#define flam3_lanczos3_kernel 6
-#define flam3_lanczos2_kernel 7
-#define flam3_mitchell_kernel 8
-#define flam3_blackman_kernel 9
-#define flam3_catrom_kernel 10
-#define flam3_hamming_kernel 11
-#define flam3_hanning_kernel 12
-#define flam3_quadratic_kernel 13
-
-/* Temporal filters */
-#define flam3_temporal_box 0
-#define flam3_temporal_gaussian 1
-#define flam3_temporal_exp 2
-
 typedef struct {
    int max_filtered_counts;
    int max_filter_index;
diff -Naur flam3-3.0.1/src/flam3.c trunk/src/flam3.c
--- flam3-3.0.1/src/flam3.c	2010-11-18 05:16:25.000000000 +0100
+++ trunk/src/flam3.c	2011-10-21 21:37:26.070164945 +0200
@@ -34,6 +34,9 @@
 #ifdef HAVE_STDINT_H
 #include <stdint.h>
 #endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 #include <errno.h>
 
 #ifdef HAVE_LIBPTHREAD
@@ -60,11 +63,12 @@
 
   if (strcmp(SVN_REV, "exported"))
     return flam3_os "-" VERSION "." SVN_REV;
-  return VERSION;
+  return flam3_os "-" VERSION;
 }
 
 
-#define CHOOSE_XFORM_GRAIN 10000
+#define CHOOSE_XFORM_GRAIN 16384
+#define CHOOSE_XFORM_GRAIN_M1 16383
 
 #define random_distrib(v) ((v)[random()%vlen(v)])
                                    
@@ -244,10 +248,11 @@
 
    for (i = -4*fuse; i < 4*n; i+=4) {
    
+//         fn = xform_distrib[ lastxf*CHOOSE_XFORM_GRAIN + (((unsigned)irand(rc)) % CHOOSE_XFORM_GRAIN)];
       if (cp->chaos_enable)
-         fn = xform_distrib[ lastxf*CHOOSE_XFORM_GRAIN + (((unsigned)irand(rc)) % CHOOSE_XFORM_GRAIN)];
+         fn = xform_distrib[ lastxf*CHOOSE_XFORM_GRAIN + (((unsigned)irand(rc)) & CHOOSE_XFORM_GRAIN_M1)];
       else
-         fn = xform_distrib[ ((unsigned)irand(rc)) % CHOOSE_XFORM_GRAIN ];
+         fn = xform_distrib[ ((unsigned)irand(rc)) & CHOOSE_XFORM_GRAIN_M1 ];
       
       if (apply_xform(cp, fn, p, q, rc)>0) {
          consec ++;
@@ -674,6 +679,14 @@
       APPMOT(auger_freq);
       APPMOT(auger_scale);
       APPMOT(flux_spread);
+      APPMOT(mobius_re_a);
+      APPMOT(mobius_re_b);
+      APPMOT(mobius_re_c);
+      APPMOT(mobius_re_d);
+      APPMOT(mobius_im_a);
+      APPMOT(mobius_im_b);
+      APPMOT(mobius_im_c);
+      APPMOT(mobius_im_d);
 
       for (j = 0; j < flam3_nvariations; j++)
          APPMOT(var[j]);
@@ -974,6 +987,16 @@
    } else if (varn==VAR_FLUX) {
       /* flux */
       dest->flux_spread = src->flux_spread;
+   } else if (varn==VAR_MOBIUS) {
+      /* mobius */
+      dest->mobius_re_a = src->mobius_re_a;
+      dest->mobius_re_b = src->mobius_re_b;
+      dest->mobius_re_c = src->mobius_re_c;
+      dest->mobius_re_d = src->mobius_re_d;
+      dest->mobius_im_a = src->mobius_im_a;
+      dest->mobius_im_b = src->mobius_im_b;
+      dest->mobius_im_c = src->mobius_im_c;
+      dest->mobius_im_d = src->mobius_im_d;
    }
 }
 
@@ -1599,7 +1622,31 @@
    long stringbytes;
    char *genome_string;
    
+   int using_tmpdir = 0;
+   char *tmp_path;
+   char tmpnam[256];
+   
    tmpflame = tmpfile();
+   if (NULL==tmpflame) {
+#ifdef _WIN32       
+       // This might be a permissions problem, so let's try to open a
+       // tempfile in the env var TEMP's area instead
+       tmp_path = getenv("TEMP");
+
+       if (tmp_path != NULL) {
+          strcpy(tmpnam, tmp_path);
+          strcat(tmpnam, "\\fr0st.tmp");
+          tmpflame = fopen(tmpnam, "w+");
+          if (tmpflame != NULL) {
+             using_tmpdir = 1;
+          }
+       }
+#endif
+       if (using_tmpdir == 0) {
+          perror("FLAM3: opening temporary file");
+          return (NULL);
+       }
+   }
    flam3_print(tmpflame,cp,NULL,flam3_dont_print_edits);
    stringbytes = ftell(tmpflame);
    fseek(tmpflame,0L, SEEK_SET);
@@ -1608,6 +1655,9 @@
        perror("FLAM3: reading string from temp file");
    }
    fclose(tmpflame);
+
+   if (using_tmpdir)
+      unlink(tmpnam);
    
    return(genome_string);
 }
@@ -1749,6 +1799,32 @@
 
    }
 
+   int hexpalette = argi("hexpalette",0);
+
+   if (hexpalette) {
+
+      fprintf(f,"   <palette count=\"256\" format=\"RGB\">");
+
+      for (i=0; i < 256; i++) {
+
+         int r, g, b;
+         r = rint(cp->palette[i].color[0] * 255.0);
+         g = rint(cp->palette[i].color[1] * 255.0);
+         b = rint(cp->palette[i].color[2] * 255.0);
+
+         if (i % 8 == 0) {
+            fprintf(f,"\n");
+            fprintf(f,"      ");
+         }
+
+         fprintf(f,"%2x%2x%2x",r,g,b);
+
+      }
+
+      fprintf(f,"\n");
+      fprintf(f,"   </palette>\n");
+
+   } else {
    for (i = 0; i < 256; i++) {
       double r, g, b, a;
       r = (cp->palette[i].color[0] * 255.0);
@@ -1756,8 +1832,7 @@
       b = (cp->palette[i].color[2] * 255.0);
       a = (cp->palette[i].color[3] * 255.0);
       
-//      if (i%4 == 0)
-         fprintf(f, "   ");
+      fprintf(f, "   ");
       
       if (flam27_flag || a==255.0) {
       
@@ -1783,6 +1858,7 @@
          fprintf(f, "\n");
          
    }
+   }
 
    if (cp->edits != NULL && print_edits==flam3_print_edits) {
 
@@ -1813,7 +1889,8 @@
    int modulus_var=0,oscope_var=0,popcorn2_var=0,separation_var=0;
    int split_var=0,splits_var=0,stripes_var=0,wedge_var=0,wedgeJ_var=0;
    int wedgeS_var=0,whorl_var=0,waves2_var=0,auger_var=0,flux_var=0;
-   
+   int mobius_var=0;
+
    int j;
    int lnv;
 
@@ -1929,6 +2006,8 @@
             auger_var=1;
          else if (j==VAR_FLUX)
             flux_var=1;
+         else if (j==VAR_MOBIUS)
+            mobius_var=1;
       }
    }
 
@@ -2147,6 +2226,17 @@
       if (flux_var==1)
          fprintf(f, "flux_spread=\"%g\" ", x->flux_spread);
 
+      if (mobius_var==1) {
+         fprintf(f, "mobius_re_a=\"%g\" ", x->mobius_re_a);
+         fprintf(f, "mobius_im_a=\"%g\" ", x->mobius_im_a);
+         fprintf(f, "mobius_re_b=\"%g\" ", x->mobius_re_b);
+         fprintf(f, "mobius_im_b=\"%g\" ", x->mobius_im_b);
+         fprintf(f, "mobius_re_c=\"%g\" ", x->mobius_re_c);
+         fprintf(f, "mobius_im_c=\"%g\" ", x->mobius_im_c);
+         fprintf(f, "mobius_re_d=\"%g\" ", x->mobius_re_d);
+         fprintf(f, "mobius_im_d=\"%g\" ", x->mobius_im_d);
+      }
+
       fprintf(f, "coefs=\"");
       for (j = 0; j < 3; j++) {
          if (j) fprintf(f, " ");
@@ -2304,6 +2394,15 @@
       PRINTNON(auger_scale);
 
       PRINTNON(flux_spread);
+
+      PRINTNON(mobius_re_a);
+      PRINTNON(mobius_im_a);
+      PRINTNON(mobius_re_b);
+      PRINTNON(mobius_im_b);
+      PRINTNON(mobius_re_c);
+      PRINTNON(mobius_im_c);
+      PRINTNON(mobius_re_d);
+      PRINTNON(mobius_im_d);
       
       if (!zero_matrix(x->c)) {
          fprintf(f, "coefs=\"");
@@ -2354,7 +2453,11 @@
       for (nm=0; nm<x->num_motion; nm++)
          flam3_print_xform(f, &(x->motion[nm]), 0, 0, NULL, 1);
          
-      fprintf(f,"   </xform>\n");
+      if (final_flag)
+         fprintf(f,"   </finalxform>\n");
+      else
+         fprintf(f,"   </xform>\n");
+
    } else
       fprintf(f, "/>\n");
 }
@@ -2464,6 +2567,9 @@
    if (sym < 0) {
 
       i = cp->num_xforms;
+      if (cp->final_xform_enable)
+         i -= 1;
+
       flam3_add_xforms(cp,1,0,0);
 
       cp->xform[i].density = 1.0;
@@ -2489,6 +2595,9 @@
    for (k = 1; k < sym; k++) {
 
       i = cp->num_xforms;
+      if (cp->final_xform_enable)
+         i -= 1;
+
       flam3_add_xforms(cp, 1, 0,0);
 
       cp->xform[i].density = 1.0;
@@ -2559,8 +2668,13 @@
          /* Default behavior keeps the final from parent0. */
          if (cp1->final_xform_index == j)		     
             continue;
+
+         i = out->num_xforms;
+         if (out->final_xform_enable)
+            i -= 1;
+
          flam3_add_xforms(out, 1, 0, 0);
-         flam3_copy_xform(&out->xform[out->num_xforms-1],&cp1->xform[j]);
+         flam3_copy_xform(&out->xform[i],&cp1->xform[j]);
       }
       
       /* Put the final xform last (if there is one) */
@@ -3374,6 +3488,17 @@
          cp->xform[i].flux_spread = 0.5 + flam3_random01()/2.0;
       }
 
+      if (cp->xform[i].var[VAR_MOBIUS] > 0) {
+         /* Create random params for mobius */
+         cp->xform[i].mobius_re_a = flam3_random11();
+         cp->xform[i].mobius_im_a = flam3_random11();
+         cp->xform[i].mobius_re_b = flam3_random11();
+         cp->xform[i].mobius_im_b = flam3_random11();
+         cp->xform[i].mobius_re_c = flam3_random11();
+         cp->xform[i].mobius_im_c = flam3_random11();
+         cp->xform[i].mobius_re_d = flam3_random11();
+         cp->xform[i].mobius_im_d = flam3_random11();
+      }
 
    }
 
@@ -3731,15 +3856,15 @@
 {
   flam3_genome *cps = spec->genomes;
   int real_bits = spec->bits;
+  int real_bytes;
 
   if (33 == real_bits) real_bits = 32;
 
-  /* note 4 channels * 2 buffers cancels out 8 bits per byte */
-  /* does not yet include memory for density estimation filter */
+  real_bytes = real_bits / 8;
 
   return
     (double) cps[0].spatial_oversample * cps[0].spatial_oversample *
-    (double) cps[0].width * cps[0].height * real_bits;
+    (double) cps[0].width * cps[0].height * real_bytes * 9.0;
 }
 
 void bits_error(flam3_frame *spec) {
diff -Naur flam3-3.0.1/src/flam3.h trunk/src/flam3.h
--- flam3-3.0.1/src/flam3.h	2010-10-04 14:33:08.000000000 +0200
+++ trunk/src/flam3.h	2011-10-21 21:37:26.071165072 +0200
@@ -59,7 +59,7 @@
 
 extern char *flam3_variation_names[];
 
-#define flam3_nvariations 98
+#define flam3_nvariations 99
 #define flam3_nxforms     12
 
 #define flam3_parent_fn_len     30
@@ -178,6 +178,7 @@
 #define VAR_COTH 95
 #define VAR_AUGER 96
 #define VAR_FLUX 97
+#define VAR_MOBIUS 98
 
 typedef struct {
 
@@ -389,6 +390,12 @@
 
    /* Flux */
    double flux_spread;
+
+   /* Mobius */
+   double mobius_re_a, mobius_im_a;
+   double mobius_re_b, mobius_im_b;
+   double mobius_re_c, mobius_im_c;
+   double mobius_re_d, mobius_im_d;
       
    /* If perspective is used, precalculate these values */
    /* from the _angle and _dist                         */
@@ -552,7 +559,7 @@
 EXPORT void flam3_interpolate(flam3_genome *genomes, int ngenomes, double time, double stagger, flam3_genome *result);
 
 /* print genome to given file with extra_attributes if not NULL */
-void flam3_print(FILE *f, flam3_genome *g, char *extra_attributes, int print_edits);
+EXPORT void flam3_print(FILE *f, flam3_genome *g, char *extra_attributes, int print_edits);
 void flam3_print_xform(FILE *f, flam3_xform *x, int final_flag, int numstd, double *chaos_row, int motion_flag);
 EXPORT char *flam3_print_to_string(flam3_genome *cp);
 
@@ -658,4 +665,27 @@
 #define CROSS_INTERPOLATE     1  
 #define CROSS_ALTERNATE       2
 
+/* Filters */
+/* Spatial filter kernels */
+#define flam3_gaussian_kernel 0
+#define flam3_hermite_kernel 1
+#define flam3_box_kernel 2
+#define flam3_triangle_kernel 3
+#define flam3_bell_kernel 4
+#define flam3_b_spline_kernel 5
+#define flam3_lanczos3_kernel 6
+#define flam3_lanczos2_kernel 7
+#define flam3_mitchell_kernel 8
+#define flam3_blackman_kernel 9
+#define flam3_catrom_kernel 10
+#define flam3_hamming_kernel 11
+#define flam3_hanning_kernel 12
+#define flam3_quadratic_kernel 13
+
+/* Temporal filters */
+#define flam3_temporal_box 0
+#define flam3_temporal_gaussian 1
+#define flam3_temporal_exp 2
+
+
 #endif
diff -Naur flam3-3.0.1/src/interpolation.c trunk/src/interpolation.c
--- flam3-3.0.1/src/interpolation.c	2010-11-18 05:16:25.000000000 +0100
+++ trunk/src/interpolation.c	2011-10-21 21:37:26.083166599 +0200
@@ -367,6 +367,8 @@
    
       for (i = 0; i < 256; i++) {
          double t[3], s[4];
+         int alpha1 = 1;
+
          s[0] = s[1] = s[2] = s[3] = s[4] = 0.0;
          
          for (k = 0; k < ncp; k++) {
@@ -375,9 +377,14 @@
                s[j] += c[k] * t[j];
             
             s[3] += c[k] * cpi[k].palette[i].color[3];
+            if (cpi[k].palette[i].color[3] != 1.0)
+               alpha1 = 0;
             s[4] += c[k] * cpi[k].palette[i].index;
             
          }
+
+         if (alpha1 == 1)
+            s[3] = 1.0;
        
          hsv2rgb(s, result->palette[i].color);
          result->palette[i].color[3] = s[3];
@@ -582,6 +589,14 @@
       INTERP(xform[i].auger_freq);
       INTERP(xform[i].auger_scale);
       INTERP(xform[i].flux_spread);
+      INTERP(xform[i].mobius_re_a);
+      INTERP(xform[i].mobius_im_a);
+      INTERP(xform[i].mobius_re_b);
+      INTERP(xform[i].mobius_im_b);
+      INTERP(xform[i].mobius_re_c);
+      INTERP(xform[i].mobius_im_c);
+      INTERP(xform[i].mobius_re_d);
+      INTERP(xform[i].mobius_im_d);
 
       for (j = 0; j < flam3_nvariations; j++)
          INTERP(xform[i].var[j]);
diff -Naur flam3-3.0.1/src/parser.c trunk/src/parser.c
--- flam3-3.0.1/src/parser.c	2010-11-18 05:16:25.000000000 +0100
+++ trunk/src/parser.c	2011-10-21 21:37:26.114170539 +0200
@@ -1215,6 +1215,22 @@
          this_xform->auger_scale = flam3_atof(att_str);
       } else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"flux_spread")) {
          this_xform->flux_spread = flam3_atof(att_str);
+      } else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"Re_A") || !xmlStrcmp(cur_att->name, (const xmlChar *)"mobius_re_a")) {
+         this_xform->mobius_re_a = flam3_atof(att_str);
+      } else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"Re_B") || !xmlStrcmp(cur_att->name, (const xmlChar *)"mobius_re_b")) {
+         this_xform->mobius_re_b = flam3_atof(att_str);
+      } else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"Re_C") || !xmlStrcmp(cur_att->name, (const xmlChar *)"mobius_re_c")) {
+         this_xform->mobius_re_c = flam3_atof(att_str);
+      } else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"Re_D") || !xmlStrcmp(cur_att->name, (const xmlChar *)"mobius_re_d")) {
+         this_xform->mobius_re_d = flam3_atof(att_str);
+      } else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"Im_A") || !xmlStrcmp(cur_att->name, (const xmlChar *)"mobius_im_a")) {
+         this_xform->mobius_im_a = flam3_atof(att_str);
+      } else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"Im_B") || !xmlStrcmp(cur_att->name, (const xmlChar *)"mobius_im_b")) {
+         this_xform->mobius_im_b = flam3_atof(att_str);
+      } else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"Im_C") || !xmlStrcmp(cur_att->name, (const xmlChar *)"mobius_im_c")) {
+         this_xform->mobius_im_c = flam3_atof(att_str);
+      } else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"Im_D") || !xmlStrcmp(cur_att->name, (const xmlChar *)"mobius_im_d")) {
+         this_xform->mobius_im_d = flam3_atof(att_str);
       } else {
          int v = var2n((char *) cur_att->name);
          if (v != flam3_variation_none)
diff -Naur flam3-3.0.1/src/private.h trunk/src/private.h
--- flam3-3.0.1/src/private.h	2010-04-19 21:52:20.000000000 +0200
+++ trunk/src/private.h	2011-10-21 21:37:26.080166216 +0200
@@ -87,7 +87,7 @@
    double badvals; /* accumulates all badvalue resets */
    double batch_size;
    int temporal_sample_num,ntemporal_samples;
-   int batch_num, nbatches, aborted;
+   int batch_num, nbatches, aborted, cmap_size;
    time_t *progress_timer;
    time_t *progress_timer_history;
    double *progress_history;
diff -Naur flam3-3.0.1/src/rect.c trunk/src/rect.c
--- flam3-3.0.1/src/rect.c	2010-12-29 21:49:22.000000000 +0100
+++ trunk/src/rect.c	2011-10-21 21:37:26.085166853 +0200
@@ -258,6 +258,8 @@
    struct timespec pauset;
    int SBS = ficp->spec->sub_batch_size;
    int fuse;
+   int cmap_size = ficp->cmap_size;
+   int cmap_size_m1 = ficp->cmap_size-1;
 
    double eta = 0.0;
    
@@ -443,7 +445,7 @@
             
             //fprintf(stdout,"%.16f\n",p[2]*256.0);
             
-            while(color_index0 < CMAP_SIZE_M1) {
+            while(color_index0 < cmap_size_m1) {
             	if (ficp->dmap[color_index0+1].index > p[2])
             	   break;
             	else
@@ -463,15 +465,15 @@
                bump_no_overflow(b[0][3], logvis*ficp->dmap[color_index0].color[3]);
                bump_no_overflow(b[0][4], logvis*255.0);
 #else
-            dbl_index0 = p[2] * CMAP_SIZE;
+            dbl_index0 = p[2] * cmap_size;
             color_index0 = (int) (dbl_index0);
             
             if (flam3_palette_mode_linear == fthp->cp.palette_mode) {
                if (color_index0 < 0) {
                   color_index0 = 0;
                   dbl_frac = 0;
-               } else if (color_index0 >= CMAP_SIZE_M1) {
-                  color_index0 = CMAP_SIZE_M1-1;
+               } else if (color_index0 >= cmap_size_m1) {
+                  color_index0 = cmap_size_m1-1;
                   dbl_frac = 1.0;
                } else {
                   /* interpolate between color_index0 and color_index0+1 */
@@ -487,8 +489,8 @@
             
                if (color_index0 < 0) {
                   color_index0 = 0;
-               } else if (color_index0 >= CMAP_SIZE_M1) {
-                  color_index0 = CMAP_SIZE_M1;
+               } else if (color_index0 >= cmap_size_m1) {
+                  color_index0 = cmap_size_m1;
                }
                         
                for (ci=0;ci<4;ci++)
@@ -563,6 +565,8 @@
    int thi;
    time_t tstart,tend;   
    double sumfilt;
+   char *ai;
+   int cmap_size;
    
    char *last_block;
    size_t memory_rqd;
@@ -580,6 +584,9 @@
 
    stats->num_iters = 0;
 
+   /* correct for apophysis's use of 255 colors in the palette rather than all 256 */
+   cmap_size = 256 - argi("apo_palette",0);
+
    memset(&cp,0, sizeof(flam3_genome));
 
    /* interpolate and get a control point                      */
@@ -836,6 +843,7 @@
          fic.ntemporal_samples = ntemporal_samples;
          fic.batch_num = batch_num;
          fic.nbatches = nbatches;
+         fic.cmap_size = cmap_size;
 
          fic.dmap = (flam3_palette_entry *)dmap;
          fic.color_scalar = color_scalar;
diff -Naur flam3-3.0.1/src/variations.c trunk/src/variations.c
--- flam3-3.0.1/src/variations.c	2010-06-23 12:31:31.000000000 +0200
+++ trunk/src/variations.c	2011-10-21 21:37:26.080166216 +0200
@@ -131,6 +131,7 @@
   "coth",
   "auger",
   "flux",
+  "mobius",
   0
 };
 
@@ -1922,6 +1923,23 @@
     f->p1 += avgr * sin(avga);
 }
 
+void var98_mobius (flam3_iter_helper *f, double weight) {
+
+    // Mobius, by eralex
+    double re_u, im_u, re_v, im_v, rad_v;
+
+    re_u = f->xform->mobius_re_a * f->tx - f->xform->mobius_im_a * f->ty + f->xform->mobius_re_b;
+    im_u = f->xform->mobius_re_a * f->ty + f->xform->mobius_im_a * f->tx + f->xform->mobius_im_b;
+    re_v = f->xform->mobius_re_c * f->tx - f->xform->mobius_im_c * f->ty + f->xform->mobius_re_d;
+    im_v = f->xform->mobius_re_c * f->ty + f->xform->mobius_im_c * f->tx + f->xform->mobius_im_d;
+
+    rad_v = weight / (re_v*re_v + im_v*im_v);
+
+    f->p0 += rad_v * (re_u*re_v + im_u*im_v);
+    f->p1 += rad_v * (im_u*re_v - re_u*im_v);
+}
+    
+
 /* Precalc functions */
 
 void perspective_precalc(flam3_xform *xf) {
@@ -2359,6 +2377,8 @@
                 var96_auger(&f, weight); break;
          case (VAR_FLUX):
                 var97_flux(&f, weight); break;
+         case (VAR_MOBIUS):
+                var98_mobius(&f, weight); break;
       }
 
    }
@@ -2533,5 +2553,14 @@
       thiscp->xform[i].super_shape_holes = 0.0;
       thiscp->xform[i].conic_eccentricity = 1.0;
       thiscp->xform[i].conic_holes = 0.0;
+
+      thiscp->xform[i].mobius_re_a = 0.0;
+      thiscp->xform[i].mobius_re_b = 0.0;
+      thiscp->xform[i].mobius_re_c = 0.0;
+      thiscp->xform[i].mobius_re_d = 0.0;
+      thiscp->xform[i].mobius_im_a = 0.0;
+      thiscp->xform[i].mobius_im_b = 0.0;
+      thiscp->xform[i].mobius_im_c = 0.0;
+      thiscp->xform[i].mobius_im_d = 0.0;
    }
 }
diff -Naur flam3-3.0.1/src/variations.h trunk/src/variations.h
--- flam3-3.0.1/src/variations.h	2010-06-23 12:31:31.000000000 +0200
+++ trunk/src/variations.h	2011-10-21 21:37:26.081166344 +0200
@@ -122,6 +122,7 @@
 void var95_coth (flam3_iter_helper *f, double weight);
 void var96_auger (flam3_iter_helper *f, double weight);
 void var97_flux (flam3_iter_helper *f, double weight);
+void var98_mobius (flam3_iter_helper *f, double weight);
 
 /* Precalculation functions */
 void perspective_precalc(flam3_xform *xf);
