#include "imager.h" #include "imageri.h" /* =item i_copyto(C, C, C, C, C, C, C, C) =category Image Copies image data from the area (C,C)-[C,C] in the source image to a rectangle the same size with it's top-left corner at (C,C) in the destination image. If C > C or C > C then the corresponding co-ordinates are swapped. =cut */ void i_copyto(i_img *im, i_img *src, i_img_dim x1, i_img_dim y1, i_img_dim x2, i_img_dim y2, i_img_dim tx, i_img_dim ty) { i_img_dim y, t, tty; if (x2= src->xsize || y1 >= src->ysize) return; /* nothing to do */ if (x2 > src->xsize) x2 = src->xsize; if (y2 > src->ysize) y2 = src->ysize; if (x1 == x2 || y1 == y2) return; /* nothing to do */ mm_log((1,"i_copyto(im* %p, src %p, p1(" i_DFp "), p2(" i_DFp "), t(" i_DFp "))\n", im, src, i_DFcp(x1, y1), i_DFcp(x2, y2), i_DFcp(tx, ty))); #code im->bits == i_8_bits IM_COLOR *row = mymalloc(sizeof(IM_COLOR) * (x2-x1)); tty = ty; for(y=y1; ychannels != im->channels) IM_ADAPT_COLORS(im->channels, src->channels, row, x2-x1); IM_PLIN(im, tx, tx+x2-x1, tty, row); tty++; } myfree(row); #/code } #code void #ifdef IM_EIGHT_BIT i_adapt_colors #else i_adapt_fcolors #endif (int out_channels, int in_channels, IM_COLOR *colors, size_t count) { if (out_channels == in_channels) return; if (count == 0) return; switch (out_channels) { case 1: { switch (in_channels) { case 2: /* apply alpha against a black background */ while (count) { colors->channel[0] = colors->channel[0] * colors->channel[1] / IM_SAMPLE_MAX; ++colors; --count; } return; case 3: /* convert to grey */ while (count) { colors->channel[0] = IM_ROUND(color_to_grey(colors)); ++colors; --count; } return; case 4: while (count) { colors->channel[0] = IM_ROUND(color_to_grey(colors) * colors->channel[3] / IM_SAMPLE_MAX); ++colors; --count; } return; default: i_fatal(3, "i_adapt_colors: in_channels of %d invalid\n", in_channels); return; /* avoid warnings */ } } case 2: { switch (in_channels) { case 1: while (count) { colors->channel[1] = IM_SAMPLE_MAX; ++colors; --count; } return; case 3: while (count) { colors->channel[0] = IM_ROUND(color_to_grey(colors)); colors->channel[1] = IM_SAMPLE_MAX; ++colors; --count; } return; case 4: while (count) { colors->channel[0] = IM_ROUND(color_to_grey(colors)); colors->channel[1] = colors->channel[3]; ++colors; --count; } return; default: i_fatal(3, "i_adapt_colors: in_channels of %d invalid\n", in_channels); return; /* avoid warnings */ } } case 3: { switch (in_channels) { case 1: while (count) { colors->channel[1] = colors->channel[2] = colors->channel[0]; ++colors; --count; } return; case 2: while (count) { int alpha = colors->channel[1]; colors->channel[0] = colors->channel[1] = colors->channel[2] = IM_ROUND(colors->channel[0] * alpha / IM_SAMPLE_MAX); ++colors; --count; } return; case 4: while (count) { int alpha = colors->channel[3]; colors->channel[0] = IM_ROUND(colors->channel[0] * alpha / IM_SAMPLE_MAX); colors->channel[1] = IM_ROUND(colors->channel[1] * alpha / IM_SAMPLE_MAX); colors->channel[2] = IM_ROUND(colors->channel[2] * alpha / IM_SAMPLE_MAX); ++colors; --count; } return; default: i_fatal(3, "i_adapt_colors: in_channels of %d invalid\n", in_channels); return; /* avoid warnings */ } } case 4: { switch (in_channels) { case 1: while (count) { colors->channel[1] = colors->channel[2] = colors->channel[0]; colors->channel[3] = IM_SAMPLE_MAX; ++colors; --count; } return; case 2: while (count) { colors->channel[3] = colors->channel[1]; colors->channel[1] = colors->channel[2] = colors->channel[0]; ++colors; --count; } return; case 3: while (count) { colors->channel[3] = IM_SAMPLE_MAX; ++colors; --count; } return; default: i_fatal(3, "i_adapt_colors: in_channels of %d invalid\n", in_channels); return; /* avoid warnings */ } } default: i_fatal(3, "i_adapt_colors: out_channels of %d invalid\n", out_channels); return; /* avoid warnings */ } } void #ifdef IM_EIGHT_BIT i_adapt_colors_bg #else i_adapt_fcolors_bg #endif (int out_channels, int in_channels, IM_COLOR *colors, size_t count, IM_COLOR const *bg) { if (out_channels == in_channels) return; if (count == 0) return; switch (out_channels) { case 2: case 4: IM_ADAPT_COLORS(out_channels, in_channels, colors, count); return; case 1: switch (in_channels) { case 3: IM_ADAPT_COLORS(out_channels, in_channels, colors, count); return; case 2: { /* apply alpha against our given background */ IM_WORK_T grey_bg = IM_ROUND(color_to_grey(bg)); while (count) { colors->channel[0] = (colors->channel[0] * colors->channel[1] + grey_bg * (IM_SAMPLE_MAX - colors->channel[1])) / IM_SAMPLE_MAX; ++colors; --count; } } break; case 4: { IM_WORK_T grey_bg = IM_ROUND(color_to_grey(bg)); while (count) { IM_WORK_T src_grey = IM_ROUND(color_to_grey(colors)); colors->channel[0] = (src_grey * colors->channel[3] + grey_bg * (IM_SAMPLE_MAX - colors->channel[3])) / IM_SAMPLE_MAX; ++colors; --count; } } break; } break; case 3: switch (in_channels) { case 1: IM_ADAPT_COLORS(out_channels, in_channels, colors, count); return; case 2: { while (count) { int ch; IM_WORK_T src_grey = colors->channel[0]; IM_WORK_T src_alpha = colors->channel[1]; for (ch = 0; ch < 3; ++ch) { colors->channel[ch] = (src_grey * src_alpha + bg->channel[ch] * (IM_SAMPLE_MAX - src_alpha)) / IM_SAMPLE_MAX; } ++colors; --count; } } break; case 4: { while (count) { int ch; IM_WORK_T src_alpha = colors->channel[3]; for (ch = 0; ch < 3; ++ch) { colors->channel[ch] = (colors->channel[ch] * src_alpha + bg->channel[ch] * (IM_SAMPLE_MAX - src_alpha)) / IM_SAMPLE_MAX; } ++colors; --count; } } break; } break; } } /* =item i_gsamp_bg(im, l, r, y, samples, out_channels, background) =category Drawing Like C but applies the source image color over a supplied background color. This is intended for output to image formats that don't support alpha channels. =cut =item i_gsampf_bg(im, l, r, y, samples, out_channels, background) =category Drawing Like C but applies the source image color over a supplied background color. This is intended for output to image formats that don't support alpha channels. =cut */ int #ifdef IM_EIGHT_BIT i_gsamp_bg #else i_gsampf_bg #endif (i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, IM_SAMPLE_T *samples, int out_channels, IM_COLOR const *bg) { if (out_channels == im->channels) return IM_GSAMP(im, l, r, y, samples, NULL, im->channels); switch (out_channels) { case 1: switch (im->channels) { case 2: { i_img_dim x; IM_SAMPLE_T *inp = samples, *outp = samples; IM_WORK_T grey_bg = IM_ROUND(color_to_grey(bg)); i_img_dim count; count = IM_GSAMP(im, l, r, y, samples, NULL, im->channels); if (!count) return 0; for (x = l; x < r; ++x) { *outp++ = ( inp[0] * inp[1] + grey_bg * (IM_SAMPLE_MAX - inp[1])) / IM_SAMPLE_MAX; inp += 2; } return count; } break; default: i_fatal(0, "i_gsamp_bg() can only remove alpha channels"); break; } break; case 3: switch (im->channels) { case 1: { int channels[3] = { 0, 0, 0 }; return IM_GSAMP(im, l, r, y, samples, channels, out_channels); } case 2: { i_img_dim x; int ch; IM_SAMPLE_T *inp = samples, *outp = samples; i_img_dim count; int channels[4] = { 0, 0, 0, 1 }; count = IM_GSAMP(im, l, r, y, samples, channels, im->channels); if (!count) return 0; for (x = l; x < r; ++x) { IM_WORK_T alpha = inp[3]; for (ch = 0; ch < 3; ++ch) { *outp++ = ( *inp++ * alpha + bg->channel[ch] * (IM_SAMPLE_MAX - alpha)) / IM_SAMPLE_MAX; } ++inp; } return count; } case 4: { i_img_dim x; int ch; IM_SAMPLE_T *inp = samples, *outp = samples; i_img_dim count; count = IM_GSAMP(im, l, r, y, samples, NULL, im->channels); if (!count) return 0; for (x = l; x < r; ++x) { IM_WORK_T alpha = inp[3]; for (ch = 0; ch < 3; ++ch) { *outp++ = ( *inp++ * alpha + bg->channel[ch] * (IM_SAMPLE_MAX - alpha)) / IM_SAMPLE_MAX; } ++inp; } return count; } break; default: i_fatal(0, "i_gsamp_bg() can only remove alpha channels"); break; } break; default: i_fatal(0, "i_gsamp_bg() can only remove alpha channels"); } return 0; } #/code