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