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