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. */
jpc_enc_enccblks(jpc_enc_t * enc)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 
getthebyte(jas_stream_t * in,long off)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. */
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)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 
jpc_encsigpass(jpc_mqenc_t * mqenc,int bitpos,int orient,int vcausalflag,jas_matrix_t * flags,jas_matrix_t * data,int term,long * nmsedec)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 
jpc_encrawsigpass(jpc_bitstream_t * out,int bitpos,int vcausalflag,jas_matrix_t * flags,jas_matrix_t * data,int term,long * nmsedec)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 
jpc_encrefpass(jpc_mqenc_t * mqenc,int bitpos,int vcausalflag,jas_matrix_t * flags,jas_matrix_t * data,int term,long * nmsedec)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 
jpc_encrawrefpass(jpc_bitstream_t * out,int bitpos,int vcausalflag,jas_matrix_t * flags,jas_matrix_t * data,int term,long * nmsedec)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 
jpc_encclnpass(jpc_mqenc_t * mqenc,int bitpos,int orient,int vcausalflag,int segsymflag,jas_matrix_t * flags,jas_matrix_t * data,int term,long * nmsedec)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