📄 jpc_enc.c
字号:
tccp->cblkwidthexpn =
jpc_floorlog2(atoi(jas_tvparser_getval(tvp)));
break;
case OPT_CBLKHEIGHT:
tccp->cblkheightexpn =
jpc_floorlog2(atoi(jas_tvparser_getval(tvp)));
break;
case OPT_MODE:
if ((tagid = jas_taginfo_nonull(jas_taginfos_lookup(modetab,
jas_tvparser_getval(tvp)))->id) < 0) {
jas_eprintf("ignoring invalid mode %s\n",
jas_tvparser_getval(tvp));
} else {
tcp->intmode = (tagid == MODE_INT);
}
break;
case OPT_PRG:
if ((tagid = jas_taginfo_nonull(jas_taginfos_lookup(prgordtab,
jas_tvparser_getval(tvp)))->id) < 0) {
jas_eprintf("ignoring invalid progression order %s\n",
jas_tvparser_getval(tvp));
} else {
tcp->prg = tagid;
}
break;
case OPT_NOMCT:
enablemct = false;
break;
case OPT_MAXRLVLS:
tccp->maxrlvls = atoi(jas_tvparser_getval(tvp));
break;
case OPT_SOP:
cp->tcp.csty |= JPC_COD_SOP;
break;
case OPT_EPH:
cp->tcp.csty |= JPC_COD_EPH;
break;
case OPT_LAZY:
tccp->cblksty |= JPC_COX_LAZY;
break;
case OPT_TERMALL:
tccp->cblksty |= JPC_COX_TERMALL;
break;
case OPT_SEGSYM:
tccp->cblksty |= JPC_COX_SEGSYM;
break;
case OPT_VCAUSAL:
tccp->cblksty |= JPC_COX_VSC;
break;
case OPT_RESET:
tccp->cblksty |= JPC_COX_RESET;
break;
case OPT_PTERM:
tccp->cblksty |= JPC_COX_PTERM;
break;
case OPT_NUMGBITS:
cp->tccp.numgbits = atoi(jas_tvparser_getval(tvp));
break;
case OPT_RATE:
if (ratestrtosize(jas_tvparser_getval(tvp), cp->rawsize,
&cp->totalsize)) {
jas_eprintf("ignoring bad rate specifier %s\n",
jas_tvparser_getval(tvp));
}
break;
case OPT_ILYRRATES:
if (jpc_atoaf(jas_tvparser_getval(tvp), &numilyrrates,
&ilyrrates)) {
jas_eprintf("warning: invalid intermediate layer rates specifier ignored (%s)\n",
jas_tvparser_getval(tvp));
}
break;
case OPT_JP2OVERHEAD:
jp2overhead = atoi(jas_tvparser_getval(tvp));
break;
default:
jas_eprintf("warning: ignoring invalid option %s\n",
jas_tvparser_gettag(tvp));
break;
}
}
jas_tvparser_destroy(tvp);
tvp = 0;
if (cp->totalsize != UINT_FAST32_MAX) {
cp->totalsize = (cp->totalsize > jp2overhead) ?
(cp->totalsize - jp2overhead) : 0;
}
if (cp->imgareatlx == UINT_FAST32_MAX) {
cp->imgareatlx = 0;
} else {
if (hsteplcm != 1) {
jas_eprintf("warning: overriding imgareatlx value\n");
}
cp->imgareatlx *= hsteplcm;
}
if (cp->imgareatly == UINT_FAST32_MAX) {
cp->imgareatly = 0;
} else {
if (vsteplcm != 1) {
jas_eprintf("warning: overriding imgareatly value\n");
}
cp->imgareatly *= vsteplcm;
}
cp->refgrdwidth = cp->imgareatlx + jas_image_width(image);
cp->refgrdheight = cp->imgareatly + jas_image_height(image);
if (cp->tilegrdoffx == UINT_FAST32_MAX) {
cp->tilegrdoffx = cp->imgareatlx;
}
if (cp->tilegrdoffy == UINT_FAST32_MAX) {
cp->tilegrdoffy = cp->imgareatly;
}
if (!cp->tilewidth) {
cp->tilewidth = cp->refgrdwidth - cp->tilegrdoffx;
}
if (!cp->tileheight) {
cp->tileheight = cp->refgrdheight - cp->tilegrdoffy;
}
if (cp->numcmpts == 3) {
mctvalid = true;
for (cmptno = 0; cmptno < jas_image_numcmpts(image); ++cmptno) {
if (jas_image_cmptprec(image, cmptno) != jas_image_cmptprec(image, 0) ||
jas_image_cmptsgnd(image, cmptno) != jas_image_cmptsgnd(image, 0) ||
jas_image_cmptwidth(image, cmptno) != jas_image_cmptwidth(image, 0) ||
jas_image_cmptheight(image, cmptno) != jas_image_cmptheight(image, 0)) {
mctvalid = false;
}
}
} else {
mctvalid = false;
}
if (mctvalid && enablemct && jas_clrspc_fam(jas_image_clrspc(image)) != JAS_CLRSPC_FAM_RGB) {
jas_eprintf("warning: color space apparently not RGB\n");
}
if (mctvalid && enablemct && jas_clrspc_fam(jas_image_clrspc(image)) == JAS_CLRSPC_FAM_RGB) {
tcp->mctid = (tcp->intmode) ? (JPC_MCT_RCT) : (JPC_MCT_ICT);
} else {
tcp->mctid = JPC_MCT_NONE;
}
tccp->qmfbid = (tcp->intmode) ? (JPC_COX_RFT) : (JPC_COX_INS);
for (rlvlno = 0; rlvlno < tccp->maxrlvls; ++rlvlno) {
tccp->prcwidthexpns[rlvlno] = prcwidthexpn;
tccp->prcheightexpns[rlvlno] = prcheightexpn;
}
if (prcwidthexpn != 15 || prcheightexpn != 15) {
tccp->csty |= JPC_COX_PRT;
}
/* Ensure that the tile width and height is valid. */
if (!cp->tilewidth) {
jas_eprintf("invalid tile width %lu\n", (unsigned long)
cp->tilewidth);
goto error;
}
if (!cp->tileheight) {
jas_eprintf("invalid tile height %lu\n", (unsigned long)
cp->tileheight);
goto error;
}
/* Ensure that the tile grid offset is valid. */
if (cp->tilegrdoffx > cp->imgareatlx ||
cp->tilegrdoffy > cp->imgareatly ||
cp->tilegrdoffx + cp->tilewidth < cp->imgareatlx ||
cp->tilegrdoffy + cp->tileheight < cp->imgareatly) {
jas_eprintf("invalid tile grid offset (%lu, %lu)\n",
(unsigned long) cp->tilegrdoffx, (unsigned long)
cp->tilegrdoffy);
goto error;
}
cp->numhtiles = JPC_CEILDIV(cp->refgrdwidth - cp->tilegrdoffx,
cp->tilewidth);
cp->numvtiles = JPC_CEILDIV(cp->refgrdheight - cp->tilegrdoffy,
cp->tileheight);
cp->numtiles = cp->numhtiles * cp->numvtiles;
if (ilyrrates && numilyrrates > 0) {
tcp->numlyrs = numilyrrates + 1;
if (!(tcp->ilyrrates = jas_malloc((tcp->numlyrs - 1) *
sizeof(jpc_fix_t)))) {
goto error;
}
for (i = 0; i < JAS_CAST(int, tcp->numlyrs - 1); ++i) {
tcp->ilyrrates[i] = jpc_dbltofix(ilyrrates[i]);
}
}
/* Ensure that the integer mode is used in the case of lossless
coding. */
if (cp->totalsize == UINT_FAST32_MAX && (!cp->tcp.intmode)) {
jas_eprintf("cannot use real mode for lossless coding\n");
goto error;
}
/* Ensure that the precinct width is valid. */
if (prcwidthexpn > 15) {
jas_eprintf("invalid precinct width\n");
goto error;
}
/* Ensure that the precinct height is valid. */
if (prcheightexpn > 15) {
jas_eprintf("invalid precinct height\n");
goto error;
}
/* Ensure that the code block width is valid. */
if (cp->tccp.cblkwidthexpn < 2 || cp->tccp.cblkwidthexpn > 12) {
jas_eprintf("invalid code block width %d\n",
JPC_POW2(cp->tccp.cblkwidthexpn));
goto error;
}
/* Ensure that the code block height is valid. */
if (cp->tccp.cblkheightexpn < 2 || cp->tccp.cblkheightexpn > 12) {
jas_eprintf("invalid code block height %d\n",
JPC_POW2(cp->tccp.cblkheightexpn));
goto error;
}
/* Ensure that the code block size is not too large. */
if (cp->tccp.cblkwidthexpn + cp->tccp.cblkheightexpn > 12) {
jas_eprintf("code block size too large\n");
goto error;
}
/* Ensure that the number of layers is valid. */
if (cp->tcp.numlyrs > 16384) {
jas_eprintf("too many layers\n");
goto error;
}
/* There must be at least one resolution level. */
if (cp->tccp.maxrlvls < 1) {
jas_eprintf("must be at least one resolution level\n");
goto error;
}
/* Ensure that the number of guard bits is valid. */
if (cp->tccp.numgbits > 8) {
jas_eprintf("invalid number of guard bits\n");
goto error;
}
/* Ensure that the rate is within the legal range. */
if (cp->totalsize != UINT_FAST32_MAX && cp->totalsize > cp->rawsize) {
jas_eprintf("warning: specified rate is unreasonably large (%lu > %lu)\n", (unsigned long) cp->totalsize, (unsigned long) cp->rawsize);
}
/* Ensure that the intermediate layer rates are valid. */
if (tcp->numlyrs > 1) {
/* The intermediate layers rates must increase monotonically. */
for (lyrno = 0; lyrno + 2 < tcp->numlyrs; ++lyrno) {
if (tcp->ilyrrates[lyrno] >= tcp->ilyrrates[lyrno + 1]) {
jas_eprintf("intermediate layer rates must increase monotonically\n");
goto error;
}
}
/* The intermediate layer rates must be less than the overall rate. */
if (cp->totalsize != UINT_FAST32_MAX) {
for (lyrno = 0; lyrno < tcp->numlyrs - 1; ++lyrno) {
if (jpc_fixtodbl(tcp->ilyrrates[lyrno]) > ((double) cp->totalsize)
/ cp->rawsize) {
jas_eprintf("warning: intermediate layer rates must be less than overall rate\n");
goto error;
}
}
}
}
if (ilyrrates) {
jas_free(ilyrrates);
}
return cp;
error:
if (ilyrrates) {
jas_free(ilyrrates);
}
if (tvp) {
jas_tvparser_destroy(tvp);
}
if (cp) {
jpc_enc_cp_destroy(cp);
}
return 0;
}
void jpc_enc_cp_destroy(jpc_enc_cp_t *cp)
{
if (cp->ccps) {
if (cp->tcp.ilyrrates) {
jas_free(cp->tcp.ilyrrates);
}
jas_free(cp->ccps);
}
jas_free(cp);
}
int ratestrtosize(char *s, uint_fast32_t rawsize, uint_fast32_t *size)
{
char *cp;
jpc_flt_t f;
/* Note: This function must not modify output size on failure. */
if ((cp = strchr(s, 'B'))) {
*size = atoi(s);
} else {
f = atof(s);
if (f < 0) {
*size = 0;
} else if (f > 1.0) {
*size = rawsize + 1;
} else {
*size = f * rawsize;
}
}
return 0;
}
/******************************************************************************\
* Encoder constructor and destructor.
\******************************************************************************/
jpc_enc_t *jpc_enc_create(jpc_enc_cp_t *cp, jas_stream_t *out, jas_image_t *image)
{
jpc_enc_t *enc;
enc = 0;
if (!(enc = jas_malloc(sizeof(jpc_enc_t)))) {
goto error;
}
enc->image = image;
enc->out = out;
enc->cp = cp;
enc->cstate = 0;
enc->tmpstream = 0;
enc->mrk = 0;
enc->curtile = 0;
if (!(enc->cstate = jpc_cstate_create())) {
goto error;
}
enc->len = 0;
enc->mainbodysize = 0;
return enc;
error:
if (enc) {
jpc_enc_destroy(enc);
}
return 0;
}
void jpc_enc_destroy(jpc_enc_t *enc)
{
/* The image object (i.e., enc->image) and output stream object
(i.e., enc->out) are created outside of the encoder.
Therefore, they must not be destroyed here. */
if (enc->curtile) {
jpc_enc_tile_destroy(enc->curtile);
}
if (enc->cp) {
jpc_enc_cp_destroy(enc->cp);
}
if (enc->cstate) {
jpc_cstate_destroy(enc->cstate);
}
if (enc->tmpstream) {
jas_stream_close(enc->tmpstream);
}
jas_free(enc);
}
/******************************************************************************\
* Code.
\******************************************************************************/
static int jpc_calcssmant(jpc_fix_t stepsize)
{
int n;
int e;
int m;
n = jpc_firstone(stepsize);
e = n - JPC_FIX_FRACBITS;
if (n >= 11) {
m = (stepsize >> (n - 11)) & 0x7ff;
} else {
m = (stepsize & ((1 << n) - 1)) << (11 - n);
}
return m;
}
static int jpc_calcssexp(jpc_fix_t stepsize)
{
return jpc_firstone(stepsize) - JPC_FIX_FRACBITS;
}
static int jpc_enc_encodemainhdr(jpc_enc_t *enc)
{
jpc_siz_t *siz;
jpc_cod_t *cod;
jpc_qcd_t *qcd;
int i;
long startoff;
long mainhdrlen;
jpc_enc_cp_t *cp;
jpc_qcc_t *qcc;
jpc_enc_tccp_t *tccp;
uint_fast16_t cmptno;
jpc_tsfb_band_t bandinfos[JPC_MAXBANDS];
jpc_fix_t mctsynweight;
jpc_enc_tcp_t *tcp;
jpc_tsfb_t *tsfb;
jpc_tsfb_band_t *bandinfo;
uint_fast16_t numbands;
uint_fast16_t bandno;
uint_fast16_t rlvlno;
uint_fast16_t analgain;
jpc_fix_t absstepsize;
char buf[1024];
jpc_com_t *com;
cp = enc->cp;
startoff = jas_stream_getrwcount(enc->out);
/* Write SOC marker segment. */
if (!(enc->mrk = jpc_ms_create(JPC_MS_SOC))) {
return -1;
}
if (jpc_putms(enc->out, enc->cstate, enc->mrk)) {
jas_eprintf("cannot write SOC marker\n");
return -1;
}
jpc_ms_destroy(enc->mrk);
enc->mrk = 0;
/* Write SIZ marker segment. */
if (!(enc->mrk = jpc_ms_create(JPC_MS_SIZ))) {
return -1;
}
siz = &enc->mrk->parms.siz;
siz->caps = 0;
siz->xoff = cp->imgareatlx;
siz->yoff = cp->imgareatly;
siz->width = cp->refgrdwidth;
siz->height = cp->refgrdheight;
siz->tilexoff = cp->tilegrdoffx;
siz->tileyoff = cp->tilegrdoffy;
siz->tilewidth = cp->tilewidth;
siz->tileheight = cp->tileheight;
siz->numcomps = cp->numcmpts;
siz->comps = jas_malloc(siz->numcomps * sizeof(jpc_sizcomp_t));
assert(siz->comps);
for (i = 0; i < JAS_CAST(int, cp->numcmpts); ++i) {
siz->comps[i].prec = cp->ccps[i].prec;
siz->comps[i].sgnd = cp->ccps[i].sgnd;
siz->comps[i].hsamp = cp->ccps[i].sampgrdstepx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -