]> git.imager.perl.org - imager.git/blob - filters.im
correct synopsis
[imager.git] / filters.im
1 #include "imager.h"
2 #include "imageri.h"
3 #include <stdlib.h>
4 #include <math.h>
5
6
7 /*
8 =head1 NAME
9
10 filters.im - implements filters that operate on images
11
12 =head1 SYNOPSIS
13
14   
15   i_contrast(im, 0.8);
16   i_hardinvert(im);
17   i_hardinvertall(im);
18   i_unsharp_mask(im, 2.0, 1.0);
19   ... and more
20
21 =head1 DESCRIPTION
22
23 filters.c implements basic filters for Imager.  These filters
24 should be accessible from the filter interface as defined in 
25 the pod for Imager.
26
27 =head1 FUNCTION REFERENCE
28
29 Some of these functions are internal.
30
31 =over
32
33 =cut
34 */
35
36
37
38
39 /*
40 =item saturate(in) 
41
42 Clamps the input value between 0 and 255. (internal)
43
44   in - input integer
45
46 =cut
47 */
48
49 static
50 unsigned char
51 saturate(int in) {
52   if (in>255) { return 255; }
53   else if (in>0) return in;
54   return 0;
55 }
56
57
58
59 /* 
60 =item i_contrast(im, intensity)
61
62 Scales the pixel values by the amount specified.
63
64   im        - image object
65   intensity - scalefactor
66
67 =cut
68 */
69
70 void
71 i_contrast(i_img *im, float intensity) {
72   int x, y;
73   unsigned char ch;
74   unsigned int new_color;
75   i_color rcolor;
76   
77   mm_log((1,"i_contrast(im %p, intensity %f)\n", im, intensity));
78   
79   if(intensity < 0) return;
80   
81   for(y = 0; y < im->ysize; y++) for(x = 0; x < im->xsize; x++) {
82     i_gpix(im, x, y, &rcolor);
83       
84     for(ch = 0; ch < im->channels; ch++) {
85       new_color = (unsigned int) rcolor.channel[ch];
86       new_color *= intensity;
87         
88       if(new_color > 255) {
89         new_color = 255;
90       }
91       rcolor.channel[ch] = (unsigned char) new_color;
92     }
93     i_ppix(im, x, y, &rcolor);
94   }
95 }
96
97
98 static int
99 s_hardinvert_low(i_img *im, int all) {
100   int x, y;
101   int ch;
102   int invert_channels = all ? im->channels : i_img_color_channels(im);
103
104   mm_log((1,"i_hardinvert(im %p)\n", im));
105   
106 #code im->bits <= 8  
107   IM_COLOR *row, *entry;
108   
109   /* always rooms to allocate a single line of i_color */
110   row = mymalloc(sizeof(IM_COLOR) * im->xsize); /* checked 17feb2005 tonyc */
111
112   for(y = 0; y < im->ysize; y++) {
113     IM_GLIN(im, 0, im->xsize, y, row);
114     entry = row;
115     for(x = 0; x < im->xsize; x++) {
116       for(ch = 0; ch < invert_channels; ch++) {
117         entry->channel[ch] = IM_SAMPLE_MAX - entry->channel[ch];
118       }
119       ++entry;
120     }
121     IM_PLIN(im, 0, im->xsize, y, row);
122   }  
123   myfree(row);
124 #/code
125
126   return 1;
127 }
128
129 /* 
130 =item i_hardinvert(im)
131
132 Inverts the color channels of the input image.
133
134   im        - image object
135
136 =cut
137 */
138
139 void
140 i_hardinvert(i_img *im) {
141   s_hardinvert_low(im, 0);
142 }
143
144 /* 
145 =item i_hardinvertall(im)
146
147 Inverts all channels of the input image.
148
149   im        - image object
150
151 =cut
152 */
153
154 void
155 i_hardinvertall(i_img *im) {
156   s_hardinvert_low(im, 1);
157 }
158
159 /*
160 =item i_noise(im, amount, type)
161
162 Inverts the pixel values by the amount specified.
163
164   im     - image object
165   amount - deviation in pixel values
166   type   - noise individual for each channel if true
167
168 =cut
169 */
170
171 #ifdef WIN32
172 /* random() is non-ASCII, even if it is better than rand() */
173 #define random() rand()
174 #endif
175
176 void
177 i_noise(i_img *im, float amount, unsigned char type) {
178   int x, y;
179   unsigned char ch;
180   int new_color;
181   float damount = amount * 2;
182   i_color rcolor;
183   int color_inc = 0;
184   
185   mm_log((1,"i_noise(im %p, intensity %.2f\n", im, amount));
186   
187   if(amount < 0) return;
188   
189   for(y = 0; y < im->ysize; y++) for(x = 0; x < im->xsize; x++) {
190     i_gpix(im, x, y, &rcolor);
191     
192     if(type == 0) {
193       color_inc = (amount - (damount * ((float)random() / RAND_MAX)));
194     }
195     
196     for(ch = 0; ch < im->channels; ch++) {
197       new_color = (int) rcolor.channel[ch];
198       
199       if(type != 0) {
200         new_color += (amount - (damount * ((float)random() / RAND_MAX)));
201       } else {
202         new_color += color_inc;
203       }
204       
205       if(new_color < 0) {
206         new_color = 0;
207       }
208       if(new_color > 255) {
209         new_color = 255;
210       }
211       
212       rcolor.channel[ch] = (unsigned char) new_color;
213     }
214     
215     i_ppix(im, x, y, &rcolor);
216   }
217 }
218
219
220 /* 
221 =item i_noise(im, amount, type)
222
223 Inverts the pixel values by the amount specified.
224
225   im     - image object
226   amount - deviation in pixel values
227   type   - noise individual for each channel if true
228
229 =cut
230 */
231
232
233 /*
234 =item i_applyimage(im, add_im, mode)
235
236 Apply's an image to another image
237
238   im     - target image
239   add_im - image that is applied to target
240   mode   - what method is used in applying:
241
242   0   Normal    
243   1   Multiply
244   2   Screen
245   3   Overlay
246   4   Soft Light
247   5   Hard Light
248   6   Color dodge
249   7   Color Burn
250   8   Darker
251   9   Lighter
252   10  Add
253   11  Subtract
254   12  Difference
255   13  Exclusion
256         
257 =cut
258 */
259
260 void i_applyimage(i_img *im, i_img *add_im, unsigned char mode) {
261   int x, y;
262   int mx, my;
263
264   mm_log((1, "i_applyimage(im %p, add_im %p, mode %d", im, add_im, mode));
265   
266   mx = (add_im->xsize <= im->xsize) ? add_im->xsize : add_im->xsize;
267   my = (add_im->ysize <= im->ysize) ? add_im->ysize : add_im->ysize;
268   
269   for(x = 0; x < mx; x++) {             
270     for(y = 0; y < my; y++) {
271     }
272   }
273 }
274
275
276 /* 
277 =item i_bumpmap(im, bump, channel, light_x, light_y, st)
278
279 Makes a bumpmap on image im using the bump image as the elevation map.
280
281   im      - target image
282   bump    - image that contains the elevation info
283   channel - to take the elevation information from
284   light_x - x coordinate of light source
285   light_y - y coordinate of light source
286   st      - length of shadow
287
288 =cut
289 */
290
291 void
292 i_bumpmap(i_img *im, i_img *bump, int channel, int light_x, int light_y, int st) {
293   int x, y, ch;
294   int mx, my;
295   i_color x1_color, y1_color, x2_color, y2_color, dst_color;
296   double nX, nY;
297   double tX, tY, tZ;
298   double aX, aY, aL;
299   double fZ;
300   unsigned char px1, px2, py1, py2;
301   
302   i_img new_im;
303
304   mm_log((1, "i_bumpmap(im %p, add_im %p, channel %d, light_x %d, light_y %d, st %d)\n",
305           im, bump, channel, light_x, light_y, st));
306
307
308   if(channel >= bump->channels) {
309     mm_log((1, "i_bumpmap: channel = %d while bump image only has %d channels\n", channel, bump->channels));
310     return;
311   }
312
313   mx = (bump->xsize <= im->xsize) ? bump->xsize : im->xsize;
314   my = (bump->ysize <= im->ysize) ? bump->ysize : im->ysize;
315
316   i_img_empty_ch(&new_im, im->xsize, im->ysize, im->channels);
317   
318   aX = (light_x > (mx >> 1)) ? light_x : mx - light_x;
319   aY = (light_y > (my >> 1)) ? light_y : my - light_y;
320
321   aL = sqrt((aX * aX) + (aY * aY));
322
323   for(y = 1; y < my - 1; y++) {         
324     for(x = 1; x < mx - 1; x++) {
325       i_gpix(bump, x + st, y, &x1_color);
326       i_gpix(bump, x, y + st, &y1_color);
327       i_gpix(bump, x - st, y, &x2_color);
328       i_gpix(bump, x, y - st, &y2_color);
329
330       i_gpix(im, x, y, &dst_color);
331
332       px1 = x1_color.channel[channel];
333       py1 = y1_color.channel[channel];
334       px2 = x2_color.channel[channel];
335       py2 = y2_color.channel[channel];
336
337       nX = px1 - px2;
338       nY = py1 - py2;
339
340       nX += 128;
341       nY += 128;
342
343       fZ = (sqrt((nX * nX) + (nY * nY)) / aL);
344  
345       tX = abs(x - light_x) / aL;
346       tY = abs(y - light_y) / aL;
347
348       tZ = 1 - (sqrt((tX * tX) + (tY * tY)) * fZ);
349       
350       if(tZ < 0) tZ = 0;
351       if(tZ > 2) tZ = 2;
352
353       for(ch = 0; ch < im->channels; ch++)
354         dst_color.channel[ch] = (unsigned char) (float)(dst_color.channel[ch] * tZ);
355       
356       i_ppix(&new_im, x, y, &dst_color);
357     }
358   }
359
360   i_copyto(im, &new_im, 0, 0, (int)im->xsize, (int)im->ysize, 0, 0);
361   
362   i_img_exorcise(&new_im);
363 }
364
365
366
367
368 typedef struct {
369   float x,y,z;
370 } fvec;
371
372
373 static
374 float
375 dotp(fvec *a, fvec *b) {
376   return a->x*b->x+a->y*b->y+a->z*b->z;
377 }
378
379 static
380 void
381 normalize(fvec *a) {
382   double d = sqrt(dotp(a,a));
383   a->x /= d;
384   a->y /= d;
385   a->z /= d;
386 }
387
388
389 /*
390   positive directions:
391   
392   x - right, 
393   y - down
394   z - out of the plane
395   
396   I = Ia + Ip*( cd*Scol(N.L) + cs*(R.V)^n )
397   
398   Here, the variables are:
399   
400   * Ia   - ambient colour
401   * Ip   - intensity of the point light source
402   * cd   - diffuse coefficient
403   * Scol - surface colour
404   * cs   - specular coefficient
405   * n    - objects shinyness
406   * N    - normal vector
407   * L    - lighting vector
408   * R    - reflection vector
409   * V    - vision vector
410
411   static void fvec_dump(fvec *x) {
412     printf("(%.2f %.2f %.2f)", x->x, x->y, x->z);
413   }
414 */
415
416 /* XXX: Should these return a code for success? */
417
418
419
420
421 /* 
422 =item i_bumpmap_complex(im, bump, channel, tx, ty, Lx, Ly, Lz, Ip, cd, cs, n, Ia, Il, Is)
423
424 Makes a bumpmap on image im using the bump image as the elevation map.
425
426   im      - target image
427   bump    - image that contains the elevation info
428   channel - to take the elevation information from
429   tx      - shift in x direction of where to start applying bumpmap
430   ty      - shift in y direction of where to start applying bumpmap
431   Lx      - x position/direction of light
432   Ly      - y position/direction of light
433   Lz      - z position/direction of light
434   Ip      - light intensity
435   cd      - diffuse coefficient
436   cs      - specular coefficient
437   n       - surface shinyness
438   Ia      - ambient colour
439   Il      - light colour
440   Is      - specular colour
441
442 if z<0 then the L is taken to be the direction the light is shining in.  Otherwise
443 the L is taken to be the position of the Light, Relative to the image.
444
445 =cut
446 */
447
448
449 void
450 i_bumpmap_complex(i_img *im,
451                   i_img *bump,
452                   int channel,
453                   int tx,
454                   int ty,
455                   float Lx,
456                   float Ly,
457                   float Lz,
458                   float cd,
459                   float cs,
460                   float n,
461                   i_color *Ia,
462                   i_color *Il,
463                   i_color *Is) {
464   i_img new_im;
465   
466   int inflight;
467   int x, y, ch;
468   int mx, Mx, my, My;
469   
470   float cdc[MAXCHANNELS];
471   float csc[MAXCHANNELS];
472
473   i_color x1_color, y1_color, x2_color, y2_color;
474
475   i_color Scol;   /* Surface colour       */
476
477   fvec L;         /* Light vector */
478   fvec N;         /* surface normal       */
479   fvec R;         /* Reflection vector    */
480   fvec V;         /* Vision vector        */
481
482   mm_log((1, "i_bumpmap_complex(im %p, bump %p, channel %d, tx %d, ty %d, Lx %.2f, Ly %.2f, Lz %.2f, cd %.2f, cs %.2f, n %.2f, Ia %p, Il %p, Is %p)\n",
483           im, bump, channel, tx, ty, Lx, Ly, Lz, cd, cs, n, Ia, Il, Is));
484   
485   if (channel >= bump->channels) {
486     mm_log((1, "i_bumpmap_complex: channel = %d while bump image only has %d channels\n", channel, bump->channels));
487     return;
488   }
489
490   for(ch=0; ch<im->channels; ch++) {
491     cdc[ch] = (float)Il->channel[ch]*cd/255.f;
492     csc[ch] = (float)Is->channel[ch]*cs/255.f;
493   }
494
495   mx = 1;
496   my = 1;
497   Mx = bump->xsize-1;
498   My = bump->ysize-1;
499   
500   V.x = 0;
501   V.y = 0;
502   V.z = 1;
503   
504   if (Lz < 0) { /* Light specifies a direction vector, reverse it to get the vector from surface to light */
505     L.x = -Lx;
506     L.y = -Ly;
507     L.z = -Lz;
508     normalize(&L);
509   } else {      /* Light is the position of the light source */
510     inflight = 0;
511     L.x = -0.2;
512     L.y = -0.4;
513     L.z =  1;
514     normalize(&L);
515   }
516
517   i_img_empty_ch(&new_im, im->xsize, im->ysize, im->channels);
518
519   for(y = 0; y < im->ysize; y++) {              
520     for(x = 0; x < im->xsize; x++) {
521       double dp1, dp2;
522       double dx = 0, dy = 0;
523
524       /* Calculate surface normal */
525       if (mx<x && x<Mx && my<y && y<My) {
526         i_gpix(bump, x + 1, y,     &x1_color);
527         i_gpix(bump, x - 1, y,     &x2_color);
528         i_gpix(bump, x,     y + 1, &y1_color);
529         i_gpix(bump, x,     y - 1, &y2_color);
530         dx = x2_color.channel[channel] - x1_color.channel[channel];
531         dy = y2_color.channel[channel] - y1_color.channel[channel];
532       } else {
533         dx = 0;
534         dy = 0;
535       }
536       N.x = -dx * 0.015;
537       N.y = -dy * 0.015;
538       N.z = 1;
539       normalize(&N);
540
541       /* Calculate Light vector if needed */
542       if (Lz>=0) {
543         L.x = Lx - x;
544         L.y = Ly - y;
545         L.z = Lz;
546         normalize(&L);
547       }
548       
549       dp1 = dotp(&L,&N);
550       R.x = -L.x + 2*dp1*N.x;
551       R.y = -L.y + 2*dp1*N.y;
552       R.z = -L.z + 2*dp1*N.z;
553       
554       dp2 = dotp(&R,&V);
555
556       dp1 = dp1<0 ?0 : dp1;
557       dp2 = pow(dp2<0 ?0 : dp2,n);
558
559       i_gpix(im, x, y, &Scol);
560
561       for(ch = 0; ch < im->channels; ch++)
562         Scol.channel[ch] = 
563           saturate( Ia->channel[ch] + cdc[ch]*Scol.channel[ch]*dp1 + csc[ch]*dp2 );
564       
565       i_ppix(&new_im, x, y, &Scol);
566     }
567   }
568   
569   i_copyto(im, &new_im, 0, 0, (int)im->xsize, (int)im->ysize, 0, 0);
570   i_img_exorcise(&new_im);
571 }
572
573
574 /* 
575 =item i_postlevels(im, levels)
576
577 Quantizes Images to fewer levels.
578
579   im      - target image
580   levels  - number of levels
581
582 =cut
583 */
584
585 void
586 i_postlevels(i_img *im, int levels) {
587   int x, y, ch;
588   float pv;
589   int rv;
590   float av;
591
592   i_color rcolor;
593
594   rv = (int) ((float)(256 / levels));
595   av = (float)levels;
596
597   for(y = 0; y < im->ysize; y++) for(x = 0; x < im->xsize; x++) {
598     i_gpix(im, x, y, &rcolor);
599
600     for(ch = 0; ch < im->channels; ch++) {
601       pv = (((float)rcolor.channel[ch] / 255)) * av;
602       pv = (int) ((int)pv * rv);
603
604       if(pv < 0) pv = 0;
605       else if(pv > 255) pv = 255;
606
607       rcolor.channel[ch] = (unsigned char) pv;
608     }
609     i_ppix(im, x, y, &rcolor);
610   }
611 }
612
613
614 /* 
615 =item i_mosaic(im, size)
616
617 Makes an image looks like a mosaic with tilesize of size
618
619   im      - target image
620   size    - size of tiles
621
622 =cut
623 */
624
625 void
626 i_mosaic(i_img *im, int size) {
627   int x, y, ch;
628   int lx, ly, z;
629   long sqrsize;
630
631   i_color rcolor;
632   long col[256];
633   
634   sqrsize = size * size;
635   
636   for(y = 0; y < im->ysize; y += size) for(x = 0; x < im->xsize; x += size) {
637     for(z = 0; z < 256; z++) col[z] = 0;
638     
639     for(lx = 0; lx < size; lx++) {
640       for(ly = 0; ly < size; ly++) {
641         i_gpix(im, (x + lx), (y + ly), &rcolor);
642           
643         for(ch = 0; ch < im->channels; ch++) {
644           col[ch] += rcolor.channel[ch];
645         }
646       }
647     }
648       
649     for(ch = 0; ch < im->channels; ch++)
650       rcolor.channel[ch] = (int) ((float)col[ch] / sqrsize);
651     
652     
653     for(lx = 0; lx < size; lx++)
654       for(ly = 0; ly < size; ly++)
655       i_ppix(im, (x + lx), (y + ly), &rcolor);
656     
657   }
658 }
659
660
661 /*
662 =item i_watermark(im, wmark, tx, ty, pixdiff) 
663
664 Applies a watermark to the target image
665
666   im      - target image
667   wmark   - watermark image
668   tx      - x coordinate of where watermark should be applied
669   ty      - y coordinate of where watermark should be applied
670   pixdiff - the magnitude of the watermark, controls how visible it is
671
672 =cut
673 */
674
675 void
676 i_watermark(i_img *im, i_img *wmark, int tx, int ty, int pixdiff) {
677   int vx, vy, ch;
678   i_color val, wval;
679
680         int mx = wmark->xsize;
681         int my = wmark->ysize;
682
683   for(vx=0;vx<mx;vx++) for(vy=0;vy<my;vy++) {
684     
685     i_gpix(im,    tx+vx, ty+vy,&val );
686     i_gpix(wmark, vx,    vy,   &wval);
687     
688     for(ch=0;ch<im->channels;ch++) 
689       val.channel[ch] = saturate( val.channel[ch] + (pixdiff* (wval.channel[0]-128) )/128 );
690     
691     i_ppix(im,tx+vx,ty+vy,&val);
692   }
693 }
694
695
696 /*
697 =item i_autolevels(im, lsat, usat, skew)
698
699 Scales and translates each color such that it fills the range completely.
700 Skew is not implemented yet - purpose is to control the color skew that can
701 occur when changing the contrast.
702
703   im   - target image
704   lsat - fraction of pixels that will be truncated at the lower end of the spectrum
705   usat - fraction of pixels that will be truncated at the higher end of the spectrum
706   skew - not used yet
707
708 =cut
709 */
710
711 void
712 i_autolevels(i_img *im, float lsat, float usat, float skew) {
713   i_color val;
714   int i, x, y, rhist[256], ghist[256], bhist[256];
715   int rsum, rmin, rmax;
716   int gsum, gmin, gmax;
717   int bsum, bmin, bmax;
718   int rcl, rcu, gcl, gcu, bcl, bcu;
719
720   mm_log((1,"i_autolevels(im %p, lsat %f,usat %f,skew %f)\n", im, lsat,usat,skew));
721
722   rsum=gsum=bsum=0;
723   for(i=0;i<256;i++) rhist[i]=ghist[i]=bhist[i] = 0;
724   /* create histogram for each channel */
725   for(y = 0; y < im->ysize; y++) for(x = 0; x < im->xsize; x++) {
726     i_gpix(im, x, y, &val);
727     rhist[val.channel[0]]++;
728     ghist[val.channel[1]]++;
729     bhist[val.channel[2]]++;
730   }
731
732   for(i=0;i<256;i++) {
733     rsum+=rhist[i];
734     gsum+=ghist[i];
735     bsum+=bhist[i];
736   }
737   
738   rmin = gmin = bmin = 0;
739   rmax = gmax = bmax = 255;
740   
741   rcu = rcl = gcu = gcl = bcu = bcl = 0;
742   
743   for(i=0; i<256; i++) { 
744     rcl += rhist[i];     if ( (rcl<rsum*lsat) ) rmin=i;
745     rcu += rhist[255-i]; if ( (rcu<rsum*usat) ) rmax=255-i;
746
747     gcl += ghist[i];     if ( (gcl<gsum*lsat) ) gmin=i;
748     gcu += ghist[255-i]; if ( (gcu<gsum*usat) ) gmax=255-i;
749
750     bcl += bhist[i];     if ( (bcl<bsum*lsat) ) bmin=i;
751     bcu += bhist[255-i]; if ( (bcu<bsum*usat) ) bmax=255-i;
752   }
753
754   for(y = 0; y < im->ysize; y++) for(x = 0; x < im->xsize; x++) {
755     i_gpix(im, x, y, &val);
756     val.channel[0]=saturate((val.channel[0]-rmin)*255/(rmax-rmin));
757     val.channel[1]=saturate((val.channel[1]-gmin)*255/(gmax-gmin));
758     val.channel[2]=saturate((val.channel[2]-bmin)*255/(bmax-bmin));
759     i_ppix(im, x, y, &val);
760   }
761 }
762
763 /*
764 =item Noise(x,y)
765
766 Pseudo noise utility function used to generate perlin noise. (internal)
767
768   x - x coordinate
769   y - y coordinate
770
771 =cut
772 */
773
774 static
775 float
776 Noise(int x, int y) {
777   int n = x + y * 57; 
778   n = (n<<13) ^ n;
779   return ( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);
780 }
781
782 /*
783 =item SmoothedNoise1(x,y)
784
785 Pseudo noise utility function used to generate perlin noise. (internal)
786
787   x - x coordinate
788   y - y coordinate
789
790 =cut
791 */
792
793 static
794 float
795 SmoothedNoise1(float x, float y) {
796   float corners = ( Noise(x-1, y-1)+Noise(x+1, y-1)+Noise(x-1, y+1)+Noise(x+1, y+1) ) / 16;
797   float sides   = ( Noise(x-1, y)  +Noise(x+1, y)  +Noise(x, y-1)  +Noise(x, y+1) ) /  8;
798   float center  =  Noise(x, y) / 4;
799   return corners + sides + center;
800 }
801
802
803 /*
804 =item G_Interpolate(a, b, x)
805
806 Utility function used to generate perlin noise. (internal)
807
808 =cut
809 */
810
811 static
812 float C_Interpolate(float a, float b, float x) {
813   /*  float ft = x * 3.1415927; */
814   float ft = x * PI;
815   float f = (1 - cos(ft)) * .5;
816   return  a*(1-f) + b*f;
817 }
818
819
820 /*
821 =item InterpolatedNoise(x, y)
822
823 Utility function used to generate perlin noise. (internal)
824
825 =cut
826 */
827
828 static
829 float
830 InterpolatedNoise(float x, float y) {
831
832   int integer_X = x;
833   float fractional_X = x - integer_X;
834   int integer_Y = y;
835   float fractional_Y = y - integer_Y;
836
837   float v1 = SmoothedNoise1(integer_X,     integer_Y);
838   float v2 = SmoothedNoise1(integer_X + 1, integer_Y);
839   float v3 = SmoothedNoise1(integer_X,     integer_Y + 1);
840   float v4 = SmoothedNoise1(integer_X + 1, integer_Y + 1);
841
842   float i1 = C_Interpolate(v1 , v2 , fractional_X);
843   float i2 = C_Interpolate(v3 , v4 , fractional_X);
844
845   return C_Interpolate(i1 , i2 , fractional_Y);
846 }
847
848
849
850 /*
851 =item PerlinNoise_2D(x, y)
852
853 Utility function used to generate perlin noise. (internal)
854
855 =cut
856 */
857
858 static
859 float
860 PerlinNoise_2D(float x, float y) {
861   int i,frequency;
862   float amplitude;
863   float total = 0;
864   int Number_Of_Octaves=6;
865   int n = Number_Of_Octaves - 1;
866
867   for(i=0;i<n;i++) {
868     frequency = 2*i;
869     amplitude = PI;
870     total = total + InterpolatedNoise(x * frequency, y * frequency) * amplitude;
871   }
872
873   return total;
874 }
875
876
877 /*
878 =item i_radnoise(im, xo, yo, rscale, ascale)
879
880 Perlin-like radial noise.
881
882   im     - target image
883   xo     - x coordinate of center
884   yo     - y coordinate of center
885   rscale - radial scale
886   ascale - angular scale
887
888 =cut
889 */
890
891 void
892 i_radnoise(i_img *im, int xo, int yo, float rscale, float ascale) {
893   int x, y, ch;
894   i_color val;
895   unsigned char v;
896   float xc, yc, r;
897   double a;
898   
899   for(y = 0; y < im->ysize; y++) for(x = 0; x < im->xsize; x++) {
900     xc = (float)x-xo+0.5;
901     yc = (float)y-yo+0.5;
902     r = rscale*sqrt(xc*xc+yc*yc)+1.2;
903     a = (PI+atan2(yc,xc))*ascale;
904     v = saturate(128+100*(PerlinNoise_2D(a,r)));
905     /* v=saturate(120+12*PerlinNoise_2D(xo+(float)x/scale,yo+(float)y/scale));  Good soft marble */ 
906     for(ch=0; ch<im->channels; ch++) val.channel[ch]=v;
907     i_ppix(im, x, y, &val);
908   }
909 }
910
911
912 /*
913 =item i_turbnoise(im, xo, yo, scale)
914
915 Perlin-like 2d noise noise.
916
917   im     - target image
918   xo     - x coordinate translation
919   yo     - y coordinate translation
920   scale  - scale of noise
921
922 =cut
923 */
924
925 void
926 i_turbnoise(i_img *im, float xo, float yo, float scale) {
927   int x,y,ch;
928   unsigned char v;
929   i_color val;
930
931   for(y = 0; y < im->ysize; y++) for(x = 0; x < im->xsize; x++) {
932     /*    v=saturate(125*(1.0+PerlinNoise_2D(xo+(float)x/scale,yo+(float)y/scale))); */
933     v = saturate(120*(1.0+sin(xo+(float)x/scale+PerlinNoise_2D(xo+(float)x/scale,yo+(float)y/scale))));
934     for(ch=0; ch<im->channels; ch++) val.channel[ch] = v;
935     i_ppix(im, x, y, &val);
936   }
937 }
938
939
940
941 /*
942 =item i_gradgen(im, num, xo, yo, ival, dmeasure)
943
944 Gradient generating function.
945
946   im     - target image
947   num    - number of points given
948   xo     - array of x coordinates
949   yo     - array of y coordinates
950   ival   - array of i_color objects
951   dmeasure - distance measure to be used.  
952     0 = Euclidean
953     1 = Euclidean squared
954     2 = Manhattan distance
955
956 =cut
957 */
958
959
960 void
961 i_gradgen(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure) {
962   
963   i_color val;
964   int p, x, y, ch;
965   int channels = im->channels;
966   int xsize    = im->xsize;
967   int ysize    = im->ysize;
968   int bytes;
969
970   float *fdist;
971
972   mm_log((1,"i_gradgen(im %p, num %d, xo %p, yo %p, ival %p, dmeasure %d)\n", im, num, xo, yo, ival, dmeasure));
973   
974   for(p = 0; p<num; p++) {
975     mm_log((1,"i_gradgen: (%d, %d)\n", xo[p], yo[p]));
976     ICL_info(&ival[p]);
977   }
978
979   /* on the systems I have sizeof(float) == sizeof(int) and thus
980      this would be same size as the arrays xo and yo point at, but this
981      may not be true for other systems
982
983      since the arrays here are caller controlled, I assume that on
984      overflow is a programming error rather than an end-user error, so
985      calling exit() is justified.
986   */
987   bytes = sizeof(float) * num;
988   if (bytes / num != sizeof(float)) {
989     fprintf(stderr, "integer overflow calculating memory allocation");
990     exit(1);
991   }
992   fdist = mymalloc( bytes ); /* checked 14jul05 tonyc */
993   
994   for(y = 0; y<ysize; y++) for(x = 0; x<xsize; x++) {
995     float cs = 0;
996     float csd = 0;
997     for(p = 0; p<num; p++) {
998       int xd    = x-xo[p];
999       int yd    = y-yo[p];
1000       switch (dmeasure) {
1001       case 0: /* euclidean */
1002         fdist[p]  = sqrt(xd*xd + yd*yd); /* euclidean distance */
1003         break;
1004       case 1: /* euclidean squared */
1005         fdist[p]  = xd*xd + yd*yd; /* euclidean distance */
1006         break;
1007       case 2: /* euclidean squared */
1008         fdist[p]  = i_max(xd*xd, yd*yd); /* manhattan distance */
1009         break;
1010       default:
1011         i_fatal(3,"i_gradgen: Unknown distance measure\n");
1012       }
1013       cs += fdist[p];
1014     }
1015     
1016     csd = 1/((num-1)*cs);
1017
1018     for(p = 0; p<num; p++) fdist[p] = (cs-fdist[p])*csd;
1019     
1020     for(ch = 0; ch<channels; ch++) {
1021       int tres = 0;
1022       for(p = 0; p<num; p++) tres += ival[p].channel[ch] * fdist[p];
1023       val.channel[ch] = saturate(tres);
1024     }
1025     i_ppix(im, x, y, &val); 
1026   }
1027   myfree(fdist);
1028   
1029 }
1030
1031 void
1032 i_nearest_color_foo(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure) {
1033
1034   int p, x, y;
1035   int xsize    = im->xsize;
1036   int ysize    = im->ysize;
1037
1038   mm_log((1,"i_gradgen(im %p, num %d, xo %p, yo %p, ival %p, dmeasure %d)\n", im, num, xo, yo, ival, dmeasure));
1039   
1040   for(p = 0; p<num; p++) {
1041     mm_log((1,"i_gradgen: (%d, %d)\n", xo[p], yo[p]));
1042     ICL_info(&ival[p]);
1043   }
1044
1045   for(y = 0; y<ysize; y++) for(x = 0; x<xsize; x++) {
1046     int   midx    = 0;
1047     float mindist = 0;
1048     float curdist = 0;
1049
1050     int xd        = x-xo[0];
1051     int yd        = y-yo[0];
1052
1053     switch (dmeasure) {
1054     case 0: /* euclidean */
1055       mindist = sqrt(xd*xd + yd*yd); /* euclidean distance */
1056       break;
1057     case 1: /* euclidean squared */
1058       mindist = xd*xd + yd*yd; /* euclidean distance */
1059       break;
1060     case 2: /* euclidean squared */
1061       mindist = i_max(xd*xd, yd*yd); /* manhattan distance */
1062       break;
1063     default:
1064       i_fatal(3,"i_nearest_color: Unknown distance measure\n");
1065     }
1066
1067     for(p = 1; p<num; p++) {
1068       xd = x-xo[p];
1069       yd = y-yo[p];
1070       switch (dmeasure) {
1071       case 0: /* euclidean */
1072         curdist = sqrt(xd*xd + yd*yd); /* euclidean distance */
1073         break;
1074       case 1: /* euclidean squared */
1075         curdist = xd*xd + yd*yd; /* euclidean distance */
1076         break;
1077       case 2: /* euclidean squared */
1078         curdist = i_max(xd*xd, yd*yd); /* manhattan distance */
1079         break;
1080       default:
1081         i_fatal(3,"i_nearest_color: Unknown distance measure\n");
1082       }
1083       if (curdist < mindist) {
1084         mindist = curdist;
1085         midx = p;
1086       }
1087     }
1088     i_ppix(im, x, y, &ival[midx]); 
1089   }
1090 }
1091
1092 /*
1093 =item i_nearest_color(im, num, xo, yo, oval, dmeasure)
1094
1095 This wasn't document - quoth Addi:
1096
1097   An arty type of filter
1098
1099 FIXME: check IRC logs for actual text.
1100
1101 Inputs:
1102
1103 =over
1104
1105 =item *
1106
1107 i_img *im - image to render on.
1108
1109 =item *
1110
1111 int num - number of points/colors in xo, yo, oval
1112
1113 =item *
1114
1115 int *xo - array of I<num> x positions
1116
1117 =item *
1118
1119 int *yo - array of I<num> y positions
1120
1121 =item *
1122
1123 i_color *oval - array of I<num> colors
1124
1125 xo, yo, oval correspond to each other, the point xo[i], yo[i] has a
1126 color something like oval[i], at least closer to that color than other
1127 points.
1128
1129 =item *
1130
1131 int dmeasure - how we measure the distance from some point P(x,y) to
1132 any (xo[i], yo[i]).
1133
1134 Valid values are:
1135
1136 =over
1137
1138 =item 0
1139
1140 euclidean distance: sqrt((x2-x1)**2 + (y2-y1)**2)
1141
1142 =item 1
1143
1144 square of euclidean distance: ((x2-x1)**2 + (y2-y1)**2)
1145
1146 =item 2
1147
1148 manhattan distance: max((y2-y1)**2, (x2-x1)**2)
1149
1150 =back
1151
1152 An invalid value causes an error exit (the program is aborted).
1153
1154 =back
1155
1156 =cut
1157  */
1158
1159 int
1160 i_nearest_color(i_img *im, int num, int *xo, int *yo, i_color *oval, int dmeasure) {
1161   i_color *ival;
1162   float *tval;
1163   float c1, c2;
1164   i_color val;
1165   int p, x, y, ch;
1166   int xsize    = im->xsize;
1167   int ysize    = im->ysize;
1168   int *cmatch;
1169   int ival_bytes, tval_bytes;
1170
1171   mm_log((1,"i_nearest_color(im %p, num %d, xo %p, yo %p, oval %p, dmeasure %d)\n", im, num, xo, yo, oval, dmeasure));
1172
1173   i_clear_error();
1174
1175   if (num <= 0) {
1176     i_push_error(0, "no points supplied to nearest_color filter");
1177     return 0;
1178   }
1179
1180   if (dmeasure < 0 || dmeasure > i_dmeasure_limit) {
1181     i_push_error(0, "distance measure invalid");
1182     return 0;
1183   }
1184
1185   tval_bytes = sizeof(float)*num*im->channels;
1186   if (tval_bytes / num != sizeof(float) * im->channels) {
1187     i_push_error(0, "integer overflow calculating memory allocation");
1188     return 0;
1189   }
1190   ival_bytes  = sizeof(i_color) * num;
1191   if (ival_bytes / sizeof(i_color) != num) {
1192     i_push_error(0, "integer overflow calculating memory allocation");
1193     return 0;
1194   }
1195   tval   = mymalloc( tval_bytes ); /* checked 17feb2005 tonyc */
1196   ival   = mymalloc( ival_bytes ); /* checked 17feb2005 tonyc */
1197   cmatch = mymalloc( sizeof(int)*num     ); /* checked 17feb2005 tonyc */
1198
1199   for(p = 0; p<num; p++) {
1200     for(ch = 0; ch<im->channels; ch++) tval[ p * im->channels + ch] = 0;
1201     cmatch[p] = 0;
1202   }
1203
1204   
1205   for(y = 0; y<ysize; y++) for(x = 0; x<xsize; x++) {
1206     int   midx    = 0;
1207     float mindist = 0;
1208     float curdist = 0;
1209     
1210     int xd        = x-xo[0];
1211     int yd        = y-yo[0];
1212
1213     switch (dmeasure) {
1214     case 0: /* euclidean */
1215       mindist = sqrt(xd*xd + yd*yd); /* euclidean distance */
1216       break;
1217     case 1: /* euclidean squared */
1218       mindist = xd*xd + yd*yd; /* euclidean distance */
1219       break;
1220     case 2: /* manhatten distance */
1221       mindist = i_max(xd*xd, yd*yd); /* manhattan distance */
1222       break;
1223     default:
1224       i_fatal(3,"i_nearest_color: Unknown distance measure\n");
1225     }
1226     
1227     for(p = 1; p<num; p++) {
1228       xd = x-xo[p];
1229       yd = y-yo[p];
1230       switch (dmeasure) {
1231       case 0: /* euclidean */
1232         curdist = sqrt(xd*xd + yd*yd); /* euclidean distance */
1233         break;
1234       case 1: /* euclidean squared */
1235         curdist = xd*xd + yd*yd; /* euclidean distance */
1236         break;
1237       case 2: /* euclidean squared */
1238         curdist = i_max(xd*xd, yd*yd); /* manhattan distance */
1239         break;
1240       default:
1241         i_fatal(3,"i_nearest_color: Unknown distance measure\n");
1242       }
1243       if (curdist < mindist) {
1244         mindist = curdist;
1245         midx = p;
1246       }
1247     }
1248
1249     cmatch[midx]++;
1250     i_gpix(im, x, y, &val);
1251     c2 = 1.0/(float)(cmatch[midx]);
1252     c1 = 1.0-c2;
1253     
1254     for(ch = 0; ch<im->channels; ch++) 
1255       tval[midx*im->channels + ch] = 
1256         c1*tval[midx*im->channels + ch] + c2 * (float) val.channel[ch];
1257   
1258   }
1259
1260   for(p = 0; p<num; p++) for(ch = 0; ch<im->channels; ch++)
1261     ival[p].channel[ch] = tval[p*im->channels + ch];
1262
1263   i_nearest_color_foo(im, num, xo, yo, ival, dmeasure);
1264
1265   return 1;
1266 }
1267
1268 /*
1269 =item i_unsharp_mask(im, stddev, scale)
1270
1271 Perform an usharp mask, which is defined as subtracting the blurred
1272 image from double the original.
1273
1274 =cut
1275 */
1276
1277 void
1278 i_unsharp_mask(i_img *im, double stddev, double scale) {
1279   i_img *copy;
1280   int x, y, ch;
1281
1282   if (scale < 0)
1283     return;
1284   /* it really shouldn't ever be more than 1.0, but maybe ... */
1285   if (scale > 100)
1286     scale = 100;
1287
1288   copy = i_copy(im);
1289   i_gaussian(copy, stddev);
1290   if (im->bits == i_8_bits) {
1291     i_color *blur = mymalloc(im->xsize * sizeof(i_color)); /* checked 17feb2005 tonyc */
1292     i_color *out = mymalloc(im->xsize * sizeof(i_color)); /* checked 17feb2005 tonyc */
1293
1294     for (y = 0; y < im->ysize; ++y) {
1295       i_glin(copy, 0, copy->xsize, y, blur);
1296       i_glin(im, 0, im->xsize, y, out);
1297       for (x = 0; x < im->xsize; ++x) {
1298         for (ch = 0; ch < im->channels; ++ch) {
1299           /*int temp = out[x].channel[ch] + 
1300             scale * (out[x].channel[ch] - blur[x].channel[ch]);*/
1301           int temp = out[x].channel[ch] * 2 - blur[x].channel[ch];
1302           if (temp < 0)
1303             temp = 0;
1304           else if (temp > 255)
1305             temp = 255;
1306           out[x].channel[ch] = temp;
1307         }
1308       }
1309       i_plin(im, 0, im->xsize, y, out);
1310     }
1311
1312     myfree(blur);
1313     myfree(out);
1314   }
1315   else {
1316     i_fcolor *blur = mymalloc(im->xsize * sizeof(i_fcolor)); /* checked 17feb2005 tonyc */
1317     i_fcolor *out = mymalloc(im->xsize * sizeof(i_fcolor)); /* checked 17feb2005 tonyc */
1318
1319     for (y = 0; y < im->ysize; ++y) {
1320       i_glinf(copy, 0, copy->xsize, y, blur);
1321       i_glinf(im, 0, im->xsize, y, out);
1322       for (x = 0; x < im->xsize; ++x) {
1323         for (ch = 0; ch < im->channels; ++ch) {
1324           double temp = out[x].channel[ch] +
1325             scale * (out[x].channel[ch] - blur[x].channel[ch]);
1326           if (temp < 0)
1327             temp = 0;
1328           else if (temp > 1.0)
1329             temp = 1.0;
1330           out[x].channel[ch] = temp;
1331         }
1332       }
1333       i_plinf(im, 0, im->xsize, y, out);
1334     }
1335
1336     myfree(blur);
1337     myfree(out);
1338   }
1339   i_img_destroy(copy);
1340 }
1341
1342 /*
1343 =item i_diff_image(im1, im2, mindist)
1344
1345 Creates a new image that is transparent, except where the pixel in im2
1346 is different from im1, where it is the pixel from im2.
1347
1348 The samples must differ by at least mindiff to be considered different.
1349
1350 =cut
1351 */
1352
1353 i_img *
1354 i_diff_image(i_img *im1, i_img *im2, double mindist) {
1355   i_img *out;
1356   int outchans, diffchans;
1357   int xsize, ysize;
1358
1359   i_clear_error();
1360   if (im1->channels != im2->channels) {
1361     i_push_error(0, "different number of channels");
1362     return NULL;
1363   }
1364
1365   outchans = diffchans = im1->channels;
1366   if (outchans == 1 || outchans == 3)
1367     ++outchans;
1368
1369   xsize = i_min(im1->xsize, im2->xsize);
1370   ysize = i_min(im1->ysize, im2->ysize);
1371
1372   out = i_sametype_chans(im1, xsize, ysize, outchans);
1373   
1374   if (im1->bits == i_8_bits && im2->bits == i_8_bits) {
1375     i_color *line1 = mymalloc(xsize * sizeof(*line1)); /* checked 17feb2005 tonyc */
1376     i_color *line2 = mymalloc(xsize * sizeof(*line1)); /* checked 17feb2005 tonyc */
1377     i_color empty;
1378     int x, y, ch;
1379     int imindist = (int)mindist;
1380
1381     for (ch = 0; ch < MAXCHANNELS; ++ch)
1382       empty.channel[ch] = 0;
1383
1384     for (y = 0; y < ysize; ++y) {
1385       i_glin(im1, 0, xsize, y, line1);
1386       i_glin(im2, 0, xsize, y, line2);
1387       if (outchans != diffchans) {
1388         /* give the output an alpha channel since it doesn't have one */
1389         for (x = 0; x < xsize; ++x)
1390           line2[x].channel[diffchans] = 255;
1391       }
1392       for (x = 0; x < xsize; ++x) {
1393         int diff = 0;
1394         for (ch = 0; ch < diffchans; ++ch) {
1395           if (line1[x].channel[ch] != line2[x].channel[ch]
1396               && abs(line1[x].channel[ch] - line2[x].channel[ch]) > imindist) {
1397             diff = 1;
1398             break;
1399           }
1400         }
1401         if (!diff)
1402           line2[x] = empty;
1403       }
1404       i_plin(out, 0, xsize, y, line2);
1405     }
1406     myfree(line1);
1407     myfree(line2);
1408   }
1409   else {
1410     i_fcolor *line1 = mymalloc(xsize * sizeof(*line1)); /* checked 17feb2005 tonyc */
1411     i_fcolor *line2 = mymalloc(xsize * sizeof(*line2)); /* checked 17feb2005 tonyc */
1412     i_fcolor empty;
1413     int x, y, ch;
1414     double dist = mindist / 255.0;
1415
1416     for (ch = 0; ch < MAXCHANNELS; ++ch)
1417       empty.channel[ch] = 0;
1418
1419     for (y = 0; y < ysize; ++y) {
1420       i_glinf(im1, 0, xsize, y, line1);
1421       i_glinf(im2, 0, xsize, y, line2);
1422       if (outchans != diffchans) {
1423         /* give the output an alpha channel since it doesn't have one */
1424         for (x = 0; x < xsize; ++x)
1425           line2[x].channel[diffchans] = 1.0;
1426       }
1427       for (x = 0; x < xsize; ++x) {
1428         int diff = 0;
1429         for (ch = 0; ch < diffchans; ++ch) {
1430           if (line1[x].channel[ch] != line2[x].channel[ch]
1431               && fabs(line1[x].channel[ch] - line2[x].channel[ch]) > dist) {
1432             diff = 1;
1433             break;
1434           }
1435         }
1436         if (!diff)
1437           line2[x] = empty;
1438       }
1439       i_plinf(out, 0, xsize, y, line2);
1440     }
1441     myfree(line1);
1442     myfree(line2);
1443   }
1444
1445   return out;
1446 }
1447
1448 struct fount_state;
1449 static double linear_fount_f(double x, double y, struct fount_state *state);
1450 static double bilinear_fount_f(double x, double y, struct fount_state *state);
1451 static double radial_fount_f(double x, double y, struct fount_state *state);
1452 static double square_fount_f(double x, double y, struct fount_state *state);
1453 static double revolution_fount_f(double x, double y, 
1454                                  struct fount_state *state);
1455 static double conical_fount_f(double x, double y, struct fount_state *state);
1456
1457 typedef double (*fount_func)(double, double, struct fount_state *);
1458 static fount_func fount_funcs[] =
1459 {
1460   linear_fount_f,
1461   bilinear_fount_f,
1462   radial_fount_f,
1463   square_fount_f,
1464   revolution_fount_f,
1465   conical_fount_f,
1466 };
1467
1468 static double linear_interp(double pos, i_fountain_seg *seg);
1469 static double sine_interp(double pos, i_fountain_seg *seg);
1470 static double sphereup_interp(double pos, i_fountain_seg *seg);
1471 static double spheredown_interp(double pos, i_fountain_seg *seg);
1472 typedef double (*fount_interp)(double pos, i_fountain_seg *seg);
1473 static fount_interp fount_interps[] =
1474 {
1475   linear_interp,
1476   linear_interp,
1477   sine_interp,
1478   sphereup_interp,
1479   spheredown_interp,
1480 };
1481
1482 static void direct_cinterp(i_fcolor *out, double pos, i_fountain_seg *seg);
1483 static void hue_up_cinterp(i_fcolor *out, double pos, i_fountain_seg *seg);
1484 static void hue_down_cinterp(i_fcolor *out, double pos, i_fountain_seg *seg);
1485 typedef void (*fount_cinterp)(i_fcolor *out, double pos, i_fountain_seg *seg);
1486 static fount_cinterp fount_cinterps[] =
1487 {
1488   direct_cinterp,
1489   hue_up_cinterp,
1490   hue_down_cinterp,
1491 };
1492
1493 typedef double (*fount_repeat)(double v);
1494 static double fount_r_none(double v);
1495 static double fount_r_sawtooth(double v);
1496 static double fount_r_triangle(double v);
1497 static double fount_r_saw_both(double v);
1498 static double fount_r_tri_both(double v);
1499 static fount_repeat fount_repeats[] =
1500 {
1501   fount_r_none,
1502   fount_r_sawtooth,
1503   fount_r_triangle,
1504   fount_r_saw_both,
1505   fount_r_tri_both,
1506 };
1507
1508 static int simple_ssample(i_fcolor *out, double x, double y, 
1509                            struct fount_state *state);
1510 static int random_ssample(i_fcolor *out, double x, double y, 
1511                            struct fount_state *state);
1512 static int circle_ssample(i_fcolor *out, double x, double y, 
1513                            struct fount_state *state);
1514 typedef int (*fount_ssample)(i_fcolor *out, double x, double y, 
1515                               struct fount_state *state);
1516 static fount_ssample fount_ssamples[] =
1517 {
1518   NULL,
1519   simple_ssample,
1520   random_ssample,
1521   circle_ssample,
1522 };
1523
1524 static int
1525 fount_getat(i_fcolor *out, double x, double y, struct fount_state *state);
1526
1527 /*
1528   Keep state information used by each type of fountain fill
1529 */
1530 struct fount_state {
1531   /* precalculated for the equation of the line perpendicular to the line AB */
1532   double lA, lB, lC;
1533   double AB;
1534   double sqrtA2B2;
1535   double mult;
1536   double cos;
1537   double sin;
1538   double theta;
1539   int xa, ya;
1540   void *ssample_data;
1541   fount_func ffunc;
1542   fount_repeat rpfunc;
1543   fount_ssample ssfunc;
1544   double parm;
1545   i_fountain_seg *segs;
1546   int count;
1547 };
1548
1549 static void
1550 fount_init_state(struct fount_state *state, double xa, double ya, 
1551                  double xb, double yb, i_fountain_type type, 
1552                  i_fountain_repeat repeat, int combine, int super_sample, 
1553                  double ssample_param, int count, i_fountain_seg *segs);
1554
1555 static void
1556 fount_finish_state(struct fount_state *state);
1557
1558 #define EPSILON (1e-6)
1559
1560 /*
1561 =item i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, count, segs)
1562
1563 Draws a fountain fill using A(xa, ya) and B(xb, yb) as reference points.
1564
1565 I<type> controls how the reference points are used:
1566
1567 =over
1568
1569 =item i_ft_linear
1570
1571 linear, where A is 0 and B is 1.
1572
1573 =item i_ft_bilinear
1574
1575 linear in both directions from A.
1576
1577 =item i_ft_radial
1578
1579 circular, where A is the centre of the fill, and B is a point
1580 on the radius.
1581
1582 =item i_ft_radial_square
1583
1584 where A is the centre of the fill and B is the centre of
1585 one side of the square.
1586
1587 =item i_ft_revolution
1588
1589 where A is the centre of the fill and B defines the 0/1.0
1590 angle of the fill.
1591
1592 =item i_ft_conical
1593
1594 similar to i_ft_revolution, except that the revolution goes in both
1595 directions
1596
1597 =back
1598
1599 I<repeat> can be one of:
1600
1601 =over
1602
1603 =item i_fr_none
1604
1605 values < 0 are treated as zero, values > 1 are treated as 1.
1606
1607 =item i_fr_sawtooth
1608
1609 negative values are treated as 0, positive values are modulo 1.0
1610
1611 =item i_fr_triangle
1612
1613 negative values are treated as zero, if (int)value is odd then the value is treated as 1-(value
1614 mod 1.0), otherwise the same as for sawtooth.
1615
1616 =item i_fr_saw_both
1617
1618 like i_fr_sawtooth, except that the sawtooth pattern repeats into
1619 negative values.
1620
1621 =item i_fr_tri_both
1622
1623 Like i_fr_triangle, except that negative values are handled as their
1624 absolute values.
1625
1626 =back
1627
1628 If combine is non-zero then non-opaque values are combined with the
1629 underlying color.
1630
1631 I<super_sample> controls super sampling, if any.  At some point I'll
1632 probably add a adaptive super-sampler.  Current possible values are:
1633
1634 =over
1635
1636 =item i_fts_none
1637
1638 No super-sampling is done.
1639
1640 =item i_fts_grid
1641
1642 A square grid of points withing the pixel are sampled.
1643
1644 =item i_fts_random
1645
1646 Random points within the pixel are sampled.
1647
1648 =item i_fts_circle
1649
1650 Points on the radius of a circle are sampled.  This produces fairly
1651 good results, but is fairly slow since sin() and cos() are evaluated
1652 for each point.
1653
1654 =back
1655
1656 I<ssample_param> is intended to be roughly the number of points
1657 sampled within the pixel.
1658
1659 I<count> and I<segs> define the segments of the fill.
1660
1661 =cut
1662
1663 */
1664
1665 int
1666 i_fountain(i_img *im, double xa, double ya, double xb, double yb, 
1667            i_fountain_type type, i_fountain_repeat repeat, 
1668            int combine, int super_sample, double ssample_param, 
1669            int count, i_fountain_seg *segs) {
1670   struct fount_state state;
1671   int x, y;
1672   i_fcolor *line = NULL;
1673   i_fcolor *work = NULL;
1674   int line_bytes;
1675   i_fountain_seg *my_segs;
1676   i_fill_combine_f combine_func = NULL;
1677   i_fill_combinef_f combinef_func = NULL;
1678
1679   i_clear_error();
1680
1681   /* i_fountain() allocates floating colors even for 8-bit images,
1682      so we need to do this check */
1683   line_bytes = sizeof(i_fcolor) * im->xsize;
1684   if (line_bytes / sizeof(i_fcolor) != im->xsize) {
1685     i_push_error(0, "integer overflow calculating memory allocation");
1686     return 0;
1687   }
1688   
1689   line = mymalloc(line_bytes); /* checked 17feb2005 tonyc */
1690
1691   i_get_combine(combine, &combine_func, &combinef_func);
1692   if (combinef_func)
1693     work = mymalloc(line_bytes); /* checked 17feb2005 tonyc */
1694
1695   fount_init_state(&state, xa, ya, xb, yb, type, repeat, combine, 
1696                    super_sample, ssample_param, count, segs);
1697   my_segs = state.segs;
1698
1699   for (y = 0; y < im->ysize; ++y) {
1700     i_glinf(im, 0, im->xsize, y, line);
1701     for (x = 0; x < im->xsize; ++x) {
1702       i_fcolor c;
1703       int got_one;
1704       if (super_sample == i_fts_none)
1705         got_one = fount_getat(&c, x, y, &state);
1706       else
1707         got_one = state.ssfunc(&c, x, y, &state);
1708       if (got_one) {
1709         if (combine)
1710           work[x] = c;
1711         else 
1712           line[x] = c;
1713       }
1714     }
1715     if (combine)
1716       combinef_func(line, work, im->channels, im->xsize);
1717     i_plinf(im, 0, im->xsize, y, line);
1718   }
1719   fount_finish_state(&state);
1720   if (work) myfree(work);
1721   myfree(line);
1722
1723   return 1;
1724 }
1725
1726 typedef struct {
1727   i_fill_t base;
1728   struct fount_state state;
1729 } i_fill_fountain_t;
1730
1731 static void
1732 fill_fountf(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width, int channels, 
1733             i_fcolor *data);
1734 static void
1735 fount_fill_destroy(i_fill_t *fill);
1736
1737 static i_fill_fountain_t
1738 fount_fill_proto =
1739   {
1740     {
1741       NULL,
1742       fill_fountf,
1743       fount_fill_destroy
1744     }
1745   };
1746
1747
1748 /*
1749 =item i_new_fill_fount(C<xa>, C<ya>, C<xb>, C<yb>, C<type>, C<repeat>, C<combine>, C<super_sample>, C<ssample_param>, C<count>, C<segs>)
1750
1751 =category Fills
1752 =synopsis fill = i_new_fill_fount(0, 0, 100, 100, i_ft_linear, i_ft_linear, 
1753 =synopsis                         i_fr_triangle, 0, i_fts_grid, 9, 1, segs);
1754
1755
1756 Creates a new general fill which fills with a fountain fill.
1757
1758 =cut
1759 */
1760
1761 i_fill_t *
1762 i_new_fill_fount(double xa, double ya, double xb, double yb, 
1763                  i_fountain_type type, i_fountain_repeat repeat, 
1764                  int combine, int super_sample, double ssample_param, 
1765                  int count, i_fountain_seg *segs) {
1766   i_fill_fountain_t *fill = mymalloc(sizeof(i_fill_fountain_t));
1767   
1768   *fill = fount_fill_proto;
1769   if (combine)
1770     i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
1771   else {
1772     fill->base.combine = NULL;
1773     fill->base.combinef = NULL;
1774   }
1775   fount_init_state(&fill->state, xa, ya, xb, yb, type, repeat, combine, 
1776                    super_sample, ssample_param, count, segs);
1777
1778   return &fill->base;
1779 }
1780
1781 /*
1782 =back
1783
1784 =head1 INTERNAL FUNCTIONS
1785
1786 =over
1787
1788 =item fount_init_state(...)
1789
1790 Used by both the fountain fill filter and the fountain fill.
1791
1792 =cut
1793 */
1794
1795 static void
1796 fount_init_state(struct fount_state *state, double xa, double ya, 
1797                  double xb, double yb, i_fountain_type type, 
1798                  i_fountain_repeat repeat, int combine, int super_sample, 
1799                  double ssample_param, int count, i_fountain_seg *segs) {
1800   int i, j;
1801   int bytes;
1802   i_fountain_seg *my_segs = mymalloc(sizeof(i_fountain_seg) * count); /* checked 2jul06 - duplicating original */
1803   /*int have_alpha = im->channels == 2 || im->channels == 4;*/
1804   
1805   memset(state, 0, sizeof(*state));
1806   /* we keep a local copy that we can adjust for speed */
1807   for (i = 0; i < count; ++i) {
1808     i_fountain_seg *seg = my_segs + i;
1809
1810     *seg = segs[i];
1811     if (seg->type < 0 || seg->type >= i_fst_end)
1812       seg->type = i_fst_linear;
1813     if (seg->color < 0 || seg->color >= i_fc_end)
1814       seg->color = i_fc_direct;
1815     if (seg->color == i_fc_hue_up || seg->color == i_fc_hue_down) {
1816       /* so we don't have to translate to HSV on each request, do it here */
1817       for (j = 0; j < 2; ++j) {
1818         i_rgb_to_hsvf(seg->c+j);
1819       }
1820       if (seg->color == i_fc_hue_up) {
1821         if (seg->c[1].channel[0] <= seg->c[0].channel[0])
1822           seg->c[1].channel[0] += 1.0;
1823       }
1824       else {
1825         if (seg->c[0].channel[0] <= seg->c[0].channel[1])
1826           seg->c[0].channel[0] += 1.0;
1827       }
1828     }
1829     /*printf("start %g mid %g end %g c0(%g,%g,%g,%g) c1(%g,%g,%g,%g) type %d color %d\n", 
1830            seg->start, seg->middle, seg->end, seg->c[0].channel[0], 
1831            seg->c[0].channel[1], seg->c[0].channel[2], seg->c[0].channel[3],
1832            seg->c[1].channel[0], seg->c[1].channel[1], seg->c[1].channel[2], 
1833            seg->c[1].channel[3], seg->type, seg->color);*/
1834            
1835   }
1836
1837   /* initialize each engine */
1838   /* these are so common ... */
1839   state->lA = xb - xa;
1840   state->lB = yb - ya;
1841   state->AB = sqrt(state->lA * state->lA + state->lB * state->lB);
1842   state->xa = xa;
1843   state->ya = ya;
1844   switch (type) {
1845   default:
1846     type = i_ft_linear; /* make the invalid value valid */
1847   case i_ft_linear:
1848   case i_ft_bilinear:
1849     state->lC = ya * ya - ya * yb + xa * xa - xa * xb;
1850     state->mult = 1;
1851     state->mult = 1/linear_fount_f(xb, yb, state);
1852     break;
1853
1854   case i_ft_radial:
1855     state->mult = 1.0 / sqrt((double)(xb-xa)*(xb-xa) 
1856                              + (double)(yb-ya)*(yb-ya));
1857     break;
1858
1859   case i_ft_radial_square:
1860     state->cos = state->lA / state->AB;
1861     state->sin = state->lB / state->AB;
1862     state->mult = 1.0 / state->AB;
1863     break;
1864
1865   case i_ft_revolution:
1866     state->theta = atan2(yb-ya, xb-xa);
1867     state->mult = 1.0 / (PI * 2);
1868     break;
1869
1870   case i_ft_conical:
1871     state->theta = atan2(yb-ya, xb-xa);
1872     state->mult = 1.0 / PI;
1873     break;
1874   }
1875   state->ffunc = fount_funcs[type];
1876   if (super_sample < 0 
1877       || super_sample >= (int)(sizeof(fount_ssamples)/sizeof(*fount_ssamples))) {
1878     super_sample = 0;
1879   }
1880   state->ssample_data = NULL;
1881   switch (super_sample) {
1882   case i_fts_grid:
1883     ssample_param = floor(0.5 + sqrt(ssample_param));
1884     bytes = ssample_param * ssample_param * sizeof(i_fcolor);
1885     if (bytes / sizeof(i_fcolor) == ssample_param * ssample_param) {
1886       state->ssample_data = mymalloc(sizeof(i_fcolor) * ssample_param * ssample_param); /* checked 1jul06 tonyc */
1887     }
1888     else {
1889       super_sample = i_fts_none;
1890     }
1891     break;
1892
1893   case i_fts_random:
1894   case i_fts_circle:
1895     ssample_param = floor(0.5+ssample_param);
1896     bytes = sizeof(i_fcolor) * ssample_param;
1897     if (bytes / sizeof(i_fcolor) == ssample_param) {
1898       state->ssample_data = mymalloc(sizeof(i_fcolor) * ssample_param);
1899     }
1900     else {
1901       super_sample = i_fts_none;
1902     }
1903     break;
1904   }
1905   state->parm = ssample_param;
1906   state->ssfunc = fount_ssamples[super_sample];
1907   if (repeat < 0 || repeat >= (sizeof(fount_repeats)/sizeof(*fount_repeats)))
1908     repeat = 0;
1909   state->rpfunc = fount_repeats[repeat];
1910   state->segs = my_segs;
1911   state->count = count;
1912 }
1913
1914 static void
1915 fount_finish_state(struct fount_state *state) {
1916   if (state->ssample_data)
1917     myfree(state->ssample_data);
1918   myfree(state->segs);
1919 }
1920
1921
1922 /*
1923 =item fount_getat(out, x, y, ffunc, rpfunc, state, segs, count)
1924
1925 Evaluates the fountain fill at the given point.
1926
1927 This is called by both the non-super-sampling and super-sampling code.
1928
1929 You might think that it would make sense to sample the fill parameter
1930 instead, and combine those, but this breaks badly.
1931
1932 =cut
1933 */
1934
1935 static int
1936 fount_getat(i_fcolor *out, double x, double y, struct fount_state *state) {
1937   double v = (state->rpfunc)((state->ffunc)(x, y, state));
1938   int i;
1939
1940   i = 0;
1941   while (i < state->count 
1942          && (v < state->segs[i].start || v > state->segs[i].end)) {
1943     ++i;
1944   }
1945   if (i < state->count) {
1946     v = (fount_interps[state->segs[i].type])(v, state->segs+i);
1947     (fount_cinterps[state->segs[i].color])(out, v, state->segs+i);
1948     return 1;
1949   }
1950   else
1951     return 0;
1952 }
1953
1954 /*
1955 =item linear_fount_f(x, y, state)
1956
1957 Calculate the fill parameter for a linear fountain fill.
1958
1959 Uses the point to line distance function, with some precalculation
1960 done in i_fountain().
1961
1962 =cut
1963 */
1964 static double
1965 linear_fount_f(double x, double y, struct fount_state *state) {
1966   return (state->lA * x + state->lB * y + state->lC) / state->AB * state->mult;
1967 }
1968
1969 /*
1970 =item bilinear_fount_f(x, y, state)
1971
1972 Calculate the fill parameter for a bi-linear fountain fill.
1973
1974 =cut
1975 */
1976 static double
1977 bilinear_fount_f(double x, double y, struct fount_state *state) {
1978   return fabs((state->lA * x + state->lB * y + state->lC) / state->AB * state->mult);
1979 }
1980
1981 /*
1982 =item radial_fount_f(x, y, state)
1983
1984 Calculate the fill parameter for a radial fountain fill.
1985
1986 Simply uses the distance function.
1987
1988 =cut
1989  */
1990 static double
1991 radial_fount_f(double x, double y, struct fount_state *state) {
1992   return sqrt((double)(state->xa-x)*(state->xa-x) 
1993               + (double)(state->ya-y)*(state->ya-y)) * state->mult;
1994 }
1995
1996 /*
1997 =item square_fount_f(x, y, state)
1998
1999 Calculate the fill parameter for a square fountain fill.
2000
2001 Works by rotating the reference co-ordinate around the centre of the
2002 square.
2003
2004 =cut
2005 */
2006 static double
2007 square_fount_f(double x, double y, struct fount_state *state) {
2008   int xc, yc; /* centred on A */
2009   double xt, yt; /* rotated by theta */
2010   xc = x - state->xa;
2011   yc = y - state->ya;
2012   xt = fabs(xc * state->cos + yc * state->sin);
2013   yt = fabs(-xc * state->sin + yc * state->cos);
2014   return (xt > yt ? xt : yt) * state->mult;
2015 }
2016
2017 /*
2018 =item revolution_fount_f(x, y, state)
2019
2020 Calculates the fill parameter for the revolution fountain fill.
2021
2022 =cut
2023 */
2024 static double
2025 revolution_fount_f(double x, double y, struct fount_state *state) {
2026   double angle = atan2(y - state->ya, x - state->xa);
2027   
2028   angle -= state->theta;
2029   if (angle < 0) {
2030     angle = fmod(angle+ PI * 4, PI*2);
2031   }
2032
2033   return angle * state->mult;
2034 }
2035
2036 /*
2037 =item conical_fount_f(x, y, state)
2038
2039 Calculates the fill parameter for the conical fountain fill.
2040
2041 =cut
2042 */
2043 static double
2044 conical_fount_f(double x, double y, struct fount_state *state) {
2045   double angle = atan2(y - state->ya, x - state->xa);
2046   
2047   angle -= state->theta;
2048   if (angle < -PI)
2049     angle += PI * 2;
2050   else if (angle > PI) 
2051     angle -= PI * 2;
2052
2053   return fabs(angle) * state->mult;
2054 }
2055
2056 /*
2057 =item linear_interp(pos, seg)
2058
2059 Calculates linear interpolation on the fill parameter.  Breaks the
2060 segment into 2 regions based in the I<middle> value.
2061
2062 =cut
2063 */
2064 static double
2065 linear_interp(double pos, i_fountain_seg *seg) {
2066   if (pos < seg->middle) {
2067     double len = seg->middle - seg->start;
2068     if (len < EPSILON)
2069       return 0.0;
2070     else
2071       return (pos - seg->start) / len / 2;
2072   }
2073   else {
2074     double len = seg->end - seg->middle;
2075     if (len < EPSILON)
2076       return 1.0;
2077     else
2078       return 0.5 + (pos - seg->middle) / len / 2;
2079   }
2080 }
2081
2082 /*
2083 =item sine_interp(pos, seg)
2084
2085 Calculates sine function interpolation on the fill parameter.
2086
2087 =cut
2088 */
2089 static double
2090 sine_interp(double pos, i_fountain_seg *seg) {
2091   /* I wonder if there's a simple way to smooth the transition for this */
2092   double work = linear_interp(pos, seg);
2093
2094   return (1-cos(work * PI))/2;
2095 }
2096
2097 /*
2098 =item sphereup_interp(pos, seg)
2099
2100 Calculates spherical interpolation on the fill parameter, with the cusp 
2101 at the low-end.
2102
2103 =cut
2104 */
2105 static double
2106 sphereup_interp(double pos, i_fountain_seg *seg) {
2107   double work = linear_interp(pos, seg);
2108
2109   return sqrt(1.0 - (1-work) * (1-work));
2110 }
2111
2112 /*
2113 =item spheredown_interp(pos, seg)
2114
2115 Calculates spherical interpolation on the fill parameter, with the cusp 
2116 at the high-end.
2117
2118 =cut
2119 */
2120 static double
2121 spheredown_interp(double pos, i_fountain_seg *seg) {
2122   double work = linear_interp(pos, seg);
2123
2124   return 1-sqrt(1.0 - work * work);
2125 }
2126
2127 /*
2128 =item direct_cinterp(out, pos, seg)
2129
2130 Calculates the fountain color based on direct scaling of the channels
2131 of the color channels.
2132
2133 =cut
2134 */
2135 static void
2136 direct_cinterp(i_fcolor *out, double pos, i_fountain_seg *seg) {
2137   int ch;
2138   for (ch = 0; ch < MAXCHANNELS; ++ch) {
2139     out->channel[ch] = seg->c[0].channel[ch] * (1 - pos) 
2140       + seg->c[1].channel[ch] * pos;
2141   }
2142 }
2143
2144 /*
2145 =item hue_up_cinterp(put, pos, seg)
2146
2147 Calculates the fountain color based on scaling a HSV value.  The hue
2148 increases as the fill parameter increases.
2149
2150 =cut
2151 */
2152 static void
2153 hue_up_cinterp(i_fcolor *out, double pos, i_fountain_seg *seg) {
2154   int ch;
2155   for (ch = 0; ch < MAXCHANNELS; ++ch) {
2156     out->channel[ch] = seg->c[0].channel[ch] * (1 - pos) 
2157       + seg->c[1].channel[ch] * pos;
2158   }
2159   i_hsv_to_rgbf(out);
2160 }
2161
2162 /*
2163 =item hue_down_cinterp(put, pos, seg)
2164
2165 Calculates the fountain color based on scaling a HSV value.  The hue
2166 decreases as the fill parameter increases.
2167
2168 =cut
2169 */
2170 static void
2171 hue_down_cinterp(i_fcolor *out, double pos, i_fountain_seg *seg) {
2172   int ch;
2173   for (ch = 0; ch < MAXCHANNELS; ++ch) {
2174     out->channel[ch] = seg->c[0].channel[ch] * (1 - pos) 
2175       + seg->c[1].channel[ch] * pos;
2176   }
2177   i_hsv_to_rgbf(out);
2178 }
2179
2180 /*
2181 =item simple_ssample(out, parm, x, y, state, ffunc, rpfunc, segs, count)
2182
2183 Simple grid-based super-sampling.
2184
2185 =cut
2186 */
2187 static int
2188 simple_ssample(i_fcolor *out, double x, double y, struct fount_state *state) {
2189   i_fcolor *work = state->ssample_data;
2190   int dx, dy;
2191   int grid = state->parm;
2192   double base = -0.5 + 0.5 / grid;
2193   double step = 1.0 / grid;
2194   int ch, i;
2195   int samp_count = 0;
2196
2197   for (dx = 0; dx < grid; ++dx) {
2198     for (dy = 0; dy < grid; ++dy) {
2199       if (fount_getat(work+samp_count, x + base + step * dx, 
2200                       y + base + step * dy, state)) {
2201         ++samp_count;
2202       }
2203     }
2204   }
2205   for (ch = 0; ch < MAXCHANNELS; ++ch) {
2206     out->channel[ch] = 0;
2207     for (i = 0; i < samp_count; ++i) {
2208       out->channel[ch] += work[i].channel[ch];
2209     }
2210     /* we divide by 4 rather than samp_count since if there's only one valid
2211        sample it should be mostly transparent */
2212     out->channel[ch] /= grid * grid;
2213   }
2214   return samp_count;
2215 }
2216
2217 /*
2218 =item random_ssample(out, parm, x, y, state, ffunc, rpfunc, segs, count)
2219
2220 Random super-sampling.
2221
2222 =cut
2223 */
2224 static int
2225 random_ssample(i_fcolor *out, double x, double y, 
2226                struct fount_state *state) {
2227   i_fcolor *work = state->ssample_data;
2228   int i, ch;
2229   int maxsamples = state->parm;
2230   double rand_scale = 1.0 / RAND_MAX;
2231   int samp_count = 0;
2232   for (i = 0; i < maxsamples; ++i) {
2233     if (fount_getat(work+samp_count, x - 0.5 + rand() * rand_scale, 
2234                     y - 0.5 + rand() * rand_scale, state)) {
2235       ++samp_count;
2236     }
2237   }
2238   for (ch = 0; ch < MAXCHANNELS; ++ch) {
2239     out->channel[ch] = 0;
2240     for (i = 0; i < samp_count; ++i) {
2241       out->channel[ch] += work[i].channel[ch];
2242     }
2243     /* we divide by maxsamples rather than samp_count since if there's
2244        only one valid sample it should be mostly transparent */
2245     out->channel[ch] /= maxsamples;
2246   }
2247   return samp_count;
2248 }
2249
2250 /*
2251 =item circle_ssample(out, parm, x, y, state, ffunc, rpfunc, segs, count)
2252
2253 Super-sampling around the circumference of a circle.
2254
2255 I considered saving the sin()/cos() values and transforming step-size
2256 around the circle, but that's inaccurate, though it may not matter
2257 much.
2258
2259 =cut
2260  */
2261 static int
2262 circle_ssample(i_fcolor *out, double x, double y, 
2263                struct fount_state *state) {
2264   i_fcolor *work = state->ssample_data;
2265   int i, ch;
2266   int maxsamples = state->parm;
2267   double angle = 2 * PI / maxsamples;
2268   double radius = 0.3; /* semi-random */
2269   int samp_count = 0;
2270   for (i = 0; i < maxsamples; ++i) {
2271     if (fount_getat(work+samp_count, x + radius * cos(angle * i), 
2272                     y + radius * sin(angle * i), state)) {
2273       ++samp_count;
2274     }
2275   }
2276   for (ch = 0; ch < MAXCHANNELS; ++ch) {
2277     out->channel[ch] = 0;
2278     for (i = 0; i < samp_count; ++i) {
2279       out->channel[ch] += work[i].channel[ch];
2280     }
2281     /* we divide by maxsamples rather than samp_count since if there's
2282        only one valid sample it should be mostly transparent */
2283     out->channel[ch] /= maxsamples;
2284   }
2285   return samp_count;
2286 }
2287
2288 /*
2289 =item fount_r_none(v)
2290
2291 Implements no repeats.  Simply clamps the fill value.
2292
2293 =cut
2294 */
2295 static double
2296 fount_r_none(double v) {
2297   return v < 0 ? 0 : v > 1 ? 1 : v;
2298 }
2299
2300 /*
2301 =item fount_r_sawtooth(v)
2302
2303 Implements sawtooth repeats.  Clamps negative values and uses fmod()
2304 on others.
2305
2306 =cut
2307 */
2308 static double
2309 fount_r_sawtooth(double v) {
2310   return v < 0 ? 0 : fmod(v, 1.0);
2311 }
2312
2313 /*
2314 =item fount_r_triangle(v)
2315
2316 Implements triangle repeats.  Clamps negative values, uses fmod to get
2317 a range 0 through 2 and then adjusts values > 1.
2318
2319 =cut
2320 */
2321 static double
2322 fount_r_triangle(double v) {
2323   if (v < 0)
2324     return 0;
2325   else {
2326     v = fmod(v, 2.0);
2327     return v > 1.0 ? 2.0 - v : v;
2328   }
2329 }
2330
2331 /*
2332 =item fount_r_saw_both(v)
2333
2334 Implements sawtooth repeats in the both postive and negative directions.
2335
2336 Adjusts the value to be postive and then just uses fmod().
2337
2338 =cut
2339 */
2340 static double
2341 fount_r_saw_both(double v) {
2342   if (v < 0)
2343     v += 1+(int)(-v);
2344   return fmod(v, 1.0);
2345 }
2346
2347 /*
2348 =item fount_r_tri_both(v)
2349
2350 Implements triangle repeats in the both postive and negative directions.
2351
2352 Uses fmod on the absolute value, and then adjusts values > 1.
2353
2354 =cut
2355 */
2356 static double
2357 fount_r_tri_both(double v) {
2358   v = fmod(fabs(v), 2.0);
2359   return v > 1.0 ? 2.0 - v : v;
2360 }
2361
2362 /*
2363 =item fill_fountf(fill, x, y, width, channels, data)
2364
2365 The fill function for fountain fills.
2366
2367 =cut
2368 */
2369 static void
2370 fill_fountf(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width,
2371             int channels, i_fcolor *data) {
2372   i_fill_fountain_t *f = (i_fill_fountain_t *)fill;
2373   
2374   while (width--) {
2375     i_fcolor c;
2376     int got_one;
2377     
2378     if (f->state.ssfunc)
2379       got_one = f->state.ssfunc(&c, x, y, &f->state);
2380     else
2381       got_one = fount_getat(&c, x, y, &f->state);
2382     
2383     *data++ = c;
2384     
2385     ++x;
2386   }
2387 }
2388
2389 /*
2390 =item fount_fill_destroy(fill)
2391
2392 =cut
2393 */
2394 static void
2395 fount_fill_destroy(i_fill_t *fill) {
2396   i_fill_fountain_t *f = (i_fill_fountain_t *)fill;
2397   fount_finish_state(&f->state);
2398 }
2399
2400 /*
2401 =back
2402
2403 =head1 AUTHOR
2404
2405 Arnar M. Hrafnkelsson <addi@umich.edu>
2406
2407 Tony Cook <tony@develop-help.com> (i_fountain())
2408
2409 =head1 SEE ALSO
2410
2411 Imager(3)
2412
2413 =cut
2414 */