- if (f->src->channels == 3) {
- /* just set the alpha */
- for (i = 0; i < width; ++i) {
- data->channel[3] = 1.0;
- data++;
- }
- }
- else if (f->src->channels == 2) {
- /* copy the alpha to channel 3, duplicate the grey value */
- for (i = 0; i < width; ++i) {
- data->channel[3] = data->channel[1];
- data->channel[1] = data->channel[2] = data->channel[0];
- data++;
- }
- }
- else if (f->src->channels == 1) {
- /* set the alpha, duplicate grey */
- for (i = 0; i < width; ++i) {
- data->channel[3] = 1.0;
- data->channel[1] = data->channel[2] = data->channel[0];
- data++;
- }
- }
-}
-
-static void combine_replace(i_color *, i_color *, int, int);
-static void combine_replacef(i_fcolor *, i_fcolor *, int, int);
-static void combine_alphablend(i_color *, i_color *, int, int);
-static void combine_alphablendf(i_fcolor *, i_fcolor *, int, int);
-static void combine_mult(i_color *, i_color *, int, int);
-static void combine_multf(i_fcolor *, i_fcolor *, int, int);
-static void combine_dissolve(i_color *, i_color *, int, int);
-static void combine_dissolvef(i_fcolor *, i_fcolor *, int, int);
-static void combine_add(i_color *, i_color *, int, int);
-static void combine_addf(i_fcolor *, i_fcolor *, int, int);
-static void combine_subtract(i_color *, i_color *, int, int);
-static void combine_subtractf(i_fcolor *, i_fcolor *, int, int);
-static void combine_diff(i_color *, i_color *, int, int);
-static void combine_difff(i_fcolor *, i_fcolor *, int, int);
-static void combine_darken(i_color *, i_color *, int, int);
-static void combine_darkenf(i_fcolor *, i_fcolor *, int, int);
-static void combine_lighten(i_color *, i_color *, int, int);
-static void combine_lightenf(i_fcolor *, i_fcolor *, int, int);
-static void combine_hue(i_color *, i_color *, int, int);
-static void combine_huef(i_fcolor *, i_fcolor *, int, int);
-static void combine_sat(i_color *, i_color *, int, int);
-static void combine_satf(i_fcolor *, i_fcolor *, int, int);
-static void combine_value(i_color *, i_color *, int, int);
-static void combine_valuef(i_fcolor *, i_fcolor *, int, int);
-static void combine_color(i_color *, i_color *, int, int);
-static void combine_colorf(i_fcolor *, i_fcolor *, int, int);
-
-static struct i_combines {
- i_fill_combine_f combine;
- i_fill_combinef_f combinef;
-} combines[] =
-{
- { /* replace */
- combine_replace,
- combine_replacef,
- },
- { /* alpha blend */
- combine_alphablend,
- combine_alphablendf,
- },
- {
- /* multiply */
- combine_mult,
- combine_multf,
- },
- {
- /* dissolve */
- combine_dissolve,
- combine_dissolvef,
- },
- {
- /* add */
- combine_add,
- combine_addf,
- },
- {
- /* subtract */
- combine_subtract,
- combine_subtractf,
- },
- {
- /* diff */
- combine_diff,
- combine_difff,
- },
- {
- combine_lighten,
- combine_lightenf,
- },
- {
- combine_darken,
- combine_darkenf,
- },
- {
- combine_hue,
- combine_huef,
- },
- {
- combine_sat,
- combine_satf,
- },
- {
- combine_value,
- combine_valuef,
- },
- {
- combine_color,
- combine_colorf,
- },
-};
-
-/*
-=item i_get_combine(combine, color_func, fcolor_func)
-
-=cut
-*/
-
-void i_get_combine(int combine, i_fill_combine_f *color_func,
- i_fill_combinef_f *fcolor_func) {
- if (combine < 0 || combine > sizeof(combines) / sizeof(*combines))
- combine = 0;
-
- *color_func = combines[combine].combine;
- *fcolor_func = combines[combine].combinef;
-}
-
-static void combine_replace(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- *out++ = *in++;
- }
-}
-
-static void combine_replacef(i_fcolor *out, i_fcolor *in, int channels, int count) {
- while (count--) {
- *out++ = *in++;
- }
-}
-
-static void combine_alphablend(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- COMBINE(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_alphablendf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- while (count--) {
- COMBINEF(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_mult(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- double mult[MAXCHANNELS];
- mult[3] = in->channel[3];
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3)
- mult[ch] = (out->channel[ch] * in->channel[ch]) * (1.0 / 255);
- }
- COMBINEA(*out, mult, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_multf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_fcolor c = *in;
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3)
- c.channel[ch] = out->channel[ch] * in->channel[ch];
- }
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_dissolve(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- if (in->channel[3] > rand() * (255.0 / RAND_MAX))
- COMBINE(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_dissolvef(i_fcolor *out, i_fcolor *in, int channels, int count) {
- while (count--) {
- if (in->channel[3] > rand() * (1.0 / RAND_MAX))
- COMBINEF(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_add(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_color c = *in;
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3) {
- int total = out->channel[ch] + in->channel[ch];
- if (total > 255)
- total = 255;
- c.channel[ch] = total;
- }
- }
- COMBINE(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_addf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_fcolor c = *in;
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3) {
- double total = out->channel[ch] + in->channel[ch];
- if (total > 1.0)
- total = 1.0;
- out->channel[ch] = total;
- }
- }
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_subtract(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_color c = *in;
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3) {
- int total = out->channel[ch] - in->channel[ch];
- if (total < 0)
- total = 0;
- c.channel[ch] = total;
- }
- }
- COMBINE(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_subtractf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_fcolor c = *in;
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3) {
- double total = out->channel[ch] - in->channel[ch];
- if (total < 0)
- total = 0;
- c.channel[ch] = total;
- }
- }
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_diff(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_color c = *in;
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3)
- c.channel[ch] = abs(out->channel[ch] - in->channel[ch]);
- }
- COMBINE(*out, c, channels)
- ++out;
- ++in;
- }
-}
-
-static void combine_difff(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_fcolor c = *in;
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3)
- c.channel[ch] = fabs(out->channel[ch] - in->channel[ch]);
- }
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_darken(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3 && out->channel[ch] < in->channel[ch])
- in->channel[ch] = out->channel[ch];
- }
- COMBINE(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_darkenf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3 && out->channel[ch] < in->channel[ch])
- in->channel[ch] = out->channel[ch];
- }
- COMBINEF(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_lighten(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3 && out->channel[ch] > in->channel[ch])
- in->channel[ch] = out->channel[ch];
- }
- COMBINE(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_lightenf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3 && out->channel[ch] > in->channel[ch])
- in->channel[ch] = out->channel[ch];
- }
- COMBINEF(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_hue(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- i_color c = *out;
- i_rgb_to_hsv(&c);
- i_rgb_to_hsv(in);
- c.channel[0] = in->channel[0];
- i_hsv_to_rgb(&c);
- c.channel[3] = in->channel[3];
- COMBINE(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_huef(i_fcolor *out, i_fcolor *in, int channels, int count) {
- while (count--) {
- i_fcolor c = *out;
- i_rgb_to_hsvf(&c);
- i_rgb_to_hsvf(in);
- c.channel[0] = in->channel[0];
- i_hsv_to_rgbf(&c);
- c.channel[3] = in->channel[3];
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_sat(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- i_color c = *out;
- i_rgb_to_hsv(&c);
- i_rgb_to_hsv(in);
- c.channel[1] = in->channel[1];
- i_hsv_to_rgb(&c);
- c.channel[3] = in->channel[3];
- COMBINE(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_satf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- while (count--) {
- i_fcolor c = *out;
- i_rgb_to_hsvf(&c);
- i_rgb_to_hsvf(in);
- c.channel[1] = in->channel[1];
- i_hsv_to_rgbf(&c);
- c.channel[3] = in->channel[3];
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_value(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- i_color c = *out;
- i_rgb_to_hsv(&c);
- i_rgb_to_hsv(in);
- c.channel[2] = in->channel[2];
- i_hsv_to_rgb(&c);
- c.channel[3] = in->channel[3];
- COMBINE(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_valuef(i_fcolor *out, i_fcolor *in, int channels,
- int count) {
- while (count--) {
- i_fcolor c = *out;
- i_rgb_to_hsvf(&c);
- i_rgb_to_hsvf(in);
- c.channel[2] = in->channel[2];
- i_hsv_to_rgbf(&c);
- c.channel[3] = in->channel[3];
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }