fixed MCT check bug in t1_getwmsedec. See http://groups.google.com/group/openjpeg...
[openjpeg.git] / libopenjpeg / t1.c
1 /*
2  * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
3  * Copyright (c) 2002-2007, Professor Benoit Macq
4  * Copyright (c) 2001-2003, David Janssens
5  * Copyright (c) 2002-2003, Yannick Verschueren
6  * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
7  * Copyright (c) 2005, Herve Drolon, FreeImage Team
8  * Copyright (c) 2007, Callum Lerwick <seg@haxxed.com>
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "opj_includes.h"
34 #include "t1_luts.h"
35
36 /** @defgroup T1 T1 - Implementation of the tier-1 coding */
37 /*@{*/
38
39 /** @name Local static functions */
40 /*@{*/
41
42 static INLINE char t1_getctxno_zc(int f, int orient);
43 static char t1_getctxno_sc(int f);
44 static INLINE int t1_getctxno_mag(int f);
45 static char t1_getspb(int f);
46 static short t1_getnmsedec_sig(int x, int bitpos);
47 static short t1_getnmsedec_ref(int x, int bitpos);
48 static void t1_updateflags(flag_t *flagsp, int s, int stride);
49 /**
50 Encode significant pass
51 */
52 static void t1_enc_sigpass_step(
53                 opj_t1_t *t1,
54                 flag_t *flagsp,
55                 int *datap,
56                 int orient,
57                 int bpno,
58                 int one,
59                 int *nmsedec,
60                 char type,
61                 int vsc);
62 /**
63 Decode significant pass
64 */
65 static void t1_dec_sigpass_step(
66                 opj_t1_t *t1,
67                 flag_t *flagsp,
68                 int *datap,
69                 int orient,
70                 int oneplushalf,
71                 char type,
72                 int vsc);
73 /**
74 Encode significant pass
75 */
76 static void t1_enc_sigpass(
77                 opj_t1_t *t1,
78                 int bpno,
79                 int orient,
80                 int *nmsedec,
81                 char type,
82                 int cblksty);
83 /**
84 Decode significant pass
85 */
86 static void t1_dec_sigpass(
87                 opj_t1_t *t1,
88                 int bpno,
89                 int orient,
90                 char type,
91                 int cblksty);
92 /**
93 Encode refinement pass
94 */
95 static void t1_enc_refpass_step(
96                 opj_t1_t *t1,
97                 flag_t *flagsp,
98                 int *datap,
99                 int bpno,
100                 int one,
101                 int *nmsedec,
102                 char type,
103                 int vsc);
104 /**
105 Decode refinement pass
106 */
107 static void t1_dec_refpass_step(
108                 opj_t1_t *t1,
109                 flag_t *flagsp,
110                 int *datap,
111                 int poshalf,
112                 int neghalf,
113                 char type,
114                 int vsc);
115 /**
116 Encode refinement pass
117 */
118 static void t1_enc_refpass(
119                 opj_t1_t *t1,
120                 int bpno,
121                 int *nmsedec,
122                 char type,
123                 int cblksty);
124 /**
125 Decode refinement pass
126 */
127 static void t1_dec_refpass(
128                 opj_t1_t *t1,
129                 int bpno,
130                 char type,
131                 int cblksty);
132 /**
133 Encode clean-up pass
134 */
135 static void t1_enc_clnpass_step(
136                 opj_t1_t *t1,
137                 flag_t *flagsp,
138                 int *datap,
139                 int orient,
140                 int bpno,
141                 int one,
142                 int *nmsedec,
143                 int partial,
144                 int vsc);
145 /**
146 Decode clean-up pass
147 */
148 static void t1_dec_clnpass_step(
149                 opj_t1_t *t1,
150                 flag_t *flagsp,
151                 int *datap,
152                 int orient,
153                 int oneplushalf,
154                 int partial,
155                 int vsc);
156 /**
157 Encode clean-up pass
158 */
159 static void t1_enc_clnpass(
160                 opj_t1_t *t1,
161                 int bpno,
162                 int orient,
163                 int *nmsedec,
164                 int cblksty);
165 /**
166 Decode clean-up pass
167 */
168 static void t1_dec_clnpass(
169                 opj_t1_t *t1,
170                 int bpno,
171                 int orient,
172                 int cblksty);
173 static double t1_getwmsedec(
174                 int nmsedec,
175                 int compno,
176                 int level,
177                 int orient,
178                 int bpno,
179                 int qmfbid,
180                 double stepsize,
181                 int numcomps,
182                 int mct);
183 /**
184 Encode 1 code-block
185 @param t1 T1 handle
186 @param cblk Code-block coding parameters
187 @param orient
188 @param compno Component number
189 @param level
190 @param qmfbid
191 @param stepsize
192 @param cblksty Code-block style
193 @param numcomps
194 @param tile
195 */
196 static void t1_encode_cblk(
197                 opj_t1_t *t1,
198                 opj_tcd_cblk_enc_t* cblk,
199                 int orient,
200                 int compno,
201                 int level,
202                 int qmfbid,
203                 double stepsize,
204                 int cblksty,
205                 int numcomps,
206                 int mct,
207                 opj_tcd_tile_t * tile);
208 /**
209 Decode 1 code-block
210 @param t1 T1 handle
211 @param cblk Code-block coding parameters
212 @param orient
213 @param roishift Region of interest shifting value
214 @param cblksty Code-block style
215 */
216 static void t1_decode_cblk(
217                 opj_t1_t *t1,
218                 opj_tcd_cblk_dec_t* cblk,
219                 int orient,
220                 int roishift,
221                 int cblksty);
222
223 /*@}*/
224
225 /*@}*/
226
227 /* ----------------------------------------------------------------------- */
228
229 static char t1_getctxno_zc(int f, int orient) {
230         return lut_ctxno_zc[(orient << 8) | (f & T1_SIG_OTH)];
231 }
232
233 static char t1_getctxno_sc(int f) {
234         return lut_ctxno_sc[(f & (T1_SIG_PRIM | T1_SGN)) >> 4];
235 }
236
237 static int t1_getctxno_mag(int f) {
238         int tmp1 = (f & T1_SIG_OTH) ? T1_CTXNO_MAG + 1 : T1_CTXNO_MAG;
239         int tmp2 = (f & T1_REFINE) ? T1_CTXNO_MAG + 2 : tmp1;
240         return (tmp2);
241 }
242
243 static char t1_getspb(int f) {
244         return lut_spb[(f & (T1_SIG_PRIM | T1_SGN)) >> 4];
245 }
246
247 static short t1_getnmsedec_sig(int x, int bitpos) {
248         if (bitpos > T1_NMSEDEC_FRACBITS) {
249                 return lut_nmsedec_sig[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)];
250         }
251         
252         return lut_nmsedec_sig0[x & ((1 << T1_NMSEDEC_BITS) - 1)];
253 }
254
255 static short t1_getnmsedec_ref(int x, int bitpos) {
256         if (bitpos > T1_NMSEDEC_FRACBITS) {
257                 return lut_nmsedec_ref[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)];
258         }
259
260     return lut_nmsedec_ref0[x & ((1 << T1_NMSEDEC_BITS) - 1)];
261 }
262
263 static void t1_updateflags(flag_t *flagsp, int s, int stride) {
264         flag_t *np = flagsp - stride;
265         flag_t *sp = flagsp + stride;
266
267         static const flag_t mod[] = {
268                 T1_SIG_S, T1_SIG_S|T1_SGN_S,
269                 T1_SIG_E, T1_SIG_E|T1_SGN_E,
270                 T1_SIG_W, T1_SIG_W|T1_SGN_W,
271                 T1_SIG_N, T1_SIG_N|T1_SGN_N
272         };
273
274         np[-1] |= T1_SIG_SE;
275         np[0]  |= mod[s];
276         np[1]  |= T1_SIG_SW;
277
278         flagsp[-1] |= mod[s+2];
279         flagsp[0]  |= T1_SIG;
280         flagsp[1]  |= mod[s+4];
281
282         sp[-1] |= T1_SIG_NE;
283         sp[0]  |= mod[s+6];
284         sp[1]  |= T1_SIG_NW;
285 }
286
287 static void t1_enc_sigpass_step(
288                 opj_t1_t *t1,
289                 flag_t *flagsp,
290                 int *datap,
291                 int orient,
292                 int bpno,
293                 int one,
294                 int *nmsedec,
295                 char type,
296                 int vsc)
297 {
298         int v, flag;
299         
300         opj_mqc_t *mqc = t1->mqc;       /* MQC component */
301         
302         flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp);
303         if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) {
304                 v = int_abs(*datap) & one ? 1 : 0;
305                 mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient));       /* ESSAI */
306                 if (type == T1_TYPE_RAW) {      /* BYPASS/LAZY MODE */
307                         mqc_bypass_enc(mqc, v);
308                 } else {
309                         mqc_encode(mqc, v);
310                 }
311                 if (v) {
312                         v = *datap < 0 ? 1 : 0;
313                         *nmsedec +=     t1_getnmsedec_sig(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS);
314                         mqc_setcurctx(mqc, t1_getctxno_sc(flag));       /* ESSAI */
315                         if (type == T1_TYPE_RAW) {      /* BYPASS/LAZY MODE */
316                                 mqc_bypass_enc(mqc, v);
317                         } else {
318                                 mqc_encode(mqc, v ^ t1_getspb(flag));
319                         }
320                         t1_updateflags(flagsp, v, t1->flags_stride);
321                 }
322                 *flagsp |= T1_VISIT;
323         }
324 }
325
326 static void t1_dec_sigpass_step(
327                 opj_t1_t *t1,
328                 flag_t *flagsp,
329                 int *datap,
330                 int orient,
331                 int oneplushalf,
332                 char type,
333                 int vsc)
334 {
335         int v, flag;
336         
337         opj_raw_t *raw = t1->raw;       /* RAW component */
338         opj_mqc_t *mqc = t1->mqc;       /* MQC component */
339         
340         flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp);
341         if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) {
342                 if (type == T1_TYPE_RAW) {
343                         if (raw_decode(raw)) {
344                                 v = raw_decode(raw);    /* ESSAI */
345                                 *datap = v ? -oneplushalf : oneplushalf;
346                                 t1_updateflags(flagsp, v, t1->flags_stride);
347                         }
348                 } else {
349                         mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient));
350                         if (mqc_decode(mqc)) {
351                                 mqc_setcurctx(mqc, t1_getctxno_sc(flag));
352                                 v = mqc_decode(mqc) ^ t1_getspb(flag);
353                                 *datap = v ? -oneplushalf : oneplushalf;
354                                 t1_updateflags(flagsp, v, t1->flags_stride);
355                         }
356                 }
357                 *flagsp |= T1_VISIT;
358         }
359 }                               /* VSC and  BYPASS by Antonin */
360
361 static void t1_enc_sigpass(
362                 opj_t1_t *t1,
363                 int bpno,
364                 int orient,
365                 int *nmsedec,
366                 char type,
367                 int cblksty)
368 {
369         int i, j, k, one, vsc;
370         *nmsedec = 0;
371         one = 1 << (bpno + T1_NMSEDEC_FRACBITS);
372         for (k = 0; k < t1->h; k += 4) {
373                 for (i = 0; i < t1->w; ++i) {
374                         for (j = k; j < k + 4 && j < t1->h; ++j) {
375                                 vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0;
376                                 t1_enc_sigpass_step(
377                                                 t1,
378                                                 &t1->flags[((j+1) * t1->flags_stride) + i + 1],
379                                                 &t1->data[(j * t1->w) + i],
380                                                 orient,
381                                                 bpno,
382                                                 one,
383                                                 nmsedec,
384                                                 type,
385                                                 vsc);
386                         }
387                 }
388         }
389 }
390
391 static void t1_dec_sigpass(
392                 opj_t1_t *t1,
393                 int bpno,
394                 int orient,
395                 char type,
396                 int cblksty)
397 {
398         int i, j, k, one, half, oneplushalf, vsc;
399         one = 1 << bpno;
400         half = one >> 1;
401         oneplushalf = one | half;
402         for (k = 0; k < t1->h; k += 4) {
403                 for (i = 0; i < t1->w; ++i) {
404                         for (j = k; j < k + 4 && j < t1->h; ++j) {
405                                 vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0;
406                                 t1_dec_sigpass_step(
407                                                 t1,
408                                                 &t1->flags[((j+1) * t1->flags_stride) + i + 1],
409                                                 &t1->data[(j * t1->w) + i],
410                                                 orient,
411                                                 oneplushalf,
412                                                 type,
413                                                 vsc);
414                         }
415                 }
416         }
417 }                               /* VSC and  BYPASS by Antonin */
418
419 static void t1_enc_refpass_step(
420                 opj_t1_t *t1,
421                 flag_t *flagsp,
422                 int *datap,
423                 int bpno,
424                 int one,
425                 int *nmsedec,
426                 char type,
427                 int vsc)
428 {
429         int v, flag;
430         
431         opj_mqc_t *mqc = t1->mqc;       /* MQC component */
432         
433         flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp);
434         if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) {
435                 *nmsedec += t1_getnmsedec_ref(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS);
436                 v = int_abs(*datap) & one ? 1 : 0;
437                 mqc_setcurctx(mqc, t1_getctxno_mag(flag));      /* ESSAI */
438                 if (type == T1_TYPE_RAW) {      /* BYPASS/LAZY MODE */
439                         mqc_bypass_enc(mqc, v);
440                 } else {
441                         mqc_encode(mqc, v);
442                 }
443                 *flagsp |= T1_REFINE;
444         }
445 }
446
447 static void t1_dec_refpass_step(
448                 opj_t1_t *t1,
449                 flag_t *flagsp,
450                 int *datap,
451                 int poshalf,
452                 int neghalf,
453                 char type,
454                 int vsc)
455 {
456         int v, t, flag;
457         
458         opj_mqc_t *mqc = t1->mqc;       /* MQC component */
459         opj_raw_t *raw = t1->raw;       /* RAW component */
460         
461         flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp);
462         if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) {
463                 mqc_setcurctx(mqc, t1_getctxno_mag(flag));      /* ESSAI */
464                 if (type == T1_TYPE_RAW) {
465                         v = raw_decode(raw);
466                 } else {
467                         v = mqc_decode(mqc);
468                 }
469                 t = v ? poshalf : neghalf;
470                 *datap += *datap < 0 ? -t : t;
471                 *flagsp |= T1_REFINE;
472         }
473 }                               /* VSC and  BYPASS by Antonin  */
474
475 static void t1_enc_refpass(
476                 opj_t1_t *t1,
477                 int bpno,
478                 int *nmsedec,
479                 char type,
480                 int cblksty)
481 {
482         int i, j, k, one, vsc;
483         *nmsedec = 0;
484         one = 1 << (bpno + T1_NMSEDEC_FRACBITS);
485         for (k = 0; k < t1->h; k += 4) {
486                 for (i = 0; i < t1->w; ++i) {
487                         for (j = k; j < k + 4 && j < t1->h; ++j) {
488                                 vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0;
489                                 t1_enc_refpass_step(
490                                                 t1,
491                                                 &t1->flags[((j+1) * t1->flags_stride) + i + 1],
492                                                 &t1->data[(j * t1->w) + i],
493                                                 bpno,
494                                                 one,
495                                                 nmsedec,
496                                                 type,
497                                                 vsc);
498                         }
499                 }
500         }
501 }
502
503 static void t1_dec_refpass(
504                 opj_t1_t *t1,
505                 int bpno,
506                 char type,
507                 int cblksty)
508 {
509         int i, j, k, one, poshalf, neghalf;
510         int vsc;
511         one = 1 << bpno;
512         poshalf = one >> 1;
513         neghalf = bpno > 0 ? -poshalf : -1;
514         for (k = 0; k < t1->h; k += 4) {
515                 for (i = 0; i < t1->w; ++i) {
516                         for (j = k; j < k + 4 && j < t1->h; ++j) {
517                                 vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0;
518                                 t1_dec_refpass_step(
519                                                 t1,
520                                                 &t1->flags[((j+1) * t1->flags_stride) + i + 1],
521                                                 &t1->data[(j * t1->w) + i],
522                                                 poshalf,
523                                                 neghalf,
524                                                 type,
525                                                 vsc);
526                         }
527                 }
528         }
529 }                               /* VSC and  BYPASS by Antonin */
530
531 static void t1_enc_clnpass_step(
532                 opj_t1_t *t1,
533                 flag_t *flagsp,
534                 int *datap,
535                 int orient,
536                 int bpno,
537                 int one,
538                 int *nmsedec,
539                 int partial,
540                 int vsc)
541 {
542         int v, flag;
543         
544         opj_mqc_t *mqc = t1->mqc;       /* MQC component */
545         
546         flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp);
547         if (partial) {
548                 goto LABEL_PARTIAL;
549         }
550         if (!(*flagsp & (T1_SIG | T1_VISIT))) {
551                 mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient));
552                 v = int_abs(*datap) & one ? 1 : 0;
553                 mqc_encode(mqc, v);
554                 if (v) {
555 LABEL_PARTIAL:
556                         *nmsedec += t1_getnmsedec_sig(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS);
557                         mqc_setcurctx(mqc, t1_getctxno_sc(flag));
558                         v = *datap < 0 ? 1 : 0;
559                         mqc_encode(mqc, v ^ t1_getspb(flag));
560                         t1_updateflags(flagsp, v, t1->flags_stride);
561                 }
562         }
563         *flagsp &= ~T1_VISIT;
564 }
565
566 static void t1_dec_clnpass_step(
567                 opj_t1_t *t1,
568                 flag_t *flagsp,
569                 int *datap,
570                 int orient,
571                 int oneplushalf,
572                 int partial,
573                 int vsc)
574 {
575         int v, flag;
576         
577         opj_mqc_t *mqc = t1->mqc;       /* MQC component */
578         
579         flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp);
580         if (partial) {
581                 goto LABEL_PARTIAL;
582         }
583         if (!(flag & (T1_SIG | T1_VISIT))) {
584                 mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient));
585                 if (mqc_decode(mqc)) {
586 LABEL_PARTIAL:
587                         mqc_setcurctx(mqc, t1_getctxno_sc(flag));
588                         v = mqc_decode(mqc) ^ t1_getspb(flag);
589                         *datap = v ? -oneplushalf : oneplushalf;
590                         t1_updateflags(flagsp, v, t1->flags_stride);
591                 }
592         }
593         *flagsp &= ~T1_VISIT;
594 }                               /* VSC and  BYPASS by Antonin */
595
596 static void t1_enc_clnpass(
597                 opj_t1_t *t1,
598                 int bpno,
599                 int orient,
600                 int *nmsedec,
601                 int cblksty)
602 {
603         int i, j, k, one, agg, runlen, vsc;
604         
605         opj_mqc_t *mqc = t1->mqc;       /* MQC component */
606         
607         *nmsedec = 0;
608         one = 1 << (bpno + T1_NMSEDEC_FRACBITS);
609         for (k = 0; k < t1->h; k += 4) {
610                 for (i = 0; i < t1->w; ++i) {
611                         if (k + 3 < t1->h) {
612                                 if (cblksty & J2K_CCP_CBLKSTY_VSC) {
613                                         agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
614                                                 || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
615                                                 || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
616                                                 || (MACRO_t1_flags(1 + k + 3,1 + i) 
617                                                 & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) & (T1_SIG | T1_VISIT | T1_SIG_OTH));
618                                 } else {
619                                         agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
620                                                 || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
621                                                 || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
622                                                 || MACRO_t1_flags(1 + k + 3,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH));
623                                 }
624                         } else {
625                                 agg = 0;
626                         }
627                         if (agg) {
628                                 for (runlen = 0; runlen < 4; ++runlen) {
629                                         if (int_abs(t1->data[((k + runlen)*t1->w) + i]) & one)
630                                                 break;
631                                 }
632                                 mqc_setcurctx(mqc, T1_CTXNO_AGG);
633                                 mqc_encode(mqc, runlen != 4);
634                                 if (runlen == 4) {
635                                         continue;
636                                 }
637                                 mqc_setcurctx(mqc, T1_CTXNO_UNI);
638                                 mqc_encode(mqc, runlen >> 1);
639                                 mqc_encode(mqc, runlen & 1);
640                         } else {
641                                 runlen = 0;
642                         }
643                         for (j = k + runlen; j < k + 4 && j < t1->h; ++j) {
644                                 vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0;
645                                 t1_enc_clnpass_step(
646                                                 t1,
647                                                 &t1->flags[((j+1) * t1->flags_stride) + i + 1],
648                                                 &t1->data[(j * t1->w) + i],
649                                                 orient,
650                                                 bpno,
651                                                 one,
652                                                 nmsedec,
653                                                 agg && (j == k + runlen),
654                                                 vsc);
655                         }
656                 }
657         }
658 }
659
660 static void t1_dec_clnpass(
661                 opj_t1_t *t1,
662                 int bpno,
663                 int orient,
664                 int cblksty)
665 {
666         int i, j, k, one, half, oneplushalf, agg, runlen, vsc;
667         int segsym = cblksty & J2K_CCP_CBLKSTY_SEGSYM;
668         
669         opj_mqc_t *mqc = t1->mqc;       /* MQC component */
670         
671         one = 1 << bpno;
672         half = one >> 1;
673         oneplushalf = one | half;
674         for (k = 0; k < t1->h; k += 4) {
675                 for (i = 0; i < t1->w; ++i) {
676                         if (k + 3 < t1->h) {
677                                 if (cblksty & J2K_CCP_CBLKSTY_VSC) {
678                                         agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
679                                                 || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
680                                                 || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
681                                                 || (MACRO_t1_flags(1 + k + 3,1 + i) 
682                                                 & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) & (T1_SIG | T1_VISIT | T1_SIG_OTH));
683                                 } else {
684                                         agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
685                                                 || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
686                                                 || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
687                                                 || MACRO_t1_flags(1 + k + 3,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH));
688                                 }
689                         } else {
690                                 agg = 0;
691                         }
692                         if (agg) {
693                                 mqc_setcurctx(mqc, T1_CTXNO_AGG);
694                                 if (!mqc_decode(mqc)) {
695                                         continue;
696                                 }
697                                 mqc_setcurctx(mqc, T1_CTXNO_UNI);
698                                 runlen = mqc_decode(mqc);
699                                 runlen = (runlen << 1) | mqc_decode(mqc);
700                         } else {
701                                 runlen = 0;
702                         }
703                         for (j = k + runlen; j < k + 4 && j < t1->h; ++j) {
704                                 vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0;
705                                 t1_dec_clnpass_step(
706                                                 t1,
707                                                 &t1->flags[((j+1) * t1->flags_stride) + i + 1],
708                                                 &t1->data[(j * t1->w) + i],
709                                                 orient,
710                                                 oneplushalf,
711                                                 agg && (j == k + runlen),
712                                                 vsc);
713                         }
714                 }
715         }
716         if (segsym) {
717                 int v = 0;
718                 mqc_setcurctx(mqc, T1_CTXNO_UNI);
719                 v = mqc_decode(mqc);
720                 v = (v << 1) | mqc_decode(mqc);
721                 v = (v << 1) | mqc_decode(mqc);
722                 v = (v << 1) | mqc_decode(mqc);
723                 /*
724                 if (v!=0xa) {
725                         opj_event_msg(t1->cinfo, EVT_WARNING, "Bad segmentation symbol %x\n", v);
726                 } 
727                 */
728         }
729 }                               /* VSC and  BYPASS by Antonin */
730
731
732 /** mod fixed_quality */
733 static double t1_getwmsedec(
734                 int nmsedec,
735                 int compno,
736                 int level,
737                 int orient,
738                 int bpno,
739                 int qmfbid,
740                 double stepsize,
741                 int numcomps,
742                 int mct)
743 {
744         double w1, w2, wmsedec;
745         if (qmfbid == 1) {
746                 w1 = (mct && numcomps==3) ? mct_getnorm(compno) : 1.0;
747                 w2 = dwt_getnorm(level, orient);
748         } else {                        /* if (qmfbid == 0) */
749                 w1 = (mct && numcomps==3) ? mct_getnorm_real(compno) : 1.0;
750                 w2 = dwt_getnorm_real(level, orient);
751         }
752         wmsedec = w1 * w2 * stepsize * (1 << bpno);
753         wmsedec *= wmsedec * nmsedec / 8192.0;
754         
755         return wmsedec;
756 }
757
758 static bool allocate_buffers(
759                 opj_t1_t *t1,
760                 int w,
761                 int h)
762 {
763         int datasize=w * h;
764         int flagssize;
765
766         if(datasize > t1->datasize){
767                 opj_aligned_free(t1->data);
768                 t1->data = (int*) opj_aligned_malloc(datasize * sizeof(int));
769                 if(!t1->data){
770                         return false;
771                 }
772                 t1->datasize=datasize;
773         }
774         memset(t1->data,0,datasize * sizeof(int));
775
776         t1->flags_stride=w+2;
777         flagssize=t1->flags_stride * (h+2);
778
779         if(flagssize > t1->flagssize){
780                 opj_aligned_free(t1->flags);
781                 t1->flags = (flag_t*) opj_aligned_malloc(flagssize * sizeof(flag_t));
782                 if(!t1->flags){
783                         return false;
784                 }
785                 t1->flagssize=flagssize;
786         }
787         memset(t1->flags,0,flagssize * sizeof(flag_t));
788
789         t1->w=w;
790         t1->h=h;
791
792         return true;
793 }
794
795 /** mod fixed_quality */
796 static void t1_encode_cblk(
797                 opj_t1_t *t1,
798                 opj_tcd_cblk_enc_t* cblk,
799                 int orient,
800                 int compno,
801                 int level,
802                 int qmfbid,
803                 double stepsize,
804                 int cblksty,
805                 int numcomps,
806                 int mct,
807                 opj_tcd_tile_t * tile)
808 {
809         double cumwmsedec = 0.0;
810
811         opj_mqc_t *mqc = t1->mqc;       /* MQC component */
812
813         int passno, bpno, passtype;
814         int nmsedec = 0;
815         int i, max;
816         char type = T1_TYPE_MQ;
817         double tempwmsedec;
818
819         max = 0;
820         for (i = 0; i < t1->w * t1->h; ++i) {
821                 int tmp = abs(t1->data[i]);
822                 max = int_max(max, tmp);
823         }
824
825         cblk->numbps = max ? (int_floorlog2(max) + 1) - T1_NMSEDEC_FRACBITS : 0;
826         
827         bpno = cblk->numbps - 1;
828         passtype = 2;
829         
830         mqc_resetstates(mqc);
831         mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46);
832         mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3);
833         mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4);
834         mqc_init_enc(mqc, cblk->data);
835         
836         for (passno = 0; bpno >= 0; ++passno) {
837                 opj_tcd_pass_t *pass = &cblk->passes[passno];
838                 int correction = 3;
839                 type = ((bpno < (cblk->numbps - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
840                 
841                 switch (passtype) {
842                         case 0:
843                                 t1_enc_sigpass(t1, bpno, orient, &nmsedec, type, cblksty);
844                                 break;
845                         case 1:
846                                 t1_enc_refpass(t1, bpno, &nmsedec, type, cblksty);
847                                 break;
848                         case 2:
849                                 t1_enc_clnpass(t1, bpno, orient, &nmsedec, cblksty);
850                                 /* code switch SEGMARK (i.e. SEGSYM) */
851                                 if (cblksty & J2K_CCP_CBLKSTY_SEGSYM)
852                                         mqc_segmark_enc(mqc);
853                                 break;
854                 }
855                 
856                 /* fixed_quality */
857                 tempwmsedec = t1_getwmsedec(nmsedec, compno, level, orient, bpno, qmfbid, stepsize, numcomps, mct);
858                 cumwmsedec += tempwmsedec;
859                 tile->distotile += tempwmsedec;
860                 
861                 /* Code switch "RESTART" (i.e. TERMALL) */
862                 if ((cblksty & J2K_CCP_CBLKSTY_TERMALL) && !((passtype == 2) && (bpno - 1 < 0))) {
863                         if (type == T1_TYPE_RAW) {
864                                 mqc_flush(mqc);
865                                 correction = 1;
866                                 /* correction = mqc_bypass_flush_enc(); */
867                         } else {                        /* correction = mqc_restart_enc(); */
868                                 mqc_flush(mqc);
869                                 correction = 1;
870                         }
871                         pass->term = 1;
872                 } else {
873                         if (((bpno < (cblk->numbps - 4) && (passtype > 0)) 
874                                 || ((bpno == (cblk->numbps - 4)) && (passtype == 2))) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) {
875                                 if (type == T1_TYPE_RAW) {
876                                         mqc_flush(mqc);
877                                         correction = 1;
878                                         /* correction = mqc_bypass_flush_enc(); */
879                                 } else {                /* correction = mqc_restart_enc(); */
880                                         mqc_flush(mqc);
881                                         correction = 1;
882                                 }
883                                 pass->term = 1;
884                         } else {
885                                 pass->term = 0;
886                         }
887                 }
888                 
889                 if (++passtype == 3) {
890                         passtype = 0;
891                         bpno--;
892                 }
893                 
894                 if (pass->term && bpno > 0) {
895                         type = ((bpno < (cblk->numbps - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
896                         if (type == T1_TYPE_RAW)
897                                 mqc_bypass_init_enc(mqc);
898                         else
899                                 mqc_restart_init_enc(mqc);
900                 }
901                 
902                 pass->distortiondec = cumwmsedec;
903                 pass->rate = mqc_numbytes(mqc) + correction;    /* FIXME */
904                 
905                 /* Code-switch "RESET" */
906                 if (cblksty & J2K_CCP_CBLKSTY_RESET)
907                         mqc_reset_enc(mqc);
908         }
909         
910         /* Code switch "ERTERM" (i.e. PTERM) */
911         if (cblksty & J2K_CCP_CBLKSTY_PTERM)
912                 mqc_erterm_enc(mqc);
913         else /* Default coding */ if (!(cblksty & J2K_CCP_CBLKSTY_LAZY))
914                 mqc_flush(mqc);
915         
916         cblk->totalpasses = passno;
917
918         for (passno = 0; passno<cblk->totalpasses; passno++) {
919                 opj_tcd_pass_t *pass = &cblk->passes[passno];
920                 if (pass->rate > mqc_numbytes(mqc))
921                         pass->rate = mqc_numbytes(mqc);
922                 /*Preventing generation of FF as last data byte of a pass*/
923                 if((pass->rate>1) && (cblk->data[pass->rate - 1] == 0xFF)){
924                         pass->rate--;
925                 }
926                 pass->len = pass->rate - (passno == 0 ? 0 : cblk->passes[passno - 1].rate);             
927         }
928 }
929
930 static void t1_decode_cblk(
931                 opj_t1_t *t1,
932                 opj_tcd_cblk_dec_t* cblk,
933                 int orient,
934                 int roishift,
935                 int cblksty)
936 {
937         opj_raw_t *raw = t1->raw;       /* RAW component */
938         opj_mqc_t *mqc = t1->mqc;       /* MQC component */
939
940         int bpno, passtype;
941         int segno, passno;
942         char type = T1_TYPE_MQ; /* BYPASS mode */
943
944         if(!allocate_buffers(
945                                 t1,
946                                 cblk->x1 - cblk->x0,
947                                 cblk->y1 - cblk->y0))
948         {
949                 return;
950         }
951
952         bpno = roishift + cblk->numbps - 1;
953         passtype = 2;
954         
955         mqc_resetstates(mqc);
956         mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46);
957         mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3);
958         mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4);
959         
960         for (segno = 0; segno < cblk->numsegs; ++segno) {
961                 opj_tcd_seg_t *seg = &cblk->segs[segno];
962                 
963                 /* BYPASS mode */
964                 type = ((bpno <= (cblk->numbps - 1) - 4) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
965                 /* FIXME: slviewer gets here with a null pointer. Why? Partially downloaded and/or corrupt textures? */
966                 if(seg->data == NULL){
967                         continue;
968                 }
969                 if (type == T1_TYPE_RAW) {
970                         raw_init_dec(raw, (*seg->data) + seg->dataindex, seg->len);
971                 } else {
972                         mqc_init_dec(mqc, (*seg->data) + seg->dataindex, seg->len);
973                 }
974                 
975                 for (passno = 0; passno < seg->numpasses; ++passno) {
976                         switch (passtype) {
977                                 case 0:
978                                         t1_dec_sigpass(t1, bpno+1, orient, type, cblksty);
979                                         break;
980                                 case 1:
981                                         t1_dec_refpass(t1, bpno+1, type, cblksty);
982                                         break;
983                                 case 2:
984                                         t1_dec_clnpass(t1, bpno+1, orient, cblksty);
985                                         break;
986                         }
987                         
988                         if ((cblksty & J2K_CCP_CBLKSTY_RESET) && type == T1_TYPE_MQ) {
989                                 mqc_resetstates(mqc);
990                                 mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46);                         
991                                 mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3);
992                                 mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4);
993                         }
994                         if (++passtype == 3) {
995                                 passtype = 0;
996                                 bpno--;
997                         }
998                 }
999         }
1000 }
1001
1002 /* ----------------------------------------------------------------------- */
1003
1004 opj_t1_t* t1_create(opj_common_ptr cinfo) {
1005         opj_t1_t *t1 = (opj_t1_t*) opj_malloc(sizeof(opj_t1_t));
1006         if(!t1)
1007                 return NULL;
1008
1009         t1->cinfo = cinfo;
1010         /* create MQC and RAW handles */
1011         t1->mqc = mqc_create();
1012         t1->raw = raw_create();
1013
1014         t1->data=NULL;
1015         t1->flags=NULL;
1016         t1->datasize=0;
1017         t1->flagssize=0;
1018
1019         return t1;
1020 }
1021
1022 void t1_destroy(opj_t1_t *t1) {
1023         if(t1) {
1024                 /* destroy MQC and RAW handles */
1025                 mqc_destroy(t1->mqc);
1026                 raw_destroy(t1->raw);
1027                 opj_aligned_free(t1->data);
1028                 opj_aligned_free(t1->flags);
1029                 opj_free(t1);
1030         }
1031 }
1032
1033 void t1_encode_cblks(
1034                 opj_t1_t *t1,
1035                 opj_tcd_tile_t *tile,
1036                 opj_tcp_t *tcp)
1037 {
1038         int compno, resno, bandno, precno, cblkno;
1039
1040         tile->distotile = 0;            /* fixed_quality */
1041
1042         for (compno = 0; compno < tile->numcomps; ++compno) {
1043                 opj_tcd_tilecomp_t* tilec = &tile->comps[compno];
1044                 opj_tccp_t* tccp = &tcp->tccps[compno];
1045                 int tile_w = tilec->x1 - tilec->x0;
1046
1047                 for (resno = 0; resno < tilec->numresolutions; ++resno) {
1048                         opj_tcd_resolution_t *res = &tilec->resolutions[resno];
1049
1050                         for (bandno = 0; bandno < res->numbands; ++bandno) {
1051                                 opj_tcd_band_t* restrict band = &res->bands[bandno];
1052
1053                                 for (precno = 0; precno < res->pw * res->ph; ++precno) {
1054                                         opj_tcd_precinct_t *prc = &band->precincts[precno];
1055
1056                                         for (cblkno = 0; cblkno < prc->cw * prc->ch; ++cblkno) {
1057                                                 opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno];
1058                                                 int* restrict datap;
1059                                                 int* restrict tiledp;
1060                                                 int cblk_w;
1061                                                 int cblk_h;
1062                                                 int i, j;
1063
1064                                                 int x = cblk->x0 - band->x0;
1065                                                 int y = cblk->y0 - band->y0;
1066                                                 if (band->bandno & 1) {
1067                                                         opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1];
1068                                                         x += pres->x1 - pres->x0;
1069                                                 }
1070                                                 if (band->bandno & 2) {
1071                                                         opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1];
1072                                                         y += pres->y1 - pres->y0;
1073                                                 }
1074
1075                                                 if(!allocate_buffers(
1076                                                                         t1,
1077                                                                         cblk->x1 - cblk->x0,
1078                                                                         cblk->y1 - cblk->y0))
1079                                                 {
1080                                                         return;
1081                                                 }
1082
1083                                                 datap=t1->data;
1084                                                 cblk_w = t1->w;
1085                                                 cblk_h = t1->h;
1086
1087                                                 tiledp=&tilec->data[(y * tile_w) + x];
1088                                                 if (tccp->qmfbid == 1) {
1089                                                         for (j = 0; j < cblk_h; ++j) {
1090                                                                 for (i = 0; i < cblk_w; ++i) {
1091                                                                         int tmp = tiledp[(j * tile_w) + i];
1092                                                                         datap[(j * cblk_w) + i] = tmp << T1_NMSEDEC_FRACBITS;
1093                                                                 }
1094                                                         }
1095                                                 } else {                /* if (tccp->qmfbid == 0) */
1096                                                         for (j = 0; j < cblk_h; ++j) {
1097                                                                 for (i = 0; i < cblk_w; ++i) {
1098                                                                         int tmp = tiledp[(j * tile_w) + i];
1099                                                                         datap[(j * cblk_w) + i] =
1100                                                                                 fix_mul(
1101                                                                                 tmp,
1102                                                                                 8192 * 8192 / ((int) floor(band->stepsize * 8192))) >> (11 - T1_NMSEDEC_FRACBITS);
1103                                                                 }
1104                                                         }
1105                                                 }
1106
1107                                                 t1_encode_cblk(
1108                                                                 t1,
1109                                                                 cblk,
1110                                                                 band->bandno,
1111                                                                 compno,
1112                                                                 tilec->numresolutions - 1 - resno,
1113                                                                 tccp->qmfbid,
1114                                                                 band->stepsize,
1115                                                                 tccp->cblksty,
1116                                                                 tile->numcomps,
1117                                                                 tcp->mct,
1118                                                                 tile);
1119
1120                                         } /* cblkno */
1121                                 } /* precno */
1122                         } /* bandno */
1123                 } /* resno  */
1124         } /* compno  */
1125 }
1126
1127 void t1_decode_cblks(
1128                 opj_t1_t* t1,
1129                 opj_tcd_tilecomp_t* tilec,
1130                 opj_tccp_t* tccp)
1131 {
1132         int resno, bandno, precno, cblkno;
1133
1134         int tile_w = tilec->x1 - tilec->x0;
1135
1136         for (resno = 0; resno < tilec->numresolutions; ++resno) {
1137                 opj_tcd_resolution_t* res = &tilec->resolutions[resno];
1138
1139                 for (bandno = 0; bandno < res->numbands; ++bandno) {
1140                         opj_tcd_band_t* restrict band = &res->bands[bandno];
1141
1142                         for (precno = 0; precno < res->pw * res->ph; ++precno) {
1143                                 opj_tcd_precinct_t* precinct = &band->precincts[precno];
1144
1145                                 for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) {
1146                                         opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno];
1147                                         int* restrict datap;
1148                                         void* restrict tiledp;
1149                                         int cblk_w, cblk_h;
1150                                         int x, y;
1151                                         int i, j;
1152
1153                                         t1_decode_cblk(
1154                                                         t1,
1155                                                         cblk,
1156                                                         band->bandno,
1157                                                         tccp->roishift,
1158                                                         tccp->cblksty);
1159
1160                                         x = cblk->x0 - band->x0;
1161                                         y = cblk->y0 - band->y0;
1162                                         if (band->bandno & 1) {
1163                                                 opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1];
1164                                                 x += pres->x1 - pres->x0;
1165                                         }
1166                                         if (band->bandno & 2) {
1167                                                 opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1];
1168                                                 y += pres->y1 - pres->y0;
1169                                         }
1170
1171                                         datap=t1->data;
1172                                         cblk_w = t1->w;
1173                                         cblk_h = t1->h;
1174
1175                                         if (tccp->roishift) {
1176                                                 int thresh = 1 << tccp->roishift;
1177                                                 for (j = 0; j < cblk_h; ++j) {
1178                                                         for (i = 0; i < cblk_w; ++i) {
1179                                                                 int val = datap[(j * cblk_w) + i];
1180                                                                 int mag = abs(val);
1181                                                                 if (mag >= thresh) {
1182                                                                         mag >>= tccp->roishift;
1183                                                                         datap[(j * cblk_w) + i] = val < 0 ? -mag : mag;
1184                                                                 }
1185                                                         }
1186                                                 }
1187                                         }
1188
1189                                         tiledp=(void*)&tilec->data[(y * tile_w) + x];
1190                                         if (tccp->qmfbid == 1) {
1191                                                 for (j = 0; j < cblk_h; ++j) {
1192                                                         for (i = 0; i < cblk_w; ++i) {
1193                                                                 int tmp = datap[(j * cblk_w) + i];
1194                                                                 ((int*)tiledp)[(j * tile_w) + i] = tmp / 2;
1195                                                         }
1196                                                 }
1197                                         } else {                /* if (tccp->qmfbid == 0) */
1198                                                 for (j = 0; j < cblk_h; ++j) {
1199                                                         for (i = 0; i < cblk_w; ++i) {
1200                                                                 float tmp = datap[(j * cblk_w) + i] * band->stepsize;
1201                                                                 ((float*)tiledp)[(j * tile_w) + i] = tmp;
1202                                                         }
1203                                                 }
1204                                         }
1205                                         opj_free(cblk->data);
1206                                         opj_free(cblk->segs);
1207                                 } /* cblkno */
1208                                 opj_free(precinct->cblks.dec);
1209                         } /* precno */
1210                 } /* bandno */
1211         } /* resno */
1212 }
1213