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 Software License
11 *
12 * IMAGE POWER JPEG-2000 PUBLIC LICENSE
13 * ************************************
14 *
15 * GRANT:
16 *
17 * Permission is hereby granted, free of charge, to any person (the "User")
18 * obtaining a copy of this software and associated documentation, to deal
19 * in the JasPer Software without restriction, including without limitation
20 * the right to use, copy, modify, merge, publish, distribute, sublicense,
21 * and/or sell copies of the JasPer Software (in source and binary forms),
22 * and to permit persons to whom the JasPer Software is furnished to do so,
23 * provided further that the License Conditions below are met.
24 *
25 * License Conditions
26 * ******************
27 *
28 * A.  Redistributions of source code must retain the above copyright notice,
29 * and this list of conditions, and the following disclaimer.
30 *
31 * B.  Redistributions in binary form must reproduce the above copyright
32 * notice, and this list of conditions, and the following disclaimer in
33 * the documentation and/or other materials provided with the distribution.
34 *
35 * C.  Neither the name of Image Power, Inc. nor any other contributor
36 * (including, but not limited to, the University of British Columbia and
37 * Michael David Adams) may be used to endorse or promote products derived
38 * from this software without specific prior written permission.
39 *
40 * D.  User agrees that it shall not commence any action against Image Power,
41 * Inc., the University of British Columbia, Michael David Adams, or any
42 * other contributors (collectively "Licensors") for infringement of any
43 * intellectual property rights ("IPR") held by the User in respect of any
44 * technology that User owns or has a right to license or sublicense and
45 * which is an element required in order to claim compliance with ISO/IEC
46 * 15444-1 (i.e., JPEG-2000 Part 1).  "IPR" means all intellectual property
47 * rights worldwide arising under statutory or common law, and whether
48 * or not perfected, including, without limitation, all (i) patents and
49 * patent applications owned or licensable by User; (ii) rights associated
50 * with works of authorship including copyrights, copyright applications,
51 * copyright registrations, mask work rights, mask work applications,
52 * mask work registrations; (iii) rights relating to the protection of
53 * trade secrets and confidential information; (iv) any right analogous
54 * to those set forth in subsections (i), (ii), or (iii) and any other
55 * proprietary rights relating to intangible property (other than trademark,
56 * trade dress, or service mark rights); and (v) divisions, continuations,
57 * renewals, reissues and extensions of the foregoing (as and to the extent
58 * applicable) now existing, hereafter filed, issued or acquired.
59 *
60 * E.  If User commences an infringement action against any Licensor(s) then
61 * such Licensor(s) shall have the right to terminate User's license and
62 * all sublicenses that have been granted hereunder by User to other parties.
63 *
64 * F.  This software is for use only in hardware or software products that
65 * are compliant with ISO/IEC 15444-1 (i.e., JPEG-2000 Part 1).  No license
66 * or right to this Software is granted for products that do not comply
67 * with ISO/IEC 15444-1.  The JPEG-2000 Part 1 standard can be purchased
68 * from the ISO.
69 *
70 * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
71 * NO USE OF THE JASPER SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
72 * THIS DISCLAIMER.  THE JASPER SOFTWARE IS PROVIDED BY THE LICENSORS AND
73 * CONTRIBUTORS UNDER THIS LICENSE ON AN ``AS-IS'' BASIS, WITHOUT WARRANTY
74 * OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
75 * WARRANTIES THAT THE JASPER SOFTWARE IS FREE OF DEFECTS, IS MERCHANTABLE,
76 * IS FIT FOR A PARTICULAR PURPOSE OR IS NON-INFRINGING.  THOSE INTENDING
77 * TO USE THE JASPER SOFTWARE OR MODIFICATIONS THEREOF FOR USE IN HARDWARE
78 * OR SOFTWARE PRODUCTS ARE ADVISED THAT THEIR USE MAY INFRINGE EXISTING
79 * PATENTS, COPYRIGHTS, TRADEMARKS, OR OTHER INTELLECTUAL PROPERTY RIGHTS.
80 * THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE JASPER SOFTWARE
81 * IS WITH THE USER.  SHOULD ANY PART OF THE JASPER SOFTWARE PROVE DEFECTIVE
82 * IN ANY RESPECT, THE USER (AND NOT THE INITIAL DEVELOPERS, THE UNIVERSITY
83 * OF BRITISH COLUMBIA, IMAGE POWER, INC., MICHAEL DAVID ADAMS, OR ANY
84 * OTHER CONTRIBUTOR) SHALL ASSUME THE COST OF ANY NECESSARY SERVICING,
85 * REPAIR OR CORRECTION.  UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY,
86 * WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE
87 * INITIAL DEVELOPER, THE UNIVERSITY OF BRITISH COLUMBIA, IMAGE POWER, INC.,
88 * MICHAEL DAVID ADAMS, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF THE
89 * JASPER SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO
90 * THE USER OR ANY OTHER PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR
91 * CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION,
92 * DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR
93 * MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF
94 * SUCH PARTY HAD BEEN INFORMED, OR OUGHT TO HAVE KNOWN, OF THE POSSIBILITY
95 * OF SUCH DAMAGES.  THE JASPER SOFTWARE AND UNDERLYING TECHNOLOGY ARE NOT
96 * FAULT-TOLERANT AND ARE NOT DESIGNED, MANUFACTURED OR INTENDED FOR USE OR
97 * RESALE AS ON-LINE CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING
98 * FAIL-SAFE PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES,
99 * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT
100 * LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
101 * JASPER SOFTWARE OR UNDERLYING TECHNOLOGY OR PRODUCT COULD LEAD DIRECTLY
102 * TO DEATH, PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE
103 * ("HIGH RISK ACTIVITIES").  LICENSOR SPECIFICALLY DISCLAIMS ANY EXPRESS
104 * OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.  USER WILL NOT
105 * KNOWINGLY USE, DISTRIBUTE OR RESELL THE JASPER SOFTWARE OR UNDERLYING
106 * TECHNOLOGY OR PRODUCTS FOR HIGH RISK ACTIVITIES AND WILL ENSURE THAT ITS
107 * CUSTOMERS AND END-USERS OF ITS PRODUCTS ARE PROVIDED WITH A COPY OF THE
108 * NOTICE SPECIFIED IN THIS SECTION.
109 *
110 * __END_OF_JASPER_LICENSE__
111 */
112
113/*
114 * Tier 1 Encoder
115 *
116 * $Id: jpc_t1enc.c 14449 2005-10-20 12:15:56Z stippi $
117 */
118
119/******************************************************************************\
120* Includes.
121\******************************************************************************/
122
123#include <stdio.h>
124#include <stdlib.h>
125#include <assert.h>
126
127#include "jasper/jas_fix.h"
128#include "jasper/jas_malloc.h"
129#include "jasper/jas_math.h"
130
131#include "jpc_t1enc.h"
132#include "jpc_t1cod.h"
133#include "jpc_enc.h"
134#include "jpc_cod.h"
135#include "jpc_math.h"
136
137static int jpc_encsigpass(jpc_mqenc_t *mqenc, int bitpos, int orient, int,
138  jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec);
139
140static int jpc_encrefpass(jpc_mqenc_t *mqenc, int bitpos, int, jas_matrix_t *flags,
141  jas_matrix_t *data, int term, long *nmsedec);
142
143static int jpc_encclnpass(jpc_mqenc_t *mqenc, int bitpos, int orient, int,
144  int, jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec);
145
146static int jpc_encrawsigpass(jpc_bitstream_t *out, int bitpos, int,
147  jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec);
148
149static int jpc_encrawrefpass(jpc_bitstream_t *out, int bitpos, int,
150  jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec);
151
152/******************************************************************************\
153* Code for encoding code blocks.
154\******************************************************************************/
155
156/* Encode all of the code blocks associated with the current tile. */
157int jpc_enc_enccblks(jpc_enc_t *enc)
158{
159	jpc_enc_tcmpt_t *tcmpt;
160	jpc_enc_tcmpt_t *endcomps;
161	jpc_enc_rlvl_t *lvl;
162	jpc_enc_rlvl_t *endlvls;
163	jpc_enc_band_t *band;
164	jpc_enc_band_t *endbands;
165	jpc_enc_cblk_t *cblk;
166	jpc_enc_cblk_t *endcblks;
167	int i;
168	int j;
169	int mx;
170	int bmx;
171	int v;
172	jpc_enc_tile_t *tile;
173	uint_fast32_t prcno;
174	jpc_enc_prc_t *prc;
175
176	tile = enc->curtile;
177
178	endcomps = &tile->tcmpts[tile->numtcmpts];
179	for (tcmpt = tile->tcmpts; tcmpt != endcomps; ++tcmpt) {
180		endlvls = &tcmpt->rlvls[tcmpt->numrlvls];
181		for (lvl = tcmpt->rlvls; lvl != endlvls; ++lvl) {
182			if (!lvl->bands) {
183				continue;
184			}
185			endbands = &lvl->bands[lvl->numbands];
186			for (band = lvl->bands; band != endbands; ++band) {
187				if (!band->data) {
188					continue;
189				}
190				for (prcno = 0, prc = band->prcs; prcno < lvl->numprcs; ++prcno, ++prc) {
191					if (!prc->cblks) {
192						continue;
193					}
194					bmx = 0;
195					endcblks = &prc->cblks[prc->numcblks];
196					for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
197						mx = 0;
198						for (i = 0; i < jas_matrix_numrows(cblk->data); ++i) {
199							for (j = 0; j < jas_matrix_numcols(cblk->data); ++j) {
200								v = abs(jas_matrix_get(cblk->data, i, j));
201								if (v > mx) {
202									mx = v;
203								}
204							}
205						}
206						if (mx > bmx) {
207							bmx = mx;
208						}
209						cblk->numbps = JAS_MAX(jpc_firstone(mx) + 1 - JPC_NUMEXTRABITS, 0);
210					}
211
212					for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
213						cblk->numimsbs = band->numbps - cblk->numbps;
214						assert(cblk->numimsbs >= 0);
215					}
216
217					for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
218						if (jpc_enc_enccblk(enc, cblk->stream, tcmpt, band, cblk)) {
219							return -1;
220						}
221					}
222				}
223			}
224		}
225	}
226	return 0;
227}
228
229int getthebyte(jas_stream_t *in, long off)
230{
231	int c;
232	long oldpos;
233	oldpos = jas_stream_tell(in);
234	assert(oldpos >= 0);
235	jas_stream_seek(in, off, SEEK_SET);
236	c = jas_stream_peekc(in);
237	jas_stream_seek(in, oldpos, SEEK_SET);
238	return c;
239}
240
241/* Encode a single code block. */
242int 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)
243{
244	jpc_enc_pass_t *pass;
245	jpc_enc_pass_t *endpasses;
246	int bitpos;
247	int n;
248	int adjust;
249	int ret;
250	int passtype;
251	int t;
252	jpc_bitstream_t *bout;
253	jpc_enc_pass_t *termpass;
254	jpc_enc_rlvl_t *rlvl;
255	int vcausal;
256	int segsym;
257	int termmode;
258	int c;
259
260	bout = 0;
261	rlvl = band->rlvl;
262
263	cblk->stream = jas_stream_memopen(0, 0);
264	assert(cblk->stream);
265	cblk->mqenc = jpc_mqenc_create(JPC_NUMCTXS, cblk->stream);
266	assert(cblk->mqenc);
267	jpc_mqenc_setctxs(cblk->mqenc, JPC_NUMCTXS, jpc_mqctxs);
268
269	cblk->numpasses = (cblk->numbps > 0) ? (3 * cblk->numbps - 2) : 0;
270	if (cblk->numpasses > 0) {
271		cblk->passes = jas_malloc(cblk->numpasses * sizeof(jpc_enc_pass_t));
272		assert(cblk->passes);
273	} else {
274		cblk->passes = 0;
275	}
276	endpasses = &cblk->passes[cblk->numpasses];
277	for (pass = cblk->passes; pass != endpasses; ++pass) {
278		pass->start = 0;
279		pass->end = 0;
280		pass->term = JPC_ISTERMINATED(pass - cblk->passes, 0, cblk->numpasses, (tcmpt->cblksty & JPC_COX_TERMALL) != 0, (tcmpt->cblksty & JPC_COX_LAZY) != 0);
281		pass->type = JPC_SEGTYPE(pass - cblk->passes, 0, (tcmpt->cblksty & JPC_COX_LAZY) != 0);
282		pass->lyrno = -1;
283if (pass == endpasses - 1) {
284assert(pass->term == 1);
285	pass->term = 1;
286}
287	}
288
289	cblk->flags = jas_matrix_create(jas_matrix_numrows(cblk->data) + 2,
290	  jas_matrix_numcols(cblk->data) + 2);
291	assert(cblk->flags);
292
293
294	bitpos = cblk->numbps - 1;
295	pass = cblk->passes;
296	n = cblk->numpasses;
297	while (--n >= 0) {
298
299		if (pass->type == JPC_SEG_MQ) {
300			/* NOP */
301		} else {
302			assert(pass->type == JPC_SEG_RAW);
303			if (!bout) {
304				bout = jpc_bitstream_sopen(cblk->stream, "w");
305				assert(bout);
306			}
307		}
308
309#if 1
310		passtype = (pass - cblk->passes + 2) % 3;
311#else
312		passtype = JPC_PASSTYPE(pass - cblk->passes + 2);
313#endif
314		pass->start = jas_stream_tell(cblk->stream);
315#if 0
316assert(jas_stream_tell(cblk->stream) == jas_stream_getrwcount(cblk->stream));
317#endif
318		assert(bitpos >= 0);
319		vcausal = (tcmpt->cblksty & JPC_COX_VSC) != 0;
320		segsym = (tcmpt->cblksty & JPC_COX_SEGSYM) != 0;
321		if (pass->term) {
322			termmode = ((tcmpt->cblksty & JPC_COX_PTERM) ?
323			  JPC_MQENC_PTERM : JPC_MQENC_DEFTERM) + 1;
324		} else {
325			termmode = 0;
326		}
327		switch (passtype) {
328		case JPC_SIGPASS:
329			ret = (pass->type == JPC_SEG_MQ) ? jpc_encsigpass(cblk->mqenc,
330			  bitpos, band->orient, vcausal, cblk->flags,
331			  cblk->data, termmode, &pass->nmsedec) :
332			  jpc_encrawsigpass(bout, bitpos, vcausal, cblk->flags,
333			  cblk->data, termmode, &pass->nmsedec);
334			break;
335		case JPC_REFPASS:
336			ret = (pass->type == JPC_SEG_MQ) ? jpc_encrefpass(cblk->mqenc,
337			  bitpos, vcausal, cblk->flags, cblk->data, termmode,
338			  &pass->nmsedec) : jpc_encrawrefpass(bout, bitpos,
339			  vcausal, cblk->flags, cblk->data, termmode,
340			  &pass->nmsedec);
341			break;
342		case JPC_CLNPASS:
343			assert(pass->type == JPC_SEG_MQ);
344			ret = jpc_encclnpass(cblk->mqenc, bitpos, band->orient,
345			  vcausal, segsym, cblk->flags, cblk->data, termmode,
346			  &pass->nmsedec);
347			break;
348		default:
349			assert(0);
350			break;
351		}
352
353		if (pass->type == JPC_SEG_MQ) {
354			if (pass->term) {
355				jpc_mqenc_init(cblk->mqenc);
356			}
357			jpc_mqenc_getstate(cblk->mqenc, &pass->mqencstate);
358			pass->end = jas_stream_tell(cblk->stream);
359			if (tcmpt->cblksty & JPC_COX_RESET) {
360				jpc_mqenc_setctxs(cblk->mqenc, JPC_NUMCTXS, jpc_mqctxs);
361			}
362		} else {
363			if (pass->term) {
364				if (jpc_bitstream_pending(bout)) {
365					jpc_bitstream_outalign(bout, 0x2a);
366				}
367				jpc_bitstream_close(bout);
368				bout = 0;
369				pass->end = jas_stream_tell(cblk->stream);
370			} else {
371				pass->end = jas_stream_tell(cblk->stream) +
372				  jpc_bitstream_pending(bout);
373/* NOTE - This will not work.  need to adjust by # of pending output bytes */
374			}
375		}
376#if 0
377/* XXX - This assertion fails sometimes when various coding modes are used.
378This seems to be harmless, but why does it happen at all? */
379assert(jas_stream_tell(cblk->stream) == jas_stream_getrwcount(cblk->stream));
380#endif
381
382		pass->wmsedec = jpc_fixtodbl(band->rlvl->tcmpt->synweight) *
383		  jpc_fixtodbl(band->rlvl->tcmpt->synweight) *
384		  jpc_fixtodbl(band->synweight) *
385		  jpc_fixtodbl(band->synweight) *
386		  jpc_fixtodbl(band->absstepsize) * jpc_fixtodbl(band->absstepsize) *
387		  ((double) (1 << bitpos)) * ((double)(1 << bitpos)) *
388		  jpc_fixtodbl(pass->nmsedec);
389		pass->cumwmsedec = pass->wmsedec;
390		if (pass != cblk->passes) {
391			pass->cumwmsedec += pass[-1].cumwmsedec;
392		}
393		if (passtype == JPC_CLNPASS) {
394			--bitpos;
395		}
396		++pass;
397	}
398
399#if 0
400dump_passes(cblk->passes, cblk->numpasses, cblk);
401#endif
402
403	n = 0;
404	endpasses = &cblk->passes[cblk->numpasses];
405	for (pass = cblk->passes; pass != endpasses; ++pass) {
406		if (pass->start < n) {
407			pass->start = n;
408		}
409		if (pass->end < n) {
410			pass->end = n;
411		}
412		if (!pass->term) {
413			termpass = pass;
414			while (termpass - pass < cblk->numpasses &&
415			  !termpass->term) {
416				++termpass;
417			}
418			if (pass->type == JPC_SEG_MQ) {
419				t = (pass->mqencstate.lastbyte == 0xff) ? 1 : 0;
420				if (pass->mqencstate.ctreg >= 5) {
421					adjust = 4 + t;
422				} else {
423					adjust = 5 + t;
424				}
425				pass->end += adjust;
426			}
427			if (pass->end > termpass->end) {
428				pass->end = termpass->end;
429			}
430			if ((c = getthebyte(cblk->stream, pass->end - 1)) == EOF) {
431				abort();
432			}
433			if (c == 0xff) {
434				++pass->end;
435			}
436			n = JAS_MAX(n, pass->end);
437		} else {
438			n = JAS_MAX(n, pass->end);
439		}
440	}
441
442#if 0
443dump_passes(cblk->passes, cblk->numpasses, cblk);
444#endif
445
446	if (bout) {
447		jpc_bitstream_close(bout);
448	}
449
450	return 0;
451}
452
453/******************************************************************************\
454* Code for significance pass.
455\******************************************************************************/
456
457#define	sigpass_step(fp, frowstep, dp, bitpos, one, nmsedec, orient, mqenc, vcausalflag) \
458{ \
459	int f; \
460	int v; \
461	f = *(fp); \
462	if ((f & JPC_OTHSIGMSK) && !(f & (JPC_SIG | JPC_VISIT))) { \
463		v = (abs(*(dp)) & (one)) ? 1 : 0; \
464		jpc_mqenc_setcurctx(mqenc, JPC_GETZCCTXNO(f, (orient))); \
465		jpc_mqenc_putbit(mqenc, v); \
466		if (v) { \
467			*(nmsedec) += JPC_GETSIGNMSEDEC(abs(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \
468			v = ((*(dp) < 0) ? 1 : 0); \
469			jpc_mqenc_setcurctx(mqenc, JPC_GETSCCTXNO(f)); \
470			jpc_mqenc_putbit(mqenc, v ^ JPC_GETSPB(f)); \
471			JPC_UPDATEFLAGS4(fp, frowstep, v, vcausalflag); \
472			*(fp) |= JPC_SIG; \
473		} \
474		*(fp) |= JPC_VISIT; \
475	} \
476}
477
478static int jpc_encsigpass(jpc_mqenc_t *mqenc, int bitpos, int orient, int vcausalflag,
479  jas_matrix_t *flags, jas_matrix_t *data, int term, long *nmsedec)
480{
481	int i;
482	int j;
483	int one;
484	int vscanlen;
485	int width;
486	int height;
487	int frowstep;
488	int drowstep;
489	int fstripestep;
490	int dstripestep;
491	jpc_fix_t *fstripestart;
492	jpc_fix_t *dstripestart;
493	jpc_fix_t *fp;
494	jpc_fix_t *dp;
495	jpc_fix_t *fvscanstart;
496	jpc_fix_t *dvscanstart;
497	int k;
498
499	*nmsedec = 0;
500	width = jas_matrix_numcols(data);
501	height = jas_matrix_numrows(data);
502	frowstep = jas_matrix_rowstep(flags);
503	drowstep = jas_matrix_rowstep(data);
504	fstripestep = frowstep << 2;
505	dstripestep = drowstep << 2;
506
507	one = 1 << (bitpos + JPC_NUMEXTRABITS);
508
509	fstripestart = jas_matrix_getref(flags, 1, 1);
510	dstripestart = jas_matrix_getref(data, 0, 0);
511	for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
512	  dstripestart += dstripestep) {
513		fvscanstart = fstripestart;
514		dvscanstart = dstripestart;
515		vscanlen = JAS_MIN(i, 4);
516		for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
517			fp = fvscanstart;
518			dp = dvscanstart;
519			k = vscanlen;
520
521			sigpass_step(fp, frowstep, dp, bitpos, one,
522			  nmsedec, orient, mqenc, vcausalflag);
523			if (--k <= 0) {
524				continue;
525			}
526			fp += frowstep;
527			dp += drowstep;
528			sigpass_step(fp, frowstep, dp, bitpos, one,
529			  nmsedec, orient, mqenc, 0);
530			if (--k <= 0) {
531				continue;
532			}
533			fp += frowstep;
534			dp += drowstep;
535			sigpass_step(fp, frowstep, dp, bitpos, one,
536			  nmsedec, orient, mqenc, 0);
537			if (--k <= 0) {
538				continue;
539			}
540			fp += frowstep;
541			dp += drowstep;
542			sigpass_step(fp, frowstep, dp, bitpos, one,
543			  nmsedec, orient, mqenc, 0);
544
545		}
546	}
547
548	if (term) {
549		jpc_mqenc_flush(mqenc, term - 1);
550	}
551
552	return jpc_mqenc_error(mqenc) ? (-1) : 0;
553}
554
555#define	rawsigpass_step(fp, frowstep, dp, bitpos, one, nmsedec, out, vcausalflag) \
556{ \
557	jpc_fix_t f = *(fp); \
558	jpc_fix_t v; \
559	if ((f & JPC_OTHSIGMSK) && !(f & (JPC_SIG | JPC_VISIT))) { \
560		v = (abs(*(dp)) & (one)) ? 1 : 0; \
561		if ((jpc_bitstream_putbit((out), v)) == EOF) { \
562			return -1; \
563		} \
564		if (v) { \
565			*(nmsedec) += JPC_GETSIGNMSEDEC(abs(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \
566			v = ((*(dp) < 0) ? 1 : 0); \
567			if (jpc_bitstream_putbit(out, v) == EOF) { \
568				return -1; \
569			} \
570			JPC_UPDATEFLAGS4(fp, frowstep, v, vcausalflag); \
571			*(fp) |= JPC_SIG; \
572		} \
573		*(fp) |= JPC_VISIT; \
574	} \
575}
576
577static int jpc_encrawsigpass(jpc_bitstream_t *out, int bitpos, int vcausalflag, jas_matrix_t *flags,
578  jas_matrix_t *data, int term, long *nmsedec)
579{
580	int i;
581	int j;
582	int k;
583	int one;
584	int vscanlen;
585	int width;
586	int height;
587	int frowstep;
588	int drowstep;
589	int fstripestep;
590	int dstripestep;
591	jpc_fix_t *fstripestart;
592	jpc_fix_t *dstripestart;
593	jpc_fix_t *fp;
594	jpc_fix_t *dp;
595	jpc_fix_t *fvscanstart;
596	jpc_fix_t *dvscanstart;
597
598	*nmsedec = 0;
599	width = jas_matrix_numcols(data);
600	height = jas_matrix_numrows(data);
601	frowstep = jas_matrix_rowstep(flags);
602	drowstep = jas_matrix_rowstep(data);
603	fstripestep = frowstep << 2;
604	dstripestep = drowstep << 2;
605
606	one = 1 << (bitpos + JPC_NUMEXTRABITS);
607
608	fstripestart = jas_matrix_getref(flags, 1, 1);
609	dstripestart = jas_matrix_getref(data, 0, 0);
610	for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
611	  dstripestart += dstripestep) {
612		fvscanstart = fstripestart;
613		dvscanstart = dstripestart;
614		vscanlen = JAS_MIN(i, 4);
615		for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
616			fp = fvscanstart;
617			dp = dvscanstart;
618			k = vscanlen;
619
620			rawsigpass_step(fp, frowstep, dp, bitpos, one,
621			  nmsedec, out, vcausalflag);
622			if (--k <= 0) {
623				continue;
624			}
625			fp += frowstep;
626			dp += drowstep;
627
628			rawsigpass_step(fp, frowstep, dp, bitpos, one,
629			  nmsedec, out, 0);
630			if (--k <= 0) {
631				continue;
632			}
633			fp += frowstep;
634			dp += drowstep;
635
636			rawsigpass_step(fp, frowstep, dp, bitpos, one,
637			  nmsedec, out, 0);
638			if (--k <= 0) {
639				continue;
640			}
641			fp += frowstep;
642			dp += drowstep;
643
644			rawsigpass_step(fp, frowstep, dp, bitpos, one,
645			  nmsedec, out, 0);
646			if (--k <= 0) {
647				continue;
648			}
649			fp += frowstep;
650			dp += drowstep;
651
652		}
653	}
654
655	if (term) {
656		jpc_bitstream_outalign(out, 0x2a);
657	}
658
659	return 0;
660}
661
662/******************************************************************************\
663* Code for refinement pass.
664\******************************************************************************/
665
666#define	refpass_step(fp, dp, bitpos, one, nmsedec, mqenc, vcausalflag) \
667{ \
668	int v; \
669	if (((*(fp)) & (JPC_SIG | JPC_VISIT)) == JPC_SIG) { \
670		(d) = *(dp); \
671		*(nmsedec) += JPC_GETREFNMSEDEC(abs(d), (bitpos) + JPC_NUMEXTRABITS); \
672		jpc_mqenc_setcurctx((mqenc), JPC_GETMAGCTXNO(*(fp))); \
673		v = (abs(d) & (one)) ? 1 : 0; \
674		jpc_mqenc_putbit((mqenc), v); \
675		*(fp) |= JPC_REFINE; \
676	} \
677}
678
679static int jpc_encrefpass(jpc_mqenc_t *mqenc, int bitpos, int vcausalflag, jas_matrix_t *flags, jas_matrix_t *data,
680  int term, long *nmsedec)
681{
682	int i;
683	int j;
684	int one;
685	int vscanlen;
686	int d;
687	int width;
688	int height;
689	int frowstep;
690	int drowstep;
691	int fstripestep;
692	int dstripestep;
693	jpc_fix_t *fstripestart;
694	jpc_fix_t *dstripestart;
695	jpc_fix_t *fvscanstart;
696	jpc_fix_t *dvscanstart;
697	jpc_fix_t *dp;
698	jpc_fix_t *fp;
699int k;
700
701	*nmsedec = 0;
702	width = jas_matrix_numcols(data);
703	height = jas_matrix_numrows(data);
704	frowstep = jas_matrix_rowstep(flags);
705	drowstep = jas_matrix_rowstep(data);
706	fstripestep = frowstep << 2;
707	dstripestep = drowstep << 2;
708
709	one = 1 << (bitpos + JPC_NUMEXTRABITS);
710
711	fstripestart = jas_matrix_getref(flags, 1, 1);
712	dstripestart = jas_matrix_getref(data, 0, 0);
713	for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
714	  dstripestart += dstripestep) {
715		fvscanstart = fstripestart;
716		dvscanstart = dstripestart;
717		vscanlen = JAS_MIN(i, 4);
718		for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
719			fp = fvscanstart;
720			dp = dvscanstart;
721			k = vscanlen;
722
723			refpass_step(fp, dp, bitpos, one, nmsedec,
724			  mqenc, vcausalflag);
725			if (--k <= 0) {
726				continue;
727			}
728			fp += frowstep;
729			dp += drowstep;
730			refpass_step(fp, dp, bitpos, one, nmsedec,
731			  mqenc, 0);
732			if (--k <= 0) {
733				continue;
734			}
735			fp += frowstep;
736			dp += drowstep;
737			refpass_step(fp, dp, bitpos, one, nmsedec,
738			  mqenc, 0);
739			if (--k <= 0) {
740				continue;
741			}
742			fp += frowstep;
743			dp += drowstep;
744			refpass_step(fp, dp, bitpos, one, nmsedec,
745			  mqenc, 0);
746
747		}
748	}
749
750	if (term) {
751		jpc_mqenc_flush(mqenc, term - 1);
752	}
753
754	return jpc_mqenc_error(mqenc) ? (-1) : 0;
755}
756
757#define	rawrefpass_step(fp, dp, bitpos, one, nmsedec, out, vcausalflag) \
758{ \
759	jpc_fix_t d; \
760	jpc_fix_t v; \
761	if (((*(fp)) & (JPC_SIG | JPC_VISIT)) == JPC_SIG) { \
762		d = *(dp); \
763		*(nmsedec) += JPC_GETREFNMSEDEC(abs(d), (bitpos) + JPC_NUMEXTRABITS); \
764		v = (abs(d) & (one)) ? 1 : 0; \
765		if (jpc_bitstream_putbit((out), v) == EOF) { \
766			return -1; \
767		} \
768		*(fp) |= JPC_REFINE; \
769	} \
770}
771
772static int jpc_encrawrefpass(jpc_bitstream_t *out, int bitpos, int vcausalflag, jas_matrix_t *flags,
773  jas_matrix_t *data, int term, long *nmsedec)
774{
775	int i;
776	int j;
777	int k;
778	int one;
779	int vscanlen;
780	int width;
781	int height;
782	int frowstep;
783	int drowstep;
784	int fstripestep;
785	int dstripestep;
786	jpc_fix_t *fstripestart;
787	jpc_fix_t *dstripestart;
788	jpc_fix_t *fvscanstart;
789	jpc_fix_t *dvscanstart;
790	jpc_fix_t *dp;
791	jpc_fix_t *fp;
792
793	*nmsedec = 0;
794	width = jas_matrix_numcols(data);
795	height = jas_matrix_numrows(data);
796	frowstep = jas_matrix_rowstep(flags);
797	drowstep = jas_matrix_rowstep(data);
798	fstripestep = frowstep << 2;
799	dstripestep = drowstep << 2;
800
801	one = 1 << (bitpos + JPC_NUMEXTRABITS);
802
803	fstripestart = jas_matrix_getref(flags, 1, 1);
804	dstripestart = jas_matrix_getref(data, 0, 0);
805	for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
806	  dstripestart += dstripestep) {
807		fvscanstart = fstripestart;
808		dvscanstart = dstripestart;
809		vscanlen = JAS_MIN(i, 4);
810		for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
811			fp = fvscanstart;
812			dp = dvscanstart;
813			k = vscanlen;
814
815			rawrefpass_step(fp, dp, bitpos, one, nmsedec,
816			  out, vcausalflag);
817			if (--k <= 0) {
818				continue;
819			}
820			fp += frowstep;
821			dp += drowstep;
822			rawrefpass_step(fp, dp, bitpos, one, nmsedec,
823			  out, vcausalflag);
824			if (--k <= 0) {
825				continue;
826			}
827			fp += frowstep;
828			dp += drowstep;
829			rawrefpass_step(fp, dp, bitpos, one, nmsedec,
830			  out, vcausalflag);
831			if (--k <= 0) {
832				continue;
833			}
834			fp += frowstep;
835			dp += drowstep;
836			rawrefpass_step(fp, dp, bitpos, one, nmsedec,
837			  out, vcausalflag);
838
839		}
840	}
841
842	if (term) {
843		jpc_bitstream_outalign(out, 0x2a);
844	}
845
846	return 0;
847}
848
849/******************************************************************************\
850* Code for cleanup pass.
851\******************************************************************************/
852
853#define	clnpass_step(fp, frowstep, dp, bitpos, one, orient, nmsedec, mqenc, label1, label2, vcausalflag) \
854{ \
855	int f; \
856	int v; \
857label1 \
858	f = *(fp); \
859	if (!(f & (JPC_SIG | JPC_VISIT))) { \
860		jpc_mqenc_setcurctx(mqenc, JPC_GETZCCTXNO(f, (orient))); \
861		v = (abs(*(dp)) & (one)) ? 1 : 0; \
862		jpc_mqenc_putbit((mqenc), v); \
863		if (v) { \
864label2 \
865			f = *(fp); \
866			/* Coefficient is significant. */ \
867			*(nmsedec) += JPC_GETSIGNMSEDEC(abs(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \
868			jpc_mqenc_setcurctx((mqenc), JPC_GETSCCTXNO(f)); \
869			v = ((*(dp) < 0) ? 1 : 0); \
870			jpc_mqenc_putbit((mqenc), v ^ JPC_GETSPB(f)); \
871			JPC_UPDATEFLAGS4((fp), (frowstep), v, vcausalflag); \
872			*(fp) |= JPC_SIG; \
873		} \
874	} \
875	*(fp) &= ~JPC_VISIT; \
876}
877
878static int jpc_encclnpass(jpc_mqenc_t *mqenc, int bitpos, int orient, int vcausalflag, int segsymflag, jas_matrix_t *flags,
879  jas_matrix_t *data, int term, long *nmsedec)
880{
881	int i;
882	int j;
883	int k;
884	int vscanlen;
885	int v;
886	int runlen;
887	jpc_fix_t *fp;
888	int width;
889	int height;
890	jpc_fix_t *dp;
891	int one;
892	int frowstep;
893	int drowstep;
894	int fstripestep;
895	int dstripestep;
896	jpc_fix_t *fstripestart;
897	jpc_fix_t *dstripestart;
898	jpc_fix_t *fvscanstart;
899	jpc_fix_t *dvscanstart;
900
901	*nmsedec = 0;
902	width = jas_matrix_numcols(data);
903	height = jas_matrix_numrows(data);
904	frowstep = jas_matrix_rowstep(flags);
905	drowstep = jas_matrix_rowstep(data);
906	fstripestep = frowstep << 2;
907	dstripestep = drowstep << 2;
908
909	one = 1 << (bitpos + JPC_NUMEXTRABITS);
910
911	fstripestart = jas_matrix_getref(flags, 1, 1);
912	dstripestart = jas_matrix_getref(data, 0, 0);
913	for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
914	  dstripestart += dstripestep) {
915		fvscanstart = fstripestart;
916		dvscanstart = dstripestart;
917		vscanlen = JAS_MIN(i, 4);
918		for (j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
919
920			fp = fvscanstart;
921			if (vscanlen >= 4 && !((*fp) & (JPC_SIG | JPC_VISIT |
922			  JPC_OTHSIGMSK)) && (fp += frowstep, !((*fp) & (JPC_SIG |
923			  JPC_VISIT | JPC_OTHSIGMSK))) && (fp += frowstep, !((*fp) &
924			  (JPC_SIG | JPC_VISIT | JPC_OTHSIGMSK))) && (fp += frowstep,
925			  !((*fp) & (JPC_SIG | JPC_VISIT | JPC_OTHSIGMSK)))) {
926				dp = dvscanstart;
927				for (k = 0; k < vscanlen; ++k) {
928					v = (abs(*dp) & one) ? 1 : 0;
929					if (v) {
930						break;
931					}
932					dp += drowstep;
933				}
934				runlen = k;
935				if (runlen >= 4) {
936					jpc_mqenc_setcurctx(mqenc, JPC_AGGCTXNO);
937					jpc_mqenc_putbit(mqenc, 0);
938					continue;
939				}
940				jpc_mqenc_setcurctx(mqenc, JPC_AGGCTXNO);
941				jpc_mqenc_putbit(mqenc, 1);
942				jpc_mqenc_setcurctx(mqenc, JPC_UCTXNO);
943				jpc_mqenc_putbit(mqenc, runlen >> 1);
944				jpc_mqenc_putbit(mqenc, runlen & 1);
945				fp = fvscanstart + frowstep * runlen;
946				dp = dvscanstart + drowstep * runlen;
947				k = vscanlen - runlen;
948				switch (runlen) {
949				case 0:
950					goto clnpass_partial0;
951					break;
952				case 1:
953					goto clnpass_partial1;
954					break;
955				case 2:
956					goto clnpass_partial2;
957					break;
958				case 3:
959					goto clnpass_partial3;
960					break;
961				}
962			} else {
963				runlen = 0;
964				fp = fvscanstart;
965				dp = dvscanstart;
966				k = vscanlen;
967				goto clnpass_full0;
968			}
969			clnpass_step(fp, frowstep, dp, bitpos, one,
970			  orient, nmsedec, mqenc, clnpass_full0:, clnpass_partial0:, vcausalflag);
971			if (--k <= 0) {
972				continue;
973			}
974			fp += frowstep;
975			dp += drowstep;
976			clnpass_step(fp, frowstep, dp, bitpos, one,
977				orient, nmsedec, mqenc, ;, clnpass_partial1:, 0);
978			if (--k <= 0) {
979				continue;
980			}
981			fp += frowstep;
982			dp += drowstep;
983			clnpass_step(fp, frowstep, dp, bitpos, one,
984				orient, nmsedec, mqenc, ;, clnpass_partial2:, 0);
985			if (--k <= 0) {
986				continue;
987			}
988			fp += frowstep;
989			dp += drowstep;
990			clnpass_step(fp, frowstep, dp, bitpos, one,
991				orient, nmsedec, mqenc, ;, clnpass_partial3:, 0);
992		}
993	}
994
995	if (segsymflag) {
996		jpc_mqenc_setcurctx(mqenc, JPC_UCTXNO);
997		jpc_mqenc_putbit(mqenc, 1);
998		jpc_mqenc_putbit(mqenc, 0);
999		jpc_mqenc_putbit(mqenc, 1);
1000		jpc_mqenc_putbit(mqenc, 0);
1001	}
1002
1003	if (term) {
1004		jpc_mqenc_flush(mqenc, term - 1);
1005	}
1006
1007	return jpc_mqenc_error(mqenc) ? (-1) : 0;
1008}
1009