]> Creatis software - gdcm.git/blob - src/gdcmjasper/src/libjasper/jpc/jpc_t1enc.c
cb7a19aab3d8ed58193ba2a2aa44b7ab9e7879a4
[gdcm.git] / src / gdcmjasper / src / libjasper / jpc / jpc_t1enc.c
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) 1999-2000 Image Power, Inc.
13  * Copyright (c) 1999-2000 The University of British Columbia
14  * Copyright (c) 2001-2003 Michael David Adams
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 2005/06/07 19:22:42 malaterre 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   int_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   // Unused vars:
211   (void)enc;
212   (void)out;
213
214   bout = 0;
215   rlvl = band->rlvl;
216
217   cblk->stream = jas_stream_memopen(0, 0);
218   assert(cblk->stream);
219   cblk->mqenc = jpc_mqenc_create(JPC_NUMCTXS, cblk->stream);
220   assert(cblk->mqenc);
221   jpc_mqenc_setctxs(cblk->mqenc, JPC_NUMCTXS, jpc_mqctxs);
222
223   cblk->numpasses = (cblk->numbps > 0) ? (3 * cblk->numbps - 2) : 0;
224   if (cblk->numpasses > 0) {
225     cblk->passes = jas_malloc(cblk->numpasses * sizeof(jpc_enc_pass_t));
226     assert(cblk->passes);
227   } else {
228     cblk->passes = 0;
229   }
230   endpasses = &cblk->passes[cblk->numpasses];
231   for (pass = cblk->passes; pass != endpasses; ++pass) {
232     pass->start = 0;
233     pass->end = 0;
234     pass->term = JPC_ISTERMINATED(pass - cblk->passes, 0, cblk->numpasses, (tcmpt->cblksty & JPC_COX_TERMALL) != 0, (tcmpt->cblksty & JPC_COX_LAZY) != 0);
235     pass->type = JPC_SEGTYPE(pass - cblk->passes, 0, (tcmpt->cblksty & JPC_COX_LAZY) != 0);
236     pass->lyrno = -1;
237 if (pass == endpasses - 1) {
238 assert(pass->term == 1);
239   pass->term = 1;
240 }
241   }
242
243   cblk->flags = jas_matrix_create(jas_matrix_numrows(cblk->data) + 2,
244     jas_matrix_numcols(cblk->data) + 2);
245   assert(cblk->flags);
246
247
248   bitpos = cblk->numbps - 1;
249   pass = cblk->passes;
250   n = cblk->numpasses;
251   while (--n >= 0) {
252
253     if (pass->type == JPC_SEG_MQ) {
254       /* NOP */
255     } else {
256       assert(pass->type == JPC_SEG_RAW);
257       if (!bout) {
258         bout = jpc_bitstream_sopen(cblk->stream, "w");
259         assert(bout);
260       }
261     }
262
263 #if 1
264     passtype = (pass - cblk->passes + 2) % 3;
265 #else
266     passtype = JPC_PASSTYPE(pass - cblk->passes + 2);
267 #endif
268     pass->start = jas_stream_tell(cblk->stream);
269 #if 0
270 assert(jas_stream_tell(cblk->stream) == jas_stream_getrwcount(cblk->stream));
271 #endif
272     assert(bitpos >= 0);
273     vcausal = (tcmpt->cblksty & JPC_COX_VSC) != 0;
274     segsym = (tcmpt->cblksty & JPC_COX_SEGSYM) != 0;
275     if (pass->term) {
276       termmode = ((tcmpt->cblksty & JPC_COX_PTERM) ?
277         JPC_MQENC_PTERM : JPC_MQENC_DEFTERM) + 1;
278     } else {
279       termmode = 0;
280     }
281     switch (passtype) {
282     case JPC_SIGPASS:
283       ret = (pass->type == JPC_SEG_MQ) ? jpc_encsigpass(cblk->mqenc,
284         bitpos, band->orient, vcausal, cblk->flags,
285         cblk->data, termmode, &pass->nmsedec) :
286         jpc_encrawsigpass(bout, bitpos, vcausal, cblk->flags,
287         cblk->data, termmode, &pass->nmsedec);
288       break;
289     case JPC_REFPASS:
290       ret = (pass->type == JPC_SEG_MQ) ? jpc_encrefpass(cblk->mqenc,
291         bitpos, vcausal, cblk->flags, cblk->data, termmode,
292         &pass->nmsedec) : jpc_encrawrefpass(bout, bitpos,
293         vcausal, cblk->flags, cblk->data, termmode,
294         &pass->nmsedec);
295       break;
296     case JPC_CLNPASS:
297       assert(pass->type == JPC_SEG_MQ);
298       ret = jpc_encclnpass(cblk->mqenc, bitpos, band->orient,
299         vcausal, segsym, cblk->flags, cblk->data, termmode,
300         &pass->nmsedec);
301       break;
302     default:
303       assert(0);
304       break;
305     }
306
307     if (pass->type == JPC_SEG_MQ) {
308       if (pass->term) {
309         jpc_mqenc_init(cblk->mqenc);
310       }
311       jpc_mqenc_getstate(cblk->mqenc, &pass->mqencstate);
312       pass->end = jas_stream_tell(cblk->stream);
313       if (tcmpt->cblksty & JPC_COX_RESET) {
314         jpc_mqenc_setctxs(cblk->mqenc, JPC_NUMCTXS, jpc_mqctxs);
315       }
316     } else {
317       if (pass->term) {
318         if (jpc_bitstream_pending(bout)) {
319           jpc_bitstream_outalign(bout, 0x2a);
320         }
321         jpc_bitstream_close(bout);
322         bout = 0;
323         pass->end = jas_stream_tell(cblk->stream);
324       } else {
325         pass->end = jas_stream_tell(cblk->stream) +
326           jpc_bitstream_pending(bout);
327 /* NOTE - This will not work.  need to adjust by # of pending output bytes */
328       }
329     }
330 #if 0
331 /* XXX - This assertion fails sometimes when various coding modes are used.
332 This seems to be harmless, but why does it happen at all? */
333 assert(jas_stream_tell(cblk->stream) == jas_stream_getrwcount(cblk->stream));
334 #endif
335
336     pass->wmsedec = jpc_fixtodbl(band->rlvl->tcmpt->synweight) *
337       jpc_fixtodbl(band->rlvl->tcmpt->synweight) *
338       jpc_fixtodbl(band->synweight) *
339       jpc_fixtodbl(band->synweight) *
340       jpc_fixtodbl(band->absstepsize) * jpc_fixtodbl(band->absstepsize) *
341       ((double) (1 << bitpos)) * ((double)(1 << bitpos)) *
342       jpc_fixtodbl(pass->nmsedec);
343     pass->cumwmsedec = pass->wmsedec;
344     if (pass != cblk->passes) {
345       pass->cumwmsedec += pass[-1].cumwmsedec;
346     }
347     if (passtype == JPC_CLNPASS) {
348       --bitpos;
349     }
350     ++pass;
351   }
352
353 #if 0
354 dump_passes(cblk->passes, cblk->numpasses, cblk);
355 #endif
356
357   n = 0;
358   endpasses = &cblk->passes[cblk->numpasses];
359   for (pass = cblk->passes; pass != endpasses; ++pass) {
360     if (pass->start < n) {
361       pass->start = n;
362     }
363     if (pass->end < n) {
364       pass->end = n;
365     }
366     if (!pass->term) {
367       termpass = pass;
368       while (termpass - pass < cblk->numpasses &&
369         !termpass->term) {
370         ++termpass;
371       }
372       if (pass->type == JPC_SEG_MQ) {
373         t = (pass->mqencstate.lastbyte == 0xff) ? 1 : 0;
374         if (pass->mqencstate.ctreg >= 5) {
375           adjust = 4 + t;
376         } else {
377           adjust = 5 + t;
378         }
379         pass->end += adjust;
380       }
381       if (pass->end > termpass->end) {
382         pass->end = termpass->end;
383       }
384       if ((c = getthebyte(cblk->stream, pass->end - 1)) == EOF) {
385         abort();
386       }
387       if (c == 0xff) {
388         ++pass->end;
389       }
390       n = JAS_MAX(n, pass->end);
391     } else {
392       n = JAS_MAX(n, pass->end);
393     }
394   }
395
396 #if 0
397 dump_passes(cblk->passes, cblk->numpasses, cblk);
398 #endif
399
400   if (bout) {
401     jpc_bitstream_close(bout);
402   }
403
404   return 0;
405 }
406
407 /******************************************************************************\
408 * Code for significance pass.
409 \******************************************************************************/
410
411 #define  sigpass_step(fp, frowstep, dp, bitpos, one, nmsedec, orient, mqenc, vcausalflag) \
412 { \
413   int f; \
414   int v; \
415   f = *(fp); \
416   if ((f & JPC_OTHSIGMSK) && !(f & (JPC_SIG | JPC_VISIT))) { \
417     v = (abs(*(dp)) & (one)) ? 1 : 0; \
418     jpc_mqenc_setcurctx(mqenc, JPC_GETZCCTXNO(f, (orient))); \
419     jpc_mqenc_putbit(mqenc, v); \
420     if (v) { \
421       *(nmsedec) += JPC_GETSIGNMSEDEC(abs(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \
422       v = ((*(dp) < 0) ? 1 : 0); \
423       jpc_mqenc_setcurctx(mqenc, JPC_GETSCCTXNO(f)); \
424       jpc_mqenc_putbit(mqenc, v ^ JPC_GETSPB(f)); \
425       JPC_UPDATEFLAGS4(fp, frowstep, v, vcausalflag); \
426       *(fp) |= JPC_SIG; \
427     } \
428     *(fp) |= JPC_VISIT; \
429   } \
430 }
431
432 static int jpc_encsigpass(jpc_mqenc_t *mqenc, int bitpos, int orient, int vcausalflag,
433   jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec)
434 {
435   int i;
436   int j;
437   int one;
438   int vscanlen;
439   int width;
440   int height;
441   int frowstep;
442   int drowstep;
443   int fstripestep;
444   int dstripestep;
445   jpc_fix_t *fstripestart;
446   jpc_fix_t *dstripestart;
447   jpc_fix_t *fp;
448   jpc_fix_t *dp;
449   jpc_fix_t *fvscanstart;
450   jpc_fix_t *dvscanstart;
451   int k;
452
453   *nmsedec = 0;
454   width = jas_matrix_numcols(data);
455   height = jas_matrix_numrows(data);
456   frowstep = jas_matrix_rowstep(flags);
457   drowstep = jas_matrix_rowstep(data);
458   fstripestep = frowstep << 2;
459   dstripestep = drowstep << 2;
460
461   one = 1 << (bitpos + JPC_NUMEXTRABITS);
462
463   fstripestart = jas_matrix_getref(flags, 1, 1);
464   dstripestart = jas_matrix_getref(data, 0, 0);
465   for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
466     dstripestart += dstripestep) {
467     fvscanstart = fstripestart;
468     dvscanstart = dstripestart;
469     vscanlen = JAS_MIN(i, 4);
470     for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
471       fp = fvscanstart;
472       dp = dvscanstart;
473       k = vscanlen;
474
475       sigpass_step(fp, frowstep, dp, bitpos, one,
476         nmsedec, orient, mqenc, vcausalflag);
477       if (--k <= 0) {
478         continue;
479       }
480       fp += frowstep;
481       dp += drowstep;
482       sigpass_step(fp, frowstep, dp, bitpos, one,
483         nmsedec, orient, mqenc, 0);
484       if (--k <= 0) {
485         continue;
486       }
487       fp += frowstep;
488       dp += drowstep;
489       sigpass_step(fp, frowstep, dp, bitpos, one,
490         nmsedec, orient, mqenc, 0);
491       if (--k <= 0) {
492         continue;
493       }
494       fp += frowstep;
495       dp += drowstep;
496       sigpass_step(fp, frowstep, dp, bitpos, one,
497         nmsedec, orient, mqenc, 0);
498
499     }
500   }
501
502   if (term) {
503     jpc_mqenc_flush(mqenc, term - 1);
504   }
505
506   return jpc_mqenc_error(mqenc) ? (-1) : 0;
507 }
508
509 #define  rawsigpass_step(fp, frowstep, dp, bitpos, one, nmsedec, out, vcausalflag) \
510 { \
511   jpc_fix_t f = *(fp); \
512   jpc_fix_t v; \
513   if ((f & JPC_OTHSIGMSK) && !(f & (JPC_SIG | JPC_VISIT))) { \
514     v = (abs(*(dp)) & (one)) ? 1 : 0; \
515     if ((jpc_bitstream_putbit((out), v)) == EOF) { \
516       return -1; \
517     } \
518     if (v) { \
519       *(nmsedec) += JPC_GETSIGNMSEDEC(abs(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \
520       v = ((*(dp) < 0) ? 1 : 0); \
521       if (jpc_bitstream_putbit(out, v) == EOF) { \
522         return -1; \
523       } \
524       JPC_UPDATEFLAGS4(fp, frowstep, v, vcausalflag); \
525       *(fp) |= JPC_SIG; \
526     } \
527     *(fp) |= JPC_VISIT; \
528   } \
529 }
530
531 static int jpc_encrawsigpass(jpc_bitstream_t *out, int bitpos, int vcausalflag, jas_matrix_t *flags,
532   jas_matrix_t *data, int term, long *nmsedec)
533 {
534   int i;
535   int j;
536   int k;
537   int one;
538   int vscanlen;
539   int width;
540   int height;
541   int frowstep;
542   int drowstep;
543   int fstripestep;
544   int dstripestep;
545   jpc_fix_t *fstripestart;
546   jpc_fix_t *dstripestart;
547   jpc_fix_t *fp;
548   jpc_fix_t *dp;
549   jpc_fix_t *fvscanstart;
550   jpc_fix_t *dvscanstart;
551
552   *nmsedec = 0;
553   width = jas_matrix_numcols(data);
554   height = jas_matrix_numrows(data);
555   frowstep = jas_matrix_rowstep(flags);
556   drowstep = jas_matrix_rowstep(data);
557   fstripestep = frowstep << 2;
558   dstripestep = drowstep << 2;
559
560   one = 1 << (bitpos + JPC_NUMEXTRABITS);
561
562   fstripestart = jas_matrix_getref(flags, 1, 1);
563   dstripestart = jas_matrix_getref(data, 0, 0);
564   for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
565     dstripestart += dstripestep) {
566     fvscanstart = fstripestart;
567     dvscanstart = dstripestart;
568     vscanlen = JAS_MIN(i, 4);
569     for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
570       fp = fvscanstart;
571       dp = dvscanstart;
572       k = vscanlen;
573
574       rawsigpass_step(fp, frowstep, dp, bitpos, one,
575         nmsedec, out, vcausalflag);
576       if (--k <= 0) {
577         continue;
578       }
579       fp += frowstep;
580       dp += drowstep;
581
582       rawsigpass_step(fp, frowstep, dp, bitpos, one,
583         nmsedec, out, 0);
584       if (--k <= 0) {
585         continue;
586       }
587       fp += frowstep;
588       dp += drowstep;
589
590       rawsigpass_step(fp, frowstep, dp, bitpos, one,
591         nmsedec, out, 0);
592       if (--k <= 0) {
593         continue;
594       }
595       fp += frowstep;
596       dp += drowstep;
597
598       rawsigpass_step(fp, frowstep, dp, bitpos, one,
599         nmsedec, out, 0);
600       if (--k <= 0) {
601         continue;
602       }
603       fp += frowstep;
604       dp += drowstep;
605
606     }
607   }
608
609   if (term) {
610     jpc_bitstream_outalign(out, 0x2a);
611   }
612
613   return 0;
614 }
615
616 /******************************************************************************\
617 * Code for refinement pass.
618 \******************************************************************************/
619
620 #define  refpass_step(fp, dp, bitpos, one, nmsedec, mqenc, vcausalflag) \
621 { \
622   int v; \
623   if (((*(fp)) & (JPC_SIG | JPC_VISIT)) == JPC_SIG) { \
624     (d) = *(dp); \
625     *(nmsedec) += JPC_GETREFNMSEDEC(abs(d), (bitpos) + JPC_NUMEXTRABITS); \
626     jpc_mqenc_setcurctx((mqenc), JPC_GETMAGCTXNO(*(fp))); \
627     v = (abs(d) & (one)) ? 1 : 0; \
628     jpc_mqenc_putbit((mqenc), v); \
629     *(fp) |= JPC_REFINE; \
630   } \
631 }
632
633 static int jpc_encrefpass(jpc_mqenc_t *mqenc, int bitpos, int vcausalflag, jas_matrix_t *flags, jas_matrix_t *data,
634   int term, long *nmsedec)
635 {
636   int i;
637   int j;
638   int one;
639   int vscanlen;
640   int d;
641   int width;
642   int height;
643   int frowstep;
644   int drowstep;
645   int fstripestep;
646   int dstripestep;
647   jpc_fix_t *fstripestart;
648   jpc_fix_t *dstripestart;
649   jpc_fix_t *fvscanstart;
650   jpc_fix_t *dvscanstart;
651   jpc_fix_t *dp;
652   jpc_fix_t *fp;
653   int k;
654   // Unused:
655   (void)vcausalflag;
656
657   *nmsedec = 0;
658   width = jas_matrix_numcols(data);
659   height = jas_matrix_numrows(data);
660   frowstep = jas_matrix_rowstep(flags);
661   drowstep = jas_matrix_rowstep(data);
662   fstripestep = frowstep << 2;
663   dstripestep = drowstep << 2;
664
665   one = 1 << (bitpos + JPC_NUMEXTRABITS);
666
667   fstripestart = jas_matrix_getref(flags, 1, 1);
668   dstripestart = jas_matrix_getref(data, 0, 0);
669   for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
670     dstripestart += dstripestep) {
671     fvscanstart = fstripestart;
672     dvscanstart = dstripestart;
673     vscanlen = JAS_MIN(i, 4);
674     for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
675       fp = fvscanstart;
676       dp = dvscanstart;
677       k = vscanlen;
678
679       refpass_step(fp, dp, bitpos, one, nmsedec,
680         mqenc, vcausalflag);
681       if (--k <= 0) {
682         continue;
683       }
684       fp += frowstep;
685       dp += drowstep;
686       refpass_step(fp, dp, bitpos, one, nmsedec,
687         mqenc, 0);
688       if (--k <= 0) {
689         continue;
690       }
691       fp += frowstep;
692       dp += drowstep;
693       refpass_step(fp, dp, bitpos, one, nmsedec,
694         mqenc, 0);
695       if (--k <= 0) {
696         continue;
697       }
698       fp += frowstep;
699       dp += drowstep;
700       refpass_step(fp, dp, bitpos, one, nmsedec,
701         mqenc, 0);
702
703     }
704   }
705
706   if (term) {
707     jpc_mqenc_flush(mqenc, term - 1);
708   }
709
710   return jpc_mqenc_error(mqenc) ? (-1) : 0;
711 }
712
713 #define  rawrefpass_step(fp, dp, bitpos, one, nmsedec, out, vcausalflag) \
714 { \
715   jpc_fix_t d; \
716   jpc_fix_t v; \
717   if (((*(fp)) & (JPC_SIG | JPC_VISIT)) == JPC_SIG) { \
718     d = *(dp); \
719     *(nmsedec) += JPC_GETREFNMSEDEC(abs(d), (bitpos) + JPC_NUMEXTRABITS); \
720     v = (abs(d) & (one)) ? 1 : 0; \
721     if (jpc_bitstream_putbit((out), v) == EOF) { \
722       return -1; \
723     } \
724     *(fp) |= JPC_REFINE; \
725   } \
726 }
727
728 static int jpc_encrawrefpass(jpc_bitstream_t *out, int bitpos, int vcausalflag, jas_matrix_t *flags,
729   jas_matrix_t *data, int term, long *nmsedec)
730 {
731   int i;
732   int j;
733   int k;
734   int one;
735   int vscanlen;
736   int width;
737   int height;
738   int frowstep;
739   int drowstep;
740   int fstripestep;
741   int dstripestep;
742   jpc_fix_t *fstripestart;
743   jpc_fix_t *dstripestart;
744   jpc_fix_t *fvscanstart;
745   jpc_fix_t *dvscanstart;
746   jpc_fix_t *dp;
747   jpc_fix_t *fp;
748   // Unused
749   (void)vcausalflag;
750
751   *nmsedec = 0;
752   width = jas_matrix_numcols(data);
753   height = jas_matrix_numrows(data);
754   frowstep = jas_matrix_rowstep(flags);
755   drowstep = jas_matrix_rowstep(data);
756   fstripestep = frowstep << 2;
757   dstripestep = drowstep << 2;
758
759   one = 1 << (bitpos + JPC_NUMEXTRABITS);
760
761   fstripestart = jas_matrix_getref(flags, 1, 1);
762   dstripestart = jas_matrix_getref(data, 0, 0);
763   for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
764     dstripestart += dstripestep) {
765     fvscanstart = fstripestart;
766     dvscanstart = dstripestart;
767     vscanlen = JAS_MIN(i, 4);
768     for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
769       fp = fvscanstart;
770       dp = dvscanstart;
771       k = vscanlen;
772
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       if (--k <= 0) {
790         continue;
791       }
792       fp += frowstep;
793       dp += drowstep;
794       rawrefpass_step(fp, dp, bitpos, one, nmsedec,
795         out, vcausalflag);
796
797     }
798   }
799
800   if (term) {
801     jpc_bitstream_outalign(out, 0x2a);
802   }
803
804   return 0;
805 }
806
807 /******************************************************************************\
808 * Code for cleanup pass.
809 \******************************************************************************/
810
811 #define  clnpass_step(fp, frowstep, dp, bitpos, one, orient, nmsedec, mqenc, label1, label2, vcausalflag) \
812 { \
813   int f; \
814   int v; \
815 label1 \
816   f = *(fp); \
817   if (!(f & (JPC_SIG | JPC_VISIT))) { \
818     jpc_mqenc_setcurctx(mqenc, JPC_GETZCCTXNO(f, (orient))); \
819     v = (abs(*(dp)) & (one)) ? 1 : 0; \
820     jpc_mqenc_putbit((mqenc), v); \
821     if (v) { \
822 label2 \
823       f = *(fp); \
824       /* Coefficient is significant. */ \
825       *(nmsedec) += JPC_GETSIGNMSEDEC(abs(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \
826       jpc_mqenc_setcurctx((mqenc), JPC_GETSCCTXNO(f)); \
827       v = ((*(dp) < 0) ? 1 : 0); \
828       jpc_mqenc_putbit((mqenc), v ^ JPC_GETSPB(f)); \
829       JPC_UPDATEFLAGS4((fp), (frowstep), v, vcausalflag); \
830       *(fp) |= JPC_SIG; \
831     } \
832   } \
833   *(fp) &= ~JPC_VISIT; \
834 }
835
836 static int jpc_encclnpass(jpc_mqenc_t *mqenc, int bitpos, int orient, int vcausalflag, int segsymflag, jas_matrix_t *flags,
837   jas_matrix_t *data, int term, long *nmsedec)
838 {
839   int i;
840   int j;
841   int k;
842   int vscanlen;
843   int v;
844   int runlen;
845   jpc_fix_t *fp;
846   int width;
847   int height;
848   jpc_fix_t *dp;
849   int one;
850   int frowstep;
851   int drowstep;
852   int fstripestep;
853   int dstripestep;
854   jpc_fix_t *fstripestart;
855   jpc_fix_t *dstripestart;
856   jpc_fix_t *fvscanstart;
857   jpc_fix_t *dvscanstart;
858
859   *nmsedec = 0;
860   width = jas_matrix_numcols(data);
861   height = jas_matrix_numrows(data);
862   frowstep = jas_matrix_rowstep(flags);
863   drowstep = jas_matrix_rowstep(data);
864   fstripestep = frowstep << 2;
865   dstripestep = drowstep << 2;
866
867   one = 1 << (bitpos + JPC_NUMEXTRABITS);
868
869   fstripestart = jas_matrix_getref(flags, 1, 1);
870   dstripestart = jas_matrix_getref(data, 0, 0);
871   for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
872     dstripestart += dstripestep) {
873     fvscanstart = fstripestart;
874     dvscanstart = dstripestart;
875     vscanlen = JAS_MIN(i, 4);
876     for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
877
878       fp = fvscanstart;
879       if (vscanlen >= 4 && !((*fp) & (JPC_SIG | JPC_VISIT |
880         JPC_OTHSIGMSK)) && (fp += frowstep, !((*fp) & (JPC_SIG |
881         JPC_VISIT | JPC_OTHSIGMSK))) && (fp += frowstep, !((*fp) &
882         (JPC_SIG | JPC_VISIT | JPC_OTHSIGMSK))) && (fp += frowstep,
883         !((*fp) & (JPC_SIG | JPC_VISIT | JPC_OTHSIGMSK)))) {
884         dp = dvscanstart;
885         for (k = 0; k < vscanlen; ++k) {
886           v = (abs(*dp) & one) ? 1 : 0;
887           if (v) {
888             break;
889           }
890           dp += drowstep;
891         }
892         runlen = k;
893         if (runlen >= 4) {
894           jpc_mqenc_setcurctx(mqenc, JPC_AGGCTXNO);
895           jpc_mqenc_putbit(mqenc, 0);
896           continue;
897         }
898         jpc_mqenc_setcurctx(mqenc, JPC_AGGCTXNO);
899         jpc_mqenc_putbit(mqenc, 1);
900         jpc_mqenc_setcurctx(mqenc, JPC_UCTXNO);
901         jpc_mqenc_putbit(mqenc, runlen >> 1);
902         jpc_mqenc_putbit(mqenc, runlen & 1);
903         fp = fvscanstart + frowstep * runlen;
904         dp = dvscanstart + drowstep * runlen;
905         k = vscanlen - runlen;
906         switch (runlen) {
907         case 0:
908           goto clnpass_partial0;
909           break;
910         case 1:
911           goto clnpass_partial1;
912           break;
913         case 2:
914           goto clnpass_partial2;
915           break;
916         case 3:
917           goto clnpass_partial3;
918           break;
919         }
920       } else {
921         runlen = 0;
922         fp = fvscanstart;
923         dp = dvscanstart;
924         k = vscanlen;
925         goto clnpass_full0;
926       }
927       clnpass_step(fp, frowstep, dp, bitpos, one,
928         orient, nmsedec, mqenc, clnpass_full0:, clnpass_partial0:, vcausalflag);
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_partial1:, 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_partial2:, 0);
943       if (--k <= 0) {
944         continue;
945       }
946       fp += frowstep;
947       dp += drowstep;
948       clnpass_step(fp, frowstep, dp, bitpos, one,
949         orient, nmsedec, mqenc, ;, clnpass_partial3:, 0);
950     }
951   }
952
953   if (segsymflag) {
954     jpc_mqenc_setcurctx(mqenc, JPC_UCTXNO);
955     jpc_mqenc_putbit(mqenc, 1);
956     jpc_mqenc_putbit(mqenc, 0);
957     jpc_mqenc_putbit(mqenc, 1);
958     jpc_mqenc_putbit(mqenc, 0);
959   }
960
961   if (term) {
962     jpc_mqenc_flush(mqenc, term - 1);
963   }
964
965   return jpc_mqenc_error(mqenc) ? (-1) : 0;
966 }