X-Git-Url: http://git.imager.perl.org/imager.git/blobdiff_plain/b33c08f8410d40346ed7e445d45f842409842dda..8ceea84c875883b426fb102cb57a1e43e602b010:/fills.c diff --git a/fills.c b/fills.c index de9f1628..6e929199 100644 --- a/fills.c +++ b/fills.c @@ -1,5 +1,5 @@ -#include "image.h" -#include "imagei.h" +#include "imager.h" +#include "imageri.h" /* =head1 NAME @@ -104,7 +104,7 @@ regmach - use the register machine to generate colors =cut */ -static i_color fcolor_to_color(i_fcolor *c) { +static i_color fcolor_to_color(const i_fcolor *c) { int ch; i_color out; @@ -114,7 +114,7 @@ static i_color fcolor_to_color(i_fcolor *c) { return out; } -static i_fcolor color_to_fcolor(i_color *c) { +static i_fcolor color_to_fcolor(const i_color *c) { int ch; i_fcolor out; @@ -195,6 +195,8 @@ static i_fill_solid_t base_solid_fill_comb = /* =item i_fill_destroy(fill) +=category Fills + Call to destroy any fill object. =cut @@ -210,6 +212,8 @@ i_fill_destroy(i_fill_t *fill) { /* =item i_new_fill_solidf(color, combine) +=category Fills + Create a solid fill based on a float color. If combine is non-zero then alpha values will be combined. @@ -218,9 +222,9 @@ If combine is non-zero then alpha values will be combined. */ i_fill_t * -i_new_fill_solidf(i_fcolor *c, int combine) { +i_new_fill_solidf(const i_fcolor *c, int combine) { int ch; - i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t)); + i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t)); /* checked 14jul05 tonyc */ if (combine) { *fill = base_solid_fill_comb; @@ -239,7 +243,9 @@ i_new_fill_solidf(i_fcolor *c, int combine) { /* =item i_new_fill_solid(color, combine) -Create a solid fill based. +=category Fills + +Create a solid fill based on an 8-bit color. If combine is non-zero then alpha values will be combined. @@ -247,9 +253,9 @@ If combine is non-zero then alpha values will be combined. */ i_fill_t * -i_new_fill_solid(i_color *c, int combine) { +i_new_fill_solid(const i_color *c, int combine) { int ch; - i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t)); + i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t)); /* checked 14jul05 tonyc */ if (combine) { *fill = base_solid_fill_comb; @@ -413,13 +419,15 @@ static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels, i_fcolor *data); static i_fill_t * -i_new_hatch_low(i_color *fg, i_color *bg, i_fcolor *ffg, i_fcolor *fbg, - int combine, int hatch, unsigned char *cust_hatch, +i_new_hatch_low(const i_color *fg, const i_color *bg, const i_fcolor *ffg, const i_fcolor *fbg, + int combine, int hatch, const unsigned char *cust_hatch, int dx, int dy); /* =item i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy) +=category Fills + Creates a new hatched fill with the fg color used for the 1 bits in the hatch and bg for the 0 bits. If combine is non-zero alpha values will be combined. @@ -434,8 +442,8 @@ If cust_hatch is NULL then one of the standard hatches is used. =cut */ i_fill_t * -i_new_fill_hatch(i_color *fg, i_color *bg, int combine, int hatch, - unsigned char *cust_hatch, int dx, int dy) { +i_new_fill_hatch(const i_color *fg, const i_color *bg, int combine, int hatch, + const unsigned char *cust_hatch, int dx, int dy) { return i_new_hatch_low(fg, bg, NULL, NULL, combine, hatch, cust_hatch, dx, dy); } @@ -443,6 +451,8 @@ i_new_fill_hatch(i_color *fg, i_color *bg, int combine, int hatch, /* =item i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy) +=category Fills + Creates a new hatched fill with the fg color used for the 1 bits in the hatch and bg for the 0 bits. If combine is non-zero alpha values will be combined. @@ -457,8 +467,8 @@ If cust_hatch is NULL then one of the standard hatches is used. =cut */ i_fill_t * -i_new_fill_hatchf(i_fcolor *fg, i_fcolor *bg, int combine, int hatch, - unsigned char *cust_hatch, int dx, int dy) { +i_new_fill_hatchf(const i_fcolor *fg, const i_fcolor *bg, int combine, int hatch, + const unsigned char *cust_hatch, int dx, int dy) { return i_new_hatch_low(NULL, NULL, fg, bg, combine, hatch, cust_hatch, dx, dy); } @@ -478,13 +488,19 @@ struct i_fill_image_t { /* =item i_new_fill_image(im, matrix, xoff, yoff, combine) +=category Fills + Create an image based fill. +matrix is an array of 9 doubles representing a transformation matrix. + +xoff and yoff are the offset into the image to start filling from. + =cut */ i_fill_t * -i_new_fill_image(i_img *im, double *matrix, int xoff, int yoff, int combine) { - struct i_fill_image_t *fill = mymalloc(sizeof(*fill)); +i_new_fill_image(i_img *im, const double *matrix, int xoff, int yoff, int combine) { + struct i_fill_image_t *fill = mymalloc(sizeof(*fill)); /* checked 14jul05 tonyc */ fill->base.fill_with_color = fill_image; fill->base.fill_with_fcolor = fill_imagef; @@ -596,18 +612,34 @@ Implements creation of hatch fill objects. */ static i_fill_t * -i_new_hatch_low(i_color *fg, i_color *bg, i_fcolor *ffg, i_fcolor *fbg, - int combine, int hatch, unsigned char *cust_hatch, +i_new_hatch_low(const i_color *fg, const i_color *bg, + const i_fcolor *ffg, const i_fcolor *fbg, + int combine, int hatch, const unsigned char *cust_hatch, int dx, int dy) { - i_fill_hatch_t *fill = mymalloc(sizeof(i_fill_hatch_t)); + i_fill_hatch_t *fill = mymalloc(sizeof(i_fill_hatch_t)); /* checked 14jul05 tonyc */ fill->base.fill_with_color = fill_hatch; fill->base.fill_with_fcolor = fill_hatchf; fill->base.destroy = NULL; - fill->fg = fg ? *fg : fcolor_to_color(ffg); - fill->bg = bg ? *bg : fcolor_to_color(fbg); - fill->ffg = ffg ? *ffg : color_to_fcolor(fg); - fill->fbg = fbg ? *fbg : color_to_fcolor(bg); + /* Some Sun C didn't like the condition expressions that were here. + See https://rt.cpan.org/Ticket/Display.html?id=21944 + */ + if (fg) + fill->fg = *fg; + else + fill->fg = fcolor_to_color(ffg); + if (bg) + fill->bg = *bg; + else + fill->bg = fcolor_to_color(fbg); + if (ffg) + fill->ffg = *ffg; + else + fill->ffg = color_to_fcolor(fg); + if (fbg) + fill->fbg = *fbg; + else + fill->fbg = color_to_fcolor(bg); if (combine) { i_get_combine(combine, &fill->base.combine, &fill->base.combinef); } @@ -644,7 +676,10 @@ static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels, int mask = 128 >> xpos; while (width-- > 0) { - *data++ = (byte & mask) ? f->fg : f->bg; + if (byte & mask) + *data++ = f->fg; + else + *data++ = f->bg; if ((mask >>= 1) == 0) mask = 128; @@ -666,7 +701,10 @@ static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels, int mask = 128 >> xpos; while (width-- > 0) { - *data++ = (byte & mask) ? f->ffg : f->fbg; + if (byte & mask) + *data++ = f->ffg; + else + *data++ = f->fbg; if ((mask >>= 1) == 0) mask = 128; @@ -683,7 +721,7 @@ static i_color interp_i_color(i_color before, i_color after, double pos, pos -= floor(pos); for (ch = 0; ch < channels; ++ch) out.channel[ch] = (1-pos) * before.channel[ch] + pos * after.channel[ch]; - if (out.channel[3]) + if (channels > 3 && out.channel[3]) for (ch = 0; ch < channels; ++ch) if (ch != 3) { int temp = out.channel[ch] * 255 / out.channel[3]; @@ -726,7 +764,7 @@ static void fill_image(i_fill_t *fill, int x, int y, int width, int channels, i_color *data) { struct i_fill_image_t *f = (struct i_fill_image_t *)fill; int i = 0; - i_color c; + i_color *out = data; if (f->has_matrix) { /* the hard way */ @@ -761,7 +799,7 @@ static void fill_image(i_fill_t *fill, int x, int y, int width, int channels, } c2[dy] = interp_i_color(c[dy][0], c[dy][1], rx, f->src->channels); } - *data++ = interp_i_color(c2[0], c2[1], ry, f->src->channels); + *out++ = interp_i_color(c2[0], c2[1], ry, f->src->channels); ++i; } } @@ -784,11 +822,34 @@ static void fill_image(i_fill_t *fill, int x, int y, int width, int channels, } rx -= ix * f->src->xsize; ry -= iy * f->src->ysize; - i_gpix(f->src, rx, ry, data); - ++data; + i_gpix(f->src, rx, ry, out); + ++out; ++i; } } + if (f->src->channels == 3) { + /* just set the alpha */ + for (i = 0; i < width; ++i) { + data->channel[3] = 255; + 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] = 255; + data->channel[1] = data->channel[2] = data->channel[0]; + data++; + } + } } /* @@ -800,7 +861,6 @@ static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels, i_fcolor *data) { struct i_fill_image_t *f = (struct i_fill_image_t *)fill; int i = 0; - i_fcolor c; if (f->has_matrix) { /* the hard way */ @@ -863,6 +923,29 @@ static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels, ++i; } } + 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); @@ -1003,7 +1086,6 @@ static void combine_mult(i_color *out, i_color *in, int channels, int count) { int ch; while (count--) { - i_color c = *in; double mult[MAXCHANNELS]; mult[3] = in->channel[3]; for (ch = 0; ch < (channels); ++ch) { @@ -1032,8 +1114,6 @@ static void combine_multf(i_fcolor *out, i_fcolor *in, int channels, int count) } static void combine_dissolve(i_color *out, i_color *in, int channels, int count) { - int ch; - while (count--) { if (in->channel[3] > rand() * (255.0 / RAND_MAX)) COMBINE(*out, *in, channels); @@ -1043,8 +1123,6 @@ static void combine_dissolve(i_color *out, i_color *in, int channels, int count) } static void combine_dissolvef(i_fcolor *out, i_fcolor *in, int channels, int count) { - int ch; - while (count--) { if (in->channel[3] > rand() * (1.0 / RAND_MAX)) COMBINEF(*out, *in, channels);