Blob Blame Raw


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); }