9 filters.c - implements filters that operate on images
20 filters.c implements basic filters for Imager. These filters
21 should be accessible from the filter interface as defined in
24 =head1 FUNCTION REFERENCE
26 Some of these functions are internal.
40 =item i_contrast(im, intensity)
42 Scales the pixel values by the amount specified.
45 intensity - scalefactor
51 i_contrast(i_img *im, float intensity) {
54 unsigned int new_color;
57 mm_log((1,"i_contrast(im %p, intensity %f)\n", im, intensity));
59 if(intensity < 0) return;
61 for(y = 0; y < im->ysize; y++) for(x = 0; x < im->xsize; x++) {
62 i_gpix(im, x, y, &rcolor);
64 for(ch = 0; ch < im->channels; ch++) {
65 new_color = (unsigned int) rcolor.channel[ch];
66 new_color *= intensity;
71 rcolor.channel[ch] = (unsigned char) new_color;
73 i_ppix(im, x, y, &rcolor);
79 =item i_hardinvert(im)
81 Inverts the pixel values of the input image.
89 i_hardinvert(i_img *im) {
95 mm_log((1,"i_hardinvert(im %p)\n", im));
97 for(y = 0; y < im->ysize; y++) {
98 for(x = 0; x < im->xsize; x++) {
99 i_gpix(im, x, y, &rcolor);
101 for(ch = 0; ch < im->channels; ch++) {
102 rcolor.channel[ch] = 255 - rcolor.channel[ch];
105 i_ppix(im, x, y, &rcolor);
113 =item i_noise(im, amount, type)
115 Inverts the pixel values by the amount specified.
118 amount - deviation in pixel values
119 type - noise individual for each channel if true
125 /* random() is non-ASCII, even if it is better than rand() */
126 #define random() rand()
130 i_noise(i_img *im, float amount, unsigned char type) {
134 float damount = amount * 2;
138 mm_log((1,"i_noise(im %p, intensity %.2f\n", im, amount));
140 if(amount < 0) return;
142 for(y = 0; y < im->ysize; y++) for(x = 0; x < im->xsize; x++) {
143 i_gpix(im, x, y, &rcolor);
146 color_inc = (amount - (damount * ((float)random() / RAND_MAX)));
149 for(ch = 0; ch < im->channels; ch++) {
150 new_color = (int) rcolor.channel[ch];
153 new_color += (amount - (damount * ((float)random() / RAND_MAX)));
155 new_color += color_inc;
161 if(new_color > 255) {
165 rcolor.channel[ch] = (unsigned char) new_color;
168 i_ppix(im, x, y, &rcolor);
174 =item i_noise(im, amount, type)
176 Inverts the pixel values by the amount specified.
179 amount - deviation in pixel values
180 type - noise individual for each channel if true
187 =item i_applyimage(im, add_im, mode)
189 Apply's an image to another image
192 add_im - image that is applied to target
193 mode - what method is used in applying:
213 void i_applyimage(i_img *im, i_img *add_im, unsigned char mode) {
217 mm_log((1, "i_applyimage(im %p, add_im %p, mode %d", im, add_im, mode));
219 mx = (add_im->xsize <= im->xsize) ? add_im->xsize : add_im->xsize;
220 my = (add_im->ysize <= im->ysize) ? add_im->ysize : add_im->ysize;
222 for(x = 0; x < mx; x++) {
223 for(y = 0; y < my; y++) {
230 =item i_bumpmap(im, bump, channel, light_x, light_y, st)
232 Makes a bumpmap on image im using the bump image as the elevation map.
235 bump - image that contains the elevation info
236 channel - to take the elevation information from
237 light_x - x coordinate of light source
238 light_y - y coordinate of light source
239 st - length of shadow
245 i_bumpmap(i_img *im, i_img *bump, int channel, int light_x, int light_y, int st) {
248 i_color x1_color, y1_color, x2_color, y2_color, dst_color;
253 unsigned char px1, px2, py1, py2;
257 mm_log((1, "i_bumpmap(im %p, add_im %p, channel %d, light_x %d, light_y %d, st %d)\n",
258 im, bump, channel, light_x, light_y, st));
261 if(channel >= bump->channels) {
262 mm_log((1, "i_bumpmap: channel = %d while bump image only has %d channels\n", channel, bump->channels));
266 mx = (bump->xsize <= im->xsize) ? bump->xsize : im->xsize;
267 my = (bump->ysize <= im->ysize) ? bump->ysize : im->ysize;
269 i_img_empty_ch(&new_im, im->xsize, im->ysize, im->channels);
271 aX = (light_x > (mx >> 1)) ? light_x : mx - light_x;
272 aY = (light_y > (my >> 1)) ? light_y : my - light_y;
274 aL = sqrt((aX * aX) + (aY * aY));
276 for(y = 1; y < my - 1; y++) {
277 for(x = 1; x < mx - 1; x++) {
278 i_gpix(bump, x + st, y, &x1_color);
279 i_gpix(bump, x, y + st, &y1_color);
280 i_gpix(bump, x - st, y, &x2_color);
281 i_gpix(bump, x, y - st, &y2_color);
283 i_gpix(im, x, y, &dst_color);
285 px1 = x1_color.channel[channel];
286 py1 = y1_color.channel[channel];
287 px2 = x2_color.channel[channel];
288 py2 = y2_color.channel[channel];
296 fZ = (sqrt((nX * nX) + (nY * nY)) / aL);
298 tX = abs(x - light_x) / aL;
299 tY = abs(y - light_y) / aL;
301 tZ = 1 - (sqrt((tX * tX) + (tY * tY)) * fZ);
306 for(ch = 0; ch < im->channels; ch++)
307 dst_color.channel[ch] = (unsigned char) (float)(dst_color.channel[ch] * tZ);
309 i_ppix(&new_im, x, y, &dst_color);
313 i_copyto(im, &new_im, 0, 0, (int)im->xsize, (int)im->ysize, 0, 0);
315 i_img_exorcise(&new_im);
321 =item i_postlevels(im, levels)
323 Quantizes Images to fewer levels.
326 levels - number of levels
332 i_postlevels(i_img *im, int levels) {
340 rv = (int) ((float)(256 / levels));
343 for(y = 0; y < im->ysize; y++) for(x = 0; x < im->xsize; x++) {
344 i_gpix(im, x, y, &rcolor);
346 for(ch = 0; ch < im->channels; ch++) {
347 pv = (((float)rcolor.channel[ch] / 255)) * av;
348 pv = (int) ((int)pv * rv);
351 else if(pv > 255) pv = 255;
353 rcolor.channel[ch] = (unsigned char) pv;
355 i_ppix(im, x, y, &rcolor);
361 =item i_mosaic(im, size)
363 Makes an image looks like a mosaic with tilesize of size
372 i_mosaic(i_img *im, int size) {
380 sqrsize = size * size;
382 for(y = 0; y < im->ysize; y += size) for(x = 0; x < im->xsize; x += size) {
383 for(z = 0; z < 256; z++) col[z] = 0;
385 for(lx = 0; lx < size; lx++) {
386 for(ly = 0; ly < size; ly++) {
387 i_gpix(im, (x + lx), (y + ly), &rcolor);
389 for(ch = 0; ch < im->channels; ch++) {
390 col[ch] += rcolor.channel[ch];
395 for(ch = 0; ch < im->channels; ch++)
396 rcolor.channel[ch] = (int) ((float)col[ch] / sqrsize);
399 for(lx = 0; lx < size; lx++)
400 for(ly = 0; ly < size; ly++)
401 i_ppix(im, (x + lx), (y + ly), &rcolor);
409 Clamps the input value between 0 and 255. (internal)
419 if (in>255) { return 255; }
420 else if (in>0) return in;
426 =item i_watermark(im, wmark, tx, ty, pixdiff)
428 Applies a watermark to the target image
431 wmark - watermark image
432 tx - x coordinate of where watermark should be applied
433 ty - y coordinate of where watermark should be applied
434 pixdiff - the magnitude of the watermark, controls how visible it is
440 i_watermark(i_img *im, i_img *wmark, int tx, int ty, int pixdiff) {
444 for(vx=0;vx<128;vx++) for(vy=0;vy<110;vy++) {
446 i_gpix(im, tx+vx, ty+vy,&val );
447 i_gpix(wmark, vx, vy, &wval);
449 for(ch=0;ch<im->channels;ch++)
450 val.channel[ch] = saturate( val.channel[ch] + (pixdiff* (wval.channel[0]-128) )/128 );
452 i_ppix(im,tx+vx,ty+vy,&val);
458 =item i_autolevels(im, lsat, usat, skew)
460 Scales and translates each color such that it fills the range completely.
461 Skew is not implemented yet - purpose is to control the color skew that can
462 occur when changing the contrast.
465 lsat - fraction of pixels that will be truncated at the lower end of the spectrum
466 usat - fraction of pixels that will be truncated at the higher end of the spectrum
473 i_autolevels(i_img *im, float lsat, float usat, float skew) {
475 int i, x, y, rhist[256], ghist[256], bhist[256];
476 int rsum, rmin, rmax;
477 int gsum, gmin, gmax;
478 int bsum, bmin, bmax;
479 int rcl, rcu, gcl, gcu, bcl, bcu;
481 mm_log((1,"i_autolevels(im %p, lsat %f,usat %f,skew %f)\n", im, lsat,usat,skew));
484 for(i=0;i<256;i++) rhist[i]=ghist[i]=bhist[i] = 0;
485 /* create histogram for each channel */
486 for(y = 0; y < im->ysize; y++) for(x = 0; x < im->xsize; x++) {
487 i_gpix(im, x, y, &val);
488 rhist[val.channel[0]]++;
489 ghist[val.channel[1]]++;
490 bhist[val.channel[2]]++;
499 rmin = gmin = bmin = 0;
500 rmax = gmax = bmax = 255;
502 rcu = rcl = gcu = gcl = bcu = bcl = 0;
504 for(i=0; i<256; i++) {
505 rcl += rhist[i]; if ( (rcl<rsum*lsat) ) rmin=i;
506 rcu += rhist[255-i]; if ( (rcu<rsum*usat) ) rmax=255-i;
508 gcl += ghist[i]; if ( (gcl<gsum*lsat) ) gmin=i;
509 gcu += ghist[255-i]; if ( (gcu<gsum*usat) ) gmax=255-i;
511 bcl += bhist[i]; if ( (bcl<bsum*lsat) ) bmin=i;
512 bcu += bhist[255-i]; if ( (bcu<bsum*usat) ) bmax=255-i;
515 for(y = 0; y < im->ysize; y++) for(x = 0; x < im->xsize; x++) {
516 i_gpix(im, x, y, &val);
517 val.channel[0]=saturate((val.channel[0]-rmin)*255/(rmax-rmin));
518 val.channel[1]=saturate((val.channel[1]-gmin)*255/(gmax-gmin));
519 val.channel[2]=saturate((val.channel[2]-bmin)*255/(bmax-bmin));
520 i_ppix(im, x, y, &val);
527 Pseudo noise utility function used to generate perlin noise. (internal)
537 Noise(int x, int y) {
540 return ( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);
544 =item SmoothedNoise1(x,y)
546 Pseudo noise utility function used to generate perlin noise. (internal)
556 SmoothedNoise1(float x, float y) {
557 float corners = ( Noise(x-1, y-1)+Noise(x+1, y-1)+Noise(x-1, y+1)+Noise(x+1, y+1) ) / 16;
558 float sides = ( Noise(x-1, y) +Noise(x+1, y) +Noise(x, y-1) +Noise(x, y+1) ) / 8;
559 float center = Noise(x, y) / 4;
560 return corners + sides + center;
565 =item G_Interpolate(a, b, x)
567 Utility function used to generate perlin noise. (internal)
573 float C_Interpolate(float a, float b, float x) {
574 /* float ft = x * 3.1415927; */
576 float f = (1 - cos(ft)) * .5;
577 return a*(1-f) + b*f;
582 =item InterpolatedNoise(x, y)
584 Utility function used to generate perlin noise. (internal)
591 InterpolatedNoise(float x, float y) {
594 float fractional_X = x - integer_X;
596 float fractional_Y = y - integer_Y;
598 float v1 = SmoothedNoise1(integer_X, integer_Y);
599 float v2 = SmoothedNoise1(integer_X + 1, integer_Y);
600 float v3 = SmoothedNoise1(integer_X, integer_Y + 1);
601 float v4 = SmoothedNoise1(integer_X + 1, integer_Y + 1);
603 float i1 = C_Interpolate(v1 , v2 , fractional_X);
604 float i2 = C_Interpolate(v3 , v4 , fractional_X);
606 return C_Interpolate(i1 , i2 , fractional_Y);
612 =item PerlinNoise_2D(x, y)
614 Utility function used to generate perlin noise. (internal)
621 PerlinNoise_2D(float x, float y) {
625 int Number_Of_Octaves=6;
626 int n = Number_Of_Octaves - 1;
631 total = total + InterpolatedNoise(x * frequency, y * frequency) * amplitude;
639 =item i_radnoise(im, xo, yo, rscale, ascale)
641 Perlin-like radial noise.
644 xo - x coordinate of center
645 yo - y coordinate of center
646 rscale - radial scale
647 ascale - angular scale
653 i_radnoise(i_img *im, int xo, int yo, float rscale, float ascale) {
660 for(y = 0; y < im->ysize; y++) for(x = 0; x < im->xsize; x++) {
661 xc = (float)x-xo+0.5;
662 yc = (float)y-yo+0.5;
663 r = rscale*sqrt(xc*xc+yc*yc)+1.2;
664 a = (PI+atan2(yc,xc))*ascale;
665 v = saturate(128+100*(PerlinNoise_2D(a,r)));
666 /* v=saturate(120+12*PerlinNoise_2D(xo+(float)x/scale,yo+(float)y/scale)); Good soft marble */
667 for(ch=0; ch<im->channels; ch++) val.channel[ch]=v;
668 i_ppix(im, x, y, &val);
674 =item i_turbnoise(im, xo, yo, scale)
676 Perlin-like 2d noise noise.
679 xo - x coordinate translation
680 yo - y coordinate translation
681 scale - scale of noise
687 i_turbnoise(i_img *im, float xo, float yo, float scale) {
692 for(y = 0; y < im->ysize; y++) for(x = 0; x < im->xsize; x++) {
693 /* v=saturate(125*(1.0+PerlinNoise_2D(xo+(float)x/scale,yo+(float)y/scale))); */
694 v = saturate(120*(1.0+sin(xo+(float)x/scale+PerlinNoise_2D(xo+(float)x/scale,yo+(float)y/scale))));
695 for(ch=0; ch<im->channels; ch++) val.channel[ch] = v;
696 i_ppix(im, x, y, &val);
703 =item i_gradgen(im, num, xo, yo, ival, dmeasure)
705 Gradient generating function.
708 num - number of points given
709 xo - array of x coordinates
710 yo - array of y coordinates
711 ival - array of i_color objects
712 dmeasure - distance measure to be used.
714 1 = Euclidean squared
715 2 = Manhattan distance
722 i_gradgen(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure) {
726 int channels = im->channels;
727 int xsize = im->xsize;
728 int ysize = im->ysize;
732 mm_log((1,"i_gradgen(im %p, num %d, xo %p, yo %p, ival %p, dmeasure %d)\n", im, num, xo, yo, ival, dmeasure));
734 for(p = 0; p<num; p++) {
735 mm_log((1,"i_gradgen: (%d, %d)\n", xo[p], yo[p]));
739 fdist = mymalloc( sizeof(float) * num );
741 for(y = 0; y<ysize; y++) for(x = 0; x<xsize; x++) {
744 for(p = 0; p<num; p++) {
748 case 0: /* euclidean */
749 fdist[p] = sqrt(xd*xd + yd*yd); /* euclidean distance */
751 case 1: /* euclidean squared */
752 fdist[p] = xd*xd + yd*yd; /* euclidean distance */
754 case 2: /* euclidean squared */
755 fdist[p] = max(xd*xd, yd*yd); /* manhattan distance */
758 m_fatal(3,"i_gradgen: Unknown distance measure\n");
763 csd = 1/((num-1)*cs);
765 for(p = 0; p<num; p++) fdist[p] = (cs-fdist[p])*csd;
767 for(ch = 0; ch<channels; ch++) {
769 for(p = 0; p<num; p++) tres += ival[p].channel[ch] * fdist[p];
770 val.channel[ch] = saturate(tres);
772 i_ppix(im, x, y, &val);
778 i_nearest_color_foo(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure) {
781 int xsize = im->xsize;
782 int ysize = im->ysize;
784 mm_log((1,"i_gradgen(im %p, num %d, xo %p, yo %p, ival %p, dmeasure %d)\n", im, num, xo, yo, ival, dmeasure));
786 for(p = 0; p<num; p++) {
787 mm_log((1,"i_gradgen: (%d, %d)\n", xo[p], yo[p]));
791 for(y = 0; y<ysize; y++) for(x = 0; x<xsize; x++) {
800 case 0: /* euclidean */
801 mindist = sqrt(xd*xd + yd*yd); /* euclidean distance */
803 case 1: /* euclidean squared */
804 mindist = xd*xd + yd*yd; /* euclidean distance */
806 case 2: /* euclidean squared */
807 mindist = max(xd*xd, yd*yd); /* manhattan distance */
810 m_fatal(3,"i_nearest_color: Unknown distance measure\n");
813 for(p = 1; p<num; p++) {
817 case 0: /* euclidean */
818 curdist = sqrt(xd*xd + yd*yd); /* euclidean distance */
820 case 1: /* euclidean squared */
821 curdist = xd*xd + yd*yd; /* euclidean distance */
823 case 2: /* euclidean squared */
824 curdist = max(xd*xd, yd*yd); /* manhattan distance */
827 m_fatal(3,"i_nearest_color: Unknown distance measure\n");
829 if (curdist < mindist) {
834 i_ppix(im, x, y, &ival[midx]);
839 i_nearest_color(i_img *im, int num, int *xo, int *yo, i_color *oval, int dmeasure) {
845 int xsize = im->xsize;
846 int ysize = im->ysize;
849 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));
851 tval = mymalloc( sizeof(float)*num*im->channels );
852 ival = mymalloc( sizeof(i_color)*num );
853 cmatch = mymalloc( sizeof(int)*num );
855 for(p = 0; p<num; p++) {
856 for(ch = 0; ch<im->channels; ch++) tval[ p * im->channels + ch] = 0;
861 for(y = 0; y<ysize; y++) for(x = 0; x<xsize; x++) {
870 case 0: /* euclidean */
871 mindist = sqrt(xd*xd + yd*yd); /* euclidean distance */
873 case 1: /* euclidean squared */
874 mindist = xd*xd + yd*yd; /* euclidean distance */
876 case 2: /* euclidean squared */
877 mindist = max(xd*xd, yd*yd); /* manhattan distance */
880 m_fatal(3,"i_nearest_color: Unknown distance measure\n");
883 for(p = 1; p<num; p++) {
887 case 0: /* euclidean */
888 curdist = sqrt(xd*xd + yd*yd); /* euclidean distance */
890 case 1: /* euclidean squared */
891 curdist = xd*xd + yd*yd; /* euclidean distance */
893 case 2: /* euclidean squared */
894 curdist = max(xd*xd, yd*yd); /* manhattan distance */
897 m_fatal(3,"i_nearest_color: Unknown distance measure\n");
899 if (curdist < mindist) {
906 i_gpix(im, x, y, &val);
907 c2 = 1.0/(float)(cmatch[midx]);
910 for(ch = 0; ch<im->channels; ch++)
911 tval[midx*im->channels + ch] = c1*tval[midx*im->channels + ch] + c2 * (float) val.channel[ch];
916 for(p = 0; p<num; p++) for(ch = 0; ch<im->channels; ch++) ival[p].channel[ch] = tval[p*im->channels + ch];
918 i_nearest_color_foo(im, num, xo, yo, ival, dmeasure);
922 static double linear_fount_f(double x, double y, struct fount_state *state);
923 static double bilinear_fount_f(double x, double y, struct fount_state *state);
924 static double radial_fount_f(double x, double y, struct fount_state *state);
925 static double square_fount_f(double x, double y, struct fount_state *state);
926 static double revolution_fount_f(double x, double y,
927 struct fount_state *state);
928 static double conical_fount_f(double x, double y, struct fount_state *state);
930 typedef double (*fount_func)(double, double, struct fount_state *);
931 static fount_func fount_funcs[] =
941 static double linear_interp(double pos, i_fountain_seg *seg);
942 static double sine_interp(double pos, i_fountain_seg *seg);
943 static double sphereup_interp(double pos, i_fountain_seg *seg);
944 static double spheredown_interp(double pos, i_fountain_seg *seg);
945 typedef double (*fount_interp)(double pos, i_fountain_seg *seg);
946 static fount_interp fount_interps[] =
955 static void direct_cinterp(i_fcolor *out, double pos, i_fountain_seg *seg);
956 static void hue_up_cinterp(i_fcolor *out, double pos, i_fountain_seg *seg);
957 static void hue_down_cinterp(i_fcolor *out, double pos, i_fountain_seg *seg);
958 typedef void (*fount_cinterp)(i_fcolor *out, double pos, i_fountain_seg *seg);
959 static fount_cinterp fount_cinterps[] =
966 typedef double (*fount_repeat)(double v);
967 static double fount_r_none(double v);
968 static double fount_r_sawtooth(double v);
969 static double fount_r_triangle(double v);
970 static double fount_r_saw_both(double v);
971 static double fount_r_tri_both(double v);
972 static fount_repeat fount_repeats[] =
981 static int simple_ssample(i_fcolor *out, double x, double y,
982 struct fount_state *state);
983 static int random_ssample(i_fcolor *out, double x, double y,
984 struct fount_state *state);
985 static int circle_ssample(i_fcolor *out, double x, double y,
986 struct fount_state *state);
987 typedef int (*fount_ssample)(i_fcolor *out, double x, double y,
988 struct fount_state *state);
989 static fount_ssample fount_ssamples[] =
998 fount_getat(i_fcolor *out, double x, double y, struct fount_state *state);
1001 Keep state information used by each type of fountain fill
1003 struct fount_state {
1004 /* precalculated for the equation of the line perpendicular to the line AB */
1015 fount_repeat rpfunc;
1016 fount_ssample ssfunc;
1018 i_fountain_seg *segs;
1023 fount_init_state(struct fount_state *state, double xa, double ya,
1024 double xb, double yb, i_fountain_type type,
1025 i_fountain_repeat repeat, int combine, int super_sample,
1026 double ssample_param, int count, i_fountain_seg *segs);
1029 fount_finish_state(struct fount_state *state);
1031 #define EPSILON (1e-6)
1034 =item i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, count, segs)
1036 Draws a fountain fill using A(xa, ya) and B(xb, yb) as reference points.
1038 I<type> controls how the reference points are used:
1044 linear, where A is 0 and B is 1.
1048 linear in both directions from A.
1052 circular, where A is the centre of the fill, and B is a point
1055 =item i_ft_radial_square
1057 where A is the centre of the fill and B is the centre of
1058 one side of the square.
1060 =item i_ft_revolution
1062 where A is the centre of the fill and B defines the 0/1.0
1067 similar to i_ft_revolution, except that the revolution goes in both
1072 I<repeat> can be one of:
1078 values < 0 are treated as zero, values > 1 are treated as 1.
1082 negative values are treated as 0, positive values are modulo 1.0
1086 negative values are treated as zero, if (int)value is odd then the value is treated as 1-(value
1087 mod 1.0), otherwise the same as for sawtooth.
1091 like i_fr_sawtooth, except that the sawtooth pattern repeats into
1096 Like i_fr_triangle, except that negative values are handled as their
1101 If combine is non-zero then non-opaque values are combined with the
1104 I<super_sample> controls super sampling, if any. At some point I'll
1105 probably add a adaptive super-sampler. Current possible values are:
1111 No super-sampling is done.
1115 A square grid of points withing the pixel are sampled.
1119 Random points within the pixel are sampled.
1123 Points on the radius of a circle are sampled. This produces fairly
1124 good results, but is fairly slow since sin() and cos() are evaluated
1129 I<ssample_param> is intended to be roughly the number of points
1130 sampled within the pixel.
1132 I<count> and I<segs> define the segments of the fill.
1139 i_fountain(i_img *im, double xa, double ya, double xb, double yb,
1140 i_fountain_type type, i_fountain_repeat repeat,
1141 int combine, int super_sample, double ssample_param,
1142 int count, i_fountain_seg *segs) {
1143 struct fount_state state;
1145 i_fcolor *line = mymalloc(sizeof(i_fcolor) * im->xsize);
1147 i_fountain_seg *my_segs;
1149 fount_init_state(&state, xa, ya, xb, yb, type, repeat, combine,
1150 super_sample, ssample_param, count, segs);
1151 my_segs = state.segs;
1153 for (y = 0; y < im->ysize; ++y) {
1154 i_glinf(im, 0, im->xsize, y, line);
1155 for (x = 0; x < im->xsize; ++x) {
1159 if (super_sample == i_fts_none)
1160 got_one = fount_getat(&c, x, y, &state);
1162 got_one = state.ssfunc(&c, x, y, &state);
1165 for (ch = 0; ch < im->channels; ++ch) {
1166 line[x].channel[ch] = line[x].channel[ch] * (1.0 - c.channel[3])
1167 + c.channel[ch] * c.channel[3];
1174 i_plinf(im, 0, im->xsize, y, line);
1176 fount_finish_state(&state);
1182 struct fount_state state;
1183 } i_fill_fountain_t;
1186 fill_fountf(i_fill_t *fill, int x, int y, int width, int channels,
1189 fount_fill_destroy(i_fill_t *fill);
1192 =item i_new_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, count, segs)
1194 Creates a new general fill which fills with a fountain fill.
1200 i_new_fill_fount(double xa, double ya, double xb, double yb,
1201 i_fountain_type type, i_fountain_repeat repeat,
1202 int combine, int super_sample, double ssample_param,
1203 int count, i_fountain_seg *segs) {
1204 i_fill_fountain_t *fill = mymalloc(sizeof(i_fill_fountain_t));
1206 fill->base.fill_with_color = NULL;
1207 fill->base.fill_with_fcolor = fill_fountf;
1208 fill->base.destroy = fount_fill_destroy;
1209 fill->base.combines = combine;
1210 fount_init_state(&fill->state, xa, ya, xb, yb, type, repeat, combine,
1211 super_sample, ssample_param, count, segs);
1219 =head1 INTERNAL FUNCTIONS
1223 =item fount_init_state(...)
1225 Used by both the fountain fill filter and the fountain fill.
1231 fount_init_state(struct fount_state *state, double xa, double ya,
1232 double xb, double yb, i_fountain_type type,
1233 i_fountain_repeat repeat, int combine, int super_sample,
1234 double ssample_param, int count, i_fountain_seg *segs) {
1236 i_fountain_seg *my_segs = mymalloc(sizeof(i_fountain_seg) * count);
1237 /*int have_alpha = im->channels == 2 || im->channels == 4;*/
1240 memset(state, 0, sizeof(*state));
1241 /* we keep a local copy that we can adjust for speed */
1242 for (i = 0; i < count; ++i) {
1243 i_fountain_seg *seg = my_segs + i;
1246 if (seg->type < 0 || type >= i_ft_end)
1247 seg->type = i_ft_linear;
1248 if (seg->color < 0 || seg->color >= i_fc_end)
1249 seg->color = i_fc_direct;
1250 if (seg->color == i_fc_hue_up || seg->color == i_fc_hue_down) {
1251 /* so we don't have to translate to HSV on each request, do it here */
1252 for (j = 0; j < 2; ++j) {
1253 i_rgb_to_hsvf(seg->c+j);
1255 if (seg->color == i_fc_hue_up) {
1256 if (seg->c[1].channel[0] <= seg->c[0].channel[0])
1257 seg->c[1].channel[0] += 1.0;
1260 if (seg->c[0].channel[0] <= seg->c[0].channel[1])
1261 seg->c[0].channel[0] += 1.0;
1264 /*printf("start %g mid %g end %g c0(%g,%g,%g,%g) c1(%g,%g,%g,%g) type %d color %d\n",
1265 seg->start, seg->middle, seg->end, seg->c[0].channel[0],
1266 seg->c[0].channel[1], seg->c[0].channel[2], seg->c[0].channel[3],
1267 seg->c[1].channel[0], seg->c[1].channel[1], seg->c[1].channel[2],
1268 seg->c[1].channel[3], seg->type, seg->color);*/
1272 /* initialize each engine */
1273 /* these are so common ... */
1274 state->lA = xb - xa;
1275 state->lB = yb - ya;
1276 state->AB = sqrt(state->lA * state->lA + state->lB * state->lB);
1281 type = i_ft_linear; /* make the invalid value valid */
1284 state->lC = ya * ya - ya * yb + xa * xa - xa * xb;
1286 state->mult = 1/linear_fount_f(xb, yb, state);
1290 state->mult = 1.0 / sqrt((double)(xb-xa)*(xb-xa)
1291 + (double)(yb-ya)*(yb-ya));
1294 case i_ft_radial_square:
1295 state->cos = state->lA / state->AB;
1296 state->sin = state->lB / state->AB;
1297 state->mult = 1.0 / state->AB;
1300 case i_ft_revolution:
1301 state->theta = atan2(yb-ya, xb-xa);
1302 state->mult = 1.0 / (PI * 2);
1306 state->theta = atan2(yb-ya, xb-xa);
1307 state->mult = 1.0 / PI;
1310 state->ffunc = fount_funcs[type];
1311 if (super_sample < 0
1312 || super_sample >= (sizeof(fount_ssamples)/sizeof(*fount_ssamples))) {
1315 state->ssample_data = NULL;
1316 switch (super_sample) {
1318 ssample_param = floor(0.5 + sqrt(ssample_param));
1319 state->ssample_data = mymalloc(sizeof(i_fcolor) * ssample_param * ssample_param);
1324 ssample_param = floor(0.5+ssample_param);
1325 state->ssample_data = mymalloc(sizeof(i_fcolor) * ssample_param);
1328 state->parm = ssample_param;
1329 state->ssfunc = fount_ssamples[super_sample];
1330 if (repeat < 0 || repeat >= (sizeof(fount_repeats)/sizeof(*fount_repeats)))
1332 state->rpfunc = fount_repeats[repeat];
1333 state->segs = my_segs;
1334 state->count = count;
1338 fount_finish_state(struct fount_state *state) {
1339 if (state->ssample_data)
1340 myfree(state->ssample_data);
1341 myfree(state->segs);
1346 =item fount_getat(out, x, y, ffunc, rpfunc, state, segs, count)
1348 Evaluates the fountain fill at the given point.
1350 This is called by both the non-super-sampling and super-sampling code.
1352 You might think that it would make sense to sample the fill parameter
1353 instead, and combine those, but this breaks badly.
1359 fount_getat(i_fcolor *out, double x, double y, struct fount_state *state) {
1360 double v = (state->rpfunc)((state->ffunc)(x, y, state));
1364 while (i < state->count
1365 && (v < state->segs[i].start || v > state->segs[i].end)) {
1368 if (i < state->count) {
1369 v = (fount_interps[state->segs[i].type])(v, state->segs+i);
1370 (fount_cinterps[state->segs[i].color])(out, v, state->segs+i);
1378 =item linear_fount_f(x, y, state)
1380 Calculate the fill parameter for a linear fountain fill.
1382 Uses the point to line distance function, with some precalculation
1383 done in i_fountain().
1388 linear_fount_f(double x, double y, struct fount_state *state) {
1389 return (state->lA * x + state->lB * y + state->lC) / state->AB * state->mult;
1393 =item bilinear_fount_f(x, y, state)
1395 Calculate the fill parameter for a bi-linear fountain fill.
1400 bilinear_fount_f(double x, double y, struct fount_state *state) {
1401 return fabs((state->lA * x + state->lB * y + state->lC) / state->AB * state->mult);
1405 =item radial_fount_f(x, y, state)
1407 Calculate the fill parameter for a radial fountain fill.
1409 Simply uses the distance function.
1414 radial_fount_f(double x, double y, struct fount_state *state) {
1415 return sqrt((double)(state->xa-x)*(state->xa-x)
1416 + (double)(state->ya-y)*(state->ya-y)) * state->mult;
1420 =item square_fount_f(x, y, state)
1422 Calculate the fill parameter for a square fountain fill.
1424 Works by rotating the reference co-ordinate around the centre of the
1430 square_fount_f(double x, double y, struct fount_state *state) {
1431 int xc, yc; /* centred on A */
1432 double xt, yt; /* rotated by theta */
1435 xt = fabs(xc * state->cos + yc * state->sin);
1436 yt = fabs(-xc * state->sin + yc * state->cos);
1437 return (xt > yt ? xt : yt) * state->mult;
1441 =item revolution_fount_f(x, y, state)
1443 Calculates the fill parameter for the revolution fountain fill.
1448 revolution_fount_f(double x, double y, struct fount_state *state) {
1449 double angle = atan2(y - state->ya, x - state->xa);
1451 angle -= state->theta;
1453 angle = fmod(angle+ PI * 4, PI*2);
1456 return angle * state->mult;
1460 =item conical_fount_f(x, y, state)
1462 Calculates the fill parameter for the conical fountain fill.
1467 conical_fount_f(double x, double y, struct fount_state *state) {
1468 double angle = atan2(y - state->ya, x - state->xa);
1470 angle -= state->theta;
1473 else if (angle > PI)
1476 return fabs(angle) * state->mult;
1480 =item linear_interp(pos, seg)
1482 Calculates linear interpolation on the fill parameter. Breaks the
1483 segment into 2 regions based in the I<middle> value.
1488 linear_interp(double pos, i_fountain_seg *seg) {
1489 if (pos < seg->middle) {
1490 double len = seg->middle - seg->start;
1494 return (pos - seg->start) / len / 2;
1497 double len = seg->end - seg->middle;
1501 return 0.5 + (pos - seg->middle) / len / 2;
1506 =item sine_interp(pos, seg)
1508 Calculates sine function interpolation on the fill parameter.
1513 sine_interp(double pos, i_fountain_seg *seg) {
1514 /* I wonder if there's a simple way to smooth the transition for this */
1515 double work = linear_interp(pos, seg);
1517 return (1-cos(work * PI))/2;
1521 =item sphereup_interp(pos, seg)
1523 Calculates spherical interpolation on the fill parameter, with the cusp
1529 sphereup_interp(double pos, i_fountain_seg *seg) {
1530 double work = linear_interp(pos, seg);
1532 return sqrt(1.0 - (1-work) * (1-work));
1536 =item spheredown_interp(pos, seg)
1538 Calculates spherical interpolation on the fill parameter, with the cusp
1544 spheredown_interp(double pos, i_fountain_seg *seg) {
1545 double work = linear_interp(pos, seg);
1547 return 1-sqrt(1.0 - work * work);
1551 =item direct_cinterp(out, pos, seg)
1553 Calculates the fountain color based on direct scaling of the channels
1554 of the color channels.
1559 direct_cinterp(i_fcolor *out, double pos, i_fountain_seg *seg) {
1561 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1562 out->channel[ch] = seg->c[0].channel[ch] * (1 - pos)
1563 + seg->c[1].channel[ch] * pos;
1568 =item hue_up_cinterp(put, pos, seg)
1570 Calculates the fountain color based on scaling a HSV value. The hue
1571 increases as the fill parameter increases.
1576 hue_up_cinterp(i_fcolor *out, double pos, i_fountain_seg *seg) {
1578 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1579 out->channel[ch] = seg->c[0].channel[ch] * (1 - pos)
1580 + seg->c[1].channel[ch] * pos;
1586 =item hue_down_cinterp(put, pos, seg)
1588 Calculates the fountain color based on scaling a HSV value. The hue
1589 decreases as the fill parameter increases.
1594 hue_down_cinterp(i_fcolor *out, double pos, i_fountain_seg *seg) {
1596 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1597 out->channel[ch] = seg->c[0].channel[ch] * (1 - pos)
1598 + seg->c[1].channel[ch] * pos;
1604 =item simple_ssample(out, parm, x, y, state, ffunc, rpfunc, segs, count)
1606 Simple grid-based super-sampling.
1611 simple_ssample(i_fcolor *out, double x, double y, struct fount_state *state) {
1612 i_fcolor *work = state->ssample_data;
1614 int grid = state->parm;
1615 double base = -0.5 + 0.5 / grid;
1616 double step = 1.0 / grid;
1620 for (dx = 0; dx < grid; ++dx) {
1621 for (dy = 0; dy < grid; ++dy) {
1622 if (fount_getat(work+samp_count, x + base + step * dx,
1623 y + base + step * dy, state)) {
1628 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1629 out->channel[ch] = 0;
1630 for (i = 0; i < samp_count; ++i) {
1631 out->channel[ch] += work[i].channel[ch];
1633 /* we divide by 4 rather than samp_count since if there's only one valid
1634 sample it should be mostly transparent */
1635 out->channel[ch] /= grid * grid;
1641 =item random_ssample(out, parm, x, y, state, ffunc, rpfunc, segs, count)
1643 Random super-sampling.
1648 random_ssample(i_fcolor *out, double x, double y,
1649 struct fount_state *state) {
1650 i_fcolor *work = state->ssample_data;
1652 int maxsamples = state->parm;
1653 double rand_scale = 1.0 / RAND_MAX;
1655 for (i = 0; i < maxsamples; ++i) {
1656 if (fount_getat(work+samp_count, x - 0.5 + rand() * rand_scale,
1657 y - 0.5 + rand() * rand_scale, state)) {
1661 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1662 out->channel[ch] = 0;
1663 for (i = 0; i < samp_count; ++i) {
1664 out->channel[ch] += work[i].channel[ch];
1666 /* we divide by maxsamples rather than samp_count since if there's
1667 only one valid sample it should be mostly transparent */
1668 out->channel[ch] /= maxsamples;
1674 =item circle_ssample(out, parm, x, y, state, ffunc, rpfunc, segs, count)
1676 Super-sampling around the circumference of a circle.
1678 I considered saving the sin()/cos() values and transforming step-size
1679 around the circle, but that's inaccurate, though it may not matter
1685 circle_ssample(i_fcolor *out, double x, double y,
1686 struct fount_state *state) {
1687 i_fcolor *work = state->ssample_data;
1689 int maxsamples = state->parm;
1690 double angle = 2 * PI / maxsamples;
1691 double radius = 0.3; /* semi-random */
1693 for (i = 0; i < maxsamples; ++i) {
1694 if (fount_getat(work+samp_count, x + radius * cos(angle * i),
1695 y + radius * sin(angle * i), state)) {
1699 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1700 out->channel[ch] = 0;
1701 for (i = 0; i < samp_count; ++i) {
1702 out->channel[ch] += work[i].channel[ch];
1704 /* we divide by maxsamples rather than samp_count since if there's
1705 only one valid sample it should be mostly transparent */
1706 out->channel[ch] /= maxsamples;
1712 =item fount_r_none(v)
1714 Implements no repeats. Simply clamps the fill value.
1719 fount_r_none(double v) {
1720 return v < 0 ? 0 : v > 1 ? 1 : v;
1724 =item fount_r_sawtooth(v)
1726 Implements sawtooth repeats. Clamps negative values and uses fmod()
1732 fount_r_sawtooth(double v) {
1733 return v < 0 ? 0 : fmod(v, 1.0);
1737 =item fount_r_triangle(v)
1739 Implements triangle repeats. Clamps negative values, uses fmod to get
1740 a range 0 through 2 and then adjusts values > 1.
1745 fount_r_triangle(double v) {
1750 return v > 1.0 ? 2.0 - v : v;
1755 =item fount_r_saw_both(v)
1757 Implements sawtooth repeats in the both postive and negative directions.
1759 Adjusts the value to be postive and then just uses fmod().
1764 fount_r_saw_both(double v) {
1767 return fmod(v, 1.0);
1771 =item fount_r_tri_both(v)
1773 Implements triangle repeats in the both postive and negative directions.
1775 Uses fmod on the absolute value, and then adjusts values > 1.
1780 fount_r_tri_both(double v) {
1781 v = fmod(fabs(v), 2.0);
1782 return v > 1.0 ? 2.0 - v : v;
1786 =item fill_fountf(fill, x, y, width, channels, data)
1788 The fill function for fountain fills.
1793 fill_fountf(i_fill_t *fill, int x, int y, int width, int channels,
1795 i_fill_fountain_t *f = (i_fill_fountain_t *)fill;
1802 if (f->state.ssfunc)
1803 got_one = f->state.ssfunc(&c, x, y, &f->state);
1805 got_one = fount_getat(&c, x, y, &f->state);
1808 if (f->base.combines) {
1809 for (ch = 0; ch < channels; ++ch) {
1810 data->channel[ch] = data->channel[ch] * (1.0 - c.channel[3])
1811 + c.channel[ch] * c.channel[3];
1824 =item fount_fill_destroy(fill)
1829 fount_fill_destroy(i_fill_t *fill) {
1830 i_fill_fountain_t *f = (i_fill_fountain_t *)fill;
1831 fount_finish_state(&f->state);
1839 Arnar M. Hrafnkelsson <addi@umich.edu>
1841 Tony Cook <tony@develop-help.com> (i_fountain())