📄 jas_cm.c
字号:
}
return 0;
}
static void jas_cmshapmatlut_init(jas_cmshapmatlut_t *lut)
{
lut->data = 0;
lut->size = 0;
}
static void jas_cmshapmatlut_cleanup(jas_cmshapmatlut_t *lut)
{
if (lut->data) {
jas_free(lut->data);
lut->data = 0;
}
lut->size = 0;
}
static double gammafn(double x, double gamma)
{
if (x == 0.0)
return 0.0;
return pow(x, gamma);
}
static int jas_cmshapmatlut_set(jas_cmshapmatlut_t *lut, jas_icccurv_t *curv)
{
jas_cmreal_t gamma;
int i;
gamma = 0;
jas_cmshapmatlut_cleanup(lut);
if (curv->numents == 0) {
lut->size = 2;
if (!(lut->data = jas_malloc(lut->size * sizeof(jas_cmreal_t))))
goto error;
lut->data[0] = 0.0;
lut->data[1] = 1.0;
} else if (curv->numents == 1) {
lut->size = 256;
if (!(lut->data = jas_malloc(lut->size * sizeof(jas_cmreal_t))))
goto error;
gamma = curv->ents[0] / 256.0;
for (i = 0; i < lut->size; ++i) {
lut->data[i] = gammafn(i / (double) (lut->size - 1), gamma);
}
} else {
lut->size = curv->numents;
if (!(lut->data = jas_malloc(lut->size * sizeof(jas_cmreal_t))))
goto error;
for (i = 0; i < lut->size; ++i) {
lut->data[i] = curv->ents[i] / 65535.0;
}
}
return 0;
error:
return -1;
}
static jas_cmreal_t jas_cmshapmatlut_lookup(jas_cmshapmatlut_t *lut, jas_cmreal_t x)
{
jas_cmreal_t t;
int lo;
int hi;
t = x * (lut->size - 1);
lo = floor(t);
if (lo < 0)
return lut->data[0];
hi = ceil(t);
if (hi >= lut->size)
return lut->data[lut->size - 1];
return lut->data[lo] + (t - lo) * (lut->data[hi] - lut->data[lo]);
}
static int jas_cmshapmatlut_invert(jas_cmshapmatlut_t *invlut,
jas_cmshapmatlut_t *lut, int n)
{
int i;
int j;
int k;
jas_cmreal_t ax;
jas_cmreal_t ay;
jas_cmreal_t bx;
jas_cmreal_t by;
jas_cmreal_t sx;
jas_cmreal_t sy;
assert(n >= 2);
if (invlut->data) {
jas_free(invlut->data);
invlut->data = 0;
}
/* The sample values should be nondecreasing. */
for (i = 1; i < lut->size; ++i) {
if (lut->data[i - 1] > lut->data[i]) {
assert(0);
return -1;
}
}
if (!(invlut->data = jas_malloc(n * sizeof(jas_cmreal_t))))
return -1;
invlut->size = n;
for (i = 0; i < invlut->size; ++i) {
sy = ((double) i) / (invlut->size - 1);
sx = 1.0;
for (j = 0; j < lut->size; ++j) {
ay = lut->data[j];
if (sy == ay) {
for (k = j + 1; k < lut->size; ++k) {
by = lut->data[k];
if (by != sy)
break;
#if 0
assert(0);
#endif
}
if (k < lut->size) {
--k;
ax = ((double) j) / (lut->size - 1);
bx = ((double) k) / (lut->size - 1);
sx = (ax + bx) / 2.0;
}
break;
}
if (j < lut->size - 1) {
by = lut->data[j + 1];
if (sy > ay && sy < by) {
ax = ((double) j) / (lut->size - 1);
bx = ((double) j + 1) / (lut->size - 1);
sx = ax +
(sy - ay) / (by - ay) * (bx - ax);
break;
}
}
}
invlut->data[i] = sx;
}
#if 0
for (i=0;i<lut->size;++i)
jas_eprintf("lut[%d]=%f ", i, lut->data[i]);
for (i=0;i<invlut->size;++i)
jas_eprintf("invlut[%d]=%f ", i, invlut->data[i]);
#endif
return 0;
}
static int jas_cmshapmat_invmat(jas_cmreal_t out[3][4], jas_cmreal_t in[3][4])
{
jas_cmreal_t d;
d = in[0][0] * (in[1][1] * in[2][2] - in[1][2] * in[2][1])
- in[0][1] * (in[1][0] * in[2][2] - in[1][2] * in[2][0])
+ in[0][2] * (in[1][0] * in[2][1] - in[1][1] * in[2][0]);
#if 0
jas_eprintf("delta=%f\n", d);
#endif
if (JAS_ABS(d) < 1e-6)
return -1;
out[0][0] = (in[1][1] * in[2][2] - in[1][2] * in[2][1]) / d;
out[1][0] = -(in[1][0] * in[2][2] - in[1][2] * in[2][0]) / d;
out[2][0] = (in[1][0] * in[2][1] - in[1][1] * in[2][0]) / d;
out[0][1] = -(in[0][1] * in[2][2] - in[0][2] * in[2][1]) / d;
out[1][1] = (in[0][0] * in[2][2] - in[0][2] * in[2][0]) / d;
out[2][1] = -(in[0][0] * in[2][1] - in[0][1] * in[2][0]) / d;
out[0][2] = (in[0][1] * in[1][2] - in[0][2] * in[1][1]) / d;
out[1][2] = -(in[0][0] * in[1][2] - in[1][0] * in[0][2]) / d;
out[2][2] = (in[0][0] * in[1][1] - in[0][1] * in[1][0]) / d;
out[0][3] = -in[0][3];
out[1][3] = -in[1][3];
out[2][3] = -in[2][3];
#if 0
jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n",
in[0][0], in[0][1], in[0][2], in[0][3],
in[1][0], in[1][1], in[1][2], in[1][3],
in[2][0], in[2][1], in[2][2], in[2][3]);
jas_eprintf("[ %f %f %f %f ]\n[ %f %f %f %f ]\n[ %f %f %f %f ]\n",
out[0][0], out[0][1], out[0][2], out[0][3],
out[1][0], out[1][1], out[1][2], out[1][3],
out[2][0], out[2][1], out[2][2], out[2][3]);
#endif
return 0;
}
/******************************************************************************\
*
\******************************************************************************/
static int icctoclrspc(int iccclrspc, int refflag)
{
if (refflag) {
switch (iccclrspc) {
case JAS_ICC_COLORSPC_XYZ:
return JAS_CLRSPC_CIEXYZ;
case JAS_ICC_COLORSPC_LAB:
return JAS_CLRSPC_CIELAB;
default:
abort();
break;
}
} else {
switch (iccclrspc) {
case JAS_ICC_COLORSPC_YCBCR:
return JAS_CLRSPC_GENYCBCR;
case JAS_ICC_COLORSPC_RGB:
return JAS_CLRSPC_GENRGB;
case JAS_ICC_COLORSPC_GRAY:
return JAS_CLRSPC_GENGRAY;
default:
abort();
break;
}
}
}
static int mono(jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxformseq)
{
jas_iccattrval_t *graytrc;
jas_cmshapmat_t *shapmat;
jas_cmpxform_t *pxform;
jas_cmpxformseq_t *pxformseq;
jas_cmshapmatlut_t lut;
jas_cmshapmatlut_init(&lut);
if (!(graytrc = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRYTRC)) ||
graytrc->type != JAS_ICC_TYPE_CURV)
goto error;
if (!(pxform = jas_cmpxform_createshapmat()))
goto error;
shapmat = &pxform->data.shapmat;
if (!(pxformseq = jas_cmpxformseq_create()))
goto error;
if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform))
goto error;
pxform->numinchans = 1;
pxform->numoutchans = 3;
shapmat->mono = 1;
shapmat->useluts = 1;
shapmat->usemat = 1;
if (!op) {
shapmat->order = 0;
shapmat->mat[0][0] = 0.9642;
shapmat->mat[1][0] = 1.0;
shapmat->mat[2][0] = 0.8249;
if (jas_cmshapmatlut_set(&shapmat->luts[0], &graytrc->data.curv))
goto error;
} else {
shapmat->order = 1;
shapmat->mat[0][0] = 1.0 / 0.9642;
shapmat->mat[1][0] = 1.0;
shapmat->mat[2][0] = 1.0 / 0.8249;
jas_cmshapmatlut_init(&lut);
if (jas_cmshapmatlut_set(&lut, &graytrc->data.curv))
goto error;
if (jas_cmshapmatlut_invert(&shapmat->luts[0], &lut, lut.size))
goto error;
jas_cmshapmatlut_cleanup(&lut);
}
jas_iccattrval_destroy(graytrc);
jas_cmpxform_destroy(pxform);
*retpxformseq = pxformseq;
return 0;
error:
return -1;
}
static int triclr(jas_iccprof_t *iccprof, int op, jas_cmpxformseq_t **retpxformseq)
{
int i;
jas_iccattrval_t *trcs[3];
jas_iccattrval_t *cols[3];
jas_cmshapmat_t *shapmat;
jas_cmpxform_t *pxform;
jas_cmpxformseq_t *pxformseq;
jas_cmreal_t mat[3][4];
jas_cmshapmatlut_t lut;
pxform = 0;
pxformseq = 0;
for (i = 0; i < 3; ++i) {
trcs[i] = 0;
cols[i] = 0;
}
jas_cmshapmatlut_init(&lut);
if (!(trcs[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDTRC)) ||
!(trcs[1] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRNTRC)) ||
!(trcs[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUTRC)) ||
!(cols[0] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_REDMATCOL)) ||
!(cols[1] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_GRNMATCOL)) ||
!(cols[2] = jas_iccprof_getattr(iccprof, JAS_ICC_TAG_BLUMATCOL)))
goto error;
for (i = 0; i < 3; ++i) {
if (trcs[i]->type != JAS_ICC_TYPE_CURV ||
cols[i]->type != JAS_ICC_TYPE_XYZ)
goto error;
}
if (!(pxform = jas_cmpxform_createshapmat()))
goto error;
pxform->numinchans = 3;
pxform->numoutchans = 3;
shapmat = &pxform->data.shapmat;
if (!(pxformseq = jas_cmpxformseq_create()))
goto error;
if (jas_cmpxformseq_insertpxform(pxformseq, -1, pxform))
goto error;
shapmat->mono = 0;
shapmat->useluts = 1;
shapmat->usemat = 1;
if (!op) {
shapmat->order = 0;
for (i = 0; i < 3; ++i) {
shapmat->mat[0][i] = cols[i]->data.xyz.x / 65536.0;
shapmat->mat[1][i] = cols[i]->data.xyz.y / 65536.0;
shapmat->mat[2][i] = cols[i]->data.xyz.z / 65536.0;
}
for (i = 0; i < 3; ++i)
shapmat->mat[i][3] = 0.0;
for (i = 0; i < 3; ++i) {
if (jas_cmshapmatlut_set(&shapmat->luts[i], &trcs[i]->data.curv))
goto error;
}
} else {
shapmat->order = 1;
for (i = 0; i < 3; ++i) {
mat[0][i] = cols[i]->data.xyz.x / 65536.0;
mat[1][i] = cols[i]->data.xyz.y / 65536.0;
mat[2][i] = cols[i]->data.xyz.z / 65536.0;
}
for (i = 0; i < 3; ++i)
mat[i][3] = 0.0;
if (jas_cmshapmat_invmat(shapmat->mat, mat))
goto error;
for (i = 0; i < 3; ++i) {
jas_cmshapmatlut_init(&lut);
if (jas_cmshapmatlut_set(&lut, &trcs[i]->data.curv))
goto error;
if (jas_cmshapmatlut_invert(&shapmat->luts[i], &lut, lut.size))
goto error;
jas_cmshapmatlut_cleanup(&lut);
}
}
for (i = 0; i < 3; ++i) {
jas_iccattrval_destroy(trcs[i]);
jas_iccattrval_destroy(cols[i]);
}
jas_cmpxform_destroy(pxform);
*retpxformseq = pxformseq;
return 0;
error:
for (i = 0; i < 3; ++i) {
if (trcs[i]) {
jas_iccattrval_destroy(trcs[i]);
}
if (cols[i]) {
jas_iccattrval_destroy(cols[i]);
}
}
if (pxformseq) {
jas_cmpxformseq_destroy(pxformseq);
}
if (pxform) {
jas_cmpxform_destroy(pxform);
}
return -1;
}
static int jas_cmgetint(long **bufptr, int sgnd, int prec, long *val)
{
long v;
int m;
v = **bufptr;
if (sgnd) {
m = (1 << (prec - 1));
if (v < -m || v >= m)
return -1;
} else {
if (v < 0 || v >= (1 << prec))
return -1;
}
++(*bufptr);
*val = v;
return 0;
}
static int jas_cmputint(long **bufptr, int sgnd, int prec, long val)
{
int m;
if (sgnd) {
m = (1 << (prec - 1));
if (val < -m || val >= m)
return -1;
} else {
if (val < 0 || val >= (1 << prec))
return -1;
}
**bufptr = val;
++(*bufptr);
return 0;
}
int jas_clrspc_numchans(int clrspc)
{
switch (jas_clrspc_fam(clrspc)) {
case JAS_CLRSPC_FAM_XYZ:
case JAS_CLRSPC_FAM_LAB:
case JAS_CLRSPC_FAM_RGB:
case JAS_CLRSPC_FAM_YCBCR:
return 3;
break;
case JAS_CLRSPC_FAM_GRAY:
return 1;
break;
default:
abort();
break;
}
}
jas_iccprof_t *jas_iccprof_createfromcmprof(jas_cmprof_t *prof)
{
return jas_iccprof_copy(prof->iccprof);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -