typedef void (*BlendFunc)(double *dst, double *src, double val);
void bfuncCopy(double *dst, double *src, double val)
{ memcpy(dst, src, 4*sizeof(double)); }
void bfuncMix(double *dst, double *src, double val) {
double iv = 1 - val;
dst[0] = dst[0]*iv + src[0]*val;
dst[1] = dst[1]*iv + src[1]*val;
dst[2] = dst[2]*iv + src[2]*val;
dst[3] = dst[3]*iv + src[3]*val;
}
void bfuncComposite(double *dst, double *src, double val) {
val *= src[3];
double iv = 1 - val;
dst[0] = dst[0]*iv + src[0]*val;
dst[1] = dst[1]*iv + src[1]*val;
dst[2] = dst[2]*iv + src[2]*val;
dst[3] = 1 - (1 - dst[3])*val;
}
void bfuncSum(double *dst, double *src, double val) {
val *= src[3];
dst[0] = dst[0] + src[0]*val;
dst[1] = dst[1] + src[1]*val;
dst[2] = dst[2] + src[2]*val;
}
void bfuncMul(double *dst, double *src, double val) {
val *= src[3];
double iv = 1 - val;
dst[0] = dst[0]*iv + dst[0]*src[0]*val;
dst[1] = dst[1]*iv + dst[1]*src[1]*val;
dst[2] = dst[2]*iv + dst[2]*src[2]*val;
}
void filterBlendEx(Img *img, Img *src, BlendFunc func, double val, int dx, int dy, int sx, int sy, int w, int h) {
if (!img->data || !src->data || !func) return;
if (sx < 0) { dx -= sx; w += sx; sx = 0; }
if (sy < 0) { dy -= sy; h += sy; sy = 0; }
if (dx < 0) { sx -= dx; w += dx; dx = 0; }
if (dy < 0) { sy -= dy; h += dy; dy = 0; }
if (w > img->w - dx) w = img->w - dx;
if (h > img->h - dy) h = img->h - dy;
if (w > src->w - sx) w = src->w - sx;
if (h > src->h - sy) h = src->h - sy;
if (w <= 0 || h <= 0) return;
int dr = 4*(img->w - w);
int sr = 4*(src->w - w);
if (img == src) {
int offset = ((sy - dy)*img->w + sx - dx)*4;
if (offset > 0) {
for(double *pd = imgPixel(img, dx, dy), *e = pd + 4*h*img->w; pd < e; pd += dr)
for(double *re = pd + 4*w; pd < re; pd += 4)
func(pd, pd + offset, val);
} else
if (offset < 0) {
for(double *pd = imgPixel(img, dx+w-1, dy+h-1), *e = pd - 4*h*img->w; pd > e; pd -= dr)
for(double *re = pd - 4*w; pd > re; pd -= 4)
func(pd, pd + offset, val);
} else {
double ps[4];
for(double *pd = imgPixel(img, dx, dy), *e = pd + 4*h*img->w; pd < e; pd += dr)
for(double *re = pd + 4*w; pd < re; pd += 4)
{ memcpy(ps, pd, sizeof(ps)); func(pd, ps, val); }
}
} else {
for(double *pd = imgPixel(img, dx, dy), *ps = imgPixel(src, sx, sy), *e = pd + 4*h*img->w; pd < e; pd += dr, ps += sr)
for(double *re = pd + 4*w; pd < re; pd += 4, ps += 4)
func(pd, ps, val);
}
}
void filterBlend(Img *img, Img *src, BlendFunc func, double val)
{ filterBlendEx(img, src, func, val, 0, 0, 0, 0, src->w, src->h); }
void imgCopyTo(Img *img, Img *src, int dx, int dy, int sx, int sy, int w, int h)
{ filterBlendEx(img, src, bfuncCopy, 1, dx, dy, sx, sy, w, h); }
void imgCropTo(Img *img, Img *src, int x, int y, int w, int h) {
imgInit(img, w, h);
imgCopyTo(img, src, 0, 0, x, y, w, h);
}
void imgCrop(Img *img, int x, int y, int w, int h) {
Img imgC = {};
imgSwap(img, &imgC);
imgCropTo(img, &imgC, x, y, w, h);
imgDestroy(&imgC);
}
void imgCopy(Img *img, Img *src)
{ imgCropTo(img, src, 0, 0, src->w, src->h); }