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