Blame simple/imgfilters/filter.matrix.inc.c

608c44
608c44
608c44
608c44
typedef struct {
608c44
  double m[5][4];
608c44
} ClMat;
608c44
608c44
typedef void (*ClmInitFunc)(ClMat *m);
608c44
608c44
608c44
void clmZero(ClMat *m) {
608c44
  for(int r = 0; r < 5; ++r)
608c44
    for(int c = 0; c < 4; ++c)
608c44
      m->m[r][c] = 0;
608c44
}
608c44
608c44
608c44
void clmIdentity(ClMat *m) {
608c44
  for(int r = 0; r < 5; ++r)
608c44
    for(int c = 0; c < 4; ++c)
608c44
      m->m[r][c] = r == c;
608c44
}
608c44
608c44
608c44
void clmCopy(ClMat *dst, ClMat *src)
608c44
  { if (dst != src) memcpy(dst, src, sizeof(*dst)); }
608c44
608c44
608c44
void clmMulColor(ClMat *m, double val) {
608c44
  for(int r = 0; r < 5; ++r)
608c44
    for(int c = 0; c < 4; ++c)
608c44
      m->m[r][c] = r == c ? (r < 3 ? val : 1) : 0;
608c44
}
608c44
608c44
608c44
void clmMulPix(double *dst, const ClMat *m, const double *pix) {
608c44
  if (dst == pix) {
608c44
    double p[4];
608c44
    memcpy(p, pix, sizeof(p));
608c44
    clmMulPix(dst, m, p);
608c44
    return;
608c44
  }
608c44
608c44
  dst[0] = m->m[0][0]*pix[0] + m->m[1][0]*pix[1] + m->m[2][0]*pix[2] + m->m[3][0]*pix[3] + m->m[4][0];
608c44
  dst[1] = m->m[0][1]*pix[0] + m->m[1][1]*pix[1] + m->m[2][1]*pix[2] + m->m[3][1]*pix[3] + m->m[4][1];
608c44
  dst[2] = m->m[0][2]*pix[0] + m->m[1][2]*pix[1] + m->m[2][2]*pix[2] + m->m[3][2]*pix[3] + m->m[4][2];
608c44
  dst[3] = m->m[0][3]*pix[0] + m->m[1][3]*pix[1] + m->m[2][3]*pix[2] + m->m[3][3]*pix[3] + m->m[4][3];
608c44
}
608c44
608c44
608c44
void clmMul(ClMat *dst, const ClMat *a, const ClMat *b) {
608c44
  if (dst == a || dst == b) {
608c44
    ClMat m;
608c44
    clmCopy(&m, dst);
608c44
    clmMul(dst, dst == a ? &m : a, dst == b ? &m : b);
608c44
    return;
608c44
  }
608c44
608c44
  clmMulPix(dst->m[0], a, b->m[0]);
608c44
  clmMulPix(dst->m[1], a, b->m[1]);
608c44
  clmMulPix(dst->m[2], a, b->m[2]);
608c44
  clmMulPix(dst->m[3], a, b->m[3]);
608c44
  clmMulPix(dst->m[4], a, b->m[4]);
608c44
}
608c44
608c44
608c44
void clmGray(ClMat *m) {
608c44
  for(int r = 0; r < 5; ++r)
608c44
    for(int c = 0; c < 4; ++c)
608c44
      m->m[r][c] = r < 3 && c < 3 ? 1/3.0 : r == c;
608c44
}
608c44
608c44
608c44
void clmToYUV(ClMat *m) {
608c44
  m->m[0][0] = 0.299; m->m[0][1] = -0.168736; m->m[0][2] =  0.5;      m->m[0][3] = 0;
608c44
  m->m[1][0] = 0.587; m->m[1][1] =  0.331264; m->m[1][2] = -0.418688; m->m[1][3] = 0;
608c44
  m->m[2][0] = 0.114; m->m[2][1] =  0.5;      m->m[2][2] = -0.081312; m->m[2][3] = 0;
608c44
  m->m[3][0] = 0;     m->m[3][1] =  0;        m->m[3][2] =  0;        m->m[3][3] = 1;
608c44
  m->m[4][0] = 0;     m->m[4][1] =  0;        m->m[4][2] =  0;        m->m[4][3] = 0;
608c44
}
608c44
608c44
608c44
void clmFromYUV(ClMat *m) {
608c44
  m->m[0][0] = 1;     m->m[0][1] =  1;        m->m[0][2] = 1;     m->m[0][3] = 0;
608c44
  m->m[1][0] = 0;     m->m[1][1] = -0.344136; m->m[1][2] = 1.772; m->m[1][3] = 0;
608c44
  m->m[2][0] = 0.402; m->m[2][1] = -0.714136; m->m[2][2] = 0;     m->m[2][3] = 0;
608c44
  m->m[3][0] = 0;     m->m[3][1] =  0;        m->m[3][2] = 0;     m->m[3][3] = 1;
608c44
  m->m[4][0] = 0;     m->m[4][1] =  0;        m->m[4][2] = 0;     m->m[4][3] = 0;
608c44
}
608c44
608c44
608c44
void clmScreenToCompositeYUV(ClMat *m) {
608c44
  // to YUV
608c44
  clmToYUV(m);
608c44
  // Alpha = Y-Luminance, Y-Luminance = 1
608c44
  m->m[0][3] = m->m[0][0];
608c44
  m->m[1][3] = m->m[1][0];
608c44
  m->m[2][3] = m->m[2][0];
608c44
  m->m[3][3] = m->m[3][0];
608c44
  m->m[0][0] = 0;
608c44
  m->m[1][0] = 0;
608c44
  m->m[2][0] = 0;
608c44
  m->m[4][0] = 1;
608c44
  // YUV -> RGB
608c44
  ClMat mm;
608c44
  clmFromYUV(&mm);
608c44
  clmMul(m, &mm, m);
608c44
}
608c44
608c44
608c44
608c44
608c44
void filterMatrix(Img *img, const ClMat *m) {
608c44
  if (!img->data) return;
608c44
  for(double *p = img->data, *e = p + 4*img->w*img->h; p < e; p += 4)
608c44
    clmMulPix(p, m, p);
608c44
}
608c44
608c44