|
|
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 |
|