From a70405848cb06782036364a88e27f452fb0a0b32 Mon Sep 17 00:00:00 2001 From: giraffedata Date: Sat, 31 Dec 2022 00:32:37 +0000 Subject: promote Development to Advanced git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@4489 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- .../other/jpeg2000/libjasper/base/jas_image.c | 33 +- converter/other/jpeg2000/libjasper/jpc/jpc_enc.c | 2585 ++++++++++---------- converter/other/jpeg2000/libjasper/jpc/jpc_math.c | 2 + converter/other/jpeg2000/libjasper/jpc/jpc_t1enc.c | 163 +- converter/other/jpeg2000/libjasper/jpc/jpc_util.c | 71 +- converter/other/jpeg2000/pamtojpeg2k.c | 11 +- converter/ppm/ppmtompeg/frame.c | 68 +- converter/ppm/ppmtompeg/readframe.c | 103 +- 8 files changed, 1567 insertions(+), 1469 deletions(-) (limited to 'converter') 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) { - - int i; - int j; - jpc_fix_t t; - - if (stepsize == jpc_inttofix(1)) { - return; - } + uint_fast32_t const overhead = mainhdrlen + maintlrlen; - 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,1151 +1472,1361 @@ performTier2Coding(jpc_enc_t * const encP, -/*****************************************************************************\ -* Tile constructors and destructors. -\*****************************************************************************/ - -jpc_enc_tile_t * -jpc_enc_tile_create(jpc_enc_cp_t *cp, jas_image_t *image, int tileno) { - jpc_enc_tile_t *tile; - uint_fast32_t htileno; - uint_fast32_t vtileno; - uint_fast16_t lyrno; - uint_fast16_t cmptno; - jpc_enc_tcmpt_t *tcmpt; - if (!(tile = jas_malloc(sizeof(jpc_enc_tile_t)))) { - goto error; - } +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. - /* Initialize a few members used in error recovery. */ - tile->tcmpts = 0; - tile->lyrsizes = 0; - tile->numtcmpts = cp->numcmpts; - tile->pi = 0; + 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; - tile->tileno = tileno; - htileno = tileno % cp->numhtiles; - vtileno = tileno / cp->numhtiles; + int rc; - /* Calculate the coordinates of the top-left and bottom-right - corners of the tile. */ - tile->tlx = JAS_MAX(cp->tilegrdoffx + htileno * cp->tilewidth, - cp->imgareatlx); - tile->tly = JAS_MAX(cp->tilegrdoffy + vtileno * cp->tileheight, - cp->imgareatly); - tile->brx = JAS_MIN(cp->tilegrdoffx + (htileno + 1) * cp->tilewidth, - cp->refgrdwidth); - tile->bry = JAS_MIN(cp->tilegrdoffy + (vtileno + 1) * cp->tileheight, - cp->refgrdheight); + 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; - /* Initialize some tile coding parameters. */ - tile->intmode = cp->tcp.intmode; - tile->csty = cp->tcp.csty; - tile->prg = cp->tcp.prg; - tile->mctid = cp->tcp.mctid; + tileP->rawsize = cp->rawsize * rho; - tile->numlyrs = cp->tcp.numlyrs; - if (!(tile->lyrsizes = jas_malloc(tile->numlyrs * - sizeof(uint_fast32_t)))) { - goto error; - } - for (lyrno = 0; lyrno < tile->numlyrs; ++lyrno) { - tile->lyrsizes[lyrno] = 0; - } + computeLayerSizes(encoderP, tileP, cp, rho, tilehdrlen); - /* Allocate an array for the per-tile-component information. */ - if (!(tile->tcmpts = jas_malloc(cp->numcmpts * sizeof(jpc_enc_tcmpt_t)))) { - goto error; - } - /* Initialize a few members critical for error recovery. */ - for (cmptno = 0, tcmpt = tile->tcmpts; cmptno < cp->numcmpts; - ++cmptno, ++tcmpt) { - tcmpt->rlvls = 0; - tcmpt->tsfb = 0; - tcmpt->data = 0; - } - /* Initialize the per-tile-component information. */ - for (cmptno = 0, tcmpt = tile->tcmpts; cmptno < cp->numcmpts; - ++cmptno, ++tcmpt) { - if (!tcmpt_create(tcmpt, cp, image, tile)) { - goto error; - } - } + performTier2Coding(encoderP, tileP->numlyrs, tileP->lyrsizes, &error); - /* Initialize the synthesis weights for the MCT. */ - switch (tile->mctid) { - case JPC_MCT_RCT: - tile->tcmpts[0].synweight = jpc_dbltofix(sqrt(3.0)); - tile->tcmpts[1].synweight = jpc_dbltofix(sqrt(0.6875)); - tile->tcmpts[2].synweight = jpc_dbltofix(sqrt(0.6875)); - break; - case JPC_MCT_ICT: - tile->tcmpts[0].synweight = jpc_dbltofix(sqrt(3.0000)); - tile->tcmpts[1].synweight = jpc_dbltofix(sqrt(3.2584)); - tile->tcmpts[2].synweight = jpc_dbltofix(sqrt(2.4755)); - break; - default: - case JPC_MCT_NONE: - for (cmptno = 0, tcmpt = tile->tcmpts; cmptno < cp->numcmpts; - ++cmptno, ++tcmpt) { - tcmpt->synweight = JPC_FIX_ONE; - } - break; - } + if (error) { + pm_asprintf(errorP, "Tier 2 coding failed. %s", error); + pm_strfree(error); + } else { + int rc; - if (!(tile->pi = jpc_enc_pi_create(cp, tile))) { - goto error; + rc = jpc_enc_encpkts(encoderP, encoderP->tmpstream); + if (rc != 0) + pm_asprintf(errorP, "jpc_enc_encpkts() failed\n"); + else + *errorP = NULL; + } } +} - return tile; -error: - if (tile) { - jpc_enc_tile_destroy(tile); - } - return 0; +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; } -void -jpc_enc_tile_destroy(jpc_enc_tile_t *tile) { - - jpc_enc_tcmpt_t *tcmpt; - uint_fast16_t cmptno; +static int +encodemainbody(jpc_enc_t *enc) { - if (tile->tcmpts) { - for (cmptno = 0, tcmpt = tile->tcmpts; cmptno < - tile->numtcmpts; ++cmptno, ++tcmpt) { - tcmpt_destroy(tcmpt); - } - jas_free(tile->tcmpts); - } - if (tile->lyrsizes) { - jas_free(tile->lyrsizes); - } - if (tile->pi) { - jpc_pi_destroy(tile->pi); - } - jas_free(tile); -} + 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; -static jpc_enc_tcmpt_t * -tcmpt_create(jpc_enc_tcmpt_t * const tcmpt, - jpc_enc_cp_t * const cp, - jas_image_t * const image, - jpc_enc_tile_t * const tile) { + enc->curtile = jpc_enc_tile_create(enc->cp, enc->image, tileno); + if (!enc->curtile) + abort(); - uint_fast16_t cmptno; - uint_fast16_t rlvlno; - jpc_enc_rlvl_t *rlvl; - uint_fast32_t tlx; - uint_fast32_t tly; - uint_fast32_t brx; - uint_fast32_t bry; - uint_fast32_t cmpttlx; - uint_fast32_t cmpttly; - jpc_enc_ccp_t *ccp; - jpc_tsfb_band_t bandinfos[JPC_MAXBANDS]; + tile = enc->curtile; - tcmpt->tile = tile; - tcmpt->tsfb = 0; - tcmpt->data = 0; - tcmpt->rlvls = 0; + if (jas_getdbglevel() >= 10) { + jpc_enc_dump(enc); + } - /* Deduce the component number. */ - cmptno = tcmpt - tile->tcmpts; + for (cmptno = 0; cmptno < tile->numtcmpts; ++cmptno) { - ccp = &cp->ccps[cmptno]; + jpc_enc_tcmpt_t * const comp = &tile->tcmpts[cmptno]; - /* Compute the coordinates of the top-left and bottom-right - corners of this tile-component. */ - tlx = JPC_CEILDIV(tile->tlx, ccp->sampgrdstepx); - tly = JPC_CEILDIV(tile->tly, ccp->sampgrdstepy); - brx = JPC_CEILDIV(tile->brx, ccp->sampgrdstepx); - bry = JPC_CEILDIV(tile->bry, ccp->sampgrdstepy); + 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; + } + } + } + } - /* Create a sequence to hold the tile-component sample data. */ - tcmpt->data = jas_seq2d_create(tlx, tly, brx, bry); - if (!tcmpt->data) - goto error; + 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); + } + } - /* Get the image data associated with this tile-component. */ - cmpttlx = JPC_CEILDIV(cp->imgareatlx, ccp->sampgrdstepx); - cmpttly = JPC_CEILDIV(cp->imgareatly, ccp->sampgrdstepy); - if (jas_image_readcmpt(image, cmptno, tlx - cmpttlx, tly - cmpttly, - brx - tlx, bry - tly, tcmpt->data)) { - goto error; - } + 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; + } - tcmpt->synweight = 0; - tcmpt->qmfbid = cp->tccp.qmfbid; - tcmpt->numrlvls = cp->tccp.maxrlvls; - tcmpt->numbands = 3 * tcmpt->numrlvls - 2; + 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); - tcmpt->tsfb = jpc_cod_gettsfb(tcmpt->qmfbid, tcmpt->numrlvls - 1); + } - if (!tcmpt->tsfb) - goto error; + for (cmptno = 0; cmptno < tile->numtcmpts; ++cmptno) { - for (rlvlno = 0; rlvlno < tcmpt->numrlvls; ++rlvlno) { - tcmpt->prcwidthexpns[rlvlno] = cp->tccp.prcwidthexpns[rlvlno]; - tcmpt->prcheightexpns[rlvlno] = cp->tccp.prcheightexpns[rlvlno]; - } - tcmpt->cblkwidthexpn = cp->tccp.cblkwidthexpn; - tcmpt->cblkheightexpn = cp->tccp.cblkheightexpn; - tcmpt->cblksty = cp->tccp.cblksty; - tcmpt->csty = cp->tccp.csty; + jpc_enc_tcmpt_t * const comp = &tile->tcmpts[cmptno]; - tcmpt->numstepsizes = tcmpt->numbands; - assert(tcmpt->numstepsizes <= JPC_MAXBANDS); - memset(tcmpt->stepsizes, 0, - sizeof(tcmpt->numstepsizes * sizeof(uint_fast16_t))); + 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]; - /* Retrieve information about the various bands. */ - jpc_tsfb_getbands(tcmpt->tsfb, jas_seq2d_xstart(tcmpt->data), - jas_seq2d_ystart(tcmpt->data), - jas_seq2d_xend(tcmpt->data), - jas_seq2d_yend(tcmpt->data), bandinfos); + unsigned int bandno; - tcmpt->rlvls = jas_malloc(tcmpt->numrlvls * sizeof(jpc_enc_rlvl_t)); - if (!tcmpt->rlvls) - goto error; + if (!lvl->bands) { + absbandno += rlvlno ? 3 : 1; + continue; + } + for (bandno = 0; bandno < lvl->numbands; ++bandno) { + jpc_enc_band_t * const band = &lvl->bands[bandno]; - for (rlvlno = 0, rlvl = tcmpt->rlvls; rlvlno < tcmpt->numrlvls; - ++rlvlno, ++rlvl) { - rlvl->bands = 0; - rlvl->tcmpt = tcmpt; - } - for (rlvlno = 0, rlvl = tcmpt->rlvls; rlvlno < tcmpt->numrlvls; - ++rlvlno, ++rlvl) { - if (!rlvl_create(rlvl, cp, tcmpt, bandinfos)) { - goto error; - } - } + int numgbits; - return tcmpt; + quantizeBand(band, tile, cp, + cp->ccps[cmptno].prec, + cp->tccp.numgbits, + &numgbits); -error: + mingbits = MAX(mingbits, numgbits); - tcmpt_destroy(tcmpt); - return 0; - -} + 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); + } + } -static void -tcmpt_destroy(jpc_enc_tcmpt_t *tcmpt) { + if (mingbits > cp->tccp.numgbits) { + fprintf(stderr, "error: too few guard bits (need at least %d)\n", + mingbits); + return -1; + } - jpc_enc_rlvl_t *rlvl; - uint_fast16_t rlvlno; + enc->tmpstream = jas_stream_memopen(0, 0); + if (!enc->tmpstream) { + fprintf(stderr, "cannot open tmp file\n"); + return -1; + } - if (tcmpt->rlvls) { - for (rlvlno = 0, rlvl = tcmpt->rlvls; rlvlno < tcmpt->numrlvls; - ++rlvlno, ++rlvl) { - rlvl_destroy(rlvl); + /* 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; } - jas_free(tcmpt->rlvls); - } + jpc_ms_destroy(enc->mrk); + enc->mrk = 0; - if (tcmpt->data) { - jas_seq2d_destroy(tcmpt->data); - } - if (tcmpt->tsfb) { - jpc_tsfb_destroy(tcmpt->tsfb); - } -} +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + 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; + } + } -static jpc_enc_rlvl_t * -rlvl_create(jpc_enc_rlvl_t *rlvl, jpc_enc_cp_t *cp, - jpc_enc_tcmpt_t *tcmpt, jpc_tsfb_band_t *bandinfos) { + for (cmptno = 0; cmptno < cp->numcmpts; ++cmptno) { + jpc_enc_tcmpt_t * const comp = &tile->tcmpts[cmptno]; - uint_fast16_t rlvlno; - uint_fast32_t tlprctlx; - uint_fast32_t tlprctly; - uint_fast32_t brprcbrx; - uint_fast32_t brprcbry; - uint_fast16_t bandno; - jpc_enc_band_t *band; + 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; + } + } - /* Deduce the resolution level. */ - rlvlno = rlvl - tcmpt->rlvls; + /* 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); - /* Initialize members required for error recovery. */ - rlvl->bands = 0; - rlvl->tcmpt = tcmpt; +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ - /* Compute the coordinates of the top-left and bottom-right - corners of the tile-component at this resolution. */ - rlvl->tlx = - JPC_CEILDIVPOW2(jas_seq2d_xstart(tcmpt->data), tcmpt->numrlvls - - 1 - rlvlno); - rlvl->tly = - JPC_CEILDIVPOW2(jas_seq2d_ystart(tcmpt->data), tcmpt->numrlvls - - 1 - rlvlno); - rlvl->brx = - JPC_CEILDIVPOW2(jas_seq2d_xend(tcmpt->data), tcmpt->numrlvls - - 1 - rlvlno); - rlvl->bry = - JPC_CEILDIVPOW2(jas_seq2d_yend(tcmpt->data), tcmpt->numrlvls - - 1 - rlvlno); + encodeTileBody(enc, tilehdrlen, &error); + /* Encodes current tile; writes to output file */ - if (rlvl->tlx >= rlvl->brx || rlvl->tly >= rlvl->bry) { - rlvl->numhprcs = 0; - rlvl->numvprcs = 0; - rlvl->numprcs = 0; - return rlvl; - } + 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); - rlvl->numbands = (!rlvlno) ? 1 : 3; - rlvl->prcwidthexpn = cp->tccp.prcwidthexpns[rlvlno]; - rlvl->prcheightexpn = cp->tccp.prcheightexpns[rlvlno]; - if (!rlvlno) { - rlvl->cbgwidthexpn = rlvl->prcwidthexpn; - rlvl->cbgheightexpn = rlvl->prcheightexpn; - } else { - rlvl->cbgwidthexpn = rlvl->prcwidthexpn - 1; - rlvl->cbgheightexpn = rlvl->prcheightexpn - 1; - } - rlvl->cblkwidthexpn = - JAS_MIN(cp->tccp.cblkwidthexpn, rlvl->cbgwidthexpn); - rlvl->cblkheightexpn = - JAS_MIN(cp->tccp.cblkheightexpn, rlvl->cbgheightexpn); + if (jas_stream_seek(enc->tmpstream, 6, SEEK_SET) < 0) { + return -1; + } + jpc_putuint32(enc->tmpstream, tilelen); - /* Compute the number of precincts. */ - tlprctlx = JPC_FLOORTOMULTPOW2(rlvl->tlx, rlvl->prcwidthexpn); - tlprctly = JPC_FLOORTOMULTPOW2(rlvl->tly, rlvl->prcheightexpn); - brprcbrx = JPC_CEILTOMULTPOW2(rlvl->brx, rlvl->prcwidthexpn); - brprcbry = JPC_CEILTOMULTPOW2(rlvl->bry, rlvl->prcheightexpn); - rlvl->numhprcs = JPC_FLOORDIVPOW2(brprcbrx - tlprctlx, rlvl->prcwidthexpn); - rlvl->numvprcs = - JPC_FLOORDIVPOW2(brprcbry - tlprctly, rlvl->prcheightexpn); - rlvl->numprcs = rlvl->numhprcs * rlvl->numvprcs; + 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; - rlvl->bands = jas_malloc(rlvl->numbands * sizeof(jpc_enc_band_t)); - if (!rlvl->bands) - goto error; + jas_stream_close(enc->tmpstream); + enc->tmpstream = 0; - for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; - ++bandno, ++band) { - band->prcs = 0; - band->data = 0; - band->rlvl = rlvl; - } - for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; - ++bandno, ++band) { - if (!band_create(band, cp, rlvl, bandinfos)) { - goto error; - } - } + jpc_enc_tile_destroy(enc->curtile); + enc->curtile = 0; - return rlvl; -error: + } - rlvl_destroy(rlvl); return 0; } -static void -rlvl_destroy(jpc_enc_rlvl_t *rlvl) { +int +jpc_encode(jas_image_t *image, jas_stream_t *out, char *optstr) { - jpc_enc_band_t *band; - uint_fast16_t bandno; + jpc_enc_t *enc; + jpc_enc_cp_t *cp; - if (rlvl->bands) { - for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; - ++bandno, ++band) { - band_destroy(band); - } - jas_free(rlvl->bands); - } -} + enc = 0; + cp = 0; + jpc_initluts(); + if (!(cp = cp_create(optstr, image))) { + fprintf(stderr, "invalid JP encoder options\n"); + goto error; + } -static jpc_enc_band_t * -band_create(jpc_enc_band_t *band, jpc_enc_cp_t *cp, - jpc_enc_rlvl_t *rlvl, jpc_tsfb_band_t *bandinfos) { + if (!(enc = jpc_enc_create(cp, out, image))) { + goto error; + } + cp = 0; - uint_fast16_t bandno; - uint_fast16_t gblbandno; - uint_fast16_t rlvlno; - jpc_tsfb_band_t *bandinfo; - jpc_enc_tcmpt_t *tcmpt; - uint_fast32_t prcno; - jpc_enc_prc_t *prc; + /* Encode the main header. */ + if (encodemainhdr(enc)) { + goto error; + } - tcmpt = rlvl->tcmpt; - band->data = 0; - band->prcs = 0; - band->rlvl = rlvl; + /* Encode the main body. This constitutes most of the encoding work. */ + if (encodemainbody(enc)) { + goto error; + } - /* Deduce the resolution level and band number. */ - rlvlno = rlvl - rlvl->tcmpt->rlvls; - bandno = band - rlvl->bands; - gblbandno = (!rlvlno) ? 0 : (3 * (rlvlno - 1) + bandno + 1); + /* 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; - bandinfo = &bandinfos[gblbandno]; + if (jas_stream_flush(enc->out)) { + goto error; + } - if (bandinfo->xstart != bandinfo->xend && - bandinfo->ystart != bandinfo->yend) { - band->data = jas_seq2d_create(0, 0, 0, 0); - if (!band->data) - goto error; - jas_seq2d_bindsub(band->data, tcmpt->data, bandinfo->locxstart, - bandinfo->locystart, bandinfo->locxend, - bandinfo->locyend); - jas_seq2d_setshift(band->data, bandinfo->xstart, bandinfo->ystart); + jpc_enc_destroy(enc); + + return 0; + +error: + if (cp) { + cp_destroy(cp); } - band->orient = bandinfo->orient; - band->analgain = JPC_NOMINALGAIN(cp->tccp.qmfbid, tcmpt->numrlvls, rlvlno, - band->orient); - band->numbps = 0; - band->absstepsize = 0; - band->stepsize = 0; - band->synweight = bandinfo->synenergywt; + if (enc) { + jpc_enc_destroy(enc); + } + return -1; +} - if (band->data) { - band->prcs = jas_malloc(rlvl->numprcs * sizeof(jpc_enc_prc_t)); - if (!band->prcs) - goto error; - for (prcno = 0, prc = band->prcs; - prcno < rlvl->numprcs; - ++prcno, ++prc) { - prc->cblks = 0; - prc->incltree = 0; - prc->nlibtree = 0; - prc->savincltree = 0; - prc->savnlibtree = 0; - prc->band = band; - } - for (prcno = 0, prc = band->prcs; - prcno < rlvl->numprcs; - ++prcno, ++prc) { - if (!prc_create(prc, cp, band)) { - goto error; - } - } + + +/*****************************************************************************\ +* 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; } - return band; + 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: - band_destroy(band); + + if (enc) { + jpc_enc_destroy(enc); + } return 0; } -static void -band_destroy(jpc_enc_band_t *band) { +void +jpc_enc_destroy(jpc_enc_t *enc) { - jpc_enc_prc_t *prc; - jpc_enc_rlvl_t *rlvl; - uint_fast32_t prcno; + /* 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 (band->prcs) { - rlvl = band->rlvl; - for (prcno = 0, prc = band->prcs; prcno < rlvl->numprcs; - ++prcno, ++prc) { - prc_destroy(prc); - } - jas_free(band->prcs); + if (enc->curtile) { + jpc_enc_tile_destroy(enc->curtile); } - if (band->data) { - jas_seq2d_destroy(band->data); + 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); +} -static jpc_enc_prc_t * -prc_create(jpc_enc_prc_t *prc, jpc_enc_cp_t *cp, jpc_enc_band_t *band) { - uint_fast32_t prcno; - uint_fast32_t prcxind; - uint_fast32_t prcyind; - uint_fast32_t cbgtlx; - uint_fast32_t cbgtly; - uint_fast32_t tlprctlx; - uint_fast32_t tlprctly; - uint_fast32_t tlcbgtlx; - uint_fast32_t tlcbgtly; - uint_fast16_t rlvlno; - jpc_enc_rlvl_t *rlvl; - uint_fast32_t tlcblktlx; - uint_fast32_t tlcblktly; - uint_fast32_t brcblkbrx; - uint_fast32_t brcblkbry; - uint_fast32_t cblkno; - jpc_enc_cblk_t *cblk; - jpc_enc_tcmpt_t *tcmpt; +void +quantize(jas_matrix_t *data, jpc_fix_t stepsize) { - prc->cblks = 0; - prc->incltree = 0; - prc->savincltree = 0; - prc->nlibtree = 0; - prc->savnlibtree = 0; + int i; + int j; + jpc_fix_t t; - rlvl = band->rlvl; - tcmpt = rlvl->tcmpt; - rlvlno = rlvl - tcmpt->rlvls; - prcno = prc - band->prcs; - prcxind = prcno % rlvl->numhprcs; - prcyind = prcno / rlvl->numhprcs; - prc->band = band; + if (stepsize == jpc_inttofix(1)) { + return; + } - tlprctlx = JPC_FLOORTOMULTPOW2(rlvl->tlx, rlvl->prcwidthexpn); - tlprctly = JPC_FLOORTOMULTPOW2(rlvl->tly, rlvl->prcheightexpn); + 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 (!rlvlno) { - tlcbgtlx = tlprctlx; - tlcbgtly = tlprctly; +{ + if (t < 0) { + t = jpc_fix_neg(jpc_fix_div(jpc_fix_neg(t), stepsize)); } else { - tlcbgtlx = JPC_CEILDIVPOW2(tlprctlx, 1); - tlcbgtly = JPC_CEILDIVPOW2(tlprctly, 1); + t = jpc_fix_div(t, stepsize); } +} - /* Compute the coordinates of the top-left and bottom-right corners of the - precinct. - */ - cbgtlx = tlcbgtlx + (prcxind << rlvl->cbgwidthexpn); - cbgtly = tlcbgtly + (prcyind << rlvl->cbgheightexpn); - prc->tlx = JAS_MAX(jas_seq2d_xstart(band->data), cbgtlx); - prc->tly = JAS_MAX(jas_seq2d_ystart(band->data), cbgtly); - prc->brx = JAS_MIN(jas_seq2d_xend(band->data), cbgtlx + - (1 << rlvl->cbgwidthexpn)); - prc->bry = JAS_MIN(jas_seq2d_yend(band->data), cbgtly + - (1 << rlvl->cbgheightexpn)); + jas_matrix_set(data, i, j, t); + } + } +} - if (prc->tlx < prc->brx && prc->tly < prc->bry) { - /* The precinct contains at least one code block. */ - tlcblktlx = JPC_FLOORTOMULTPOW2(prc->tlx, rlvl->cblkwidthexpn); - tlcblktly = JPC_FLOORTOMULTPOW2(prc->tly, rlvl->cblkheightexpn); - brcblkbrx = JPC_CEILTOMULTPOW2(prc->brx, rlvl->cblkwidthexpn); - brcblkbry = JPC_CEILTOMULTPOW2(prc->bry, rlvl->cblkheightexpn); - prc->numhcblks = JPC_FLOORDIVPOW2(brcblkbrx - tlcblktlx, - rlvl->cblkwidthexpn); - prc->numvcblks = JPC_FLOORDIVPOW2(brcblkbry - tlcblktly, - rlvl->cblkheightexpn); - prc->numcblks = prc->numhcblks * prc->numvcblks; - if (!(prc->incltree = jpc_tagtree_create(prc->numhcblks, - prc->numvcblks))) { - goto error; - } - if (!(prc->nlibtree = jpc_tagtree_create(prc->numhcblks, - prc->numvcblks))) { - goto error; - } - if (!(prc->savincltree = jpc_tagtree_create(prc->numhcblks, - prc->numvcblks))) { - goto error; - } - if (!(prc->savnlibtree = jpc_tagtree_create(prc->numhcblks, - prc->numvcblks))) { - goto error; - } +/*****************************************************************************\ +* Tile constructors and destructors. +\*****************************************************************************/ - prc->cblks = jas_malloc(prc->numcblks * sizeof(jpc_enc_cblk_t)); - - if (!prc->cblks) - goto error; - for (cblkno = 0, cblk = prc->cblks; - cblkno < prc->numcblks; - ++cblkno, ++cblk) { - cblk->passes = 0; - cblk->stream = 0; - cblk->mqenc = 0; - cblk->data = 0; - cblk->flags = 0; - cblk->prc = prc; - } - for (cblkno = 0, cblk = prc->cblks; - cblkno < prc->numcblks; - ++cblkno, ++cblk) { - if (!cblk_create(cblk, cp, prc)) { - goto error; - } - } - } else { - /* The precinct does not contain any code blocks. */ - prc->tlx = prc->brx; - prc->tly = prc->bry; - prc->numcblks = 0; - prc->numhcblks = 0; - prc->numvcblks = 0; - prc->cblks = 0; - prc->incltree = 0; - prc->nlibtree = 0; - prc->savincltree = 0; - prc->savnlibtree = 0; - } +jpc_enc_tile_t * +jpc_enc_tile_create(jpc_enc_cp_t *cp, jas_image_t *image, int tileno) { - return prc; + jpc_enc_tile_t *tile; + uint_fast32_t htileno; + uint_fast32_t vtileno; + uint_fast16_t lyrno; + uint_fast16_t cmptno; + jpc_enc_tcmpt_t *tcmpt; -error: - prc_destroy(prc); - return 0; -} + if (!(tile = jas_malloc(sizeof(jpc_enc_tile_t)))) { + goto error; + } + /* Initialize a few members used in error recovery. */ + tile->tcmpts = 0; + tile->lyrsizes = 0; + tile->numtcmpts = cp->numcmpts; + tile->pi = 0; + tile->tileno = tileno; + htileno = tileno % cp->numhtiles; + vtileno = tileno / cp->numhtiles; -static void -prc_destroy(jpc_enc_prc_t *prc) { + /* Calculate the coordinates of the top-left and bottom-right + corners of the tile. */ + tile->tlx = JAS_MAX(cp->tilegrdoffx + htileno * cp->tilewidth, + cp->imgareatlx); + tile->tly = JAS_MAX(cp->tilegrdoffy + vtileno * cp->tileheight, + cp->imgareatly); + tile->brx = JAS_MIN(cp->tilegrdoffx + (htileno + 1) * cp->tilewidth, + cp->refgrdwidth); + tile->bry = JAS_MIN(cp->tilegrdoffy + (vtileno + 1) * cp->tileheight, + cp->refgrdheight); - jpc_enc_cblk_t *cblk; - uint_fast32_t cblkno; + /* Initialize some tile coding parameters. */ + tile->intmode = cp->tcp.intmode; + tile->csty = cp->tcp.csty; + tile->prg = cp->tcp.prg; + tile->mctid = cp->tcp.mctid; - if (prc->cblks) { - for (cblkno = 0, cblk = prc->cblks; cblkno < prc->numcblks; - ++cblkno, ++cblk) { - cblk_destroy(cblk); - } - jas_free(prc->cblks); + tile->numlyrs = cp->tcp.numlyrs; + if (!(tile->lyrsizes = jas_malloc(tile->numlyrs * + sizeof(uint_fast32_t)))) { + goto error; } - if (prc->incltree) { - jpc_tagtree_destroy(prc->incltree); + for (lyrno = 0; lyrno < tile->numlyrs; ++lyrno) { + tile->lyrsizes[lyrno] = 0; } - if (prc->nlibtree) { - jpc_tagtree_destroy(prc->nlibtree); + + /* Allocate an array for the per-tile-component information. */ + if (!(tile->tcmpts = jas_malloc(cp->numcmpts * sizeof(jpc_enc_tcmpt_t)))) { + goto error; } - if (prc->savincltree) { - jpc_tagtree_destroy(prc->savincltree); + /* Initialize a few members critical for error recovery. */ + for (cmptno = 0, tcmpt = tile->tcmpts; cmptno < cp->numcmpts; + ++cmptno, ++tcmpt) { + tcmpt->rlvls = 0; + tcmpt->tsfb = 0; + tcmpt->data = 0; } - if (prc->savnlibtree) { - jpc_tagtree_destroy(prc->savnlibtree); + /* Initialize the per-tile-component information. */ + for (cmptno = 0, tcmpt = tile->tcmpts; cmptno < cp->numcmpts; + ++cmptno, ++tcmpt) { + if (!tcmpt_create(tcmpt, cp, image, tile)) { + goto error; + } } -} - - - -static jpc_enc_cblk_t * -cblk_create(jpc_enc_cblk_t *cblk, jpc_enc_cp_t *cp, jpc_enc_prc_t *prc) { - - jpc_enc_band_t *band; - uint_fast32_t cblktlx; - uint_fast32_t cblktly; - uint_fast32_t cblkbrx; - uint_fast32_t cblkbry; - jpc_enc_rlvl_t *rlvl; - uint_fast32_t cblkxind; - uint_fast32_t cblkyind; - uint_fast32_t cblkno; - uint_fast32_t tlcblktlx; - uint_fast32_t tlcblktly; - - cblkno = cblk - prc->cblks; - cblkxind = cblkno % prc->numhcblks; - cblkyind = cblkno / prc->numhcblks; - rlvl = prc->band->rlvl; - cblk->prc = prc; - - cblk->numpasses = 0; - cblk->passes = 0; - cblk->numencpasses = 0; - cblk->numimsbs = 0; - cblk->numlenbits = 0; - cblk->stream = 0; - cblk->mqenc = 0; - cblk->flags = 0; - cblk->numbps = 0; - cblk->curpass = 0; - cblk->data = 0; - cblk->savedcurpass = 0; - cblk->savednumlenbits = 0; - cblk->savednumencpasses = 0; - band = prc->band; - tlcblktlx = JPC_FLOORTOMULTPOW2(prc->tlx, rlvl->cblkwidthexpn); - tlcblktly = JPC_FLOORTOMULTPOW2(prc->tly, rlvl->cblkheightexpn); - cblktlx = - JAS_MAX(tlcblktlx + (cblkxind << rlvl->cblkwidthexpn), prc->tlx); - cblktly = - JAS_MAX(tlcblktly + (cblkyind << rlvl->cblkheightexpn), prc->tly); - cblkbrx = - JAS_MIN(tlcblktlx + ((cblkxind + 1) << rlvl->cblkwidthexpn), prc->brx); - cblkbry = - JAS_MIN(tlcblktly + ((cblkyind + 1) << rlvl->cblkheightexpn), - prc->bry); + /* Initialize the synthesis weights for the MCT. */ + switch (tile->mctid) { + case JPC_MCT_RCT: + tile->tcmpts[0].synweight = jpc_dbltofix(sqrt(3.0)); + tile->tcmpts[1].synweight = jpc_dbltofix(sqrt(0.6875)); + tile->tcmpts[2].synweight = jpc_dbltofix(sqrt(0.6875)); + break; + case JPC_MCT_ICT: + tile->tcmpts[0].synweight = jpc_dbltofix(sqrt(3.0000)); + tile->tcmpts[1].synweight = jpc_dbltofix(sqrt(3.2584)); + tile->tcmpts[2].synweight = jpc_dbltofix(sqrt(2.4755)); + break; + default: + case JPC_MCT_NONE: + for (cmptno = 0, tcmpt = tile->tcmpts; cmptno < cp->numcmpts; + ++cmptno, ++tcmpt) { + tcmpt->synweight = JPC_FIX_ONE; + } + break; + } - assert(cblktlx < cblkbrx && cblktly < cblkbry); - cblk->data = jas_seq2d_create(0, 0, 0, 0); - if (!cblk->data) + if (!(tile->pi = jpc_enc_pi_create(cp, tile))) { goto error; - jas_seq2d_bindsub(cblk->data, band->data, - cblktlx, cblktly, cblkbrx, cblkbry); + } - return cblk; + return tile; error: - cblk_destroy(cblk); + + if (tile) { + jpc_enc_tile_destroy(tile); + } return 0; } -static void -cblk_destroy(jpc_enc_cblk_t *cblk) { +void +jpc_enc_tile_destroy(jpc_enc_tile_t *tile) { - uint_fast16_t passno; - jpc_enc_pass_t *pass; - if (cblk->passes) { - for (passno = 0, pass = cblk->passes; passno < cblk->numpasses; - ++passno, ++pass) { - pass_destroy(pass); + jpc_enc_tcmpt_t *tcmpt; + uint_fast16_t cmptno; + + if (tile->tcmpts) { + for (cmptno = 0, tcmpt = tile->tcmpts; cmptno < + tile->numtcmpts; ++cmptno, ++tcmpt) { + tcmpt_destroy(tcmpt); } - jas_free(cblk->passes); - } - if (cblk->stream) { - jas_stream_close(cblk->stream); - } - if (cblk->mqenc) { - jpc_mqenc_destroy(cblk->mqenc); + jas_free(tile->tcmpts); } - if (cblk->data) { - jas_seq2d_destroy(cblk->data); + if (tile->lyrsizes) { + jas_free(tile->lyrsizes); } - if (cblk->flags) { - jas_seq2d_destroy(cblk->flags); + if (tile->pi) { + jpc_pi_destroy(tile->pi); } + jas_free(tile); } -static void -pass_destroy(jpc_enc_pass_t *pass) { +static jpc_enc_tcmpt_t * +tcmpt_create(jpc_enc_tcmpt_t * const tcmpt, + jpc_enc_cp_t * const cp, + jas_image_t * const image, + jpc_enc_tile_t * const tile) { - /* XXX - need to free resources here */ -} + uint_fast16_t cmptno; + uint_fast16_t rlvlno; + jpc_enc_rlvl_t *rlvl; + uint_fast32_t tlx; + uint_fast32_t tly; + uint_fast32_t brx; + uint_fast32_t bry; + uint_fast32_t cmpttlx; + uint_fast32_t cmpttly; + jpc_enc_ccp_t *ccp; + jpc_tsfb_band_t bandinfos[JPC_MAXBANDS]; + tcmpt->tile = tile; + tcmpt->tsfb = 0; + tcmpt->data = 0; + tcmpt->rlvls = 0; + /* Deduce the component number. */ + cmptno = tcmpt - tile->tcmpts; -void -jpc_enc_dump(jpc_enc_t *enc) { + ccp = &cp->ccps[cmptno]; - jpc_enc_tile_t *tile; - jpc_enc_tcmpt_t *tcmpt; - jpc_enc_rlvl_t *rlvl; - jpc_enc_band_t *band; - jpc_enc_prc_t *prc; - jpc_enc_cblk_t *cblk; - uint_fast16_t cmptno; - uint_fast16_t rlvlno; - uint_fast16_t bandno; - uint_fast32_t prcno; - uint_fast32_t cblkno; + /* Compute the coordinates of the top-left and bottom-right + corners of this tile-component. */ + tlx = JPC_CEILDIV(tile->tlx, ccp->sampgrdstepx); + tly = JPC_CEILDIV(tile->tly, ccp->sampgrdstepy); + brx = JPC_CEILDIV(tile->brx, ccp->sampgrdstepx); + bry = JPC_CEILDIV(tile->bry, ccp->sampgrdstepy); - tile = enc->curtile; + /* Create a sequence to hold the tile-component sample data. */ + tcmpt->data = jas_seq2d_create(tlx, tly, brx, bry); + if (!tcmpt->data) + goto error; - for (cmptno = 0, tcmpt = tile->tcmpts; - cmptno < tile->numtcmpts; - ++cmptno, ++tcmpt) { - fprintf(stderr, " tcmpt %5d %5d %5d %5d\n", - (int)jas_seq2d_xstart(tcmpt->data), - (int)jas_seq2d_ystart(tcmpt->data), - (int)jas_seq2d_xend(tcmpt->data), - (int)jas_seq2d_yend(tcmpt->data)); - for (rlvlno = 0, rlvl = tcmpt->rlvls; - rlvlno < tcmpt->numrlvls; - ++rlvlno, ++rlvl) { - fprintf(stderr, " rlvl %5d %5d %5d %5d\n", - (int)rlvl->tlx, (int)rlvl->tly, - (int)rlvl->brx, (int)rlvl->bry); - for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; - ++bandno, ++band) { - if (!band->data) { - continue; - } - fprintf(stderr, " band %5d %5d %5d %5d\n", - (int)jas_seq2d_xstart(band->data), - (int)jas_seq2d_ystart(band->data), - (int)jas_seq2d_xend(band->data), - (int)jas_seq2d_yend(band->data)); - for (prcno = 0, prc = band->prcs; - prcno < rlvl->numprcs; - ++prcno, ++prc) { - fprintf(stderr, " prc %5d %5d %5d %5d (%5d %5d)\n", - (int)prc->tlx, (int)prc->tly, - (int)prc->brx, (int)prc->bry, - (int)(prc->brx - prc->tlx), - (int)(prc->bry - prc->tly)); - if (!prc->cblks) { - continue; - } - for (cblkno = 0, cblk = prc->cblks; cblkno < prc->numcblks; - ++cblkno, ++cblk) { - fprintf(stderr, " cblk %5d %5d %5d %5d\n", - (int)jas_seq2d_xstart(cblk->data), - (int)jas_seq2d_ystart(cblk->data), - (int)jas_seq2d_xend(cblk->data), - (int)jas_seq2d_yend(cblk->data)); - } - } - } - } + /* Get the image data associated with this tile-component. */ + cmpttlx = JPC_CEILDIV(cp->imgareatlx, ccp->sampgrdstepx); + cmpttly = JPC_CEILDIV(cp->imgareatly, ccp->sampgrdstepy); + if (jas_image_readcmpt(image, cmptno, tlx - cmpttlx, tly - cmpttly, + brx - tlx, bry - tly, tcmpt->data)) { + goto error; } -} + tcmpt->synweight = 0; + tcmpt->qmfbid = cp->tccp.qmfbid; + tcmpt->numrlvls = cp->tccp.maxrlvls; + tcmpt->numbands = 3 * tcmpt->numrlvls - 2; + tcmpt->tsfb = jpc_cod_gettsfb(tcmpt->qmfbid, tcmpt->numrlvls - 1); -static int -jpc_enc_encodemainbody(jpc_enc_t *enc) { + if (!tcmpt->tsfb) + goto error; - 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; + for (rlvlno = 0; rlvlno < tcmpt->numrlvls; ++rlvlno) { + tcmpt->prcwidthexpns[rlvlno] = cp->tccp.prcwidthexpns[rlvlno]; + tcmpt->prcheightexpns[rlvlno] = cp->tccp.prcheightexpns[rlvlno]; + } + tcmpt->cblkwidthexpn = cp->tccp.cblkwidthexpn; + tcmpt->cblkheightexpn = cp->tccp.cblkheightexpn; + tcmpt->cblksty = cp->tccp.cblksty; + tcmpt->csty = cp->tccp.csty; - cp = enc->cp; + tcmpt->numstepsizes = tcmpt->numbands; + assert(tcmpt->numstepsizes <= JPC_MAXBANDS); + memset(tcmpt->stepsizes, 0, + sizeof(tcmpt->numstepsizes * sizeof(uint_fast16_t))); - for (tileno = 0; tileno < cp->numtiles; ++tileno) { - enc->curtile = jpc_enc_tile_create(enc->cp, enc->image, tileno); - if (!enc->curtile) - abort(); + /* Retrieve information about the various bands. */ + jpc_tsfb_getbands(tcmpt->tsfb, jas_seq2d_xstart(tcmpt->data), + jas_seq2d_ystart(tcmpt->data), + jas_seq2d_xend(tcmpt->data), + jas_seq2d_yend(tcmpt->data), bandinfos); - tile = enc->curtile; + tcmpt->rlvls = jas_malloc(tcmpt->numrlvls * sizeof(jpc_enc_rlvl_t)); + if (!tcmpt->rlvls) + goto error; - if (jas_getdbglevel() >= 10) { - jpc_enc_dump(enc); + for (rlvlno = 0, rlvl = tcmpt->rlvls; rlvlno < tcmpt->numrlvls; + ++rlvlno, ++rlvl) { + rlvl->bands = 0; + rlvl->tcmpt = tcmpt; + } + for (rlvlno = 0, rlvl = tcmpt->rlvls; rlvlno < tcmpt->numrlvls; + ++rlvlno, ++rlvl) { + if (!rlvl_create(rlvl, cp, tcmpt, bandinfos)) { + goto error; } + } - 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; - } - } - } - } + return tcmpt; - if (!tile->intmode) { - endcomps = &tile->tcmpts[tile->numtcmpts]; - for (comp = tile->tcmpts; comp != endcomps; ++comp) { - jas_matrix_asl(comp->data, JPC_FIX_FRACBITS); - } - } +error: - 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; - } + tcmpt_destroy(tcmpt); + return 0; - 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; - } - } +static void +tcmpt_destroy(jpc_enc_tcmpt_t *tcmpt) { - 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); - } - } + jpc_enc_rlvl_t *rlvl; + uint_fast16_t rlvlno; - if (mingbits > cp->tccp.numgbits) { - fprintf(stderr, "error: too few guard bits (need at least %d)\n", - mingbits); - return -1; + if (tcmpt->rlvls) { + for (rlvlno = 0, rlvl = tcmpt->rlvls; rlvlno < tcmpt->numrlvls; + ++rlvlno, ++rlvl) { + rlvl_destroy(rlvl); } + jas_free(tcmpt->rlvls); + } - enc->tmpstream = jas_stream_memopen(0, 0); - if (!enc->tmpstream) { - fprintf(stderr, "cannot open tmp file\n"); - return -1; - } + if (tcmpt->data) { + jas_seq2d_destroy(tcmpt->data); + } + if (tcmpt->tsfb) { + jpc_tsfb_destroy(tcmpt->tsfb); + } +} - /* 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; - } - } +static jpc_enc_rlvl_t * +rlvl_create(jpc_enc_rlvl_t *rlvl, jpc_enc_cp_t *cp, + jpc_enc_tcmpt_t *tcmpt, jpc_tsfb_band_t *bandinfos) { - 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; - } - } + uint_fast16_t rlvlno; + uint_fast32_t tlprctlx; + uint_fast32_t tlprctly; + uint_fast32_t brprcbrx; + uint_fast32_t brprcbry; + uint_fast16_t bandno; + jpc_enc_band_t *band; - /* 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); + /* Deduce the resolution level. */ + rlvlno = rlvl - tcmpt->rlvls; -/************************************************************************/ -/************************************************************************/ -/************************************************************************/ + /* Initialize members required for error recovery. */ + rlvl->bands = 0; + rlvl->tcmpt = tcmpt; - if (jpc_enc_enccblks(enc)) { - abort(); - return -1; - } + /* Compute the coordinates of the top-left and bottom-right + corners of the tile-component at this resolution. */ + rlvl->tlx = + JPC_CEILDIVPOW2(jas_seq2d_xstart(tcmpt->data), tcmpt->numrlvls - + 1 - rlvlno); + rlvl->tly = + JPC_CEILDIVPOW2(jas_seq2d_ystart(tcmpt->data), tcmpt->numrlvls - + 1 - rlvlno); + rlvl->brx = + JPC_CEILDIVPOW2(jas_seq2d_xend(tcmpt->data), tcmpt->numrlvls - + 1 - rlvlno); + rlvl->bry = + JPC_CEILDIVPOW2(jas_seq2d_yend(tcmpt->data), tcmpt->numrlvls - + 1 - rlvlno); - 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; + if (rlvl->tlx >= rlvl->brx || rlvl->tly >= rlvl->bry) { + rlvl->numhprcs = 0; + rlvl->numvprcs = 0; + rlvl->numprcs = 0; + return rlvl; + } - computeLayerSizes(enc, tile, cp, rho, tilehdrlen, &error); - - if (!error) { - int rc; - performTier2Coding(enc, tile->numlyrs, tile->lyrsizes, &error); + rlvl->numbands = (!rlvlno) ? 1 : 3; + rlvl->prcwidthexpn = cp->tccp.prcwidthexpns[rlvlno]; + rlvl->prcheightexpn = cp->tccp.prcheightexpns[rlvlno]; + if (!rlvlno) { + rlvl->cbgwidthexpn = rlvl->prcwidthexpn; + rlvl->cbgheightexpn = rlvl->prcheightexpn; + } else { + rlvl->cbgwidthexpn = rlvl->prcwidthexpn - 1; + rlvl->cbgheightexpn = rlvl->prcheightexpn - 1; + } + rlvl->cblkwidthexpn = + JAS_MIN(cp->tccp.cblkwidthexpn, rlvl->cbgwidthexpn); + rlvl->cblkheightexpn = + JAS_MIN(cp->tccp.cblkheightexpn, rlvl->cbgheightexpn); - rc = jpc_enc_encodetiledata(enc); - if (rc != 0) - pm_asprintf(&error, "jpc_enc_encodetiledata() failed\n"); - } + /* Compute the number of precincts. */ + tlprctlx = JPC_FLOORTOMULTPOW2(rlvl->tlx, rlvl->prcwidthexpn); + tlprctly = JPC_FLOORTOMULTPOW2(rlvl->tly, rlvl->prcheightexpn); + brprcbrx = JPC_CEILTOMULTPOW2(rlvl->brx, rlvl->prcwidthexpn); + brprcbry = JPC_CEILTOMULTPOW2(rlvl->bry, rlvl->prcheightexpn); + rlvl->numhprcs = JPC_FLOORDIVPOW2(brprcbrx - tlprctlx, rlvl->prcwidthexpn); + rlvl->numvprcs = + JPC_FLOORDIVPOW2(brprcbry - tlprctly, rlvl->prcheightexpn); + rlvl->numprcs = rlvl->numhprcs * rlvl->numvprcs; - if (error) { - fprintf(stderr, "%s\n", error); - pm_strfree(error); - return -1; + rlvl->bands = jas_malloc(rlvl->numbands * sizeof(jpc_enc_band_t)); + if (!rlvl->bands) + goto error; + + for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; + ++bandno, ++band) { + band->prcs = 0; + band->data = 0; + band->rlvl = rlvl; + } + for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; + ++bandno, ++band) { + if (!band_create(band, cp, rlvl, bandinfos)) { + goto error; } + } - tilelen = jas_stream_tell(enc->tmpstream); + return rlvl; +error: - if (jas_stream_seek(enc->tmpstream, 6, SEEK_SET) < 0) { - return -1; - } - jpc_putuint32(enc->tmpstream, tilelen); + rlvl_destroy(rlvl); + return 0; +} - if (jas_stream_seek(enc->tmpstream, 0, SEEK_SET) < 0) { - return -1; - } - if (jpc_putdata(enc->out, enc->tmpstream, -1)) { - return -1; + + +static void +rlvl_destroy(jpc_enc_rlvl_t *rlvl) { + + jpc_enc_band_t *band; + uint_fast16_t bandno; + + if (rlvl->bands) { + for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; + ++bandno, ++band) { + band_destroy(band); } - enc->len += tilelen; + jas_free(rlvl->bands); + } +} - jas_stream_close(enc->tmpstream); - enc->tmpstream = 0; - jpc_enc_tile_destroy(enc->curtile); - enc->curtile = 0; +static jpc_enc_band_t * +band_create(jpc_enc_band_t *band, jpc_enc_cp_t *cp, + jpc_enc_rlvl_t *rlvl, jpc_tsfb_band_t *bandinfos) { + + uint_fast16_t bandno; + uint_fast16_t gblbandno; + uint_fast16_t rlvlno; + jpc_tsfb_band_t *bandinfo; + jpc_enc_tcmpt_t *tcmpt; + uint_fast32_t prcno; + jpc_enc_prc_t *prc; + + tcmpt = rlvl->tcmpt; + band->data = 0; + band->prcs = 0; + band->rlvl = rlvl; + + /* Deduce the resolution level and band number. */ + rlvlno = rlvl - rlvl->tcmpt->rlvls; + bandno = band - rlvl->bands; + gblbandno = (!rlvlno) ? 0 : (3 * (rlvlno - 1) + bandno + 1); + + bandinfo = &bandinfos[gblbandno]; + + if (bandinfo->xstart != bandinfo->xend && + bandinfo->ystart != bandinfo->yend) { + band->data = jas_seq2d_create(0, 0, 0, 0); + if (!band->data) + goto error; + jas_seq2d_bindsub(band->data, tcmpt->data, bandinfo->locxstart, + bandinfo->locystart, bandinfo->locxend, + bandinfo->locyend); + jas_seq2d_setshift(band->data, bandinfo->xstart, bandinfo->ystart); + } + band->orient = bandinfo->orient; + band->analgain = JPC_NOMINALGAIN(cp->tccp.qmfbid, tcmpt->numrlvls, rlvlno, + band->orient); + band->numbps = 0; + band->absstepsize = 0; + band->stepsize = 0; + band->synweight = bandinfo->synenergywt; + + if (band->data) { + band->prcs = jas_malloc(rlvl->numprcs * sizeof(jpc_enc_prc_t)); + if (!band->prcs) + goto error; + for (prcno = 0, prc = band->prcs; + prcno < rlvl->numprcs; + ++prcno, ++prc) { + prc->cblks = 0; + prc->incltree = 0; + prc->nlibtree = 0; + prc->savincltree = 0; + prc->savnlibtree = 0; + prc->band = band; + } + for (prcno = 0, prc = band->prcs; + prcno < rlvl->numprcs; + ++prcno, ++prc) { + if (!prc_create(prc, cp, band)) { + goto error; + } + } } + return band; + +error: + band_destroy(band); return 0; } +static void +band_destroy(jpc_enc_band_t *band) { + + jpc_enc_prc_t *prc; + jpc_enc_rlvl_t *rlvl; + uint_fast32_t prcno; + + if (band->prcs) { + rlvl = band->rlvl; + for (prcno = 0, prc = band->prcs; prcno < rlvl->numprcs; + ++prcno, ++prc) { + prc_destroy(prc); + } + jas_free(band->prcs); + } + if (band->data) { + jas_seq2d_destroy(band->data); + } +} + + + +static jpc_enc_prc_t * +prc_create(jpc_enc_prc_t *prc, jpc_enc_cp_t *cp, jpc_enc_band_t *band) { + + uint_fast32_t prcno; + uint_fast32_t prcxind; + uint_fast32_t prcyind; + uint_fast32_t cbgtlx; + uint_fast32_t cbgtly; + uint_fast32_t tlprctlx; + uint_fast32_t tlprctly; + uint_fast32_t tlcbgtlx; + uint_fast32_t tlcbgtly; + uint_fast16_t rlvlno; + jpc_enc_rlvl_t *rlvl; + uint_fast32_t tlcblktlx; + uint_fast32_t tlcblktly; + uint_fast32_t brcblkbrx; + uint_fast32_t brcblkbry; + uint_fast32_t cblkno; + jpc_enc_cblk_t *cblk; + jpc_enc_tcmpt_t *tcmpt; + + prc->cblks = 0; + prc->incltree = 0; + prc->savincltree = 0; + prc->nlibtree = 0; + prc->savnlibtree = 0; + + rlvl = band->rlvl; + tcmpt = rlvl->tcmpt; + rlvlno = rlvl - tcmpt->rlvls; + prcno = prc - band->prcs; + prcxind = prcno % rlvl->numhprcs; + prcyind = prcno / rlvl->numhprcs; + prc->band = band; + + tlprctlx = JPC_FLOORTOMULTPOW2(rlvl->tlx, rlvl->prcwidthexpn); + tlprctly = JPC_FLOORTOMULTPOW2(rlvl->tly, rlvl->prcheightexpn); + + if (!rlvlno) { + tlcbgtlx = tlprctlx; + tlcbgtly = tlprctly; + } else { + tlcbgtlx = JPC_CEILDIVPOW2(tlprctlx, 1); + tlcbgtly = JPC_CEILDIVPOW2(tlprctly, 1); + } + + /* Compute the coordinates of the top-left and bottom-right corners of the + precinct. + */ + cbgtlx = tlcbgtlx + (prcxind << rlvl->cbgwidthexpn); + cbgtly = tlcbgtly + (prcyind << rlvl->cbgheightexpn); + prc->tlx = JAS_MAX(jas_seq2d_xstart(band->data), cbgtlx); + prc->tly = JAS_MAX(jas_seq2d_ystart(band->data), cbgtly); + prc->brx = JAS_MIN(jas_seq2d_xend(band->data), cbgtlx + + (1 << rlvl->cbgwidthexpn)); + prc->bry = JAS_MIN(jas_seq2d_yend(band->data), cbgtly + + (1 << rlvl->cbgheightexpn)); + + if (prc->tlx < prc->brx && prc->tly < prc->bry) { + /* The precinct contains at least one code block. */ + + tlcblktlx = JPC_FLOORTOMULTPOW2(prc->tlx, rlvl->cblkwidthexpn); + tlcblktly = JPC_FLOORTOMULTPOW2(prc->tly, rlvl->cblkheightexpn); + brcblkbrx = JPC_CEILTOMULTPOW2(prc->brx, rlvl->cblkwidthexpn); + brcblkbry = JPC_CEILTOMULTPOW2(prc->bry, rlvl->cblkheightexpn); + prc->numhcblks = JPC_FLOORDIVPOW2(brcblkbrx - tlcblktlx, + rlvl->cblkwidthexpn); + prc->numvcblks = JPC_FLOORDIVPOW2(brcblkbry - tlcblktly, + rlvl->cblkheightexpn); + prc->numcblks = prc->numhcblks * prc->numvcblks; + + if (!(prc->incltree = jpc_tagtree_create(prc->numhcblks, + prc->numvcblks))) { + goto error; + } + if (!(prc->nlibtree = jpc_tagtree_create(prc->numhcblks, + prc->numvcblks))) { + goto error; + } + if (!(prc->savincltree = jpc_tagtree_create(prc->numhcblks, + prc->numvcblks))) { + goto error; + } + if (!(prc->savnlibtree = jpc_tagtree_create(prc->numhcblks, + prc->numvcblks))) { + goto error; + } + + prc->cblks = jas_malloc(prc->numcblks * sizeof(jpc_enc_cblk_t)); + + if (!prc->cblks) + goto error; + for (cblkno = 0, cblk = prc->cblks; + cblkno < prc->numcblks; + ++cblkno, ++cblk) { + cblk->passes = 0; + cblk->stream = 0; + cblk->mqenc = 0; + cblk->data = 0; + cblk->flags = 0; + cblk->prc = prc; + } + for (cblkno = 0, cblk = prc->cblks; + cblkno < prc->numcblks; + ++cblkno, ++cblk) { + if (!cblk_create(cblk, cp, prc)) { + goto error; + } + } + } else { + /* The precinct does not contain any code blocks. */ + prc->tlx = prc->brx; + prc->tly = prc->bry; + prc->numcblks = 0; + prc->numhcblks = 0; + prc->numvcblks = 0; + prc->cblks = 0; + prc->incltree = 0; + prc->nlibtree = 0; + prc->savincltree = 0; + prc->savnlibtree = 0; + } + + return prc; + +error: + prc_destroy(prc); + return 0; +} + + + +static void +prc_destroy(jpc_enc_prc_t *prc) { + + jpc_enc_cblk_t *cblk; + uint_fast32_t cblkno; + + if (prc->cblks) { + for (cblkno = 0, cblk = prc->cblks; cblkno < prc->numcblks; + ++cblkno, ++cblk) { + cblk_destroy(cblk); + } + jas_free(prc->cblks); + } + if (prc->incltree) { + jpc_tagtree_destroy(prc->incltree); + } + if (prc->nlibtree) { + jpc_tagtree_destroy(prc->nlibtree); + } + if (prc->savincltree) { + jpc_tagtree_destroy(prc->savincltree); + } + if (prc->savnlibtree) { + jpc_tagtree_destroy(prc->savnlibtree); + } +} + + + +static jpc_enc_cblk_t * +cblk_create(jpc_enc_cblk_t *cblk, jpc_enc_cp_t *cp, jpc_enc_prc_t *prc) { + + jpc_enc_band_t *band; + uint_fast32_t cblktlx; + uint_fast32_t cblktly; + uint_fast32_t cblkbrx; + uint_fast32_t cblkbry; + jpc_enc_rlvl_t *rlvl; + uint_fast32_t cblkxind; + uint_fast32_t cblkyind; + uint_fast32_t cblkno; + uint_fast32_t tlcblktlx; + uint_fast32_t tlcblktly; + + cblkno = cblk - prc->cblks; + cblkxind = cblkno % prc->numhcblks; + cblkyind = cblkno / prc->numhcblks; + rlvl = prc->band->rlvl; + cblk->prc = prc; + + cblk->numpasses = 0; + cblk->passes = 0; + cblk->numencpasses = 0; + cblk->numimsbs = 0; + cblk->numlenbits = 0; + cblk->stream = 0; + cblk->mqenc = 0; + cblk->flags = 0; + cblk->numbps = 0; + cblk->curpass = 0; + cblk->data = 0; + cblk->savedcurpass = 0; + cblk->savednumlenbits = 0; + cblk->savednumencpasses = 0; + + band = prc->band; + tlcblktlx = JPC_FLOORTOMULTPOW2(prc->tlx, rlvl->cblkwidthexpn); + tlcblktly = JPC_FLOORTOMULTPOW2(prc->tly, rlvl->cblkheightexpn); + cblktlx = + JAS_MAX(tlcblktlx + (cblkxind << rlvl->cblkwidthexpn), prc->tlx); + cblktly = + JAS_MAX(tlcblktly + (cblkyind << rlvl->cblkheightexpn), prc->tly); + cblkbrx = + JAS_MIN(tlcblktlx + ((cblkxind + 1) << rlvl->cblkwidthexpn), prc->brx); + cblkbry = + JAS_MIN(tlcblktly + ((cblkyind + 1) << rlvl->cblkheightexpn), + prc->bry); + + assert(cblktlx < cblkbrx && cblktly < cblkbry); + cblk->data = jas_seq2d_create(0, 0, 0, 0); + if (!cblk->data) + goto error; + jas_seq2d_bindsub(cblk->data, band->data, + cblktlx, cblktly, cblkbrx, cblkbry); + + return cblk; + +error: + cblk_destroy(cblk); + return 0; +} + + + +static void +cblk_destroy(jpc_enc_cblk_t *cblk) { + + uint_fast16_t passno; + jpc_enc_pass_t *pass; + if (cblk->passes) { + for (passno = 0, pass = cblk->passes; passno < cblk->numpasses; + ++passno, ++pass) { + pass_destroy(pass); + } + jas_free(cblk->passes); + } + if (cblk->stream) { + jas_stream_close(cblk->stream); + } + if (cblk->mqenc) { + jpc_mqenc_destroy(cblk->mqenc); + } + if (cblk->data) { + jas_seq2d_destroy(cblk->data); + } + if (cblk->flags) { + jas_seq2d_destroy(cblk->flags); + } +} + + + +static void +pass_destroy(jpc_enc_pass_t *pass) { + + /* XXX - need to free resources here */ +} + + + +void +jpc_enc_dump(jpc_enc_t *enc) { + + jpc_enc_tile_t *tile; + jpc_enc_tcmpt_t *tcmpt; + jpc_enc_rlvl_t *rlvl; + jpc_enc_band_t *band; + jpc_enc_prc_t *prc; + jpc_enc_cblk_t *cblk; + uint_fast16_t cmptno; + uint_fast16_t rlvlno; + uint_fast16_t bandno; + uint_fast32_t prcno; + uint_fast32_t cblkno; + + tile = enc->curtile; + + for (cmptno = 0, tcmpt = tile->tcmpts; + cmptno < tile->numtcmpts; + ++cmptno, ++tcmpt) { + fprintf(stderr, " tcmpt %5d %5d %5d %5d\n", + (int)jas_seq2d_xstart(tcmpt->data), + (int)jas_seq2d_ystart(tcmpt->data), + (int)jas_seq2d_xend(tcmpt->data), + (int)jas_seq2d_yend(tcmpt->data)); + for (rlvlno = 0, rlvl = tcmpt->rlvls; + rlvlno < tcmpt->numrlvls; + ++rlvlno, ++rlvl) { + fprintf(stderr, " rlvl %5d %5d %5d %5d\n", + (int)rlvl->tlx, (int)rlvl->tly, + (int)rlvl->brx, (int)rlvl->bry); + for (bandno = 0, band = rlvl->bands; bandno < rlvl->numbands; + ++bandno, ++band) { + if (!band->data) { + continue; + } + fprintf(stderr, " band %5d %5d %5d %5d\n", + (int)jas_seq2d_xstart(band->data), + (int)jas_seq2d_ystart(band->data), + (int)jas_seq2d_xend(band->data), + (int)jas_seq2d_yend(band->data)); + for (prcno = 0, prc = band->prcs; + prcno < rlvl->numprcs; + ++prcno, ++prc) { + fprintf(stderr, " prc %5d %5d %5d %5d (%5d %5d)\n", + (int)prc->tlx, (int)prc->tly, + (int)prc->brx, (int)prc->bry, + (int)(prc->brx - prc->tlx), + (int)(prc->bry - prc->tly)); + if (!prc->cblks) { + continue; + } + for (cblkno = 0, cblk = prc->cblks; cblkno < prc->numcblks; + ++cblkno, ++cblk) { + fprintf(stderr, " cblk %5d %5d %5d %5d\n", + (int)jas_seq2d_xstart(cblk->data), + (int)jas_seq2d_ystart(cblk->data), + (int)jas_seq2d_xend(cblk->data), + (int)jas_seq2d_yend(cblk->data)); + } + } + } + } + } +} + + + /* * 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 #include +#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 #include @@ -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; } diff --git a/converter/other/jpeg2000/pamtojpeg2k.c b/converter/other/jpeg2000/pamtojpeg2k.c index ee5189ce..8f7409c0 100644 --- a/converter/other/jpeg2000/pamtojpeg2k.c +++ b/converter/other/jpeg2000/pamtojpeg2k.c @@ -53,6 +53,8 @@ struct CmdlineInfo { enum compmode compmode; unsigned int compressionSpec; float compression; + unsigned int size; + unsigned int sizeSpec; char * ilyrrates; enum progression progression; unsigned int numrlvls; @@ -76,7 +78,7 @@ parseCommandLine(int argc, char ** argv, struct CmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- Note that many of the strings that this function returns in the - *cmdline_p structure are actually in the supplied argv array. And + *cmdlineP structure are actually in the supplied argv array. And sometimes, one of these strings is actually just a suffix of an entry in argv! -----------------------------------------------------------------------------*/ @@ -126,6 +128,8 @@ parseCommandLine(int argc, char ** argv, &modeSpec, 0); OPTENT3(0, "compression", OPT_FLOAT, &cmdlineP->compression, &cmdlineP->compressionSpec, 0); + OPTENT3(0, "size", OPT_UINT, &cmdlineP->size, + &cmdlineP->sizeSpec, 0); OPTENT3(0, "ilyrrates", OPT_STRING, &cmdlineP->ilyrrates, &ilyrratesSpec, 0); OPTENT3(0, "progression", OPT_STRING, &progressionOpt, @@ -219,6 +223,9 @@ parseCommandLine(int argc, char ** argv, if (!debuglevelSpec) cmdlineP->debuglevel = 0; + if (cmdlineP->compressionSpec && cmdlineP->sizeSpec) + pm_error("You cannot specify by -compression and -size"); + if (argc - 1 == 0) cmdlineP->inputFilename = strdup("-"); /* he wants stdin */ else if (argc - 1 == 1) @@ -405,6 +412,8 @@ writeJpc(jas_image_t * const jasperP, if (cmdline.compressionSpec) sprintf(rateOpt, "rate=%1.9f", 1.0/cmdline.compression); + else if (cmdline.sizeSpec) + sprintf(rateOpt, "rate=%uB", cmdline.size); else { /* No 'rate' option. This means there is no constraint on the image size, so the encoder will compress losslessly. Note that the diff --git a/converter/ppm/ppmtompeg/frame.c b/converter/ppm/ppmtompeg/frame.c index f5a0d39d..09e35410 100644 --- a/converter/ppm/ppmtompeg/frame.c +++ b/converter/ppm/ppmtompeg/frame.c @@ -12,7 +12,7 @@ * Frame_AllocYCC * * Frame_AllocDecoded * * Frame_AllocHalf * - * Frame_Resize * + * Frame_Resize * * * *===========================================================================*/ @@ -52,7 +52,7 @@ *===========*/ /* The maximum number of B-Frames allowed between reference frames. */ -#define B_FRAME_RUN 16 +#define B_FRAME_RUN 16 /*==================* * GLOBAL VARIABLES * @@ -64,13 +64,13 @@ static unsigned int numOfFrames; /*==================================================== * Resize_Array_Width -* +* * This function will resize any array width up * or down in size. The algorithm is based on the * least common multiple approach more commonly * used in audio frequency adjustments. *=====================================================*/ -static void +static void Resize_Array_Width(uint8 ** const inarray, int const in_x, int const in_y, @@ -86,7 +86,7 @@ Resize_Array_Width(uint8 ** const inarray, uint8 pointA,pointB; double slope,diff; #endif - + for (i = 0; i < in_y; ++i) { /* For each row */ unsigned int j; inptr = &inarray[i][0]; @@ -106,7 +106,7 @@ Resize_Array_Width(uint8 ** const inarray, in_total = in_total - out_x; --inptr; } - } else { + } else { #ifdef DOING_INTERPOLATION pointA = *inptr; #endif @@ -124,10 +124,10 @@ Resize_Array_Width(uint8 ** const inarray, } else { *outptr = (pointB - (uint8)(slope*(((float)(out_x)) - diff))); - } + } #endif /* Non-Interpolative solution */ - *outptr = *inptr; + *outptr = *inptr; ++outptr; out_total = out_total + in_x; @@ -153,7 +153,7 @@ Resize_Array_Width(uint8 ** const inarray, * Same as Resize_array_Width except pointer * manipulation must change. *===============================*/ -static void +static void Resize_Array_Height(uint8 ** const inarray, int const in_x, int const in_y, @@ -176,7 +176,7 @@ Resize_Array_Height(uint8 ** const inarray, out_total = 0; k = 0; for(j=0; j < out_y; ++j){ /* for each output value */ - if (in_total == out_total) { + if (in_total == out_total) { outarray[j][i] = inarray[k][i]; out_total=out_total+in_y; while(in_total < out_total){ @@ -187,7 +187,7 @@ Resize_Array_Height(uint8 ** const inarray, in_total = in_total - out_y; --k; } - } else { + } else { #ifdef DOING_INTERPOLATION pointA = inarray[k][i]; if (k != (in_y - 1)) { @@ -210,7 +210,7 @@ Resize_Array_Height(uint8 ** const inarray, in_total = in_total - out_y; --k; } - } + } } } } @@ -220,7 +220,7 @@ Resize_Array_Height(uint8 ** const inarray, /*======================================================== * Resize_Width *======================================================*/ -static void +static void Resize_Width(MpegFrame * const omfrw, MpegFrame * const mfrw, int const in_x, @@ -274,12 +274,12 @@ Resize_Width(MpegFrame * const omfrw, free(mfrw->orig_y[i]); } free(mfrw->orig_y); - + for (i = 0; i < in_y / 2; ++i) { free(mfrw->orig_cr[i]); } free(mfrw->orig_cr); - + for (i = 0; i < in_y / 2; ++i) { free(mfrw->orig_cb[i]); } @@ -300,9 +300,9 @@ Resize_Height(MpegFrame * const omfrh, int const in_x, int const in_y, int const out_y) { - - unsigned int y; - + + unsigned int y; + Fsize_y = out_y; /* Allocate new frame memory */ @@ -347,12 +347,12 @@ Resize_Height(MpegFrame * const omfrh, free(mfrh->orig_y[i]); } free(mfrh->orig_y); - + for (i = 0; i < in_y / 2; ++i) { free(mfrh->orig_cr[i]); } free(mfrh->orig_cr); - + for (i = 0; i < in_y / 2; ++i) { free(mfrh->orig_cb[i]); } @@ -386,8 +386,8 @@ Frame_Init(unsigned int const numOfFramesRequested) { for (idx = 0; idx < numOfFrames; ++idx) { MALLOCVAR(frameMemory[idx]); frameMemory[idx]->inUse = FALSE; - frameMemory[idx]->orig_y = NULL; - frameMemory[idx]->y_blocks = NULL; + frameMemory[idx]->orig_y = NULL; + frameMemory[idx]->y_blocks = NULL; frameMemory[idx]->decoded_y = NULL; frameMemory[idx]->halfX = NULL; frameMemory[idx]->next = NULL; @@ -458,11 +458,11 @@ FreeFrame(MpegFrame * const frameP) { for ( i = 0; i < Fsize_y; ++i ) free(frameP->halfX[i]); free(frameP->halfX); - + for (i = 0; i < Fsize_y-1; ++i) free(frameP->halfY[i]); free(frameP->halfY); - + for (i = 0; i < Fsize_y-1; ++i) free(frameP->halfBoth[i]); free(frameP->halfBoth); @@ -542,7 +542,7 @@ GetUnusedFrame() { "See the man page for help.\n"); exit(1); } - return frameMemory[idx]; + return frameMemory[idx]; } @@ -638,7 +638,7 @@ Frame_AllocBlocks(MpegFrame * const frameP) { MALLOCARRAY(frameP->y_blocks[i], dctx); ERRCHK(frameP->y_blocks[i], "malloc"); } - + MALLOCARRAY(frameP->cr_blocks, dcty / 2); ERRCHK(frameP->cr_blocks, "malloc"); MALLOCARRAY(frameP->cb_blocks, dcty / 2); @@ -672,7 +672,7 @@ Frame_AllocYCC(MpegFrame * const frameP) { /* already allocated */ } else { unsigned int y; - + DBG_PRINT(("ycc_calc:\n")); /* * first, allocate tons of memory @@ -755,7 +755,7 @@ Frame_AllocHalf(MpegFrame * const frameP) { * * allocate memory for decoded frame for the given frame, if required * if makeReference == TRUE, then makes it reference frame - * + * * RETURNS: nothing * * SIDE EFFECTS: none @@ -781,14 +781,14 @@ Frame_AllocDecoded(MpegFrame * const frameP, MALLOCARRAY(frameP->decoded_y[y], Fsize_x); ERRCHK(frameP->decoded_y[y], "malloc"); } - + MALLOCARRAY(frameP->decoded_cr, Fsize_y / 2); ERRCHK(frameP->decoded_cr, "malloc"); for (y = 0; y < (Fsize_y / 2); ++y) { MALLOCARRAY(frameP->decoded_cr[y], Fsize_x / 2); ERRCHK(frameP->decoded_cr[y], "malloc"); } - + MALLOCARRAY(frameP->decoded_cb, Fsize_y / 2); ERRCHK(frameP->decoded_cb, "malloc"); for (y = 0; y < (Fsize_y / 2); ++y) { @@ -810,7 +810,7 @@ Frame_AllocDecoded(MpegFrame * const frameP, * * Frame_Resize by James Boucher * Boston University Multimedia Communications Lab - * + * * This function takes the mf input frame, read in READFrame(), * and resizes all the input component arrays to the output * dimensions specified in the parameter file as OUT_SIZE. @@ -828,11 +828,11 @@ Frame_Resize(MpegFrame * const omf, MpegFrame * frameAP; /* intermediate frame */ MALLOCVAR_NOFAIL(frameAP); - + if (insize_x != outsize_x && insize_y != outsize_y) { Resize_Width(frameAP, mf, insize_x, insize_y, outsize_x); Resize_Height(omf, frameAP, outsize_x, insize_y, outsize_y); - } else + } else if (insize_x ==outsize_x && insize_y != outsize_y) { Resize_Height(omf, mf, insize_x, insize_y, outsize_y); } else @@ -843,3 +843,5 @@ Frame_Resize(MpegFrame * const omf, free(frameAP); } + + diff --git a/converter/ppm/ppmtompeg/readframe.c b/converter/ppm/ppmtompeg/readframe.c index 2a359b2f..dcc02052 100644 --- a/converter/ppm/ppmtompeg/readframe.c +++ b/converter/ppm/ppmtompeg/readframe.c @@ -1,13 +1,13 @@ /*===========================================================================* - * readframe.c - * - * procedures to read in frames - * - * EXPORTED PROCEDURES: - * ReadFrame - * SetFileType - * SetFileFormat - * + * readframe.c + * + * procedures to read in frames + * + * EXPORTED PROCEDURES: + * ReadFrame + * SetFileType + * SetFileFormat + * *===========================================================================*/ /* COPYRIGHT INFORMATION IS AT THE END OF THIS FILE */ @@ -62,7 +62,7 @@ struct YuvLine { #ifdef __OS2__ #define popen _popen #endif - + /*==================* * Global VARIABLES * @@ -100,7 +100,7 @@ static void DoKillDim (MpegFrame *mf, int w, int h); -void +void SetResize(bool const set) { resizeFrame = set; } @@ -134,7 +134,7 @@ ReadPNM(MpegFrame * const mpegFrameP, static void openFile(struct inputSource * const inputSourceP, unsigned int const frameNumber, - const char * const conversion, + const char * const conversion, FILE ** const ifPP) { if (inputSourceP->stdinUsed) { @@ -145,24 +145,24 @@ openFile(struct inputSource * const inputSourceP, "INPUT_CONVERTER * in the parameter file or supply the " "frames in files by specifying a directory with " "INPUT_DIRECTORY in the parameter file."); - + *ifPP = stdin; } else { const char * fileName; const char * fullFileName; - + GetNthInputFileName(inputSourceP, frameNumber, &fileName); - + pm_asprintf(&fullFileName, "%s/%s", currentPath, fileName); - + CurrFile = fullFileName; - + if (fileType == ANY_FILE_TYPE) { char command[1024]; const char * convertPtr; char * commandPtr; const char * charPtr; - + /* replace every occurrence of '*' with fullFileName */ convertPtr = conversion; commandPtr = command; @@ -172,7 +172,7 @@ openFile(struct inputSource * const inputSourceP, ++commandPtr; ++convertPtr; } - + if (*convertPtr == '*') { /* copy fullFileName */ charPtr = fullFileName; @@ -185,7 +185,7 @@ openFile(struct inputSource * const inputSourceP, } } *commandPtr = '\0'; - + *ifPP = popen(command, "r"); if (*ifPP == NULL) { pm_message( @@ -201,7 +201,7 @@ openFile(struct inputSource * const inputSourceP, *ifPP = fopen(fullFileName, "rb"); if (*ifPP == NULL) pm_error("Couldn't open input file '%s'", fullFileName); - + if (baseFormat == JMOVIE_FILE_TYPE) unlink(fullFileName); } @@ -238,7 +238,7 @@ fileIsAtEnd(FILE * const ifP) { c = getc(ifP); if (c == EOF) { - if (feof(ifP)) + if (feof(ifP)) eof = TRUE; else pm_error("File error on getc() to position to image"); @@ -248,7 +248,7 @@ fileIsAtEnd(FILE * const ifP) { eof = FALSE; rc = ungetc(c, ifP); - if (rc == EOF) + if (rc == EOF) pm_error("File error doing ungetc() to position to image."); } return eof; @@ -262,14 +262,11 @@ ReadFrameFile(MpegFrame * const frameP, const char * const conversion, bool * const eofP) { /*---------------------------------------------------------------------------- - Read a frame from the file 'ifP'. + Read a frame from the file 'ifP', doing adjustments as indicated. Return *eofP == TRUE iff we encounter EOF before we can get the frame. -----------------------------------------------------------------------------*/ - MpegFrame tempFrame; - MpegFrame * framePtr; - /* To make this code fit Netpbm properly, we should remove handling of all types except PNM and use pm_nextimage() to handle sensing of end of stream. @@ -278,53 +275,59 @@ ReadFrameFile(MpegFrame * const frameP, if (fileIsAtEnd(ifP)) *eofP = TRUE; else { + MpegFrame preResizeFrame; + /* The frame object that holds the frame before resizing */ + MpegFrame * rawFrameP; + /* The frame object with which we read in the raw frame */ + *eofP = FALSE; if (resizeFrame) { - tempFrame.inUse = FALSE; - tempFrame.orig_y = NULL; - tempFrame.y_blocks = NULL; - tempFrame.decoded_y = NULL; - tempFrame.halfX = NULL; - framePtr = &tempFrame; + preResizeFrame.inUse = FALSE; + preResizeFrame.orig_y = NULL; + preResizeFrame.y_blocks = NULL; + preResizeFrame.decoded_y = NULL; + preResizeFrame.halfX = NULL; + rawFrameP = &preResizeFrame; } else - framePtr = frameP; + rawFrameP = frameP; switch(baseFormat) { case YUV_FILE_TYPE: /* Encoder YUV */ if ((strncmp (yuvConversion, "EYUV", 4) == 0) || - (strncmp (yuvConversion, "UCB", 3) == 0)) + (strncmp (yuvConversion, "UCB", 3) == 0)) - ReadEYUV(framePtr, ifP, realWidth, realHeight); + ReadEYUV(rawFrameP, ifP, realWidth, realHeight); else /* Abekas-type (interlaced) YUV */ - ReadAYUV(framePtr, ifP, realWidth, realHeight); + ReadAYUV(rawFrameP, ifP, realWidth, realHeight); break; case Y_FILE_TYPE: - ReadY(framePtr, ifP, realWidth, realHeight); + ReadY(rawFrameP, ifP, realWidth, realHeight); break; case PNM_FILE_TYPE: - ReadPNM(framePtr, ifP); + ReadPNM(rawFrameP, ifP); break; case SUB4_FILE_TYPE: - ReadSub4(framePtr, ifP, yuvWidth, yuvHeight); + ReadSub4(rawFrameP, ifP, yuvWidth, yuvHeight); break; case JPEG_FILE_TYPE: case JMOVIE_FILE_TYPE: - ReadJPEG(framePtr, ifP); + ReadJPEG(rawFrameP, ifP); break; default: break; } - if (resizeFrame) - Frame_Resize(frameP, &tempFrame, Fsize_x, Fsize_y, + if (resizeFrame) { + assert(rawFrameP == &preResizeFrame); + Frame_Resize(frameP, &preResizeFrame, Fsize_x, Fsize_y, outputWidth, outputHeight); - + } if (GammaCorrection) DoGamma(frameP, Fsize_x, Fsize_y); @@ -338,7 +341,7 @@ ReadFrameFile(MpegFrame * const frameP, void -ReadFrame(MpegFrame * const frameP, +ReadFrame(MpegFrame * const frameP, struct inputSource * const inputSourceP, unsigned int const frameNumber, const char * const conversion, @@ -693,7 +696,7 @@ SeparateLine(fpointer, lineptr, width) fprintf(stderr, " or any even-length string consisting of the letters U, V, and Y.\n"); exit(1); } - + } } @@ -738,7 +741,7 @@ ReadY(mf, fpointer, width, height) for (y = Fsize_y; y < height; y++) { safe_fread(junk, 1, width, fpointer); } - + for (y = 0 ; y < (Fsize_y >> 1); y++) { memset(mf->orig_cb[y], 128, (Fsize_x>>1)); memset(mf->orig_cr[y], 128, (Fsize_x>>1)); @@ -830,7 +833,7 @@ int w,h; int i,j; if (!init_done) { - for(i=0; i<256; i++) + for(i=0; i<256; i++) GammaVal[i]=(unsigned char) (pow(((double) i)/255.0,GammaValue)*255.0+0.5); init_done=TRUE; } @@ -871,7 +874,7 @@ int w,h; ^ kill_dim_break ^kill_dim_end kill_dim_slope gives the slope (y = kill_dim_slope * x +0) - from 0 to kill_dim_break + from 0 to kill_dim_break * *===========================================================================*/ @@ -930,7 +933,7 @@ int w,h; * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ -/* +/* * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/readframe.c,v 1.27 1995/08/14 22:31:40 smoot Exp $ * $Log: readframe.c,v $ * Revision 1.27 1995/08/14 22:31:40 smoot -- cgit 1.4.1