jas_cm.c
来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· C语言 代码 · 共 1,374 行 · 第 1/3 页
C
1,374 行
{
jas_cmxform_t *xform;
jas_cmpxformseq_t *inpxformseq;
jas_cmpxformseq_t *outpxformseq;
jas_cmpxformseq_t *altoutpxformseq;
jas_cmpxformseq_t *prfpxformseq;
int prfintent;
/* Avoid compiler warnings about unused parameters. */
optimize = 0;
prfintent = intent;
if (!(xform = jas_malloc(sizeof(jas_cmxform_t))))
goto error;
if (!(xform->pxformseq = jas_cmpxformseq_create()))
goto error;
switch (op) {
case JAS_CMXFORM_OP_FWD:
inpxformseq = fwdpxformseq(inprof, intent);
outpxformseq = revpxformseq(outprof, intent);
if (!inpxformseq || !outpxformseq)
goto error;
if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) ||
jas_cmpxformseq_appendcnvt(xform->pxformseq,
inprof->refclrspc, outprof->refclrspc) ||
jas_cmpxformseq_append(xform->pxformseq, outpxformseq))
goto error;
xform->numinchans = jas_clrspc_numchans(inprof->clrspc);
xform->numoutchans = jas_clrspc_numchans(outprof->clrspc);
if( xform->numinchans == 0 || xform->numoutchans == 0 )
goto error;
break;
case JAS_CMXFORM_OP_REV:
outpxformseq = fwdpxformseq(outprof, intent);
inpxformseq = revpxformseq(inprof, intent);
if (!outpxformseq || !inpxformseq)
goto error;
if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) ||
jas_cmpxformseq_appendcnvt(xform->pxformseq,
outprof->refclrspc, inprof->refclrspc) ||
jas_cmpxformseq_append(xform->pxformseq, inpxformseq))
goto error;
xform->numinchans = jas_clrspc_numchans(outprof->clrspc);
xform->numoutchans = jas_clrspc_numchans(inprof->clrspc);
if( xform->numinchans == 0 || xform->numoutchans == 0 )
goto error;
break;
case JAS_CMXFORM_OP_PROOF:
assert(prfprof);
inpxformseq = fwdpxformseq(inprof, intent);
prfpxformseq = fwdpxformseq(prfprof, prfintent);
if (!inpxformseq || !prfpxformseq)
goto error;
outpxformseq = simpxformseq(outprof, intent);
altoutpxformseq = 0;
if (!outpxformseq) {
outpxformseq = revpxformseq(outprof, intent);
altoutpxformseq = fwdpxformseq(outprof, intent);
if (!outpxformseq || !altoutpxformseq)
goto error;
}
if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) ||
jas_cmpxformseq_appendcnvt(xform->pxformseq,
inprof->refclrspc, outprof->refclrspc))
goto error;
if (altoutpxformseq) {
if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq) ||
jas_cmpxformseq_append(xform->pxformseq, altoutpxformseq))
goto error;
} else {
if (jas_cmpxformseq_append(xform->pxformseq, outpxformseq))
goto error;
}
if (jas_cmpxformseq_appendcnvt(xform->pxformseq,
outprof->refclrspc, inprof->refclrspc) ||
jas_cmpxformseq_append(xform->pxformseq, prfpxformseq))
goto error;
xform->numinchans = jas_clrspc_numchans(inprof->clrspc);
xform->numoutchans = jas_clrspc_numchans(prfprof->clrspc);
if( xform->numinchans == 0 || xform->numoutchans == 0 )
goto error;
break;
case JAS_CMXFORM_OP_GAMUT:
inpxformseq = fwdpxformseq(inprof, intent);
outpxformseq = gampxformseq(outprof);
if (!inpxformseq || !outpxformseq)
goto error;
if (jas_cmpxformseq_append(xform->pxformseq, inpxformseq) ||
jas_cmpxformseq_appendcnvt(xform->pxformseq,
inprof->refclrspc, outprof->refclrspc) ||
jas_cmpxformseq_append(xform->pxformseq, outpxformseq))
goto error;
xform->numinchans = jas_clrspc_numchans(inprof->clrspc);
if( xform->numinchans == 0 )
goto error;
xform->numoutchans = 1;
break;
}
return xform;
error:
return 0;
}
#define APPLYBUFSIZ 2048
int jas_cmxform_apply(jas_cmxform_t *xform, jas_cmpixmap_t *in, jas_cmpixmap_t *out)
{
jas_cmcmptfmt_t *fmt;
jas_cmreal_t buf[2][APPLYBUFSIZ];
jas_cmpxformseq_t *pxformseq;
int i;
int j;
int width;
int height;
int total;
int n;
jas_cmreal_t *inbuf;
jas_cmreal_t *outbuf;
jas_cmpxform_t *pxform;
long *dataptr;
int maxchans;
int bufmax;
int m;
int bias;
jas_cmreal_t scale;
long v;
jas_cmreal_t *bufptr;
if (xform->numinchans > in->numcmpts || xform->numoutchans > out->numcmpts)
goto error;
fmt = &in->cmptfmts[0];
width = fmt->width;
height = fmt->height;
for (i = 1; i < xform->numinchans; ++i) {
fmt = &in->cmptfmts[i];
if (fmt->width != width || fmt->height != height) {
goto error;
}
}
for (i = 0; i < xform->numoutchans; ++i) {
fmt = &out->cmptfmts[i];
if (fmt->width != width || fmt->height != height) {
goto error;
}
}
maxchans = 0;
pxformseq = xform->pxformseq;
for (i = 0; i < pxformseq->numpxforms; ++i) {
pxform = pxformseq->pxforms[i];
if (pxform->numinchans > maxchans) {
maxchans = pxform->numinchans;
}
if (pxform->numoutchans > maxchans) {
maxchans = pxform->numoutchans;
}
}
bufmax = APPLYBUFSIZ / maxchans;
assert(bufmax > 0);
total = width * height;
n = 0;
while (n < total) {
inbuf = &buf[0][0];
m = JAS_MIN(total - n, bufmax);
for (i = 0; i < xform->numinchans; ++i) {
fmt = &in->cmptfmts[i];
scale = (double)((1 << fmt->prec) - 1);
bias = fmt->sgnd ? (1 << (fmt->prec - 1)) : 0;
dataptr = &fmt->buf[n];
bufptr = &inbuf[i];
for (j = 0; j < m; ++j) {
if (jas_cmgetint(&dataptr, fmt->sgnd, fmt->prec, &v))
goto error;
*bufptr = (v - bias) / scale;
bufptr += xform->numinchans;
}
}
inbuf = &buf[0][0];
outbuf = inbuf;
for (i = 0; i < pxformseq->numpxforms; ++i) {
pxform = pxformseq->pxforms[i];
if (pxform->numoutchans > pxform->numinchans) {
outbuf = (inbuf == &buf[0][0]) ? &buf[1][0] : &buf[0][0];
} else {
outbuf = inbuf;
}
if ((*pxform->ops->apply)(pxform, inbuf, outbuf, m))
goto error;
inbuf = outbuf;
}
for (i = 0; i < xform->numoutchans; ++i) {
fmt = &out->cmptfmts[i];
scale = (double)((1 << fmt->prec) - 1);
bias = fmt->sgnd ? (1 << (fmt->prec - 1)) : 0;
bufptr = &outbuf[i];
dataptr = &fmt->buf[n];
for (j = 0; j < m; ++j) {
v = (long)((*bufptr) * scale + bias);
bufptr += xform->numoutchans;
if (jas_cmputint(&dataptr, fmt->sgnd, fmt->prec, v))
goto error;
}
}
n += m;
}
return 0;
error:
return -1;
}
void jas_cmxform_destroy(jas_cmxform_t *xform)
{
if (xform->pxformseq)
jas_cmpxformseq_destroy(xform->pxformseq);
jas_free(xform);
}
/******************************************************************************\
* Primitive transform sequence class.
\******************************************************************************/
static jas_cmpxformseq_t *jas_cmpxformseq_create()
{
jas_cmpxformseq_t *pxformseq;
pxformseq = 0;
if (!(pxformseq = jas_malloc(sizeof(jas_cmpxformseq_t))))
goto error;
pxformseq->pxforms = 0;
pxformseq->numpxforms = 0;
pxformseq->maxpxforms = 0;
if (jas_cmpxformseq_resize(pxformseq, 16))
goto error;
return pxformseq;
error:
if (pxformseq)
jas_cmpxformseq_destroy(pxformseq);
return 0;
}
static jas_cmpxformseq_t *jas_cmpxformseq_copy(jas_cmpxformseq_t *pxformseq)
{
jas_cmpxformseq_t *newpxformseq;
if (!(newpxformseq = jas_cmpxformseq_create()))
goto error;
if (jas_cmpxformseq_append(newpxformseq, pxformseq))
goto error;
return newpxformseq;
error:
return 0;
}
static void jas_cmpxformseq_destroy(jas_cmpxformseq_t *pxformseq)
{
while (pxformseq->numpxforms > 0)
jas_cmpxformseq_delete(pxformseq, pxformseq->numpxforms - 1);
if (pxformseq->pxforms)
jas_free(pxformseq->pxforms);
jas_free(pxformseq);
}
/* Currently called by 1 function with i == pxformseq->numpxforms - 1 */
static int jas_cmpxformseq_delete(jas_cmpxformseq_t *pxformseq, int i)
{
jas_cmpxform_destroy(pxformseq->pxforms[i]);
pxformseq->pxforms[i] = 0;
--pxformseq->numpxforms;
return 0;
}
static int jas_cmpxformseq_appendcnvt(jas_cmpxformseq_t *pxformseq,
int dstclrspc, int srcclrspc)
{
if (dstclrspc == srcclrspc)
return 0;
jas_error( JAS_ERR_UNEQUAL_PARMS_IN_JAS_CMPXFORMSEQ_APPENDCNVT,
"JAS_ERR_UNEQUAL_PARMS_IN_JAS_CMPXFORMSEQ_APPENDCNVT"
);
/* Avoid compiler warnings about unused parameters. */
pxformseq = 0;
return -1;
}
static int jas_cmpxformseq_insertpxform(jas_cmpxformseq_t *pxformseq,
int i, jas_cmpxform_t *pxform)
{
jas_cmpxform_t *tmppxform;
int n;
if (i < 0)
i = pxformseq->numpxforms;
assert(i >= 0 && i <= pxformseq->numpxforms);
if (pxformseq->numpxforms >= pxformseq->maxpxforms) {
if (jas_cmpxformseq_resize(pxformseq, pxformseq->numpxforms +
16))
goto error;
}
assert(pxformseq->numpxforms < pxformseq->maxpxforms);
if (!(tmppxform = jas_cmpxform_copy(pxform)))
goto error;
n = pxformseq->numpxforms - i;
if (n > 0) {
memmove(&pxformseq->pxforms[i + 1], &pxformseq->pxforms[i],
n * sizeof(jas_cmpxform_t *));
}
pxformseq->pxforms[i] = tmppxform;
++pxformseq->numpxforms;
return 0;
error:
return -1;
}
static int jas_cmpxformseq_append(jas_cmpxformseq_t *pxformseq,
jas_cmpxformseq_t *othpxformseq)
{
int n;
int i;
jas_cmpxform_t *pxform;
jas_cmpxform_t *othpxform;
n = pxformseq->numpxforms + othpxformseq->numpxforms;
if (n > pxformseq->maxpxforms) {
if (jas_cmpxformseq_resize(pxformseq, n))
goto error;
}
for (i = 0; i < othpxformseq->numpxforms; ++i) {
othpxform = othpxformseq->pxforms[i];
if (!(pxform = jas_cmpxform_copy(othpxform)))
goto error;
pxformseq->pxforms[pxformseq->numpxforms] = pxform;
++pxformseq->numpxforms;
}
return 0;
error:
return -1;
}
static int jas_cmpxformseq_resize(jas_cmpxformseq_t *pxformseq, int n)
{
jas_cmpxform_t **p;
assert(n >= pxformseq->numpxforms);
p = (!pxformseq->pxforms) ? jas_malloc(n * sizeof(jas_cmpxform_t *)) :
jas_realloc(pxformseq->pxforms, n * sizeof(jas_cmpxform_t *));
if (!p) {
return -1;
}
pxformseq->pxforms = p;
pxformseq->maxpxforms = n;
return 0;
}
/******************************************************************************\
* Primitive transform class.
\******************************************************************************/
static jas_cmpxform_t *jas_cmpxform_create0()
{
jas_cmpxform_t *pxform;
if (!(pxform = jas_malloc(sizeof(jas_cmpxform_t))))
return 0;
memset(pxform, 0, sizeof(jas_cmpxform_t));
pxform->refcnt = 0;
pxform->ops = 0;
return pxform;
}
static void jas_cmpxform_destroy(jas_cmpxform_t *pxform)
{
if (--pxform->refcnt <= 0) {
(*pxform->ops->destroy)(pxform);
jas_free(pxform);
}
}
static jas_cmpxform_t *jas_cmpxform_copy(jas_cmpxform_t *pxform)
{
++pxform->refcnt;
return pxform;
}
/******************************************************************************\
* Shaper matrix class.
\******************************************************************************/
static jas_cmpxform_t *jas_cmpxform_createshapmat()
{
int i;
int j;
jas_cmpxform_t *pxform;
jas_cmshapmat_t *shapmat;
if (!(pxform = jas_cmpxform_create0()))
return 0;
pxform->ops = &shapmat_ops;
shapmat = &pxform->data.shapmat;
shapmat->mono = 0;
shapmat->order = 0;
shapmat->useluts = 0;
shapmat->usemat = 0;
for (i = 0; i < 3; ++i)
jas_cmshapmatlut_init(&shapmat->luts[i]);
for (i = 0; i < 3; ++i) {
for (j = 0; j < 4; ++j)
shapmat->mat[i][j] = 0.0;
}
++pxform->refcnt;
return pxform;
}
static void jas_cmshapmat_destroy(jas_cmpxform_t *pxform)
{
jas_cmshapmat_t *shapmat = &pxform->data.shapmat;
int i;
for (i = 0; i < 3; ++i)
jas_cmshapmatlut_cleanup(&shapmat->luts[i]);
}
static int jas_cmshapmat_apply(jas_cmpxform_t *pxform, jas_cmreal_t *in,
jas_cmreal_t *out, int cnt)
{
jas_cmshapmat_t *shapmat = &pxform->data.shapmat;
jas_cmreal_t *src;
jas_cmreal_t *dst;
jas_cmreal_t a0;
jas_cmreal_t a1;
jas_cmreal_t a2;
jas_cmreal_t b0;
jas_cmreal_t b1;
jas_cmreal_t b2;
src = in;
dst = out;
if (!shapmat->mono) {
while (--cnt >= 0) {
a0 = *src++;
a1 = *src++;
a2 = *src++;
if (!shapmat->order && shapmat->useluts) {
a0 = jas_cmshapmatlut_lookup(&shapmat->luts[0], a0);
a1 = jas_cmshapmatlut_lookup(&shapmat->luts[1], a1);
a2 = jas_cmshapmatlut_lookup(&shapmat->luts[2], a2);
}
if (shapmat->usemat) {
b0 = shapmat->mat[0][0] * a0
+ shapmat->mat[0][1] * a1
+ shapmat->mat[0][2] * a2
+ shapmat->mat[0][3];
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?