Blame filter.matrix.inc.c

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