diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2022-12-31 00:32:37 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2022-12-31 00:32:37 +0000 |
commit | a70405848cb06782036364a88e27f452fb0a0b32 (patch) | |
tree | 514c1d8e50b2989b77b4e1958ea1e0e149ec13c3 /converter/other/jpeg2000/libjasper | |
parent | 1c19660f1cdb62646f324615d4842a46c7681303 (diff) | |
download | netpbm-mirror-a70405848cb06782036364a88e27f452fb0a0b32.tar.gz netpbm-mirror-a70405848cb06782036364a88e27f452fb0a0b32.tar.xz netpbm-mirror-a70405848cb06782036364a88e27f452fb0a0b32.zip |
promote Development to Advanced
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@4489 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter/other/jpeg2000/libjasper')
-rw-r--r-- | converter/other/jpeg2000/libjasper/base/jas_image.c | 33 | ||||
-rw-r--r-- | converter/other/jpeg2000/libjasper/jpc/jpc_enc.c | 1377 | ||||
-rw-r--r-- | converter/other/jpeg2000/libjasper/jpc/jpc_math.c | 2 | ||||
-rw-r--r-- | converter/other/jpeg2000/libjasper/jpc/jpc_t1enc.c | 163 | ||||
-rw-r--r-- | converter/other/jpeg2000/libjasper/jpc/jpc_util.c | 71 |
5 files changed, 865 insertions, 781 deletions
diff --git a/converter/other/jpeg2000/libjasper/base/jas_image.c b/converter/other/jpeg2000/libjasper/base/jas_image.c index 5ee13a0d..c6f984c1 100644 --- a/converter/other/jpeg2000/libjasper/base/jas_image.c +++ b/converter/other/jpeg2000/libjasper/base/jas_image.c @@ -675,7 +675,7 @@ int jas_image_fmtfromname(char *name) return -1; } ++ext; - /* Try to find a format that uses this extension. */ + /* Try to find a format that uses this extension. */ for (i = 0, fmtinfo = jas_image_fmtinfos; i < jas_image_numfmts; ++i, ++fmtinfo) { /* Do we have a match? */ @@ -686,25 +686,28 @@ int jas_image_fmtfromname(char *name) return -1; } -/******************************************************************************\ +/*****************************************************************************\ * Miscellaneous operations. -\******************************************************************************/ +\*****************************************************************************/ -uint_fast32_t jas_image_rawsize(jas_image_t *image) -{ - uint_fast32_t rawsize; - uint_fast32_t cmptno; - jas_image_cmpt_t *cmpt; +uint_fast32_t +jas_image_rawsize(jas_image_t * const imageP) { +/*---------------------------------------------------------------------------- + The raw size of the image, i.e. the number of bytes the raster of the image + would take if just represented simply, with no compression. +-----------------------------------------------------------------------------*/ + uint_fast32_t rawsize; + uint_fast32_t cmptno; - rawsize = 0; - for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) { - cmpt = image->cmpts_[cmptno]; - rawsize += (cmpt->width_ * cmpt->height_ * cmpt->prec_ + - 7) / 8; - } - return rawsize; + for (cmptno = 0, rawsize = 0; cmptno < imageP->numcmpts_; ++cmptno) { + jas_image_cmpt_t * const cmptP = imageP->cmpts_[cmptno]; + rawsize += (cmptP->width_ * cmptP->height_ * cmptP->prec_ + 7) / 8; + } + return rawsize; } + + void jas_image_delcmpt(jas_image_t *image, uint_fast16_t cmptno) { if (cmptno >= image->numcmpts_) { diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c b/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c index 9db41ca2..0c77a94e 100644 --- a/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c +++ b/converter/other/jpeg2000/libjasper/jpc/jpc_enc.c @@ -69,7 +69,6 @@ static void prc_destroy(jpc_enc_prc_t *prcs); static jpc_enc_cblk_t *cblk_create(jpc_enc_cblk_t *cblk, jpc_enc_cp_t *cp, jpc_enc_prc_t *prc); static void cblk_destroy(jpc_enc_cblk_t *cblks); -int ratestrtosize(const char *s, uint_fast32_t rawsize, uint_fast32_t *size); static void pass_destroy(jpc_enc_pass_t *pass); void jpc_enc_dump(jpc_enc_t *enc); @@ -78,17 +77,8 @@ void jpc_enc_dump(jpc_enc_t *enc); \*****************************************************************************/ void quantize(jas_matrix_t *data, jpc_fix_t stepsize); -static int jpc_enc_encodemainhdr(jpc_enc_t *enc); -static int jpc_enc_encodemainbody(jpc_enc_t *enc); -int jpc_enc_encodetiledata(jpc_enc_t *enc); jpc_enc_t *jpc_enc_create(jpc_enc_cp_t *cp, jas_stream_t *out, jas_image_t *image); void jpc_enc_destroy(jpc_enc_t *enc); -static int jpc_enc_encodemainhdr(jpc_enc_t *enc); -static int jpc_enc_encodemainbody(jpc_enc_t *enc); -int jpc_enc_encodetiledata(jpc_enc_t *enc); -int setins(int numvalues, jpc_flt_t *values, jpc_flt_t value); -static jpc_enc_cp_t *cp_create(char *optstr, jas_image_t *image); -void jpc_enc_cp_destroy(jpc_enc_cp_t *cp); @@ -143,7 +133,6 @@ typedef enum { OPT_NUMGBITS, OPT_RATE, OPT_ILYRRATES, - OPT_JP2OVERHEAD } optid_t; jas_taginfo_t encopts[] = { @@ -173,7 +162,6 @@ jas_taginfo_t encopts[] = { {OPT_NUMGBITS, "numgbits"}, {OPT_RATE, "rate"}, {OPT_ILYRRATES, "ilyrrates"}, - {OPT_JP2OVERHEAD, "_jp2overhead"}, {-1, 0} }; @@ -230,72 +218,46 @@ trace(const char * const fmt, ...) { -int -jpc_encode(jas_image_t *image, jas_stream_t *out, char *optstr) { - - jpc_enc_t *enc; - jpc_enc_cp_t *cp; - - enc = 0; - cp = 0; - - jpc_initluts(); - - if (!(cp = cp_create(optstr, image))) { - fprintf(stderr, "invalid JP encoder options\n"); - goto error; - } - - if (!(enc = jpc_enc_create(cp, out, image))) { - goto error; - } - cp = 0; +/*****************************************************************************\ +* Option parsing code. +\*****************************************************************************/ - /* Encode the main header. */ - if (jpc_enc_encodemainhdr(enc)) { - goto error; - } +static void +ratestrtosize(const char * const s, + uint_fast32_t const rawsize, + uint_fast32_t * const sizeP) { - /* Encode the main body. This constitutes most of the encoding work. */ - if (jpc_enc_encodemainbody(enc)) { - goto error; - } + if (strchr(s, 'B')) { + *sizeP = atoi(s); + } else { + jpc_flt_t const f = atof(s); - /* Write EOC marker segment. */ - if (!(enc->mrk = jpc_ms_create(JPC_MS_EOC))) { - goto error; - } - if (jpc_putms(enc->out, enc->cstate, enc->mrk)) { - fprintf(stderr, "cannot write EOI marker\n"); - goto error; + if (f < 0) { + *sizeP = 0; + } else if (f > 1.0) { + *sizeP = rawsize + 1; + } else { + *sizeP = f * rawsize; + } } - jpc_ms_destroy(enc->mrk); - enc->mrk = 0; +} - if (jas_stream_flush(enc->out)) { - goto error; - } - jpc_enc_destroy(enc); - return 0; +static void +cp_destroy(jpc_enc_cp_t *cp) { -error: - if (cp) { - jpc_enc_cp_destroy(cp); - } - if (enc) { - jpc_enc_destroy(enc); + if (cp->ccps) { + if (cp->tcp.ilyrrates) { + jas_free(cp->tcp.ilyrrates); + } + jas_free(cp->ccps); } - return -1; + jas_free(cp); } -/*****************************************************************************\ -* Option parsing code. -\*****************************************************************************/ - static jpc_enc_cp_t * cp_create(char *optstr, jas_image_t *image) { @@ -314,7 +276,6 @@ cp_create(char *optstr, jas_image_t *image) { uint_fast16_t prcwidthexpn; uint_fast16_t prcheightexpn; bool enablemct; - uint_fast32_t jp2overhead; uint_fast16_t lyrno; uint_fast32_t hsteplcm; uint_fast32_t vsteplcm; @@ -332,7 +293,6 @@ cp_create(char *optstr, jas_image_t *image) { prcwidthexpn = 15; prcheightexpn = 15; enablemct = true; - jp2overhead = 0; cp->ccps = 0; cp->debug = 0; @@ -380,6 +340,10 @@ cp_create(char *optstr, jas_image_t *image) { cp->rawsize = jas_image_rawsize(image); cp->totalsize = UINT_FAST32_MAX; + /* Set default value, the special value that means size is unlimited + (so lossless coding is called for). To be overridden if user + specified + */ tcp = &cp->tcp; tcp->csty = 0; @@ -492,12 +456,8 @@ cp_create(char *optstr, jas_image_t *image) { cp->tccp.numgbits = atoi(jas_tvparser_getval(tvp)); break; case OPT_RATE: - if (ratestrtosize(jas_tvparser_getval(tvp), cp->rawsize, - &cp->totalsize)) { - fprintf(stderr, - "ignoring bad rate specifier %s\n", - jas_tvparser_getval(tvp)); - } + ratestrtosize(jas_tvparser_getval(tvp), cp->rawsize, + &cp->totalsize); break; case OPT_ILYRRATES: if (jpc_atoaf(jas_tvparser_getval(tvp), &numilyrrates, @@ -505,13 +465,10 @@ cp_create(char *optstr, jas_image_t *image) { fprintf(stderr, "warning: invalid intermediate layer rates specifier " "ignored (%s)\n", - jas_tvparser_getval(tvp)); + jas_tvparser_getval(tvp)); } break; - case OPT_JP2OVERHEAD: - jp2overhead = atoi(jas_tvparser_getval(tvp)); - break; default: fprintf(stderr, "warning: ignoring invalid option %s\n", jas_tvparser_gettag(tvp)); @@ -522,11 +479,6 @@ cp_create(char *optstr, jas_image_t *image) { 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 { @@ -697,20 +649,28 @@ cp_create(char *optstr, jas_image_t *image) { /* The intermediate layers rates must increase monotonically. */ for (lyrno = 0; lyrno + 2 < tcp->numlyrs; ++lyrno) { if (tcp->ilyrrates[lyrno] >= tcp->ilyrrates[lyrno + 1]) { - fprintf(stderr, - "intermediate layer rates must increase " - "monotonically\n"); + pm_message("Compression rate for Layer %u (%f) " + "is not greater than that for Layer %u (%f). " + "Rates must increase at every layer", + (unsigned)(lyrno+1), + jpc_fixtodbl(tcp->ilyrrates[lyrno + 1]), + (unsigned)lyrno, + jpc_fixtodbl(tcp->ilyrrates[lyrno])); 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) { - fprintf(stderr, - "warning: intermediate layer rates must be " - "less than overall rate\n"); + double const thisLyrRate = jpc_fixtodbl(tcp->ilyrrates[lyrno]); + double const completeRate = + ((double) cp->totalsize) / cp->rawsize; + if (thisLyrRate > completeRate) { + pm_message( + "Compression rate for Layer %u is %f, " + "which is greater than the rate for the complete " + "image (%f)", + (unsigned)lyrno, thisLyrRate, completeRate); goto error; } } @@ -732,118 +692,17 @@ error: 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(const 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); + cp_destroy(cp); } 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); -} - - - static int -jpc_enc_encodemainhdr(jpc_enc_t *enc) { +encodemainhdr(jpc_enc_t *enc) { + + uint_fast32_t const maintlrlen = 2; jpc_siz_t *siz; jpc_cod_t *cod; @@ -961,7 +820,7 @@ jpc_enc_encodemainhdr(jpc_enc_t *enc) { (analgain + 1)), bandinfo->synenergywt); } else { absstepsize = jpc_inttofix(1); - } + } cp->ccps[cmptno].stepsizes[bandno] = jpc_abstorelstepsize(absstepsize, cp->ccps[cmptno].prec + analgain); @@ -1038,61 +897,32 @@ jpc_enc_encodemainhdr(jpc_enc_t *enc) { enc->mrk = 0; } -#define MAINTLRLEN 2 mainhdrlen = jas_stream_getrwcount(enc->out) - startoff; enc->len += mainhdrlen; if (enc->cp->totalsize != UINT_FAST32_MAX) { - uint_fast32_t overhead; - overhead = mainhdrlen + MAINTLRLEN; - enc->mainbodysize = (enc->cp->totalsize >= overhead) ? - (enc->cp->totalsize - overhead) : 0; - } else { - enc->mainbodysize = UINT_FAST32_MAX; - } - - return 0; -} - - - -int -jpc_enc_encodetiledata(jpc_enc_t *enc) { - - assert(enc->tmpstream); - if (jpc_enc_encpkts(enc, enc->tmpstream)) { - return -1; - } - return 0; -} - - - -void -quantize(jas_matrix_t *data, jpc_fix_t stepsize) { + uint_fast32_t const overhead = mainhdrlen + maintlrlen; - int i; - int j; - jpc_fix_t t; - - if (stepsize == jpc_inttofix(1)) { - return; - } - - for (i = 0; i < jas_matrix_numrows(data); ++i) { - for (j = 0; j < jas_matrix_numcols(data); ++j) { - t = jas_matrix_get(data, i, j); + if (overhead > enc->cp->totalsize) { + pm_message("Requested limit on image size of %u bytes " + "is not possible because it is less than " + "the image metadata size (%u bytes)", + (unsigned)enc->cp->totalsize, (unsigned)overhead); + return -1; + } + enc->mainbodysize = enc->cp->totalsize - overhead; + /* This has never actually worked. 'totalsize' is supposed to be + the total all-in, so if you request total size 200, you should + get an output file 200 bytes or smaller; but we see 209 bytes. + Furthermore, at 194 bytes, we get a warning that an empty layer + is generated, which probably is actually an error. -{ - if (t < 0) { - t = jpc_fix_neg(jpc_fix_div(jpc_fix_neg(t), stepsize)); + We should fix this some day. + */ } else { - t = jpc_fix_div(t, stepsize); + enc->mainbodysize = UINT_FAST32_MAX; } -} - jas_matrix_set(data, i, j, t); - } - } + return 0; } @@ -1166,12 +996,12 @@ calcrdslopes(jpc_enc_cblk_t *cblk) { static void traceLayerSizes(const uint_fast32_t * const lyrSizes, - unsigned int const layerCt) { + uint_fast32_t const layerCt) { if (jas_getdbglevel() > 0) { - unsigned int i; + uint_fast32_t i; for (i = 0; i < layerCt; ++i) { - fprintf(stderr, "Layer %u size = ", i); + fprintf(stderr, "Layer %u size = ", (unsigned)i); if (lyrSizes[i] == UINT_FAST32_MAX) fprintf(stderr, "Unlimited"); @@ -1189,48 +1019,28 @@ computeLayerSizes(jpc_enc_t * const encP, jpc_enc_tile_t * const tileP, jpc_enc_cp_t * const cpP, double const rho, - long const tilehdrlen, - const char ** const errorP) { + long const tilehdrlen) { /* Note that in allowed sizes, UINT_FAST32_MAX is a special value meaning "unlimited". */ - unsigned int const lastLyrno = tileP->numlyrs - 1; + uint_fast32_t const lastLyrno = tileP->numlyrs - 1; - unsigned int lyrno; + uint_fast32_t lyrno; assert(tileP->numlyrs > 0); for (lyrno = 0; lyrno < lastLyrno; ++lyrno) { - tileP->lyrsizes[lyrno] = tileP->rawsize * jpc_fixtodbl( - cpP->tcp.ilyrrates[lyrno]); + tileP->lyrsizes[lyrno] = + MAX(tileP->rawsize * + jpc_fixtodbl(cpP->tcp.ilyrrates[lyrno]), + tilehdrlen + 1) - tilehdrlen; } tileP->lyrsizes[lastLyrno] = - (cpP->totalsize != UINT_FAST32_MAX) ? - (rho * encP->mainbodysize) : UINT_FAST32_MAX; - - - /* Subtract 'tilehdrlen' from every layer. */ - - for (lyrno = 0; lyrno < tileP->numlyrs; ++lyrno) { - if (tileP->lyrsizes[lyrno] != UINT_FAST32_MAX) { - if (tilehdrlen <= tileP->lyrsizes[lyrno]) { - tileP->lyrsizes[lyrno] -= tilehdrlen; - } else { - tileP->lyrsizes[lyrno] = 0; - } - } - } - - if (tileP->lyrsizes[lastLyrno] < 1) - pm_asprintf(errorP, "Cannot make image that small (%u bytes). " - "Even with pixels compressed as far as possible, metadata " - "would exceed the limit", - (unsigned)cpP->totalsize); - else - *errorP = NULL; + (cpP->totalsize == UINT_FAST32_MAX) ? + UINT_FAST32_MAX : (rho * encP->mainbodysize); traceLayerSizes(tileP->lyrsizes, tileP->numlyrs); } @@ -1313,8 +1123,8 @@ trace_layeringinfo(jpc_enc_t * const encP) { static void validateCumlensIncreases(const uint_fast32_t * const cumlens, - unsigned int const numlyrs) { - unsigned int lyrno; + uint_fast32_t const numlyrs) { + uint_fast32_t lyrno; for (lyrno = 1; lyrno < numlyrs - 1; ++lyrno) { if (cumlens[lyrno - 1] > cumlens[lyrno]) { @@ -1404,7 +1214,7 @@ findMinMaxRDSlopeValues(jpc_enc_tile_t * const tileP, static void performTier2CodingOneLayer(jpc_enc_t * const encP, jpc_enc_tile_t * const tileP, - unsigned int const lyrno, + uint_fast32_t const lyrno, jas_stream_t * const outP, const char ** const errorP) { /*---------------------------------------------------------------------------- @@ -1444,9 +1254,9 @@ performTier2CodingOneLayer(jpc_enc_t * const encP, static void assignHighSlopePassesToLayer(jpc_enc_t * const encP, jpc_enc_tile_t * const tileP, - unsigned int const lyrno, - bool const haveThresh, - jpc_flt_t const thresh) { + uint_fast32_t const lyrno, + bool const haveThresh, + jpc_flt_t const thresh) { /*---------------------------------------------------------------------------- Assign all passes with R-D slopes greater than or equal to 'thresh' to layer 'lyrno' and the rest to no layer. @@ -1505,8 +1315,7 @@ assignHighSlopePassesToLayer(jpc_enc_t * const encP, for (; passP != endpassesP; ++passP) { passP->lyrno = -1; } - - } + } } } } @@ -1522,7 +1331,7 @@ assignHighSlopePassesToLayer(jpc_enc_t * const encP, static void doLayer(jpc_enc_t * const encP, jpc_enc_tile_t * const tileP, - unsigned int const lyrno, + uint_fast32_t const lyrno, uint_fast32_t const allowedSize, jpc_flt_t const mnrdslope, jpc_flt_t const mxrdslope, @@ -1550,7 +1359,7 @@ doLayer(jpc_enc_t * const encP, long pos; jpc_flt_t lo; jpc_flt_t hi; - unsigned int numiters; + uint_fast32_t numiters; lo = mnrdslope; /* initial value */ hi = mxrdslope; /* initial value */ @@ -1559,52 +1368,46 @@ doLayer(jpc_enc_t * const encP, goodThresh = 0; /* initial value */ do { - if (allowedSize == UINT_FAST32_MAX) { - /* There's no rate constraint (This can be true of the last - layer, e.g. for lossless coding). */ - goodThresh = -1; - haveGoodThresh = true; - } else { - jpc_flt_t const thresh = (lo + hi) / 2; - - int rc; - long oldpos; - - /* Save the tier 2 coding state. */ - jpc_save_t2state(encP); - oldpos = jas_stream_tell(outP); - assert(oldpos >= 0); - - assignHighSlopePassesToLayer(encP, tileP, lyrno, true, thresh); - - performTier2CodingOneLayer(encP, tileP, lyrno, outP, errorP); - - if (!*errorP) { - pos = jas_stream_tell(outP); - - /* Check the rate constraint. */ - assert(pos >= 0); - if (pos > allowedSize) { - /* The rate is too high. */ - lo = thresh; - } else if (pos <= allowedSize) { - /* The rate is low enough, so try higher. */ - hi = thresh; - if (!haveGoodThresh || thresh < goodThresh) { - goodThresh = thresh; - haveGoodThresh = true; - } + jpc_flt_t const thresh = (lo + hi) / 2; + + int rc; + long oldpos; + + /* Save the tier 2 coding state. */ + jpc_save_t2state(encP); + oldpos = jas_stream_tell(outP); + assert(oldpos >= 0); + + assignHighSlopePassesToLayer(encP, tileP, lyrno, true, thresh); + + performTier2CodingOneLayer(encP, tileP, lyrno, outP, errorP); + + if (!*errorP) { + pos = jas_stream_tell(outP); + + /* Check the rate constraint. */ + assert(pos >= 0); + if (pos > allowedSize) { + /* The rate is too high. */ + lo = thresh; + } else if (pos <= allowedSize) { + /* The rate is low enough, so try higher. */ + hi = thresh; + if (!haveGoodThresh || thresh < goodThresh) { + goodThresh = thresh; + haveGoodThresh = true; } } - /* Restore the tier 2 coding state. */ - jpc_restore_t2state(encP); - rc = jas_stream_seek(outP, oldpos, SEEK_SET); - if (rc < 0) - abort(); - - trace("iter %u: allowedlen=%08ld actuallen=%08ld thresh=%f", - numiters, allowedSize, pos, thresh); } + /* Restore the tier 2 coding state. */ + jpc_restore_t2state(encP); + rc = jas_stream_seek(outP, oldpos, SEEK_SET); + if (rc < 0) + abort(); + + trace("iter %u: allowedlen=%08ld actuallen=%08ld thresh=%f", + numiters, allowedSize, pos, thresh); + ++numiters; } while (lo < hi - 1e-3 && numiters < 32 && !*errorP); } @@ -1625,10 +1428,10 @@ doLayer(jpc_enc_t * const encP, static void -performTier2Coding(jpc_enc_t * const encP, - unsigned int const numlyrs, - uint_fast32_t * const cumlens, - const char ** const errorP) { +performTier2Coding(jpc_enc_t * const encP, + uint_fast32_t const numlyrs, + uint_fast32_t * const cumlens, + const char ** const errorP) { /*---------------------------------------------------------------------------- Encode in 'numlyrs' layers, such that at each layer L, the size is cumlens[L]. @@ -1636,7 +1439,7 @@ performTier2Coding(jpc_enc_t * const encP, jpc_enc_tile_t * const tileP = encP->curtile; jas_stream_t * outP; - unsigned int lyrno; + uint_fast32_t lyrno; jpc_flt_t mnrdslope; jpc_flt_t mxrdslope; @@ -1669,6 +1472,562 @@ performTier2Coding(jpc_enc_t * const encP, + + +static void +encodeTileBody(jpc_enc_t * const encoderP, + long const tilehdrlen, + const char ** const errorP) { +/*---------------------------------------------------------------------------- + Encode the body of encoder *encoderP's current tile, writing the encoded + result to the encoder's output stream. + + Assume the tile header is already in that stream, and its length is + 'tilehdrlen'. +-----------------------------------------------------------------------------*/ + jpc_enc_tile_t * const tileP = encoderP->curtile; + jpc_enc_cp_t * const cp = encoderP->cp; + + int rc; + + rc = jpc_enc_enccblks(encoderP); + if (rc != 0) + pm_asprintf(errorP, "jpc_enc_enccblks() failed"); + else { + double const rho = + (double) (tileP->brx - tileP->tlx) * (tileP->bry - tileP->tly) / + ((cp->refgrdwidth - cp->imgareatlx) * (cp->refgrdheight - + cp->imgareatly)); + const char * error; + + tileP->rawsize = cp->rawsize * rho; + + computeLayerSizes(encoderP, tileP, cp, rho, tilehdrlen); + + performTier2Coding(encoderP, tileP->numlyrs, tileP->lyrsizes, &error); + + if (error) { + pm_asprintf(errorP, "Tier 2 coding failed. %s", error); + pm_strfree(error); + } else { + int rc; + + rc = jpc_enc_encpkts(encoderP, encoderP->tmpstream); + if (rc != 0) + pm_asprintf(errorP, "jpc_enc_encpkts() failed\n"); + else + *errorP = NULL; + } + } +} + + + +static void +quantizeBand(jpc_enc_band_t * const bandP, + jpc_enc_tile_t * const tileP, + jpc_enc_cp_t * const cp, + int const prec, + int const tccp_numgbits, + int * const numgbitsP) { + + if (bandP->data) { + int actualnumbps; + uint_fast32_t y; + jpc_fix_t mxmag; + + for (y = 0, actualnumbps = 0, mxmag = 0; + y < jas_matrix_numrows(bandP->data); + ++y) { + uint_fast32_t x; + + for (x = 0; x < jas_matrix_numcols(bandP->data); ++x) + mxmag = MAX(mxmag, abs(jas_matrix_get(bandP->data, y, x))); + } + if (tileP->intmode) + actualnumbps = jpc_firstone(mxmag) + 1; + else + actualnumbps = jpc_firstone(mxmag) + 1 - JPC_FIX_FRACBITS; + + *numgbitsP = actualnumbps - (prec - 1 + bandP->analgain); + + if (!tileP->intmode) { + bandP->absstepsize = + jpc_fix_div( + jpc_inttofix(1 << (bandP->analgain + 1)), + bandP->synweight); + } else { + bandP->absstepsize = jpc_inttofix(1); + } + bandP->stepsize = jpc_abstorelstepsize( + bandP->absstepsize, prec + bandP->analgain); + /* I couldn't figure out what the calculation with tccp_numgbits and + stepsize does (or even what a step size is), but there is an + assertion elsewhere than the number here is at least at large as + the 'numbps' value for every code block, which means + 'actualnumbps'. In practice, we saw that not be true, so we added + the code to make 'actualnumbps' the floor here in hopes that would + fix the problem. But with the change, the image that caused the + assertion failure produces incorrect output. 22.11.07 + */ + bandP->numbps = + MAX(actualnumbps, + tccp_numgbits + JPC_QCX_GETEXPN(bandP->stepsize) - 1); + + if (!tileP->intmode && bandP->data) + quantize(bandP->data, bandP->absstepsize); + } else + *numgbitsP = 0; +} + + + +static int +encodemainbody(jpc_enc_t *enc) { + + int tileno; + int i; + jpc_sot_t *sot; + int rlvlno; + jpc_qcc_t *qcc; + jpc_cod_t *cod; + int adjust; + int j; + int absbandno; + long tilehdrlen; + long tilelen; + jpc_enc_tile_t *tile; + jpc_enc_cp_t *cp; + int samestepsizes; + jpc_enc_ccp_t *ccps; + jpc_enc_tccp_t *tccp; + int mingbits; /* Minimum number of guard bits needed */ + const char * error; + + cp = enc->cp; + + for (tileno = 0; tileno < cp->numtiles; ++tileno) { + uint_fast16_t cmptno; + + enc->curtile = jpc_enc_tile_create(enc->cp, enc->image, tileno); + if (!enc->curtile) + abort(); + + tile = enc->curtile; + + if (jas_getdbglevel() >= 10) { + jpc_enc_dump(enc); + } + + for (cmptno = 0; cmptno < tile->numtcmpts; ++cmptno) { + + jpc_enc_tcmpt_t * const comp = &tile->tcmpts[cmptno]; + + if (!cp->ccps[cmptno].sgnd) { + adjust = 1 << (cp->ccps[cmptno].prec - 1); + for (i = 0; i < jas_matrix_numrows(comp->data); ++i) { + for (j = 0; j < jas_matrix_numcols(comp->data); ++j) { + *jas_matrix_getref(comp->data, i, j) -= adjust; + } + } + } + } + + if (!tile->intmode) { + uint_fast16_t cmptno; + for (cmptno = 0; cmptno < tile->numtcmpts; ++cmptno) { + jpc_enc_tcmpt_t * const comp = &tile->tcmpts[cmptno]; + jas_matrix_asl(comp->data, JPC_FIX_FRACBITS); + } + } + + switch (tile->mctid) { + case JPC_MCT_RCT: + assert(jas_image_numcmpts(enc->image) == 3); + jpc_rct(tile->tcmpts[0].data, tile->tcmpts[1].data, + tile->tcmpts[2].data); + break; + case JPC_MCT_ICT: + assert(jas_image_numcmpts(enc->image) == 3); + jpc_ict(tile->tcmpts[0].data, tile->tcmpts[1].data, + tile->tcmpts[2].data); + break; + default: + break; + } + + for (i = 0; i < jas_image_numcmpts(enc->image); ++i) { + jpc_enc_tcmpt_t * const comp = &tile->tcmpts[i]; + jpc_tsfb_analyze(comp->tsfb, + ((comp->qmfbid == JPC_COX_RFT) ? + JPC_TSFB_RITIMODE : 0), comp->data); + + } + + for (cmptno = 0; cmptno < tile->numtcmpts; ++cmptno) { + + jpc_enc_tcmpt_t * const comp = &tile->tcmpts[cmptno]; + + mingbits = 0; + absbandno = 0; + /* All bands must have a corresponding quantizer step size, + even if they contain no samples and are never coded. */ + /* Some bands may not be hit by the loop below, so we must + initialize all of the step sizes to a sane value. */ + memset(comp->stepsizes, 0, sizeof(comp->stepsizes)); + for (rlvlno = 0; rlvlno < comp->numrlvls; ++rlvlno) { + jpc_enc_rlvl_t * const lvl = &comp->rlvls[rlvlno]; + + unsigned int bandno; + + if (!lvl->bands) { + absbandno += rlvlno ? 3 : 1; + continue; + } + for (bandno = 0; bandno < lvl->numbands; ++bandno) { + jpc_enc_band_t * const band = &lvl->bands[bandno]; + + int numgbits; + + quantizeBand(band, tile, cp, + cp->ccps[cmptno].prec, + cp->tccp.numgbits, + &numgbits); + + mingbits = MAX(mingbits, numgbits); + + comp->stepsizes[absbandno] = band->stepsize; + + ++absbandno; + } + } + + assert(JPC_FIX_FRACBITS >= JPC_NUMEXTRABITS); + if (!tile->intmode) { + jas_matrix_divpow2(comp->data, + JPC_FIX_FRACBITS - JPC_NUMEXTRABITS); + } else { + jas_matrix_asl(comp->data, JPC_NUMEXTRABITS); + } + } + + if (mingbits > cp->tccp.numgbits) { + fprintf(stderr, "error: too few guard bits (need at least %d)\n", + mingbits); + return -1; + } + + enc->tmpstream = jas_stream_memopen(0, 0); + if (!enc->tmpstream) { + fprintf(stderr, "cannot open tmp file\n"); + return -1; + } + + /* Write the tile header. */ + enc->mrk = jpc_ms_create(JPC_MS_SOT); + if (!enc->mrk) + return -1; + sot = &enc->mrk->parms.sot; + sot->len = 0; + sot->tileno = tileno; + sot->partno = 0; + sot->numparts = 1; + if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) { + fprintf(stderr, "cannot write SOT marker\n"); + return -1; + } + jpc_ms_destroy(enc->mrk); + enc->mrk = 0; + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + + tccp = &cp->tccp; + for (cmptno = 0; cmptno < cp->numcmpts; ++cmptno) { + jpc_enc_tcmpt_t * const comp = &tile->tcmpts[cmptno]; + jpc_enc_tcmpt_t * const comp0 = &tile->tcmpts[0]; + + if (comp->numrlvls != tccp->maxrlvls) { + if (!(enc->mrk = jpc_ms_create(JPC_MS_COD))) { + return -1; + } + /* XXX = this is not really correct. we are using comp #0's + precint sizes and other characteristics */ + cod = &enc->mrk->parms.cod; + cod->compparms.csty = 0; + cod->compparms.numdlvls = comp0->numrlvls - 1; + cod->prg = tile->prg; + cod->numlyrs = tile->numlyrs; + cod->compparms.cblkwidthval = + JPC_COX_CBLKSIZEEXPN(comp0->cblkwidthexpn); + cod->compparms.cblkheightval = + JPC_COX_CBLKSIZEEXPN(comp0->cblkheightexpn); + cod->compparms.cblksty = comp0->cblksty; + cod->compparms.qmfbid = comp0->qmfbid; + cod->mctrans = (tile->mctid != JPC_MCT_NONE); + for (i = 0; i < comp0->numrlvls; ++i) { + cod->compparms.rlvls[i].parwidthval = + comp0->rlvls[i].prcwidthexpn; + cod->compparms.rlvls[i].parheightval = + comp0->rlvls[i].prcheightexpn; + } + if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) { + return -1; + } + jpc_ms_destroy(enc->mrk); + enc->mrk = 0; + } + } + + for (cmptno = 0; cmptno < cp->numcmpts; ++cmptno) { + jpc_enc_tcmpt_t * const comp = &tile->tcmpts[cmptno]; + + ccps = &cp->ccps[cmptno]; + if (ccps->numstepsizes == comp->numstepsizes) { + unsigned int bandno; + samestepsizes = 1; + for (bandno = 0; bandno < ccps->numstepsizes; ++bandno) { + if (ccps->stepsizes[bandno] != comp->stepsizes[bandno]) { + samestepsizes = 0; + break; + } + } + } else { + samestepsizes = 0; + } + if (!samestepsizes) { + if (!(enc->mrk = jpc_ms_create(JPC_MS_QCC))) { + return -1; + } + qcc = &enc->mrk->parms.qcc; + qcc->compno = cmptno; + qcc->compparms.numguard = cp->tccp.numgbits; + qcc->compparms.qntsty = (comp->qmfbid == JPC_COX_INS) ? + JPC_QCX_SEQNT : JPC_QCX_NOQNT; + qcc->compparms.numstepsizes = comp->numstepsizes; + qcc->compparms.stepsizes = comp->stepsizes; + if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) { + return -1; + } + qcc->compparms.stepsizes = 0; + jpc_ms_destroy(enc->mrk); + enc->mrk = 0; + } + } + + /* Write a SOD marker to indicate the end of the tile header. */ + if (!(enc->mrk = jpc_ms_create(JPC_MS_SOD))) { + return -1; + } + if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) { + fprintf(stderr, "cannot write SOD marker\n"); + return -1; + } + jpc_ms_destroy(enc->mrk); + enc->mrk = 0; + tilehdrlen = jas_stream_getrwcount(enc->tmpstream); + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + + encodeTileBody(enc, tilehdrlen, &error); + /* Encodes current tile; writes to output file */ + + if (error) { + fprintf(stderr, "Failed to encode body of tile %u. %s\n", + tileno, error); + pm_strfree(error); + return -1; + } + tilelen = jas_stream_tell(enc->tmpstream); + + if (jas_stream_seek(enc->tmpstream, 6, SEEK_SET) < 0) { + return -1; + } + jpc_putuint32(enc->tmpstream, tilelen); + + if (jas_stream_seek(enc->tmpstream, 0, SEEK_SET) < 0) { + return -1; + } + if (jpc_putdata(enc->out, enc->tmpstream, -1)) { + return -1; + } + enc->len += tilelen; + + jas_stream_close(enc->tmpstream); + enc->tmpstream = 0; + + jpc_enc_tile_destroy(enc->curtile); + enc->curtile = 0; + + } + + return 0; +} + + + +int +jpc_encode(jas_image_t *image, jas_stream_t *out, char *optstr) { + + jpc_enc_t *enc; + jpc_enc_cp_t *cp; + + enc = 0; + cp = 0; + + jpc_initluts(); + + if (!(cp = cp_create(optstr, image))) { + fprintf(stderr, "invalid JP encoder options\n"); + goto error; + } + + if (!(enc = jpc_enc_create(cp, out, image))) { + goto error; + } + cp = 0; + + /* Encode the main header. */ + if (encodemainhdr(enc)) { + goto error; + } + + /* Encode the main body. This constitutes most of the encoding work. */ + if (encodemainbody(enc)) { + goto error; + } + + /* Write EOC marker segment. */ + if (!(enc->mrk = jpc_ms_create(JPC_MS_EOC))) { + goto error; + } + if (jpc_putms(enc->out, enc->cstate, enc->mrk)) { + fprintf(stderr, "cannot write EOI marker\n"); + goto error; + } + jpc_ms_destroy(enc->mrk); + enc->mrk = 0; + + if (jas_stream_flush(enc->out)) { + goto error; + } + + jpc_enc_destroy(enc); + + return 0; + +error: + if (cp) { + cp_destroy(cp); + } + if (enc) { + jpc_enc_destroy(enc); + } + return -1; +} + + + +/*****************************************************************************\ +* 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) { + cp_destroy(enc->cp); + } + if (enc->cstate) { + jpc_cstate_destroy(enc->cstate); + } + if (enc->tmpstream) { + jas_stream_close(enc->tmpstream); + } + + jas_free(enc); +} + + + +void +quantize(jas_matrix_t *data, jpc_fix_t stepsize) { + + int i; + int j; + jpc_fix_t t; + + if (stepsize == jpc_inttofix(1)) { + return; + } + + for (i = 0; i < jas_matrix_numrows(data); ++i) { + for (j = 0; j < jas_matrix_numcols(data); ++j) { + t = jas_matrix_get(data, i, j); + +{ + if (t < 0) { + t = jpc_fix_neg(jpc_fix_div(jpc_fix_neg(t), stepsize)); + } else { + t = jpc_fix_div(t, stepsize); + } +} + + jas_matrix_set(data, i, j, t); + } + } +} + + + /*****************************************************************************\ * Tile constructors and destructors. \*****************************************************************************/ @@ -2227,7 +2586,7 @@ prc_create(jpc_enc_prc_t *prc, jpc_enc_cp_t *cp, jpc_enc_band_t *band) { } prc->cblks = jas_malloc(prc->numcblks * sizeof(jpc_enc_cblk_t)); - + if (!prc->cblks) goto error; for (cblkno = 0, cblk = prc->cblks; @@ -2445,9 +2804,9 @@ jpc_enc_dump(jpc_enc_t *enc) { prcno < rlvl->numprcs; ++prcno, ++prc) { fprintf(stderr, " prc %5d %5d %5d %5d (%5d %5d)\n", - (int)prc->tlx, (int)prc->tly, + (int)prc->tlx, (int)prc->tly, (int)prc->brx, (int)prc->bry, - (int)(prc->brx - prc->tlx), + (int)(prc->brx - prc->tlx), (int)(prc->bry - prc->tly)); if (!prc->cblks) { continue; @@ -2468,352 +2827,6 @@ jpc_enc_dump(jpc_enc_t *enc) { -static int -jpc_enc_encodemainbody(jpc_enc_t *enc) { - - int tileno; - int i; - jpc_sot_t *sot; - jpc_enc_tcmpt_t *comp; - jpc_enc_tcmpt_t *endcomps; - jpc_enc_band_t *band; - jpc_enc_band_t *endbands; - jpc_enc_rlvl_t *lvl; - int rlvlno; - jpc_qcc_t *qcc; - jpc_cod_t *cod; - int adjust; - int j; - int absbandno; - long tilehdrlen; - long tilelen; - jpc_enc_tile_t *tile; - jpc_enc_cp_t *cp; - double rho; - uint_fast16_t cmptno; - int samestepsizes; - jpc_enc_ccp_t *ccps; - jpc_enc_tccp_t *tccp; - int bandno; - uint_fast32_t x; - uint_fast32_t y; - int mingbits; - int actualnumbps; - jpc_fix_t mxmag; - jpc_fix_t mag; - int numgbits; - const char * error; - - cp = enc->cp; - - for (tileno = 0; tileno < cp->numtiles; ++tileno) { - enc->curtile = jpc_enc_tile_create(enc->cp, enc->image, tileno); - if (!enc->curtile) - abort(); - - tile = enc->curtile; - - if (jas_getdbglevel() >= 10) { - jpc_enc_dump(enc); - } - - endcomps = &tile->tcmpts[tile->numtcmpts]; - for (cmptno = 0, comp = tile->tcmpts; - cmptno < tile->numtcmpts; - ++cmptno, ++comp) { - if (!cp->ccps[cmptno].sgnd) { - adjust = 1 << (cp->ccps[cmptno].prec - 1); - for (i = 0; i < jas_matrix_numrows(comp->data); ++i) { - for (j = 0; j < jas_matrix_numcols(comp->data); ++j) { - *jas_matrix_getref(comp->data, i, j) -= adjust; - } - } - } - } - - if (!tile->intmode) { - endcomps = &tile->tcmpts[tile->numtcmpts]; - for (comp = tile->tcmpts; comp != endcomps; ++comp) { - jas_matrix_asl(comp->data, JPC_FIX_FRACBITS); - } - } - - switch (tile->mctid) { - case JPC_MCT_RCT: - assert(jas_image_numcmpts(enc->image) == 3); - jpc_rct(tile->tcmpts[0].data, tile->tcmpts[1].data, - tile->tcmpts[2].data); - break; - case JPC_MCT_ICT: - assert(jas_image_numcmpts(enc->image) == 3); - jpc_ict(tile->tcmpts[0].data, tile->tcmpts[1].data, - tile->tcmpts[2].data); - break; - default: - break; - } - - for (i = 0; i < jas_image_numcmpts(enc->image); ++i) { - comp = &tile->tcmpts[i]; - jpc_tsfb_analyze(comp->tsfb, - ((comp->qmfbid == JPC_COX_RFT) ? - JPC_TSFB_RITIMODE : 0), comp->data); - - } - - endcomps = &tile->tcmpts[tile->numtcmpts]; - for (cmptno = 0, comp = tile->tcmpts; - comp != endcomps; - ++cmptno, ++comp) { - mingbits = 0; - absbandno = 0; - /* All bands must have a corresponding quantizer step size, - even if they contain no samples and are never coded. */ - /* Some bands may not be hit by the loop below, so we must - initialize all of the step sizes to a sane value. */ - memset(comp->stepsizes, 0, sizeof(comp->stepsizes)); - for (rlvlno = 0, lvl = comp->rlvls; - rlvlno < comp->numrlvls; - ++rlvlno, ++lvl) { - if (!lvl->bands) { - absbandno += rlvlno ? 3 : 1; - continue; - } - endbands = &lvl->bands[lvl->numbands]; - for (band = lvl->bands; band != endbands; ++band) { - if (!band->data) { - ++absbandno; - continue; - } - actualnumbps = 0; - mxmag = 0; - for (y = 0; y < jas_matrix_numrows(band->data); ++y) { - for (x = 0; x < jas_matrix_numcols(band->data); ++x) { - mag = abs(jas_matrix_get(band->data, y, x)); - if (mag > mxmag) { - mxmag = mag; - } - } - } - if (tile->intmode) { - actualnumbps = - jpc_firstone(mxmag) + 1; - } else { - actualnumbps = - jpc_firstone(mxmag) + 1 - JPC_FIX_FRACBITS; - } - numgbits = actualnumbps - (cp->ccps[cmptno].prec - 1 + - band->analgain); - if (numgbits > mingbits) { - mingbits = numgbits; - } - if (!tile->intmode) { - band->absstepsize = - jpc_fix_div( - jpc_inttofix(1 << (band->analgain + 1)), - band->synweight); - } else { - band->absstepsize = jpc_inttofix(1); - } - band->stepsize = jpc_abstorelstepsize( - band->absstepsize, cp->ccps[cmptno].prec + - band->analgain); - band->numbps = cp->tccp.numgbits + - JPC_QCX_GETEXPN(band->stepsize) - 1; - - if ((!tile->intmode) && band->data) { - quantize(band->data, band->absstepsize); - } - - comp->stepsizes[absbandno] = band->stepsize; - ++absbandno; - } - } - - assert(JPC_FIX_FRACBITS >= JPC_NUMEXTRABITS); - if (!tile->intmode) { - jas_matrix_divpow2(comp->data, - JPC_FIX_FRACBITS - JPC_NUMEXTRABITS); - } else { - jas_matrix_asl(comp->data, JPC_NUMEXTRABITS); - } - } - - if (mingbits > cp->tccp.numgbits) { - fprintf(stderr, "error: too few guard bits (need at least %d)\n", - mingbits); - return -1; - } - - enc->tmpstream = jas_stream_memopen(0, 0); - if (!enc->tmpstream) { - fprintf(stderr, "cannot open tmp file\n"); - return -1; - } - - /* Write the tile header. */ - enc->mrk = jpc_ms_create(JPC_MS_SOT); - if (!enc->mrk) - return -1; - sot = &enc->mrk->parms.sot; - sot->len = 0; - sot->tileno = tileno; - sot->partno = 0; - sot->numparts = 1; - if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) { - fprintf(stderr, "cannot write SOT marker\n"); - return -1; - } - jpc_ms_destroy(enc->mrk); - enc->mrk = 0; - -/************************************************************************/ -/************************************************************************/ -/************************************************************************/ - - tccp = &cp->tccp; - for (cmptno = 0; cmptno < cp->numcmpts; ++cmptno) { - comp = &tile->tcmpts[cmptno]; - if (comp->numrlvls != tccp->maxrlvls) { - if (!(enc->mrk = jpc_ms_create(JPC_MS_COD))) { - return -1; - } - /* XXX = this is not really correct. we are using comp #0's - precint sizes and other characteristics */ - comp = &tile->tcmpts[0]; - cod = &enc->mrk->parms.cod; - cod->compparms.csty = 0; - cod->compparms.numdlvls = comp->numrlvls - 1; - cod->prg = tile->prg; - cod->numlyrs = tile->numlyrs; - cod->compparms.cblkwidthval = - JPC_COX_CBLKSIZEEXPN(comp->cblkwidthexpn); - cod->compparms.cblkheightval = - JPC_COX_CBLKSIZEEXPN(comp->cblkheightexpn); - cod->compparms.cblksty = comp->cblksty; - cod->compparms.qmfbid = comp->qmfbid; - cod->mctrans = (tile->mctid != JPC_MCT_NONE); - for (i = 0; i < comp->numrlvls; ++i) { - cod->compparms.rlvls[i].parwidthval = - comp->rlvls[i].prcwidthexpn; - cod->compparms.rlvls[i].parheightval = - comp->rlvls[i].prcheightexpn; - } - if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) { - return -1; - } - jpc_ms_destroy(enc->mrk); - enc->mrk = 0; - } - } - - for (cmptno = 0, comp = tile->tcmpts; - cmptno < cp->numcmpts; - ++cmptno, ++comp) { - ccps = &cp->ccps[cmptno]; - if (ccps->numstepsizes == comp->numstepsizes) { - samestepsizes = 1; - for (bandno = 0; bandno < ccps->numstepsizes; ++bandno) { - if (ccps->stepsizes[bandno] != comp->stepsizes[bandno]) { - samestepsizes = 0; - break; - } - } - } else { - samestepsizes = 0; - } - if (!samestepsizes) { - if (!(enc->mrk = jpc_ms_create(JPC_MS_QCC))) { - return -1; - } - qcc = &enc->mrk->parms.qcc; - qcc->compno = cmptno; - qcc->compparms.numguard = cp->tccp.numgbits; - qcc->compparms.qntsty = (comp->qmfbid == JPC_COX_INS) ? - JPC_QCX_SEQNT : JPC_QCX_NOQNT; - qcc->compparms.numstepsizes = comp->numstepsizes; - qcc->compparms.stepsizes = comp->stepsizes; - if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) { - return -1; - } - qcc->compparms.stepsizes = 0; - jpc_ms_destroy(enc->mrk); - enc->mrk = 0; - } - } - - /* Write a SOD marker to indicate the end of the tile header. */ - if (!(enc->mrk = jpc_ms_create(JPC_MS_SOD))) { - return -1; - } - if (jpc_putms(enc->tmpstream, enc->cstate, enc->mrk)) { - fprintf(stderr, "cannot write SOD marker\n"); - return -1; - } - jpc_ms_destroy(enc->mrk); - enc->mrk = 0; - tilehdrlen = jas_stream_getrwcount(enc->tmpstream); - -/************************************************************************/ -/************************************************************************/ -/************************************************************************/ - - if (jpc_enc_enccblks(enc)) { - abort(); - return -1; - } - - cp = enc->cp; - rho = (double) (tile->brx - tile->tlx) * (tile->bry - tile->tly) / - ((cp->refgrdwidth - cp->imgareatlx) * (cp->refgrdheight - - cp->imgareatly)); - tile->rawsize = cp->rawsize * rho; - - computeLayerSizes(enc, tile, cp, rho, tilehdrlen, &error); - - if (!error) { - int rc; - performTier2Coding(enc, tile->numlyrs, tile->lyrsizes, &error); - - rc = jpc_enc_encodetiledata(enc); - if (rc != 0) - pm_asprintf(&error, "jpc_enc_encodetiledata() failed\n"); - } - - if (error) { - fprintf(stderr, "%s\n", error); - pm_strfree(error); - return -1; - } - - tilelen = jas_stream_tell(enc->tmpstream); - - if (jas_stream_seek(enc->tmpstream, 6, SEEK_SET) < 0) { - return -1; - } - jpc_putuint32(enc->tmpstream, tilelen); - - if (jas_stream_seek(enc->tmpstream, 0, SEEK_SET) < 0) { - return -1; - } - if (jpc_putdata(enc->out, enc->tmpstream, -1)) { - return -1; - } - enc->len += tilelen; - - jas_stream_close(enc->tmpstream); - enc->tmpstream = 0; - - jpc_enc_tile_destroy(enc->curtile); - enc->curtile = 0; - - } - - return 0; -} - - - /* * Copyright (c) 1999-2000 Image Power, Inc. and the University of * British Columbia. diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_math.c b/converter/other/jpeg2000/libjasper/jpc/jpc_math.c index 01e3611e..a884ed4d 100644 --- a/converter/other/jpeg2000/libjasper/jpc/jpc_math.c +++ b/converter/other/jpeg2000/libjasper/jpc/jpc_math.c @@ -50,6 +50,8 @@ jpc_firstone(int_fast32_t const arg) { /*---------------------------------------------------------------------------- Calculate the bit position of the first leading one in a nonnegative integer. + + LSB is bit position 0. Iff there are no ones, return -1. -----------------------------------------------------------------------------*/ int n; int x; diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_t1enc.c b/converter/other/jpeg2000/libjasper/jpc/jpc_t1enc.c index e1af0f61..34b9738c 100644 --- a/converter/other/jpeg2000/libjasper/jpc/jpc_t1enc.c +++ b/converter/other/jpeg2000/libjasper/jpc/jpc_t1enc.c @@ -124,6 +124,8 @@ #include <stdlib.h> #include <assert.h> +#include "netpbm/nstring.h" + #include "jasper/jas_fix.h" #include "jasper/jas_malloc.h" #include "jasper/jas_math.h" @@ -149,74 +151,111 @@ static int jpc_encrawsigpass(jpc_bitstream_t *out, int bitpos, int, static int jpc_encrawrefpass(jpc_bitstream_t *out, int bitpos, int, jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec); -/******************************************************************************\ +/*****************************************************************************\ * Code for encoding code blocks. -\******************************************************************************/ +\*****************************************************************************/ -/* Encode all of the code blocks associated with the current tile. */ -int jpc_enc_enccblks(jpc_enc_t *enc) -{ - jpc_enc_tcmpt_t *tcmpt; - jpc_enc_tcmpt_t *endcomps; - jpc_enc_rlvl_t *lvl; - jpc_enc_rlvl_t *endlvls; - jpc_enc_band_t *band; - jpc_enc_band_t *endbands; - jpc_enc_cblk_t *cblk; - jpc_enc_cblk_t *endcblks; - int i; - int j; - int mx; - int bmx; - int v; - jpc_enc_tile_t *tile; - uint_fast32_t prcno; - jpc_enc_prc_t *prc; +static void +encodeBlocksOfPrecinct(jpc_enc_prc_t * const prcP, + jpc_enc_band_t * const bandP, + jpc_enc_tcmpt_t * const tcmptP, + jpc_enc_t * const encoderP, + const char ** const errorP) { - tile = enc->curtile; + if (prcP->cblks) { + int bmx; + uint_fast32_t cblkno; - endcomps = &tile->tcmpts[tile->numtcmpts]; - for (tcmpt = tile->tcmpts; tcmpt != endcomps; ++tcmpt) { - endlvls = &tcmpt->rlvls[tcmpt->numrlvls]; - for (lvl = tcmpt->rlvls; lvl != endlvls; ++lvl) { - if (!lvl->bands) { - continue; - } - endbands = &lvl->bands[lvl->numbands]; - for (band = lvl->bands; band != endbands; ++band) { - if (!band->data) { - continue; + for (cblkno = 0, bmx = 0; cblkno < prcP->numcblks; ++ cblkno) { + jpc_enc_cblk_t * const cblkP = &prcP->cblks[cblkno]; + + int mx; + uint_fast32_t row; + + for (row = 0, mx = 0; + row < jas_matrix_numrows(cblkP->data); + ++row) { + + uint_fast32_t col; + + for (col = 0; col < jas_matrix_numcols(cblkP->data); ++col) { + int const v = abs(jas_matrix_get(cblkP->data, row, col)); + if (v > mx) + mx = v; } - for (prcno = 0, prc = band->prcs; prcno < lvl->numprcs; ++prcno, ++prc) { - if (!prc->cblks) { - continue; - } - bmx = 0; - endcblks = &prc->cblks[prc->numcblks]; - for (cblk = prc->cblks; cblk != endcblks; ++cblk) { - mx = 0; - for (i = 0; i < jas_matrix_numrows(cblk->data); ++i) { - for (j = 0; j < jas_matrix_numcols(cblk->data); ++j) { - v = abs(jas_matrix_get(cblk->data, i, j)); - if (v > mx) { - mx = v; - } - } - } - if (mx > bmx) { - bmx = mx; - } - cblk->numbps = JAS_MAX(jpc_firstone(mx) + 1 - JPC_NUMEXTRABITS, 0); - } + } + if (mx > bmx) + bmx = mx; - for (cblk = prc->cblks; cblk != endcblks; ++cblk) { - cblk->numimsbs = band->numbps - cblk->numbps; - assert(cblk->numimsbs >= 0); - } + cblkP->numbps = MAX(jpc_firstone(mx) + 1 - JPC_NUMEXTRABITS, 0); + } + + for (cblkno = 0; cblkno < prcP->numcblks; ++ cblkno) { + jpc_enc_cblk_t * const cblkP = &prcP->cblks[cblkno]; - for (cblk = prc->cblks; cblk != endcblks; ++cblk) { - if (jpc_enc_enccblk(enc, cblk->stream, tcmpt, band, cblk)) { - return -1; + assert(cblkP->numbps <= bandP->numbps); + } + + for (cblkno = 0, *errorP = NULL; + cblkno < prcP->numcblks && !*errorP; + ++ cblkno) { + + jpc_enc_cblk_t * const cblkP = &prcP->cblks[cblkno]; + + int rc; + + rc = jpc_enc_enccblk(encoderP, + cblkP->stream, tcmptP, bandP, cblkP); + if (rc != 0) + pm_asprintf(errorP, "Encoding failed on code block %u " + "of %u", (unsigned)cblkno, + (unsigned)prcP->numcblks); + } + } else + *errorP = NULL; +} + + + +int +jpc_enc_enccblks(jpc_enc_t * const encoderP) { +/*---------------------------------------------------------------------------- + Encode all of the code blocks associated with the current tile. +-----------------------------------------------------------------------------*/ + jpc_enc_tile_t * const tileP = encoderP->curtile; + + uint_fast32_t cmptno; + + for (cmptno = 0; cmptno < tileP->numtcmpts; ++cmptno) { + jpc_enc_tcmpt_t * const tcmptP = &tileP->tcmpts[cmptno]; + + unsigned int lvlno; + for (lvlno = 0; lvlno < tcmptP->numrlvls; ++ lvlno) { + jpc_enc_rlvl_t * const lvlP = &tcmptP->rlvls[lvlno]; + + if (lvlP->bands) { + uint_fast32_t bandno; + + for (bandno = 0; bandno < lvlP->numbands; ++bandno) { + jpc_enc_band_t * const bandP = &lvlP->bands[bandno]; + + if (bandP->data) { + uint_fast32_t prcno; + + for (prcno = 0; prcno < lvlP->numprcs; ++prcno) { + + const char * error; + + encodeBlocksOfPrecinct(&bandP->prcs[prcno], + bandP, + tcmptP, + encoderP, + &error); + + if (error) { + pm_strfree(error); + return -1; + } } } } @@ -226,6 +265,8 @@ int jpc_enc_enccblks(jpc_enc_t *enc) return 0; } + + static int getthebyte(jas_stream_t *in, long off) { int c; diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_util.c b/converter/other/jpeg2000/libjasper/jpc/jpc_util.c index fede2bef..e6e3942a 100644 --- a/converter/other/jpeg2000/libjasper/jpc/jpc_util.c +++ b/converter/other/jpeg2000/libjasper/jpc/jpc_util.c @@ -114,9 +114,9 @@ * $Id$ */ -/******************************************************************************\ +/*****************************************************************************\ * Includes -\******************************************************************************/ +\*****************************************************************************/ #include <assert.h> #include <stdio.h> @@ -133,21 +133,21 @@ #include "jpc_flt.h" #include "jpc_util.h" -/******************************************************************************\ +/*****************************************************************************\ * Miscellaneous Functions -\******************************************************************************/ +\*****************************************************************************/ -int jpc_atoaf(const char *s, int *numvalues, double **values) -{ - static char delim[] = ", \t\n"; +static unsigned int +countOfTokens(const char * const s, + const char * const delim) { + + unsigned int n; char buf[4096]; - int n; - double *vs; - char *cp; + const char * cp; strncpy(buf, s, sizeof(buf)); buf[sizeof(buf) - 1] = '\0'; - n = 0; + n = 0; /* initial value */ if ((cp = strtok(buf, delim))) { ++n; while ((cp = strtok(0, delim))) { @@ -156,32 +156,57 @@ int jpc_atoaf(const char *s, int *numvalues, double **values) } } } + return n; +} + + + +int +jpc_atoaf(const char * const s, + int * const numvaluesP, + double ** const valuesP) { +/*---------------------------------------------------------------------------- + Parse a string like "3.2,9,-5". Return as *numvaluesP the number of + values in the string and as *valuesP a malloced array of the values. - if (n) { - if (!(vs = jas_malloc(n * sizeof(double)))) { + But if the string is empty (*numvaluesP is zero), return *valuesP NULL. + + Delimiters can be comma as in the example or space, tab, or newline. +-----------------------------------------------------------------------------*/ + char const delim[] = ", \t\n"; + + unsigned int const valueCt = countOfTokens(s, delim); + + if (valueCt > 0) { + unsigned int i; + double * vs; + const char * cp; + char buf[4096]; + + if (!(vs = jas_malloc(valueCt * sizeof(double)))) { return -1; } strncpy(buf, s, sizeof(buf)); buf[sizeof(buf) - 1] = '\0'; - n = 0; + i = 0; if ((cp = strtok(buf, delim))) { - vs[n] = atof(cp); - ++n; + vs[i] = atof(cp); + ++i; while ((cp = strtok(0, delim))) { if (cp[0] != '\0') { - vs[n] = atof(cp); - ++n; + vs[i] = atof(cp); + ++i; } } } + assert(i == valueCt); + *numvaluesP = valueCt; + *valuesP = vs; } else { - vs = 0; + *valuesP = NULL; + *numvaluesP = 0; } - - *numvalues = n; - *values = vs; - return 0; } |