Home | History | Annotate | Download | only in libjasper
      1 /*
      2  * Copyright (c) 1999-2000 Image Power, Inc. and the University of
      3  *   British Columbia.
      4  * Copyright (c) 2001-2002 Michael David Adams.
      5  * All rights reserved.
      6  */
      7 
      8 /* __START_OF_JASPER_LICENSE__
      9  *
     10  * JasPer License Version 2.0
     11  *
     12  * Copyright (c) 2001-2006 Michael David Adams
     13  * Copyright (c) 1999-2000 Image Power, Inc.
     14  * Copyright (c) 1999-2000 The University of British Columbia
     15  *
     16  * All rights reserved.
     17  *
     18  * Permission is hereby granted, free of charge, to any person (the
     19  * "User") obtaining a copy of this software and associated documentation
     20  * files (the "Software"), to deal in the Software without restriction,
     21  * including without limitation the rights to use, copy, modify, merge,
     22  * publish, distribute, and/or sell copies of the Software, and to permit
     23  * persons to whom the Software is furnished to do so, subject to the
     24  * following conditions:
     25  *
     26  * 1.  The above copyright notices and this permission notice (which
     27  * includes the disclaimer below) shall be included in all copies or
     28  * substantial portions of the Software.
     29  *
     30  * 2.  The name of a copyright holder shall not be used to endorse or
     31  * promote products derived from the Software without specific prior
     32  * written permission.
     33  *
     34  * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
     35  * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
     36  * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
     37  * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
     38  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
     39  * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO
     40  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
     41  * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
     42  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
     43  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
     44  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE
     45  * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
     46  * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
     47  * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
     48  * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
     49  * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS
     50  * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
     51  * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE
     52  * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
     53  * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
     54  * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
     55  * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
     56  * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
     57  * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
     58  * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
     59  * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
     60  *
     61  * __END_OF_JASPER_LICENSE__
     62  */
     63 
     64 /*
     65  * Tier 1 Encoder
     66  *
     67  * $Id: jpc_t1enc.c,v 1.2 2008-05-26 09:40:52 vp153 Exp $
     68  */
     69 
     70 /******************************************************************************\
     71 * Includes.
     72 \******************************************************************************/
     73 
     74 #include <stdio.h>
     75 #include <stdlib.h>
     76 #include <assert.h>
     77 
     78 #include "jasper/jas_fix.h"
     79 #include "jasper/jas_malloc.h"
     80 #include "jasper/jas_math.h"
     81 
     82 #include "jpc_t1enc.h"
     83 #include "jpc_t1cod.h"
     84 #include "jpc_enc.h"
     85 #include "jpc_cod.h"
     86 #include "jpc_math.h"
     87 
     88 static int jpc_encsigpass(jpc_mqenc_t *mqenc, int bitpos, int orient, int,
     89   jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec);
     90 
     91 static int jpc_encrefpass(jpc_mqenc_t *mqenc, int bitpos, int, jas_matrix_t *flags,
     92   jas_matrix_t *data, int term, long *nmsedec);
     93 
     94 static int jpc_encclnpass(jpc_mqenc_t *mqenc, int bitpos, int orient, int,
     95   int, jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec);
     96 
     97 static int jpc_encrawsigpass(jpc_bitstream_t *out, int bitpos, int,
     98   jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec);
     99 
    100 static int jpc_encrawrefpass(jpc_bitstream_t *out, int bitpos, int,
    101   jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec);
    102 
    103 /******************************************************************************\
    104 * Code for encoding code blocks.
    105 \******************************************************************************/
    106 
    107 /* Encode all of the code blocks associated with the current tile. */
    108 int jpc_enc_enccblks(jpc_enc_t *enc)
    109 {
    110     jpc_enc_tcmpt_t *tcmpt;
    111     jpc_enc_tcmpt_t *endcomps;
    112     jpc_enc_rlvl_t *lvl;
    113     jpc_enc_rlvl_t *endlvls;
    114     jpc_enc_band_t *band;
    115     jpc_enc_band_t *endbands;
    116     jpc_enc_cblk_t *cblk;
    117     jpc_enc_cblk_t *endcblks;
    118     int i;
    119     int j;
    120     int mx;
    121     int bmx;
    122     int v;
    123     jpc_enc_tile_t *tile;
    124     uint_fast32_t prcno;
    125     jpc_enc_prc_t *prc;
    126 
    127     tile = enc->curtile;
    128 
    129     endcomps = &tile->tcmpts[tile->numtcmpts];
    130     for (tcmpt = tile->tcmpts; tcmpt != endcomps; ++tcmpt) {
    131         endlvls = &tcmpt->rlvls[tcmpt->numrlvls];
    132         for (lvl = tcmpt->rlvls; lvl != endlvls; ++lvl) {
    133             if (!lvl->bands) {
    134                 continue;
    135             }
    136             endbands = &lvl->bands[lvl->numbands];
    137             for (band = lvl->bands; band != endbands; ++band) {
    138                 if (!band->data) {
    139                     continue;
    140                 }
    141                 for (prcno = 0, prc = band->prcs; prcno < lvl->numprcs; ++prcno, ++prc) {
    142                     if (!prc->cblks) {
    143                         continue;
    144                     }
    145                     bmx = 0;
    146                     endcblks = &prc->cblks[prc->numcblks];
    147                     for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
    148                         mx = 0;
    149                         for (i = 0; i < jas_matrix_numrows(cblk->data); ++i) {
    150                             for (j = 0; j < jas_matrix_numcols(cblk->data); ++j) {
    151                                 v = abs(jas_matrix_get(cblk->data, i, j));
    152                                 if (v > mx) {
    153                                     mx = v;
    154                                 }
    155                             }
    156                         }
    157                         if (mx > bmx) {
    158                             bmx = mx;
    159                         }
    160                         cblk->numbps = JAS_MAX(jpc_firstone(mx) + 1 - JPC_NUMEXTRABITS, 0);
    161                     }
    162 
    163                     for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
    164                         cblk->numimsbs = band->numbps - cblk->numbps;
    165                         assert(cblk->numimsbs >= 0);
    166                     }
    167 
    168                     for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
    169                         if (jpc_enc_enccblk(enc, cblk->stream, tcmpt, band, cblk)) {
    170                             return -1;
    171                         }
    172                     }
    173                 }
    174             }
    175         }
    176     }
    177     return 0;
    178 }
    179 
    180 int getthebyte(jas_stream_t *in, long off)
    181 {
    182     int c;
    183     long oldpos;
    184     oldpos = jas_stream_tell(in);
    185     assert(oldpos >= 0);
    186     jas_stream_seek(in, off, SEEK_SET);
    187     c = jas_stream_peekc(in);
    188     jas_stream_seek(in, oldpos, SEEK_SET);
    189     return c;
    190 }
    191 
    192 /* Encode a single code block. */
    193 int jpc_enc_enccblk(jpc_enc_t *enc, jas_stream_t *out, jpc_enc_tcmpt_t *tcmpt, jpc_enc_band_t *band, jpc_enc_cblk_t *cblk)
    194 {
    195     jpc_enc_pass_t *pass;
    196     jpc_enc_pass_t *endpasses;
    197     int bitpos;
    198     int n;
    199     int adjust;
    200     int ret;
    201     int passtype;
    202     int t;
    203     jpc_bitstream_t *bout;
    204     jpc_enc_pass_t *termpass;
    205     jpc_enc_rlvl_t *rlvl;
    206     int vcausal;
    207     int segsym;
    208     int termmode;
    209     int c;
    210 
    211     bout = 0;
    212     rlvl = band->rlvl;
    213 
    214     cblk->stream = jas_stream_memopen(0, 0);
    215     assert(cblk->stream);
    216     cblk->mqenc = jpc_mqenc_create(JPC_NUMCTXS, cblk->stream);
    217     assert(cblk->mqenc);
    218     jpc_mqenc_setctxs(cblk->mqenc, JPC_NUMCTXS, jpc_mqctxs);
    219 
    220     cblk->numpasses = (cblk->numbps > 0) ? (3 * cblk->numbps - 2) : 0;
    221     if (cblk->numpasses > 0) {
    222         cblk->passes = jas_alloc2(cblk->numpasses, sizeof(jpc_enc_pass_t));
    223         assert(cblk->passes);
    224     } else {
    225         cblk->passes = 0;
    226     }
    227     endpasses = &cblk->passes[cblk->numpasses];
    228     for (pass = cblk->passes; pass != endpasses; ++pass) {
    229         pass->start = 0;
    230         pass->end = 0;
    231         pass->term = JPC_ISTERMINATED(pass - cblk->passes, 0, cblk->numpasses, (tcmpt->cblksty & JPC_COX_TERMALL) != 0, (tcmpt->cblksty & JPC_COX_LAZY) != 0);
    232         pass->type = JPC_SEGTYPE(pass - cblk->passes, 0, (tcmpt->cblksty & JPC_COX_LAZY) != 0);
    233         pass->lyrno = -1;
    234 if (pass == endpasses - 1) {
    235 assert(pass->term == 1);
    236     pass->term = 1;
    237 }
    238     }
    239 
    240     cblk->flags = jas_matrix_create(jas_matrix_numrows(cblk->data) + 2,
    241       jas_matrix_numcols(cblk->data) + 2);
    242     assert(cblk->flags);
    243 
    244 
    245     bitpos = cblk->numbps - 1;
    246     pass = cblk->passes;
    247     n = cblk->numpasses;
    248     while (--n >= 0) {
    249 
    250         if (pass->type == JPC_SEG_MQ) {
    251             /* NOP */
    252         } else {
    253             assert(pass->type == JPC_SEG_RAW);
    254             if (!bout) {
    255                 bout = jpc_bitstream_sopen(cblk->stream, "w");
    256                 assert(bout);
    257             }
    258         }
    259 
    260 #if 1
    261         passtype = (pass - cblk->passes + 2) % 3;
    262 #else
    263         passtype = JPC_PASSTYPE(pass - cblk->passes + 2);
    264 #endif
    265         pass->start = jas_stream_tell(cblk->stream);
    266 #if 0
    267 assert(jas_stream_tell(cblk->stream) == jas_stream_getrwcount(cblk->stream));
    268 #endif
    269         assert(bitpos >= 0);
    270         vcausal = (tcmpt->cblksty & JPC_COX_VSC) != 0;
    271         segsym = (tcmpt->cblksty & JPC_COX_SEGSYM) != 0;
    272         if (pass->term) {
    273             termmode = ((tcmpt->cblksty & JPC_COX_PTERM) ?
    274               JPC_MQENC_PTERM : JPC_MQENC_DEFTERM) + 1;
    275         } else {
    276             termmode = 0;
    277         }
    278         switch (passtype) {
    279         case JPC_SIGPASS:
    280             ret = (pass->type == JPC_SEG_MQ) ? jpc_encsigpass(cblk->mqenc,
    281               bitpos, band->orient, vcausal, cblk->flags,
    282               cblk->data, termmode, &pass->nmsedec) :
    283               jpc_encrawsigpass(bout, bitpos, vcausal, cblk->flags,
    284               cblk->data, termmode, &pass->nmsedec);
    285             break;
    286         case JPC_REFPASS:
    287             ret = (pass->type == JPC_SEG_MQ) ? jpc_encrefpass(cblk->mqenc,
    288               bitpos, vcausal, cblk->flags, cblk->data, termmode,
    289               &pass->nmsedec) : jpc_encrawrefpass(bout, bitpos,
    290               vcausal, cblk->flags, cblk->data, termmode,
    291               &pass->nmsedec);
    292             break;
    293         case JPC_CLNPASS:
    294             assert(pass->type == JPC_SEG_MQ);
    295             ret = jpc_encclnpass(cblk->mqenc, bitpos, band->orient,
    296               vcausal, segsym, cblk->flags, cblk->data, termmode,
    297               &pass->nmsedec);
    298             break;
    299         default:
    300             assert(0);
    301             break;
    302         }
    303 
    304         if (pass->type == JPC_SEG_MQ) {
    305             if (pass->term) {
    306                 jpc_mqenc_init(cblk->mqenc);
    307             }
    308             jpc_mqenc_getstate(cblk->mqenc, &pass->mqencstate);
    309             pass->end = jas_stream_tell(cblk->stream);
    310             if (tcmpt->cblksty & JPC_COX_RESET) {
    311                 jpc_mqenc_setctxs(cblk->mqenc, JPC_NUMCTXS, jpc_mqctxs);
    312             }
    313         } else {
    314             if (pass->term) {
    315                 if (jpc_bitstream_pending(bout)) {
    316                     jpc_bitstream_outalign(bout, 0x2a);
    317                 }
    318                 jpc_bitstream_close(bout);
    319                 bout = 0;
    320                 pass->end = jas_stream_tell(cblk->stream);
    321             } else {
    322                 pass->end = jas_stream_tell(cblk->stream) +
    323                   jpc_bitstream_pending(bout);
    324 /* NOTE - This will not work.  need to adjust by # of pending output bytes */
    325             }
    326         }
    327 #if 0
    328 /* XXX - This assertion fails sometimes when various coding modes are used.
    329 This seems to be harmless, but why does it happen at all? */
    330 assert(jas_stream_tell(cblk->stream) == jas_stream_getrwcount(cblk->stream));
    331 #endif
    332 
    333         pass->wmsedec = jpc_fixtodbl(band->rlvl->tcmpt->synweight) *
    334           jpc_fixtodbl(band->rlvl->tcmpt->synweight) *
    335           jpc_fixtodbl(band->synweight) *
    336           jpc_fixtodbl(band->synweight) *
    337           jpc_fixtodbl(band->absstepsize) * jpc_fixtodbl(band->absstepsize) *
    338           ((double) (1 << bitpos)) * ((double)(1 << bitpos)) *
    339           jpc_fixtodbl(pass->nmsedec);
    340         pass->cumwmsedec = pass->wmsedec;
    341         if (pass != cblk->passes) {
    342             pass->cumwmsedec += pass[-1].cumwmsedec;
    343         }
    344         if (passtype == JPC_CLNPASS) {
    345             --bitpos;
    346         }
    347         ++pass;
    348     }
    349 
    350 #if 0
    351 dump_passes(cblk->passes, cblk->numpasses, cblk);
    352 #endif
    353 
    354     n = 0;
    355     endpasses = &cblk->passes[cblk->numpasses];
    356     for (pass = cblk->passes; pass != endpasses; ++pass) {
    357         if (pass->start < n) {
    358             pass->start = n;
    359         }
    360         if (pass->end < n) {
    361             pass->end = n;
    362         }
    363         if (!pass->term) {
    364             termpass = pass;
    365             while (termpass - pass < cblk->numpasses &&
    366               !termpass->term) {
    367                 ++termpass;
    368             }
    369             if (pass->type == JPC_SEG_MQ) {
    370                 t = (pass->mqencstate.lastbyte == 0xff) ? 1 : 0;
    371                 if (pass->mqencstate.ctreg >= 5) {
    372                     adjust = 4 + t;
    373                 } else {
    374                     adjust = 5 + t;
    375                 }
    376                 pass->end += adjust;
    377             }
    378             if (pass->end > termpass->end) {
    379                 pass->end = termpass->end;
    380             }
    381             if ((c = getthebyte(cblk->stream, pass->end - 1)) == EOF) {
    382                 abort();
    383             }
    384             if (c == 0xff) {
    385                 ++pass->end;
    386             }
    387             n = JAS_MAX(n, pass->end);
    388         } else {
    389             n = JAS_MAX(n, pass->end);
    390         }
    391     }
    392 
    393 #if 0
    394 dump_passes(cblk->passes, cblk->numpasses, cblk);
    395 #endif
    396 
    397     if (bout) {
    398         jpc_bitstream_close(bout);
    399     }
    400 
    401     return 0;
    402 }
    403 
    404 /******************************************************************************\
    405 * Code for significance pass.
    406 \******************************************************************************/
    407 
    408 #define	sigpass_step(fp, frowstep, dp, bitpos, one, nmsedec, orient, mqenc, vcausalflag) \
    409 { \
    410     int f; \
    411     int v; \
    412     f = *(fp); \
    413     if ((f & JPC_OTHSIGMSK) && !(f & (JPC_SIG | JPC_VISIT))) { \
    414         v = (abs(*(dp)) & (one)) ? 1 : 0; \
    415         jpc_mqenc_setcurctx(mqenc, JPC_GETZCCTXNO(f, (orient))); \
    416         jpc_mqenc_putbit(mqenc, v); \
    417         if (v) { \
    418             *(nmsedec) += JPC_GETSIGNMSEDEC(abs(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \
    419             v = ((*(dp) < 0) ? 1 : 0); \
    420             jpc_mqenc_setcurctx(mqenc, JPC_GETSCCTXNO(f)); \
    421             jpc_mqenc_putbit(mqenc, v ^ JPC_GETSPB(f)); \
    422             JPC_UPDATEFLAGS4(fp, frowstep, v, vcausalflag); \
    423             *(fp) |= JPC_SIG; \
    424         } \
    425         *(fp) |= JPC_VISIT; \
    426     } \
    427 }
    428 
    429 static int jpc_encsigpass(jpc_mqenc_t *mqenc, int bitpos, int orient, int vcausalflag,
    430   jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec)
    431 {
    432     int i;
    433     int j;
    434     int one;
    435     int vscanlen;
    436     int width;
    437     int height;
    438     int frowstep;
    439     int drowstep;
    440     int fstripestep;
    441     int dstripestep;
    442     jpc_fix_t *fstripestart;
    443     jpc_fix_t *dstripestart;
    444     jpc_fix_t *fp;
    445     jpc_fix_t *dp;
    446     jpc_fix_t *fvscanstart;
    447     jpc_fix_t *dvscanstart;
    448     int k;
    449 
    450     *nmsedec = 0;
    451     width = jas_matrix_numcols(data);
    452     height = jas_matrix_numrows(data);
    453     frowstep = jas_matrix_rowstep(flags);
    454     drowstep = jas_matrix_rowstep(data);
    455     fstripestep = frowstep << 2;
    456     dstripestep = drowstep << 2;
    457 
    458     one = 1 << (bitpos + JPC_NUMEXTRABITS);
    459 
    460     fstripestart = jas_matrix_getref(flags, 1, 1);
    461     dstripestart = jas_matrix_getref(data, 0, 0);
    462     for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
    463       dstripestart += dstripestep) {
    464         fvscanstart = fstripestart;
    465         dvscanstart = dstripestart;
    466         vscanlen = JAS_MIN(i, 4);
    467         for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
    468             fp = fvscanstart;
    469             dp = dvscanstart;
    470             k = vscanlen;
    471 
    472             sigpass_step(fp, frowstep, dp, bitpos, one,
    473               nmsedec, orient, mqenc, vcausalflag);
    474             if (--k <= 0) {
    475                 continue;
    476             }
    477             fp += frowstep;
    478             dp += drowstep;
    479             sigpass_step(fp, frowstep, dp, bitpos, one,
    480               nmsedec, orient, mqenc, 0);
    481             if (--k <= 0) {
    482                 continue;
    483             }
    484             fp += frowstep;
    485             dp += drowstep;
    486             sigpass_step(fp, frowstep, dp, bitpos, one,
    487               nmsedec, orient, mqenc, 0);
    488             if (--k <= 0) {
    489                 continue;
    490             }
    491             fp += frowstep;
    492             dp += drowstep;
    493             sigpass_step(fp, frowstep, dp, bitpos, one,
    494               nmsedec, orient, mqenc, 0);
    495 
    496         }
    497     }
    498 
    499     if (term) {
    500         jpc_mqenc_flush(mqenc, term - 1);
    501     }
    502 
    503     return jpc_mqenc_error(mqenc) ? (-1) : 0;
    504 }
    505 
    506 #define	rawsigpass_step(fp, frowstep, dp, bitpos, one, nmsedec, out, vcausalflag) \
    507 { \
    508     jpc_fix_t f = *(fp); \
    509     jpc_fix_t v; \
    510     if ((f & JPC_OTHSIGMSK) && !(f & (JPC_SIG | JPC_VISIT))) { \
    511         v = (abs(*(dp)) & (one)) ? 1 : 0; \
    512         if ((jpc_bitstream_putbit((out), v)) == EOF) { \
    513             return -1; \
    514         } \
    515         if (v) { \
    516             *(nmsedec) += JPC_GETSIGNMSEDEC(abs(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \
    517             v = ((*(dp) < 0) ? 1 : 0); \
    518             if (jpc_bitstream_putbit(out, v) == EOF) { \
    519                 return -1; \
    520             } \
    521             JPC_UPDATEFLAGS4(fp, frowstep, v, vcausalflag); \
    522             *(fp) |= JPC_SIG; \
    523         } \
    524         *(fp) |= JPC_VISIT; \
    525     } \
    526 }
    527 
    528 static int jpc_encrawsigpass(jpc_bitstream_t *out, int bitpos, int vcausalflag, jas_matrix_t *flags,
    529   jas_matrix_t *data, int term, long *nmsedec)
    530 {
    531     int i;
    532     int j;
    533     int k;
    534     int one;
    535     int vscanlen;
    536     int width;
    537     int height;
    538     int frowstep;
    539     int drowstep;
    540     int fstripestep;
    541     int dstripestep;
    542     jpc_fix_t *fstripestart;
    543     jpc_fix_t *dstripestart;
    544     jpc_fix_t *fp;
    545     jpc_fix_t *dp;
    546     jpc_fix_t *fvscanstart;
    547     jpc_fix_t *dvscanstart;
    548 
    549     *nmsedec = 0;
    550     width = jas_matrix_numcols(data);
    551     height = jas_matrix_numrows(data);
    552     frowstep = jas_matrix_rowstep(flags);
    553     drowstep = jas_matrix_rowstep(data);
    554     fstripestep = frowstep << 2;
    555     dstripestep = drowstep << 2;
    556 
    557     one = 1 << (bitpos + JPC_NUMEXTRABITS);
    558 
    559     fstripestart = jas_matrix_getref(flags, 1, 1);
    560     dstripestart = jas_matrix_getref(data, 0, 0);
    561     for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
    562       dstripestart += dstripestep) {
    563         fvscanstart = fstripestart;
    564         dvscanstart = dstripestart;
    565         vscanlen = JAS_MIN(i, 4);
    566         for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
    567             fp = fvscanstart;
    568             dp = dvscanstart;
    569             k = vscanlen;
    570 
    571             rawsigpass_step(fp, frowstep, dp, bitpos, one,
    572               nmsedec, out, vcausalflag);
    573             if (--k <= 0) {
    574                 continue;
    575             }
    576             fp += frowstep;
    577             dp += drowstep;
    578 
    579             rawsigpass_step(fp, frowstep, dp, bitpos, one,
    580               nmsedec, out, 0);
    581             if (--k <= 0) {
    582                 continue;
    583             }
    584             fp += frowstep;
    585             dp += drowstep;
    586 
    587             rawsigpass_step(fp, frowstep, dp, bitpos, one,
    588               nmsedec, out, 0);
    589             if (--k <= 0) {
    590                 continue;
    591             }
    592             fp += frowstep;
    593             dp += drowstep;
    594 
    595             rawsigpass_step(fp, frowstep, dp, bitpos, one,
    596               nmsedec, out, 0);
    597             if (--k <= 0) {
    598                 continue;
    599             }
    600             fp += frowstep;
    601             dp += drowstep;
    602 
    603         }
    604     }
    605 
    606     if (term) {
    607         jpc_bitstream_outalign(out, 0x2a);
    608     }
    609 
    610     return 0;
    611 }
    612 
    613 /******************************************************************************\
    614 * Code for refinement pass.
    615 \******************************************************************************/
    616 
    617 #define	refpass_step(fp, dp, bitpos, one, nmsedec, mqenc, vcausalflag) \
    618 { \
    619     int v; \
    620     if (((*(fp)) & (JPC_SIG | JPC_VISIT)) == JPC_SIG) { \
    621         (d) = *(dp); \
    622         *(nmsedec) += JPC_GETREFNMSEDEC(abs(d), (bitpos) + JPC_NUMEXTRABITS); \
    623         jpc_mqenc_setcurctx((mqenc), JPC_GETMAGCTXNO(*(fp))); \
    624         v = (abs(d) & (one)) ? 1 : 0; \
    625         jpc_mqenc_putbit((mqenc), v); \
    626         *(fp) |= JPC_REFINE; \
    627     } \
    628 }
    629 
    630 static int jpc_encrefpass(jpc_mqenc_t *mqenc, int bitpos, int vcausalflag, jas_matrix_t *flags, jas_matrix_t *data,
    631   int term, long *nmsedec)
    632 {
    633     int i;
    634     int j;
    635     int one;
    636     int vscanlen;
    637     int d;
    638     int width;
    639     int height;
    640     int frowstep;
    641     int drowstep;
    642     int fstripestep;
    643     int dstripestep;
    644     jpc_fix_t *fstripestart;
    645     jpc_fix_t *dstripestart;
    646     jpc_fix_t *fvscanstart;
    647     jpc_fix_t *dvscanstart;
    648     jpc_fix_t *dp;
    649     jpc_fix_t *fp;
    650 int k;
    651 
    652     *nmsedec = 0;
    653     width = jas_matrix_numcols(data);
    654     height = jas_matrix_numrows(data);
    655     frowstep = jas_matrix_rowstep(flags);
    656     drowstep = jas_matrix_rowstep(data);
    657     fstripestep = frowstep << 2;
    658     dstripestep = drowstep << 2;
    659 
    660     one = 1 << (bitpos + JPC_NUMEXTRABITS);
    661 
    662     fstripestart = jas_matrix_getref(flags, 1, 1);
    663     dstripestart = jas_matrix_getref(data, 0, 0);
    664     for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
    665       dstripestart += dstripestep) {
    666         fvscanstart = fstripestart;
    667         dvscanstart = dstripestart;
    668         vscanlen = JAS_MIN(i, 4);
    669         for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
    670             fp = fvscanstart;
    671             dp = dvscanstart;
    672             k = vscanlen;
    673 
    674             refpass_step(fp, dp, bitpos, one, nmsedec,
    675               mqenc, vcausalflag);
    676             if (--k <= 0) {
    677                 continue;
    678             }
    679             fp += frowstep;
    680             dp += drowstep;
    681             refpass_step(fp, dp, bitpos, one, nmsedec,
    682               mqenc, 0);
    683             if (--k <= 0) {
    684                 continue;
    685             }
    686             fp += frowstep;
    687             dp += drowstep;
    688             refpass_step(fp, dp, bitpos, one, nmsedec,
    689               mqenc, 0);
    690             if (--k <= 0) {
    691                 continue;
    692             }
    693             fp += frowstep;
    694             dp += drowstep;
    695             refpass_step(fp, dp, bitpos, one, nmsedec,
    696               mqenc, 0);
    697 
    698         }
    699     }
    700 
    701     if (term) {
    702         jpc_mqenc_flush(mqenc, term - 1);
    703     }
    704 
    705     return jpc_mqenc_error(mqenc) ? (-1) : 0;
    706 }
    707 
    708 #define	rawrefpass_step(fp, dp, bitpos, one, nmsedec, out, vcausalflag) \
    709 { \
    710     jpc_fix_t d; \
    711     jpc_fix_t v; \
    712     if (((*(fp)) & (JPC_SIG | JPC_VISIT)) == JPC_SIG) { \
    713         d = *(dp); \
    714         *(nmsedec) += JPC_GETREFNMSEDEC(abs(d), (bitpos) + JPC_NUMEXTRABITS); \
    715         v = (abs(d) & (one)) ? 1 : 0; \
    716         if (jpc_bitstream_putbit((out), v) == EOF) { \
    717             return -1; \
    718         } \
    719         *(fp) |= JPC_REFINE; \
    720     } \
    721 }
    722 
    723 static int jpc_encrawrefpass(jpc_bitstream_t *out, int bitpos, int vcausalflag, jas_matrix_t *flags,
    724   jas_matrix_t *data, int term, long *nmsedec)
    725 {
    726     int i;
    727     int j;
    728     int k;
    729     int one;
    730     int vscanlen;
    731     int width;
    732     int height;
    733     int frowstep;
    734     int drowstep;
    735     int fstripestep;
    736     int dstripestep;
    737     jpc_fix_t *fstripestart;
    738     jpc_fix_t *dstripestart;
    739     jpc_fix_t *fvscanstart;
    740     jpc_fix_t *dvscanstart;
    741     jpc_fix_t *dp;
    742     jpc_fix_t *fp;
    743 
    744     *nmsedec = 0;
    745     width = jas_matrix_numcols(data);
    746     height = jas_matrix_numrows(data);
    747     frowstep = jas_matrix_rowstep(flags);
    748     drowstep = jas_matrix_rowstep(data);
    749     fstripestep = frowstep << 2;
    750     dstripestep = drowstep << 2;
    751 
    752     one = 1 << (bitpos + JPC_NUMEXTRABITS);
    753 
    754     fstripestart = jas_matrix_getref(flags, 1, 1);
    755     dstripestart = jas_matrix_getref(data, 0, 0);
    756     for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
    757       dstripestart += dstripestep) {
    758         fvscanstart = fstripestart;
    759         dvscanstart = dstripestart;
    760         vscanlen = JAS_MIN(i, 4);
    761         for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
    762             fp = fvscanstart;
    763             dp = dvscanstart;
    764             k = vscanlen;
    765 
    766             rawrefpass_step(fp, dp, bitpos, one, nmsedec,
    767               out, vcausalflag);
    768             if (--k <= 0) {
    769                 continue;
    770             }
    771             fp += frowstep;
    772             dp += drowstep;
    773             rawrefpass_step(fp, dp, bitpos, one, nmsedec,
    774               out, vcausalflag);
    775             if (--k <= 0) {
    776                 continue;
    777             }
    778             fp += frowstep;
    779             dp += drowstep;
    780             rawrefpass_step(fp, dp, bitpos, one, nmsedec,
    781               out, vcausalflag);
    782             if (--k <= 0) {
    783                 continue;
    784             }
    785             fp += frowstep;
    786             dp += drowstep;
    787             rawrefpass_step(fp, dp, bitpos, one, nmsedec,
    788               out, vcausalflag);
    789 
    790         }
    791     }
    792 
    793     if (term) {
    794         jpc_bitstream_outalign(out, 0x2a);
    795     }
    796 
    797     return 0;
    798 }
    799 
    800 /******************************************************************************\
    801 * Code for cleanup pass.
    802 \******************************************************************************/
    803 
    804 #define	clnpass_step(fp, frowstep, dp, bitpos, one, orient, nmsedec, mqenc, label1, label2, vcausalflag) \
    805 { \
    806     int f; \
    807     int v; \
    808 label1 \
    809     f = *(fp); \
    810     if (!(f & (JPC_SIG | JPC_VISIT))) { \
    811         jpc_mqenc_setcurctx(mqenc, JPC_GETZCCTXNO(f, (orient))); \
    812         v = (abs(*(dp)) & (one)) ? 1 : 0; \
    813         jpc_mqenc_putbit((mqenc), v); \
    814         if (v) { \
    815 label2 \
    816             f = *(fp); \
    817             /* Coefficient is significant. */ \
    818             *(nmsedec) += JPC_GETSIGNMSEDEC(abs(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \
    819             jpc_mqenc_setcurctx((mqenc), JPC_GETSCCTXNO(f)); \
    820             v = ((*(dp) < 0) ? 1 : 0); \
    821             jpc_mqenc_putbit((mqenc), v ^ JPC_GETSPB(f)); \
    822             JPC_UPDATEFLAGS4((fp), (frowstep), v, vcausalflag); \
    823             *(fp) |= JPC_SIG; \
    824         } \
    825     } \
    826     *(fp) &= ~JPC_VISIT; \
    827 }
    828 
    829 static int jpc_encclnpass(jpc_mqenc_t *mqenc, int bitpos, int orient, int vcausalflag, int segsymflag, jas_matrix_t *flags,
    830   jas_matrix_t *data, int term, long *nmsedec)
    831 {
    832     int i;
    833     int j;
    834     int k;
    835     int vscanlen;
    836     int v;
    837     int runlen;
    838     jpc_fix_t *fp;
    839     int width;
    840     int height;
    841     jpc_fix_t *dp;
    842     int one;
    843     int frowstep;
    844     int drowstep;
    845     int fstripestep;
    846     int dstripestep;
    847     jpc_fix_t *fstripestart;
    848     jpc_fix_t *dstripestart;
    849     jpc_fix_t *fvscanstart;
    850     jpc_fix_t *dvscanstart;
    851 
    852     *nmsedec = 0;
    853     width = jas_matrix_numcols(data);
    854     height = jas_matrix_numrows(data);
    855     frowstep = jas_matrix_rowstep(flags);
    856     drowstep = jas_matrix_rowstep(data);
    857     fstripestep = frowstep << 2;
    858     dstripestep = drowstep << 2;
    859 
    860     one = 1 << (bitpos + JPC_NUMEXTRABITS);
    861 
    862     fstripestart = jas_matrix_getref(flags, 1, 1);
    863     dstripestart = jas_matrix_getref(data, 0, 0);
    864     for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
    865       dstripestart += dstripestep) {
    866         fvscanstart = fstripestart;
    867         dvscanstart = dstripestart;
    868         vscanlen = JAS_MIN(i, 4);
    869         for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
    870 
    871             fp = fvscanstart;
    872             if (vscanlen >= 4 && !((*fp) & (JPC_SIG | JPC_VISIT |
    873               JPC_OTHSIGMSK)) && (fp += frowstep, !((*fp) & (JPC_SIG |
    874               JPC_VISIT | JPC_OTHSIGMSK))) && (fp += frowstep, !((*fp) &
    875               (JPC_SIG | JPC_VISIT | JPC_OTHSIGMSK))) && (fp += frowstep,
    876               !((*fp) & (JPC_SIG | JPC_VISIT | JPC_OTHSIGMSK)))) {
    877                 dp = dvscanstart;
    878                 for (k = 0; k < vscanlen; ++k) {
    879                     v = (abs(*dp) & one) ? 1 : 0;
    880                     if (v) {
    881                         break;
    882                     }
    883                     dp += drowstep;
    884                 }
    885                 runlen = k;
    886                 if (runlen >= 4) {
    887                     jpc_mqenc_setcurctx(mqenc, JPC_AGGCTXNO);
    888                     jpc_mqenc_putbit(mqenc, 0);
    889                     continue;
    890                 }
    891                 jpc_mqenc_setcurctx(mqenc, JPC_AGGCTXNO);
    892                 jpc_mqenc_putbit(mqenc, 1);
    893                 jpc_mqenc_setcurctx(mqenc, JPC_UCTXNO);
    894                 jpc_mqenc_putbit(mqenc, runlen >> 1);
    895                 jpc_mqenc_putbit(mqenc, runlen & 1);
    896                 fp = fvscanstart + frowstep * runlen;
    897                 dp = dvscanstart + drowstep * runlen;
    898                 k = vscanlen - runlen;
    899                 switch (runlen) {
    900                 case 0:
    901                     goto clnpass_partial0;
    902                     break;
    903                 case 1:
    904                     goto clnpass_partial1;
    905                     break;
    906                 case 2:
    907                     goto clnpass_partial2;
    908                     break;
    909                 case 3:
    910                     goto clnpass_partial3;
    911                     break;
    912                 }
    913             } else {
    914                 runlen = 0;
    915                 fp = fvscanstart;
    916                 dp = dvscanstart;
    917                 k = vscanlen;
    918                 goto clnpass_full0;
    919             }
    920             clnpass_step(fp, frowstep, dp, bitpos, one,
    921               orient, nmsedec, mqenc, clnpass_full0:, clnpass_partial0:, vcausalflag);
    922             if (--k <= 0) {
    923                 continue;
    924             }
    925             fp += frowstep;
    926             dp += drowstep;
    927             clnpass_step(fp, frowstep, dp, bitpos, one,
    928                 orient, nmsedec, mqenc, ;, clnpass_partial1:, 0);
    929             if (--k <= 0) {
    930                 continue;
    931             }
    932             fp += frowstep;
    933             dp += drowstep;
    934             clnpass_step(fp, frowstep, dp, bitpos, one,
    935                 orient, nmsedec, mqenc, ;, clnpass_partial2:, 0);
    936             if (--k <= 0) {
    937                 continue;
    938             }
    939             fp += frowstep;
    940             dp += drowstep;
    941             clnpass_step(fp, frowstep, dp, bitpos, one,
    942                 orient, nmsedec, mqenc, ;, clnpass_partial3:, 0);
    943         }
    944     }
    945 
    946     if (segsymflag) {
    947         jpc_mqenc_setcurctx(mqenc, JPC_UCTXNO);
    948         jpc_mqenc_putbit(mqenc, 1);
    949         jpc_mqenc_putbit(mqenc, 0);
    950         jpc_mqenc_putbit(mqenc, 1);
    951         jpc_mqenc_putbit(mqenc, 0);
    952     }
    953 
    954     if (term) {
    955         jpc_mqenc_flush(mqenc, term - 1);
    956     }
    957 
    958     return jpc_mqenc_error(mqenc) ? (-1) : 0;
    959 }
    960