int JPC_SEGPASSCNT(int passno, int firstpassno, int numpasses, int bypass, int termall) { int ret; int passtype; if (termall) { ret = 1; } else if (bypass) { if (passno < firstpassno + 10) { ret = 10 - (passno - firstpassno); } else { passtype = JPC_PASSTYPE(passno); switch (passtype) { case JPC_SIGPASS: ret = 2; break; case JPC_REFPASS: ret = 1; break; case JPC_CLNPASS: ret = 1; break; default: ret = -1; assert(0); break; } } } else { ret = JPC_PREC * 3 - 2; } ret = JAS_MIN(ret, numpasses - passno); return ret; }
int JPC_SEGTYPE(int passno, int firstpassno, int bypass) { int passtype; if (bypass) { passtype = JPC_PASSTYPE(passno); if (passtype == JPC_CLNPASS) { return JPC_SEG_MQ; } return ((passno < firstpassno + 10) ? JPC_SEG_MQ : JPC_SEG_RAW); } else { return JPC_SEG_MQ; } }
/* Encode a single code block. */ int jpc_enc_enccblk(jpc_enc_t *enc, jas_stream_t *out, jpc_enc_tcmpt_t *tcmpt, jpc_enc_band_t *band, jpc_enc_cblk_t *cblk) { jpc_enc_pass_t *pass; jpc_enc_pass_t *endpasses; int bitpos; int n; int adjust; int ret; int passtype; int t; jpc_bitstream_t *bout; jpc_enc_pass_t *termpass; jpc_enc_rlvl_t *rlvl; int vcausal; int segsym; int termmode; int c; bout = 0; rlvl = band->rlvl; cblk->stream = jas_stream_memopen(0, 0); assert(cblk->stream); cblk->mqenc = jpc_mqenc_create(JPC_NUMCTXS, cblk->stream); assert(cblk->mqenc); jpc_mqenc_setctxs(cblk->mqenc, JPC_NUMCTXS, jpc_mqctxs); cblk->numpasses = (cblk->numbps > 0) ? (3 * cblk->numbps - 2) : 0; if (cblk->numpasses > 0) { cblk->passes = jas_malloc(cblk->numpasses * sizeof(jpc_enc_pass_t)); assert(cblk->passes); } else { cblk->passes = 0; } endpasses = &cblk->passes[cblk->numpasses]; for (pass = cblk->passes; pass != endpasses; ++pass) { pass->start = 0; pass->end = 0; pass->term = JPC_ISTERMINATED(pass - cblk->passes, 0, cblk->numpasses, (tcmpt->cblksty & JPC_COX_TERMALL) != 0, (tcmpt->cblksty & JPC_COX_LAZY) != 0); pass->type = JPC_SEGTYPE(pass - cblk->passes, 0, (tcmpt->cblksty & JPC_COX_LAZY) != 0); pass->lyrno = -1; if (pass == endpasses - 1) { assert(pass->term == 1); pass->term = 1; } } cblk->flags = jas_matrix_create(jas_matrix_numrows(cblk->data) + 2, jas_matrix_numcols(cblk->data) + 2); assert(cblk->flags); bitpos = cblk->numbps - 1; pass = cblk->passes; n = cblk->numpasses; while (--n >= 0) { if (pass->type == JPC_SEG_MQ) { /* NOP */ } else { assert(pass->type == JPC_SEG_RAW); if (!bout) { bout = jpc_bitstream_sopen(cblk->stream, "w"); assert(bout); } } #if 1 passtype = (pass - cblk->passes + 2) % 3; #else passtype = JPC_PASSTYPE(pass - cblk->passes + 2); #endif pass->start = jas_stream_tell(cblk->stream); #if 0 assert(jas_stream_tell(cblk->stream) == jas_stream_getrwcount(cblk->stream)); #endif assert(bitpos >= 0); vcausal = (tcmpt->cblksty & JPC_COX_VSC) != 0; segsym = (tcmpt->cblksty & JPC_COX_SEGSYM) != 0; if (pass->term) { termmode = ((tcmpt->cblksty & JPC_COX_PTERM) ? JPC_MQENC_PTERM : JPC_MQENC_DEFTERM) + 1; } else { termmode = 0; } switch (passtype) { case JPC_SIGPASS: ret = (pass->type == JPC_SEG_MQ) ? jpc_encsigpass(cblk->mqenc, bitpos, band->orient, vcausal, cblk->flags, cblk->data, termmode, &pass->nmsedec) : jpc_encrawsigpass(bout, bitpos, vcausal, cblk->flags, cblk->data, termmode, &pass->nmsedec); break; case JPC_REFPASS: ret = (pass->type == JPC_SEG_MQ) ? jpc_encrefpass(cblk->mqenc, bitpos, vcausal, cblk->flags, cblk->data, termmode, &pass->nmsedec) : jpc_encrawrefpass(bout, bitpos, vcausal, cblk->flags, cblk->data, termmode, &pass->nmsedec); break; case JPC_CLNPASS: assert(pass->type == JPC_SEG_MQ); ret = jpc_encclnpass(cblk->mqenc, bitpos, band->orient, vcausal, segsym, cblk->flags, cblk->data, termmode, &pass->nmsedec); break; default: assert(0); break; } if (pass->type == JPC_SEG_MQ) { if (pass->term) { jpc_mqenc_init(cblk->mqenc); } jpc_mqenc_getstate(cblk->mqenc, &pass->mqencstate); pass->end = jas_stream_tell(cblk->stream); if (tcmpt->cblksty & JPC_COX_RESET) { jpc_mqenc_setctxs(cblk->mqenc, JPC_NUMCTXS, jpc_mqctxs); } } else { if (pass->term) { if (jpc_bitstream_pending(bout)) { jpc_bitstream_outalign(bout, 0x2a); } jpc_bitstream_close(bout); bout = 0; pass->end = jas_stream_tell(cblk->stream); } else { pass->end = jas_stream_tell(cblk->stream) + jpc_bitstream_pending(bout); /* NOTE - This will not work. need to adjust by # of pending output bytes */ } } #if 0 /* XXX - This assertion fails sometimes when various coding modes are used. This seems to be harmless, but why does it happen at all? */ assert(jas_stream_tell(cblk->stream) == jas_stream_getrwcount(cblk->stream)); #endif pass->wmsedec = jpc_fixtodbl(band->rlvl->tcmpt->synweight) * jpc_fixtodbl(band->rlvl->tcmpt->synweight) * jpc_fixtodbl(band->synweight) * jpc_fixtodbl(band->synweight) * jpc_fixtodbl(band->absstepsize) * jpc_fixtodbl(band->absstepsize) * ((double) (1 << bitpos)) * ((double)(1 << bitpos)) * jpc_fixtodbl(pass->nmsedec); pass->cumwmsedec = pass->wmsedec; if (pass != cblk->passes) { pass->cumwmsedec += pass[-1].cumwmsedec; } if (passtype == JPC_CLNPASS) { --bitpos; } ++pass; } #if 0 dump_passes(cblk->passes, cblk->numpasses, cblk); #endif n = 0; endpasses = &cblk->passes[cblk->numpasses]; for (pass = cblk->passes; pass != endpasses; ++pass) { if (pass->start < n) { pass->start = n; } if (pass->end < n) { pass->end = n; } if (!pass->term) { termpass = pass; while (termpass - pass < cblk->numpasses && !termpass->term) { ++termpass; } if (pass->type == JPC_SEG_MQ) { t = (pass->mqencstate.lastbyte == 0xff) ? 1 : 0; if (pass->mqencstate.ctreg >= 5) { adjust = 4 + t; } else { adjust = 5 + t; } pass->end += adjust; } if (pass->end > termpass->end) { pass->end = termpass->end; } if ((c = getthebyte(cblk->stream, pass->end - 1)) == EOF) { abort(); } if (c == 0xff) { ++pass->end; } n = JAS_MAX(n, pass->end); } else { n = JAS_MAX(n, pass->end); } } #if 0 dump_passes(cblk->passes, cblk->numpasses, cblk); #endif if (bout) { jpc_bitstream_close(bout); } return 0; }
static int jpc_dec_decodecblk(jpc_dec_t *dec, jpc_dec_tile_t *tile, jpc_dec_tcomp_t *tcomp, jpc_dec_band_t *band, jpc_dec_cblk_t *cblk, int dopartial, int maxlyrs) { jpc_dec_seg_t *seg; int i; int bpno; int passtype; int ret; int compno; int filldata; int fillmask; jpc_dec_ccp_t *ccp; compno = tcomp - tile->tcomps; if (!cblk->flags) { /* Note: matrix is assumed to be zeroed */ if (!(cblk->flags = jas_matrix_create(jas_matrix_numrows(cblk->data) + 2, jas_matrix_numcols(cblk->data) + 2))) { return -1; } } seg = cblk->segs.head; while (seg && (seg != cblk->curseg || dopartial) && (maxlyrs < 0 || seg->lyrno < maxlyrs)) { assert(seg->numpasses >= seg->maxpasses || dopartial); assert(seg->stream); jas_stream_rewind(seg->stream); jas_stream_setrwcount(seg->stream, 0); if (seg->type == JPC_SEG_MQ) { if (!cblk->mqdec) { if (!(cblk->mqdec = jpc_mqdec_create(JPC_NUMCTXS, 0))) { return -1; } jpc_mqdec_setctxs(cblk->mqdec, JPC_NUMCTXS, jpc_mqctxs); } jpc_mqdec_setinput(cblk->mqdec, seg->stream); jpc_mqdec_init(cblk->mqdec); } else { assert(seg->type == JPC_SEG_RAW); if (!cblk->nulldec) { if (!(cblk->nulldec = jpc_bitstream_sopen(seg->stream, "r"))) { assert(0); } } } for (i = 0; i < seg->numpasses; ++i) { if (cblk->numimsbs > band->numbps) { ccp = &tile->cp->ccps[compno]; if (ccp->roishift <= 0) { jas_eprintf("warning: corrupt code stream\n"); } else { if (cblk->numimsbs < ccp->roishift - band->numbps) { jas_eprintf("warning: corrupt code stream\n"); } } } bpno = band->roishift + band->numbps - 1 - (cblk->numimsbs + (seg->passno + i - cblk->firstpassno + 2) / 3); if (bpno < 0) { goto premature_exit; } #if 1 passtype = (seg->passno + i + 2) % 3; #else passtype = JPC_PASSTYPE(seg->passno + i + 2); #endif assert(bpno >= 0 && bpno < 31); switch (passtype) { case JPC_SIGPASS: ret = (seg->type == JPC_SEG_MQ) ? dec_sigpass(dec, cblk->mqdec, bpno, band->orient, (tile->cp->ccps[compno].cblkctx & JPC_COX_VSC) != 0, cblk->flags, cblk->data) : dec_rawsigpass(dec, cblk->nulldec, bpno, (tile->cp->ccps[compno].cblkctx & JPC_COX_VSC) != 0, cblk->flags, cblk->data); break; case JPC_REFPASS: ret = (seg->type == JPC_SEG_MQ) ? dec_refpass(dec, cblk->mqdec, bpno, (tile->cp->ccps[compno].cblkctx & JPC_COX_VSC) != 0, cblk->flags, cblk->data) : dec_rawrefpass(dec, cblk->nulldec, bpno, (tile->cp->ccps[compno].cblkctx & JPC_COX_VSC) != 0, cblk->flags, cblk->data); break; case JPC_CLNPASS: assert(seg->type == JPC_SEG_MQ); ret = dec_clnpass(dec, cblk->mqdec, bpno, band->orient, (tile->cp->ccps[compno].cblkctx & JPC_COX_VSC) != 0, (tile->cp->ccps[compno].cblkctx & JPC_COX_SEGSYM) != 0, cblk->flags, cblk->data); break; default: ret = -1; break; } /* Do we need to reset after each coding pass? */ if (tile->cp->ccps[compno].cblkctx & JPC_COX_RESET) { jpc_mqdec_setctxs(cblk->mqdec, JPC_NUMCTXS, jpc_mqctxs); } if (ret) { jas_eprintf("coding pass failed passtype=%d segtype=%d\n", passtype, seg->type); return -1; } } if (seg->type == JPC_SEG_MQ) { /* Note: dont destroy mq decoder because context info will be lost */ } else { assert(seg->type == JPC_SEG_RAW); if (tile->cp->ccps[compno].cblkctx & JPC_COX_PTERM) { fillmask = 0x7f; filldata = 0x2a; } else { fillmask = 0; filldata = 0; } if ((ret = jpc_bitstream_inalign(cblk->nulldec, fillmask, filldata)) < 0) { return -1; } else if (ret > 0) { jas_eprintf("warning: bad termination pattern detected\n"); } jpc_bitstream_close(cblk->nulldec); cblk->nulldec = 0; } cblk->curseg = seg->next; jpc_seglist_remove(&cblk->segs, seg); jpc_seg_destroy(seg); seg = cblk->curseg; } assert(dopartial ? (!cblk->curseg) : 1); premature_exit: return 0; }