-#include "image.h"
+#include "imager.h"
+#include "imageri.h"
#include <stdlib.h>
#include <math.h>
i_contrast(im, 0.8);
i_hardinvert(im);
+ i_unsharp_mask(im, 2.0, 1.0);
// and more
=head1 DESCRIPTION
Some of these functions are internal.
-=over 4
+=over
=cut
*/
+/*
+=item saturate(in)
+
+Clamps the input value between 0 and 255. (internal)
+
+ in - input integer
+
+=cut
+*/
+
+static
+unsigned char
+saturate(int in) {
+ if (in>255) { return 255; }
+ else if (in>0) return in;
+ return 0;
+}
int x, y;
unsigned char ch;
- i_color rcolor;
+ i_color *row, *entry;
- mm_log((1,"i_hardinvert(im %p)\n", im));
+ mm_log((1,"i_hardinvert(im %p)\n", im));
+
+ /* always rooms to allocate a single line of i_color */
+ row = mymalloc(sizeof(i_color) * im->xsize); /* checked 17feb2005 tonyc */
for(y = 0; y < im->ysize; y++) {
+ i_glin(im, 0, im->xsize, y, row);
+ entry = row;
for(x = 0; x < im->xsize; x++) {
- i_gpix(im, x, y, &rcolor);
-
for(ch = 0; ch < im->channels; ch++) {
- rcolor.channel[ch] = 255 - rcolor.channel[ch];
+ entry->channel[ch] = 255 - entry->channel[ch];
}
-
- i_ppix(im, x, y, &rcolor);
+ ++entry;
}
+ i_plin(im, 0, im->xsize, y, row);
}
+ myfree(row);
}
=cut
*/
-#ifdef _MSC_VER
+#ifdef WIN32
/* random() is non-ASCII, even if it is better than rand() */
#define random() rand()
#endif
mm_log((1, "i_bumpmap: channel = %d while bump image only has %d channels\n", channel, bump->channels));
return;
}
-
+
mx = (bump->xsize <= im->xsize) ? bump->xsize : im->xsize;
my = (bump->ysize <= im->ysize) ? bump->ysize : im->ysize;
i_img_empty_ch(&new_im, im->xsize, im->ysize, im->channels);
-
+
aX = (light_x > (mx >> 1)) ? light_x : mx - light_x;
aY = (light_y > (my >> 1)) ? light_y : my - light_y;
+
+typedef struct {
+ float x,y,z;
+} fvec;
+
+
+static
+float
+dotp(fvec *a, fvec *b) {
+ return a->x*b->x+a->y*b->y+a->z*b->z;
+}
+
+static
+void
+normalize(fvec *a) {
+ double d = sqrt(dotp(a,a));
+ a->x /= d;
+ a->y /= d;
+ a->z /= d;
+}
+
+
+/*
+ positive directions:
+
+ x - right,
+ y - down
+ z - out of the plane
+
+ I = Ia + Ip*( cd*Scol(N.L) + cs*(R.V)^n )
+
+ Here, the variables are:
+
+ * Ia - ambient colour
+ * Ip - intensity of the point light source
+ * cd - diffuse coefficient
+ * Scol - surface colour
+ * cs - specular coefficient
+ * n - objects shinyness
+ * N - normal vector
+ * L - lighting vector
+ * R - reflection vector
+ * V - vision vector
+
+ static void fvec_dump(fvec *x) {
+ printf("(%.2f %.2f %.2f)", x->x, x->y, x->z);
+ }
+*/
+
+/* XXX: Should these return a code for success? */
+
+
+
+
+/*
+=item i_bumpmap_complex(im, bump, channel, tx, ty, Lx, Ly, Lz, Ip, cd, cs, n, Ia, Il, Is)
+
+Makes a bumpmap on image im using the bump image as the elevation map.
+
+ im - target image
+ bump - image that contains the elevation info
+ channel - to take the elevation information from
+ tx - shift in x direction of where to start applying bumpmap
+ ty - shift in y direction of where to start applying bumpmap
+ Lx - x position/direction of light
+ Ly - y position/direction of light
+ Lz - z position/direction of light
+ Ip - light intensity
+ cd - diffuse coefficient
+ cs - specular coefficient
+ n - surface shinyness
+ Ia - ambient colour
+ Il - light colour
+ Is - specular colour
+
+if z<0 then the L is taken to be the direction the light is shining in. Otherwise
+the L is taken to be the position of the Light, Relative to the image.
+
+=cut
+*/
+
+
+void
+i_bumpmap_complex(i_img *im,
+ i_img *bump,
+ int channel,
+ int tx,
+ int ty,
+ float Lx,
+ float Ly,
+ float Lz,
+ float cd,
+ float cs,
+ float n,
+ i_color *Ia,
+ i_color *Il,
+ i_color *Is) {
+ i_img new_im;
+
+ int inflight;
+ int x, y, ch;
+ int mx, Mx, my, My;
+
+ float cdc[MAXCHANNELS];
+ float csc[MAXCHANNELS];
+
+ i_color x1_color, y1_color, x2_color, y2_color;
+
+ i_color Scol; /* Surface colour */
+
+ fvec L; /* Light vector */
+ fvec N; /* surface normal */
+ fvec R; /* Reflection vector */
+ fvec V; /* Vision vector */
+
+ 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",
+ im, bump, channel, tx, ty, Lx, Ly, Lz, cd, cs, n, Ia, Il, Is));
+
+ if (channel >= bump->channels) {
+ mm_log((1, "i_bumpmap_complex: channel = %d while bump image only has %d channels\n", channel, bump->channels));
+ return;
+ }
+
+ for(ch=0; ch<im->channels; ch++) {
+ cdc[ch] = (float)Il->channel[ch]*cd/255.f;
+ csc[ch] = (float)Is->channel[ch]*cs/255.f;
+ }
+
+ mx = 1;
+ my = 1;
+ Mx = bump->xsize-1;
+ My = bump->ysize-1;
+
+ V.x = 0;
+ V.y = 0;
+ V.z = 1;
+
+ if (Lz < 0) { /* Light specifies a direction vector, reverse it to get the vector from surface to light */
+ L.x = -Lx;
+ L.y = -Ly;
+ L.z = -Lz;
+ normalize(&L);
+ } else { /* Light is the position of the light source */
+ inflight = 0;
+ L.x = -0.2;
+ L.y = -0.4;
+ L.z = 1;
+ normalize(&L);
+ }
+
+ i_img_empty_ch(&new_im, im->xsize, im->ysize, im->channels);
+
+ for(y = 0; y < im->ysize; y++) {
+ for(x = 0; x < im->xsize; x++) {
+ double dp1, dp2;
+ double dx = 0, dy = 0;
+
+ /* Calculate surface normal */
+ if (mx<x && x<Mx && my<y && y<My) {
+ i_gpix(bump, x + 1, y, &x1_color);
+ i_gpix(bump, x - 1, y, &x2_color);
+ i_gpix(bump, x, y + 1, &y1_color);
+ i_gpix(bump, x, y - 1, &y2_color);
+ dx = x2_color.channel[channel] - x1_color.channel[channel];
+ dy = y2_color.channel[channel] - y1_color.channel[channel];
+ } else {
+ dx = 0;
+ dy = 0;
+ }
+ N.x = -dx * 0.015;
+ N.y = -dy * 0.015;
+ N.z = 1;
+ normalize(&N);
+
+ /* Calculate Light vector if needed */
+ if (Lz>=0) {
+ L.x = Lx - x;
+ L.y = Ly - y;
+ L.z = Lz;
+ normalize(&L);
+ }
+
+ dp1 = dotp(&L,&N);
+ R.x = -L.x + 2*dp1*N.x;
+ R.y = -L.y + 2*dp1*N.y;
+ R.z = -L.z + 2*dp1*N.z;
+
+ dp2 = dotp(&R,&V);
+
+ dp1 = dp1<0 ?0 : dp1;
+ dp2 = pow(dp2<0 ?0 : dp2,n);
+
+ i_gpix(im, x, y, &Scol);
+
+ for(ch = 0; ch < im->channels; ch++)
+ Scol.channel[ch] =
+ saturate( Ia->channel[ch] + cdc[ch]*Scol.channel[ch]*dp1 + csc[ch]*dp2 );
+
+ i_ppix(&new_im, x, y, &Scol);
+ }
+ }
+
+ i_copyto(im, &new_im, 0, 0, (int)im->xsize, (int)im->ysize, 0, 0);
+ i_img_exorcise(&new_im);
+}
+
+
/*
=item i_postlevels(im, levels)
}
}
-/*
-=item saturate(in)
-
-Clamps the input value between 0 and 255. (internal)
-
- in - input integer
-
-=cut
-*/
-
-static
-unsigned char
-saturate(int in) {
- if (in>255) { return 255; }
- else if (in>0) return in;
- return 0;
-}
-
/*
=item i_watermark(im, wmark, tx, ty, pixdiff)
int vx, vy, ch;
i_color val, wval;
- for(vx=0;vx<128;vx++) for(vy=0;vy<110;vy++) {
+ int mx = wmark->xsize;
+ int my = wmark->ysize;
+
+ for(vx=0;vx<mx;vx++) for(vy=0;vy<my;vy++) {
i_gpix(im, tx+vx, ty+vy,&val );
i_gpix(wmark, vx, vy, &wval);
int channels = im->channels;
int xsize = im->xsize;
int ysize = im->ysize;
+ int bytes;
float *fdist;
ICL_info(&ival[p]);
}
- fdist = mymalloc( sizeof(float) * num );
+ /* on the systems I have sizeof(float) == sizeof(int) and thus
+ this would be same size as the arrays xo and yo point at, but this
+ may not be true for other systems
+
+ since the arrays here are caller controlled, I assume that on
+ overflow is a programming error rather than an end-user error, so
+ calling exit() is justified.
+ */
+ bytes = sizeof(float) * num;
+ if (bytes / num != sizeof(float)) {
+ fprintf(stderr, "integer overflow calculating memory allocation");
+ exit(1);
+ }
+ fdist = mymalloc( bytes ); /* checked 14jul05 tonyc */
for(y = 0; y<ysize; y++) for(x = 0; x<xsize; x++) {
float cs = 0;
fdist[p] = xd*xd + yd*yd; /* euclidean distance */
break;
case 2: /* euclidean squared */
- fdist[p] = max(xd*xd, yd*yd); /* manhattan distance */
+ fdist[p] = i_max(xd*xd, yd*yd); /* manhattan distance */
break;
default:
- m_fatal(3,"i_gradgen: Unknown distance measure\n");
+ i_fatal(3,"i_gradgen: Unknown distance measure\n");
}
cs += fdist[p];
}
}
i_ppix(im, x, y, &val);
}
+ myfree(fdist);
}
mindist = xd*xd + yd*yd; /* euclidean distance */
break;
case 2: /* euclidean squared */
- mindist = max(xd*xd, yd*yd); /* manhattan distance */
+ mindist = i_max(xd*xd, yd*yd); /* manhattan distance */
break;
default:
- m_fatal(3,"i_nearest_color: Unknown distance measure\n");
+ i_fatal(3,"i_nearest_color: Unknown distance measure\n");
}
for(p = 1; p<num; p++) {
curdist = xd*xd + yd*yd; /* euclidean distance */
break;
case 2: /* euclidean squared */
- curdist = max(xd*xd, yd*yd); /* manhattan distance */
+ curdist = i_max(xd*xd, yd*yd); /* manhattan distance */
break;
default:
- m_fatal(3,"i_nearest_color: Unknown distance measure\n");
+ i_fatal(3,"i_nearest_color: Unknown distance measure\n");
}
if (curdist < mindist) {
mindist = curdist;
}
}
-void
+/*
+=item i_nearest_color(im, num, xo, yo, oval, dmeasure)
+
+This wasn't document - quoth Addi:
+
+ An arty type of filter
+
+FIXME: check IRC logs for actual text.
+
+Inputs:
+
+=over
+
+=item *
+
+i_img *im - image to render on.
+
+=item *
+
+int num - number of points/colors in xo, yo, oval
+
+=item *
+
+int *xo - array of I<num> x positions
+
+=item *
+
+int *yo - array of I<num> y positions
+
+=item *
+
+i_color *oval - array of I<num> colors
+
+xo, yo, oval correspond to each other, the point xo[i], yo[i] has a
+color something like oval[i], at least closer to that color than other
+points.
+
+=item *
+
+int dmeasure - how we measure the distance from some point P(x,y) to
+any (xo[i], yo[i]).
+
+Valid values are:
+
+=over
+
+=item 0
+
+euclidean distance: sqrt((x2-x1)**2 + (y2-y1)**2)
+
+=item 1
+
+square of euclidean distance: ((x2-x1)**2 + (y2-y1)**2)
+
+=item 2
+
+manhattan distance: max((y2-y1)**2, (x2-x1)**2)
+
+=back
+
+An invalid value causes an error exit (the program is aborted).
+
+=back
+
+=cut
+ */
+
+int
i_nearest_color(i_img *im, int num, int *xo, int *yo, i_color *oval, int dmeasure) {
i_color *ival;
float *tval;
int xsize = im->xsize;
int ysize = im->ysize;
int *cmatch;
+ int ival_bytes, tval_bytes;
+
+ mm_log((1,"i_nearest_color(im %p, num %d, xo %p, yo %p, oval %p, dmeasure %d)\n", im, num, xo, yo, oval, dmeasure));
+
+ i_clear_error();
- 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));
+ if (num <= 0) {
+ i_push_error(0, "no points supplied to nearest_color filter");
+ return 0;
+ }
+
+ if (dmeasure < 0 || dmeasure > i_dmeasure_limit) {
+ i_push_error(0, "distance measure invalid");
+ return 0;
+ }
- tval = mymalloc( sizeof(float)*num*im->channels );
- ival = mymalloc( sizeof(i_color)*num );
- cmatch = mymalloc( sizeof(int)*num );
+ tval_bytes = sizeof(float)*num*im->channels;
+ if (tval_bytes / num != sizeof(float) * im->channels) {
+ i_push_error(0, "integer overflow calculating memory allocation");
+ return 0;
+ }
+ ival_bytes = sizeof(i_color) * num;
+ if (ival_bytes / sizeof(i_color) != num) {
+ i_push_error(0, "integer overflow calculating memory allocation");
+ return 0;
+ }
+ tval = mymalloc( tval_bytes ); /* checked 17feb2005 tonyc */
+ ival = mymalloc( ival_bytes ); /* checked 17feb2005 tonyc */
+ cmatch = mymalloc( sizeof(int)*num ); /* checked 17feb2005 tonyc */
for(p = 0; p<num; p++) {
for(ch = 0; ch<im->channels; ch++) tval[ p * im->channels + ch] = 0;
case 1: /* euclidean squared */
mindist = xd*xd + yd*yd; /* euclidean distance */
break;
- case 2: /* euclidean squared */
- mindist = max(xd*xd, yd*yd); /* manhattan distance */
+ case 2: /* manhatten distance */
+ mindist = i_max(xd*xd, yd*yd); /* manhattan distance */
break;
default:
- m_fatal(3,"i_nearest_color: Unknown distance measure\n");
+ i_fatal(3,"i_nearest_color: Unknown distance measure\n");
}
for(p = 1; p<num; p++) {
curdist = xd*xd + yd*yd; /* euclidean distance */
break;
case 2: /* euclidean squared */
- curdist = max(xd*xd, yd*yd); /* manhattan distance */
+ curdist = i_max(xd*xd, yd*yd); /* manhattan distance */
break;
default:
- m_fatal(3,"i_nearest_color: Unknown distance measure\n");
+ i_fatal(3,"i_nearest_color: Unknown distance measure\n");
}
if (curdist < mindist) {
mindist = curdist;
c1 = 1.0-c2;
for(ch = 0; ch<im->channels; ch++)
- tval[midx*im->channels + ch] = c1*tval[midx*im->channels + ch] + c2 * (float) val.channel[ch];
+ tval[midx*im->channels + ch] =
+ c1*tval[midx*im->channels + ch] + c2 * (float) val.channel[ch];
-
}
- for(p = 0; p<num; p++) for(ch = 0; ch<im->channels; ch++) ival[p].channel[ch] = tval[p*im->channels + ch];
+ for(p = 0; p<num; p++) for(ch = 0; ch<im->channels; ch++)
+ ival[p].channel[ch] = tval[p*im->channels + ch];
i_nearest_color_foo(im, num, xo, yo, ival, dmeasure);
+
+ return 1;
+}
+
+/*
+=item i_unsharp_mask(im, stddev, scale)
+
+Perform an usharp mask, which is defined as subtracting the blurred
+image from double the original.
+
+=cut
+*/
+
+void
+i_unsharp_mask(i_img *im, double stddev, double scale) {
+ i_img *copy;
+ int x, y, ch;
+
+ if (scale < 0)
+ return;
+ /* it really shouldn't ever be more than 1.0, but maybe ... */
+ if (scale > 100)
+ scale = 100;
+
+ copy = i_copy(im);
+ i_gaussian(copy, stddev);
+ if (im->bits == i_8_bits) {
+ i_color *blur = mymalloc(im->xsize * sizeof(i_color)); /* checked 17feb2005 tonyc */
+ i_color *out = mymalloc(im->xsize * sizeof(i_color)); /* checked 17feb2005 tonyc */
+
+ for (y = 0; y < im->ysize; ++y) {
+ i_glin(copy, 0, copy->xsize, y, blur);
+ i_glin(im, 0, im->xsize, y, out);
+ for (x = 0; x < im->xsize; ++x) {
+ for (ch = 0; ch < im->channels; ++ch) {
+ /*int temp = out[x].channel[ch] +
+ scale * (out[x].channel[ch] - blur[x].channel[ch]);*/
+ int temp = out[x].channel[ch] * 2 - blur[x].channel[ch];
+ if (temp < 0)
+ temp = 0;
+ else if (temp > 255)
+ temp = 255;
+ out[x].channel[ch] = temp;
+ }
+ }
+ i_plin(im, 0, im->xsize, y, out);
+ }
+
+ myfree(blur);
+ myfree(out);
+ }
+ else {
+ i_fcolor *blur = mymalloc(im->xsize * sizeof(i_fcolor)); /* checked 17feb2005 tonyc */
+ i_fcolor *out = mymalloc(im->xsize * sizeof(i_fcolor)); /* checked 17feb2005 tonyc */
+
+ for (y = 0; y < im->ysize; ++y) {
+ i_glinf(copy, 0, copy->xsize, y, blur);
+ i_glinf(im, 0, im->xsize, y, out);
+ for (x = 0; x < im->xsize; ++x) {
+ for (ch = 0; ch < im->channels; ++ch) {
+ double temp = out[x].channel[ch] +
+ scale * (out[x].channel[ch] - blur[x].channel[ch]);
+ if (temp < 0)
+ temp = 0;
+ else if (temp > 1.0)
+ temp = 1.0;
+ out[x].channel[ch] = temp;
+ }
+ }
+ i_plinf(im, 0, im->xsize, y, out);
+ }
+
+ myfree(blur);
+ myfree(out);
+ }
+ i_img_destroy(copy);
+}
+
+/*
+=item i_diff_image(im1, im2, mindiff)
+
+Creates a new image that is transparent, except where the pixel in im2
+is different from im1, where it is the pixel from im2.
+
+The samples must differ by at least mindiff to be considered different.
+
+=cut
+*/
+
+i_img *
+i_diff_image(i_img *im1, i_img *im2, int mindiff) {
+ i_img *out;
+ int outchans, diffchans;
+ int xsize, ysize;
+
+ i_clear_error();
+ if (im1->channels != im2->channels) {
+ i_push_error(0, "different number of channels");
+ return NULL;
+ }
+
+ outchans = diffchans = im1->channels;
+ if (outchans == 1 || outchans == 3)
+ ++outchans;
+
+ xsize = i_min(im1->xsize, im2->xsize);
+ ysize = i_min(im1->ysize, im2->ysize);
+
+ out = i_sametype_chans(im1, xsize, ysize, outchans);
+
+ if (im1->bits == i_8_bits && im2->bits == i_8_bits) {
+ i_color *line1 = mymalloc(xsize * sizeof(*line1)); /* checked 17feb2005 tonyc */
+ i_color *line2 = mymalloc(xsize * sizeof(*line1)); /* checked 17feb2005 tonyc */
+ i_color empty;
+ int x, y, ch;
+
+ for (ch = 0; ch < MAXCHANNELS; ++ch)
+ empty.channel[ch] = 0;
+
+ for (y = 0; y < ysize; ++y) {
+ i_glin(im1, 0, xsize, y, line1);
+ i_glin(im2, 0, xsize, y, line2);
+ if (outchans != diffchans) {
+ /* give the output an alpha channel since it doesn't have one */
+ for (x = 0; x < xsize; ++x)
+ line2[x].channel[diffchans] = 255;
+ }
+ for (x = 0; x < xsize; ++x) {
+ int diff = 0;
+ for (ch = 0; ch < diffchans; ++ch) {
+ if (line1[x].channel[ch] != line2[x].channel[ch]
+ && abs(line1[x].channel[ch] - line2[x].channel[ch]) > mindiff) {
+ diff = 1;
+ break;
+ }
+ }
+ if (!diff)
+ line2[x] = empty;
+ }
+ i_plin(out, 0, xsize, y, line2);
+ }
+ myfree(line1);
+ myfree(line2);
+ }
+ else {
+ i_fcolor *line1 = mymalloc(xsize * sizeof(*line1)); /* checked 17feb2005 tonyc */
+ i_fcolor *line2 = mymalloc(xsize * sizeof(*line2)); /* checked 17feb2005 tonyc */
+ i_fcolor empty;
+ int x, y, ch;
+ double dist = mindiff / 255;
+
+ for (ch = 0; ch < MAXCHANNELS; ++ch)
+ empty.channel[ch] = 0;
+
+ for (y = 0; y < ysize; ++y) {
+ i_glinf(im1, 0, xsize, y, line1);
+ i_glinf(im2, 0, xsize, y, line2);
+ if (outchans != diffchans) {
+ /* give the output an alpha channel since it doesn't have one */
+ for (x = 0; x < xsize; ++x)
+ line2[x].channel[diffchans] = 1.0;
+ }
+ for (x = 0; x < xsize; ++x) {
+ int diff = 0;
+ for (ch = 0; ch < diffchans; ++ch) {
+ if (line1[x].channel[ch] != line2[x].channel[ch]
+ && abs(line1[x].channel[ch] - line2[x].channel[ch]) > dist) {
+ diff = 1;
+ break;
+ }
+ }
+ if (!diff)
+ line2[x] = empty;
+ }
+ i_plinf(out, 0, xsize, y, line2);
+ }
+ myfree(line1);
+ myfree(line2);
+ }
+
+ return out;
}
struct fount_state;
*/
-void
+int
i_fountain(i_img *im, double xa, double ya, double xb, double yb,
i_fountain_type type, i_fountain_repeat repeat,
int combine, int super_sample, double ssample_param,
int count, i_fountain_seg *segs) {
struct fount_state state;
int x, y;
- i_fcolor *line = mymalloc(sizeof(i_fcolor) * im->xsize);
+ i_fcolor *line = NULL;
i_fcolor *work = NULL;
- int ch;
+ int line_bytes;
i_fountain_seg *my_segs;
i_fill_combine_f combine_func = NULL;
i_fill_combinef_f combinef_func = NULL;
+ i_clear_error();
+
+ /* i_fountain() allocates floating colors even for 8-bit images,
+ so we need to do this check */
+ line_bytes = sizeof(i_fcolor) * im->xsize;
+ if (line_bytes / sizeof(i_fcolor) != im->xsize) {
+ i_push_error(0, "integer overflow calculating memory allocation");
+ return 0;
+ }
+
+ line = mymalloc(line_bytes); /* checked 17feb2005 tonyc */
+
i_get_combine(combine, &combine_func, &combinef_func);
if (combinef_func)
- work = mymalloc(sizeof(i_fcolor) * im->xsize);
+ work = mymalloc(line_bytes); /* checked 17feb2005 tonyc */
fount_init_state(&state, xa, ya, xb, yb, type, repeat, combine,
super_sample, ssample_param, count, segs);
for (x = 0; x < im->xsize; ++x) {
i_fcolor c;
int got_one;
- double v;
if (super_sample == i_fts_none)
got_one = fount_getat(&c, x, y, &state);
else
i_plinf(im, 0, im->xsize, y, line);
}
fount_finish_state(&state);
+ if (work) myfree(work);
myfree(line);
+
+ return 1;
}
typedef struct {
static void
fill_fountf(i_fill_t *fill, int x, int y, int width, int channels,
- i_fcolor *data, i_fcolor *work);
+ i_fcolor *data);
static void
fount_fill_destroy(i_fill_t *fill);
/*
-=item i_new_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, count, segs)
+=item i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, count, segs)
+
+=category Fills
+=synopsis fill = i_new_fill_fount(0, 0, 100, 100, i_ft_linear, i_ft_linear,
+=synopsis i_fr_triangle, 0, i_fts_grid, 9, 1, segs);
+
Creates a new general fill which fills with a fountain fill.
i_fountain_repeat repeat, int combine, int super_sample,
double ssample_param, int count, i_fountain_seg *segs) {
int i, j;
- i_fountain_seg *my_segs = mymalloc(sizeof(i_fountain_seg) * count);
+ int bytes;
+ i_fountain_seg *my_segs = mymalloc(sizeof(i_fountain_seg) * count); /* checked 2jul06 - duplicating original */
/*int have_alpha = im->channels == 2 || im->channels == 4;*/
- int ch;
memset(state, 0, sizeof(*state));
/* we keep a local copy that we can adjust for speed */
i_fountain_seg *seg = my_segs + i;
*seg = segs[i];
- if (seg->type < 0 || type >= i_ft_end)
- seg->type = i_ft_linear;
+ if (seg->type < 0 || seg->type >= i_fst_end)
+ seg->type = i_fst_linear;
if (seg->color < 0 || seg->color >= i_fc_end)
seg->color = i_fc_direct;
if (seg->color == i_fc_hue_up || seg->color == i_fc_hue_down) {
}
state->ffunc = fount_funcs[type];
if (super_sample < 0
- || super_sample >= (sizeof(fount_ssamples)/sizeof(*fount_ssamples))) {
+ || super_sample >= (int)(sizeof(fount_ssamples)/sizeof(*fount_ssamples))) {
super_sample = 0;
}
state->ssample_data = NULL;
switch (super_sample) {
case i_fts_grid:
ssample_param = floor(0.5 + sqrt(ssample_param));
- state->ssample_data = mymalloc(sizeof(i_fcolor) * ssample_param * ssample_param);
+ bytes = ssample_param * ssample_param * sizeof(i_fcolor);
+ if (bytes / sizeof(i_fcolor) == ssample_param * ssample_param) {
+ state->ssample_data = mymalloc(sizeof(i_fcolor) * ssample_param * ssample_param); /* checked 1jul06 tonyc */
+ }
+ else {
+ super_sample = i_fts_none;
+ }
break;
case i_fts_random:
case i_fts_circle:
ssample_param = floor(0.5+ssample_param);
- state->ssample_data = mymalloc(sizeof(i_fcolor) * ssample_param);
+ bytes = sizeof(i_fcolor) * ssample_param;
+ if (bytes / sizeof(i_fcolor) == ssample_param) {
+ state->ssample_data = mymalloc(sizeof(i_fcolor) * ssample_param);
+ }
+ else {
+ super_sample = i_fts_none;
+ }
break;
}
state->parm = ssample_param;
*/
static void
fill_fountf(i_fill_t *fill, int x, int y, int width, int channels,
- i_fcolor *data, i_fcolor *work) {
+ i_fcolor *data) {
i_fill_fountain_t *f = (i_fill_fountain_t *)fill;
- if (fill->combinef) {
- i_fcolor *wstart = work;
- int count = width;
-
- while (width--) {
- i_fcolor c;
- int got_one;
- double v;
- if (f->state.ssfunc)
- got_one = f->state.ssfunc(&c, x, y, &f->state);
- else
- got_one = fount_getat(&c, x, y, &f->state);
-
- *work++ = c;
-
- ++x;
- }
- (fill->combinef)(data, wstart, channels, count);
- }
- else {
- while (width--) {
- i_fcolor c;
- int got_one;
- double v;
- if (f->state.ssfunc)
- got_one = f->state.ssfunc(&c, x, y, &f->state);
- else
- got_one = fount_getat(&c, x, y, &f->state);
-
- *data++ = c;
-
- ++x;
- }
+ while (width--) {
+ i_fcolor c;
+ int got_one;
+
+ if (f->state.ssfunc)
+ got_one = f->state.ssfunc(&c, x, y, &f->state);
+ else
+ got_one = fount_getat(&c, x, y, &f->state);
+
+ *data++ = c;
+
+ ++x;
}
}