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