Update to 2.0.0 tree from current Fremantle build
[opencv] / 3rdparty / libjasper / 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) 2001-2006 Michael David Adams
13  * Copyright (c) 1999-2000 Image Power, Inc.
14  * Copyright (c) 1999-2000 The University of British Columbia
15  * 
16  * All rights reserved.
17  * 
18  * Permission is hereby granted, free of charge, to any person (the
19  * "User") obtaining a copy of this software and associated documentation
20  * files (the "Software"), to deal in the Software without restriction,
21  * including without limitation the rights to use, copy, modify, merge,
22  * publish, distribute, and/or sell copies of the Software, and to permit
23  * persons to whom the Software is furnished to do so, subject to the
24  * following conditions:
25  * 
26  * 1.  The above copyright notices and this permission notice (which
27  * includes the disclaimer below) shall be included in all copies or
28  * substantial portions of the Software.
29  * 
30  * 2.  The name of a copyright holder shall not be used to endorse or
31  * promote products derived from the Software without specific prior
32  * written permission.
33  * 
34  * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
35  * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
36  * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
37  * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
38  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
39  * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO
40  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
41  * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
42  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
43  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
44  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE
45  * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
46  * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
47  * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
48  * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
49  * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS
50  * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
51  * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE
52  * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
53  * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
54  * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
55  * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
56  * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
57  * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
58  * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
59  * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
60  * 
61  * __END_OF_JASPER_LICENSE__
62  */
63
64 /*
65  * Tier 1 Encoder
66  *
67  * $Id: jpc_t1enc.c,v 1.2 2008-05-26 09:40:52 vp153 Exp $
68  */
69
70 /******************************************************************************\
71 * Includes.
72 \******************************************************************************/
73
74 #include <stdio.h>
75 #include <stdlib.h>
76 #include <assert.h>
77
78 #include "jasper/jas_fix.h"
79 #include "jasper/jas_malloc.h"
80 #include "jasper/jas_math.h"
81
82 #include "jpc_t1enc.h"
83 #include "jpc_t1cod.h"
84 #include "jpc_enc.h"
85 #include "jpc_cod.h"
86 #include "jpc_math.h"
87
88 static int jpc_encsigpass(jpc_mqenc_t *mqenc, int bitpos, int orient, int,
89   jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec);
90
91 static int jpc_encrefpass(jpc_mqenc_t *mqenc, int bitpos, int, jas_matrix_t *flags,
92   jas_matrix_t *data, int term, long *nmsedec);
93
94 static int jpc_encclnpass(jpc_mqenc_t *mqenc, int bitpos, int orient, int,
95   int, jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec);
96
97 static int jpc_encrawsigpass(jpc_bitstream_t *out, int bitpos, int,
98   jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec);
99
100 static int jpc_encrawrefpass(jpc_bitstream_t *out, int bitpos, int,
101   jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec);
102
103 /******************************************************************************\
104 * Code for encoding code blocks.
105 \******************************************************************************/
106
107 /* Encode all of the code blocks associated with the current tile. */
108 int jpc_enc_enccblks(jpc_enc_t *enc)
109 {
110         jpc_enc_tcmpt_t *tcmpt;
111         jpc_enc_tcmpt_t *endcomps;
112         jpc_enc_rlvl_t *lvl;
113         jpc_enc_rlvl_t *endlvls;
114         jpc_enc_band_t *band;
115         jpc_enc_band_t *endbands;
116         jpc_enc_cblk_t *cblk;
117         jpc_enc_cblk_t *endcblks;
118         int i;
119         int j;
120         int mx;
121         int bmx;
122         int v;
123         jpc_enc_tile_t *tile;
124         uint_fast32_t prcno;
125         jpc_enc_prc_t *prc;
126
127         tile = enc->curtile;
128
129         endcomps = &tile->tcmpts[tile->numtcmpts];
130         for (tcmpt = tile->tcmpts; tcmpt != endcomps; ++tcmpt) {
131                 endlvls = &tcmpt->rlvls[tcmpt->numrlvls];
132                 for (lvl = tcmpt->rlvls; lvl != endlvls; ++lvl) {
133                         if (!lvl->bands) {
134                                 continue;
135                         }
136                         endbands = &lvl->bands[lvl->numbands];
137                         for (band = lvl->bands; band != endbands; ++band) {
138                                 if (!band->data) {
139                                         continue;
140                                 }
141                                 for (prcno = 0, prc = band->prcs; prcno < lvl->numprcs; ++prcno, ++prc) {
142                                         if (!prc->cblks) {
143                                                 continue;
144                                         }
145                                         bmx = 0;
146                                         endcblks = &prc->cblks[prc->numcblks];
147                                         for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
148                                                 mx = 0;
149                                                 for (i = 0; i < jas_matrix_numrows(cblk->data); ++i) {
150                                                         for (j = 0; j < jas_matrix_numcols(cblk->data); ++j) {
151                                                                 v = abs(jas_matrix_get(cblk->data, i, j));
152                                                                 if (v > mx) {
153                                                                         mx = v;
154                                                                 }
155                                                         }
156                                                 }
157                                                 if (mx > bmx) {
158                                                         bmx = mx;
159                                                 }
160                                                 cblk->numbps = JAS_MAX(jpc_firstone(mx) + 1 - JPC_NUMEXTRABITS, 0);
161                                         }
162
163                                         for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
164                                                 cblk->numimsbs = band->numbps - cblk->numbps;
165                                                 assert(cblk->numimsbs >= 0);
166                                         }
167
168                                         for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
169                                                 if (jpc_enc_enccblk(enc, cblk->stream, tcmpt, band, cblk)) {
170                                                         return -1;
171                                                 }
172                                         }
173                                 }
174                         }
175                 }
176         }
177         return 0;
178 }
179
180 int getthebyte(jas_stream_t *in, long off)
181 {
182         int c;
183         long oldpos;
184         oldpos = jas_stream_tell(in);
185         assert(oldpos >= 0);
186         jas_stream_seek(in, off, SEEK_SET);
187         c = jas_stream_peekc(in);
188         jas_stream_seek(in, oldpos, SEEK_SET);
189         return c;
190 }
191
192 /* Encode a single code block. */
193 int jpc_enc_enccblk(jpc_enc_t *enc, jas_stream_t *out, jpc_enc_tcmpt_t *tcmpt, jpc_enc_band_t *band, jpc_enc_cblk_t *cblk)
194 {
195         jpc_enc_pass_t *pass;
196         jpc_enc_pass_t *endpasses;
197         int bitpos;
198         int n;
199         int adjust;
200         int ret;
201         int passtype;
202         int t;
203         jpc_bitstream_t *bout;
204         jpc_enc_pass_t *termpass;
205         jpc_enc_rlvl_t *rlvl;
206         int vcausal;
207         int segsym;
208         int termmode;
209         int c;
210
211         bout = 0;
212         rlvl = band->rlvl;
213
214         cblk->stream = jas_stream_memopen(0, 0);
215         assert(cblk->stream);
216         cblk->mqenc = jpc_mqenc_create(JPC_NUMCTXS, cblk->stream);
217         assert(cblk->mqenc);
218         jpc_mqenc_setctxs(cblk->mqenc, JPC_NUMCTXS, jpc_mqctxs);
219
220         cblk->numpasses = (cblk->numbps > 0) ? (3 * cblk->numbps - 2) : 0;
221         if (cblk->numpasses > 0) {
222                 cblk->passes = jas_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 }