1/*
2 * Copyright (c) 1999-2000 Image Power, Inc. and the University of
3 *   British Columbia.
4 * Copyright (c) 2001-2003 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 2 Encoder
66 *
67 * $Id: jpc_t2enc.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#include "jasper/jas_debug.h"
82
83#include "jpc_flt.h"
84#include "jpc_t2enc.h"
85#include "jpc_t2cod.h"
86#include "jpc_tagtree.h"
87#include "jpc_enc.h"
88#include "jpc_math.h"
89
90/******************************************************************************\
91* Code.
92\******************************************************************************/
93
94static int jpc_putcommacode(jpc_bitstream_t *out, int n)
95{
96    assert(n >= 0);
97
98    while (--n >= 0) {
99        if (jpc_bitstream_putbit(out, 1) == EOF) {
100            return -1;
101        }
102    }
103    if (jpc_bitstream_putbit(out, 0) == EOF) {
104        return -1;
105    }
106    return 0;
107}
108
109static int jpc_putnumnewpasses(jpc_bitstream_t *out, int n)
110{
111    int ret;
112
113    if (n <= 0) {
114        return -1;
115    } else if (n == 1) {
116        ret = jpc_bitstream_putbit(out, 0);
117    } else if (n == 2) {
118        ret = jpc_bitstream_putbits(out, 2, 2);
119    } else if (n <= 5) {
120        ret = jpc_bitstream_putbits(out, 4, 0xc | (n - 3));
121    } else if (n <= 36) {
122        ret = jpc_bitstream_putbits(out, 9, 0x1e0 | (n - 6));
123    } else if (n <= 164) {
124        ret = jpc_bitstream_putbits(out, 16, 0xff80 | (n - 37));
125    } else {
126        /* The standard has no provision for encoding a larger value.
127        In practice, however, it is highly unlikely that this
128        limitation will ever be encountered. */
129        return -1;
130    }
131
132    return (ret != EOF) ? 0 : (-1);
133}
134
135int jpc_enc_encpkts(jpc_enc_t *enc, jas_stream_t *out)
136{
137    jpc_enc_tile_t *tile;
138    jpc_pi_t *pi;
139
140    tile = enc->curtile;
141
142    jpc_init_t2state(enc, 0);
143    pi = tile->pi;
144    jpc_pi_init(pi);
145
146    if (!jpc_pi_next(pi)) {
147        for (;;) {
148            if (jpc_enc_encpkt(enc, out, jpc_pi_cmptno(pi), jpc_pi_rlvlno(pi),
149              jpc_pi_prcno(pi), jpc_pi_lyrno(pi))) {
150                return -1;
151            }
152            if (jpc_pi_next(pi)) {
153                break;
154            }
155        }
156    }
157
158    return 0;
159}
160
161int jpc_enc_encpkt(jpc_enc_t *enc, jas_stream_t *out, int compno, int lvlno, int prcno, int lyrno)
162{
163    jpc_enc_tcmpt_t *comp;
164    jpc_enc_rlvl_t *lvl;
165    jpc_enc_band_t *band;
166    jpc_enc_band_t *endbands;
167    jpc_enc_cblk_t *cblk;
168    jpc_enc_cblk_t *endcblks;
169    jpc_bitstream_t *outb;
170    jpc_enc_pass_t *pass;
171    jpc_enc_pass_t *startpass;
172    jpc_enc_pass_t *lastpass;
173    jpc_enc_pass_t *endpass;
174    jpc_enc_pass_t *endpasses;
175    int i;
176    int included;
177    int ret;
178    jpc_tagtreenode_t *leaf;
179    int n;
180    int t1;
181    int t2;
182    int adjust;
183    int maxadjust;
184    int datalen;
185    int numnewpasses;
186    int passcount;
187    jpc_enc_tile_t *tile;
188    jpc_enc_prc_t *prc;
189    jpc_enc_cp_t *cp;
190    jpc_ms_t *ms;
191
192    tile = enc->curtile;
193    cp = enc->cp;
194
195    if (cp->tcp.csty & JPC_COD_SOP) {
196        if (!(ms = jpc_ms_create(JPC_MS_SOP))) {
197            return -1;
198        }
199        ms->parms.sop.seqno = jpc_pi_getind(tile->pi);
200        if (jpc_putms(out, enc->cstate, ms)) {
201            return -1;
202        }
203        jpc_ms_destroy(ms);
204    }
205
206    outb = jpc_bitstream_sopen(out, "w+");
207    assert(outb);
208
209    if (jpc_bitstream_putbit(outb, 1) == EOF) {
210        return -1;
211    }
212    JAS_DBGLOG(10, ("\n"));
213    JAS_DBGLOG(10, ("present. "));
214
215    comp = &tile->tcmpts[compno];
216    lvl = &comp->rlvls[lvlno];
217    endbands = &lvl->bands[lvl->numbands];
218    for (band = lvl->bands; band != endbands; ++band) {
219        if (!band->data) {
220            continue;
221        }
222        prc = &band->prcs[prcno];
223        if (!prc->cblks) {
224            continue;
225        }
226
227        endcblks = &prc->cblks[prc->numcblks];
228        for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
229            if (!lyrno) {
230                leaf = jpc_tagtree_getleaf(prc->nlibtree, cblk - prc->cblks);
231                jpc_tagtree_setvalue(prc->nlibtree, leaf, cblk->numimsbs);
232            }
233            pass = cblk->curpass;
234            included = (pass && pass->lyrno == lyrno);
235            if (included && (!cblk->numencpasses)) {
236                assert(pass->lyrno == lyrno);
237                leaf = jpc_tagtree_getleaf(prc->incltree,
238                  cblk - prc->cblks);
239                jpc_tagtree_setvalue(prc->incltree, leaf, pass->lyrno);
240            }
241        }
242
243        endcblks = &prc->cblks[prc->numcblks];
244        for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
245            pass = cblk->curpass;
246            included = (pass && pass->lyrno == lyrno);
247            if (!cblk->numencpasses) {
248                leaf = jpc_tagtree_getleaf(prc->incltree,
249                  cblk - prc->cblks);
250                if (jpc_tagtree_encode(prc->incltree, leaf, lyrno
251                  + 1, outb) < 0) {
252                    return -1;
253                }
254            } else {
255                if (jpc_bitstream_putbit(outb, included) == EOF) {
256                    return -1;
257                }
258            }
259            JAS_DBGLOG(10, ("included=%d ", included));
260            if (!included) {
261                continue;
262            }
263            if (!cblk->numencpasses) {
264                i = 1;
265                leaf = jpc_tagtree_getleaf(prc->nlibtree, cblk - prc->cblks);
266                for (;;) {
267                    if ((ret = jpc_tagtree_encode(prc->nlibtree, leaf, i, outb)) < 0) {
268                        return -1;
269                    }
270                    if (ret) {
271                        break;
272                    }
273                    ++i;
274                }
275                assert(leaf->known_ && i == leaf->value_ + 1);
276            }
277
278            endpasses = &cblk->passes[cblk->numpasses];
279            startpass = pass;
280            endpass = startpass;
281            while (endpass != endpasses && endpass->lyrno == lyrno){
282                ++endpass;
283            }
284            numnewpasses = endpass - startpass;
285            if (jpc_putnumnewpasses(outb, numnewpasses)) {
286                return -1;
287            }
288            JAS_DBGLOG(10, ("numnewpasses=%d ", numnewpasses));
289
290            lastpass = endpass - 1;
291            n = startpass->start;
292            passcount = 1;
293            maxadjust = 0;
294            for (pass = startpass; pass != endpass; ++pass) {
295                if (pass->term || pass == lastpass) {
296                    datalen = pass->end - n;
297                    t1 = jpc_firstone(datalen) + 1;
298                    t2 = cblk->numlenbits + jpc_floorlog2(passcount);
299                    adjust = JAS_MAX(t1 - t2, 0);
300                    maxadjust = JAS_MAX(adjust, maxadjust);
301                    n += datalen;
302                    passcount = 1;
303                } else {
304                    ++passcount;
305                }
306            }
307            if (jpc_putcommacode(outb, maxadjust)) {
308                return -1;
309            }
310            cblk->numlenbits += maxadjust;
311
312            lastpass = endpass - 1;
313            n = startpass->start;
314            passcount = 1;
315            for (pass = startpass; pass != endpass; ++pass) {
316                if (pass->term || pass == lastpass) {
317                    datalen = pass->end - n;
318assert(jpc_firstone(datalen) < cblk->numlenbits + jpc_floorlog2(passcount));
319                    if (jpc_bitstream_putbits(outb, cblk->numlenbits + jpc_floorlog2(passcount), datalen) == EOF) {
320                        return -1;
321                    }
322                    n += datalen;
323                    passcount = 1;
324                } else {
325                    ++passcount;
326                }
327            }
328        }
329    }
330
331    jpc_bitstream_outalign(outb, 0);
332    jpc_bitstream_close(outb);
333
334    if (cp->tcp.csty & JPC_COD_EPH) {
335        if (!(ms = jpc_ms_create(JPC_MS_EPH))) {
336            return -1;
337        }
338        jpc_putms(out, enc->cstate, ms);
339        jpc_ms_destroy(ms);
340    }
341
342    comp = &tile->tcmpts[compno];
343    lvl = &comp->rlvls[lvlno];
344    endbands = &lvl->bands[lvl->numbands];
345    for (band = lvl->bands; band != endbands; ++band) {
346        if (!band->data) {
347            continue;
348        }
349        prc = &band->prcs[prcno];
350        if (!prc->cblks) {
351            continue;
352        }
353        endcblks = &prc->cblks[prc->numcblks];
354        for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
355            pass = cblk->curpass;
356
357            if (!pass) {
358                continue;
359            }
360            if (pass->lyrno != lyrno) {
361                assert(pass->lyrno < 0 || pass->lyrno > lyrno);
362                continue;
363            }
364
365            endpasses = &cblk->passes[cblk->numpasses];
366            startpass = pass;
367            endpass = startpass;
368            while (endpass != endpasses && endpass->lyrno == lyrno){
369                ++endpass;
370            }
371            lastpass = endpass - 1;
372            numnewpasses = endpass - startpass;
373
374            jas_stream_seek(cblk->stream, startpass->start, SEEK_SET);
375            assert(jas_stream_tell(cblk->stream) == startpass->start);
376            if (jas_stream_copy(out, cblk->stream, lastpass->end - startpass->start)) {
377                return -1;
378            }
379            cblk->curpass = (endpass != endpasses) ? endpass : 0;
380            cblk->numencpasses += numnewpasses;
381
382        }
383    }
384
385    return 0;
386}
387
388void jpc_save_t2state(jpc_enc_t *enc)
389{
390/* stream pos in embedded T1 stream may be wrong since not saved/restored! */
391
392    jpc_enc_tcmpt_t *comp;
393    jpc_enc_tcmpt_t *endcomps;
394    jpc_enc_rlvl_t *lvl;
395    jpc_enc_rlvl_t *endlvls;
396    jpc_enc_band_t *band;
397    jpc_enc_band_t *endbands;
398    jpc_enc_cblk_t *cblk;
399    jpc_enc_cblk_t *endcblks;
400    jpc_enc_tile_t *tile;
401    int prcno;
402    jpc_enc_prc_t *prc;
403
404    tile = enc->curtile;
405
406    endcomps = &tile->tcmpts[tile->numtcmpts];
407    for (comp = tile->tcmpts; comp != endcomps; ++comp) {
408        endlvls = &comp->rlvls[comp->numrlvls];
409        for (lvl = comp->rlvls; lvl != endlvls; ++lvl) {
410            if (!lvl->bands) {
411                continue;
412            }
413            endbands = &lvl->bands[lvl->numbands];
414            for (band = lvl->bands; band != endbands; ++band) {
415                if (!band->data) {
416                    continue;
417                }
418                for (prcno = 0, prc = band->prcs; prcno < lvl->numprcs; ++prcno, ++prc) {
419                    if (!prc->cblks) {
420                        continue;
421                    }
422                    jpc_tagtree_copy(prc->savincltree, prc->incltree);
423                    jpc_tagtree_copy(prc->savnlibtree, prc->nlibtree);
424                    endcblks = &prc->cblks[prc->numcblks];
425                    for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
426                        cblk->savedcurpass = cblk->curpass;
427                        cblk->savednumencpasses = cblk->numencpasses;
428                        cblk->savednumlenbits = cblk->numlenbits;
429                    }
430                }
431            }
432        }
433    }
434
435}
436
437void jpc_restore_t2state(jpc_enc_t *enc)
438{
439
440    jpc_enc_tcmpt_t *comp;
441    jpc_enc_tcmpt_t *endcomps;
442    jpc_enc_rlvl_t *lvl;
443    jpc_enc_rlvl_t *endlvls;
444    jpc_enc_band_t *band;
445    jpc_enc_band_t *endbands;
446    jpc_enc_cblk_t *cblk;
447    jpc_enc_cblk_t *endcblks;
448    jpc_enc_tile_t *tile;
449    int prcno;
450    jpc_enc_prc_t *prc;
451
452    tile = enc->curtile;
453
454    endcomps = &tile->tcmpts[tile->numtcmpts];
455    for (comp = tile->tcmpts; comp != endcomps; ++comp) {
456        endlvls = &comp->rlvls[comp->numrlvls];
457        for (lvl = comp->rlvls; lvl != endlvls; ++lvl) {
458            if (!lvl->bands) {
459                continue;
460            }
461            endbands = &lvl->bands[lvl->numbands];
462            for (band = lvl->bands; band != endbands; ++band) {
463                if (!band->data) {
464                    continue;
465                }
466                for (prcno = 0, prc = band->prcs; prcno < lvl->numprcs; ++prcno, ++prc) {
467                    if (!prc->cblks) {
468                        continue;
469                    }
470                    jpc_tagtree_copy(prc->incltree, prc->savincltree);
471                    jpc_tagtree_copy(prc->nlibtree, prc->savnlibtree);
472                    endcblks = &prc->cblks[prc->numcblks];
473                    for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
474                        cblk->curpass = cblk->savedcurpass;
475                        cblk->numencpasses = cblk->savednumencpasses;
476                        cblk->numlenbits = cblk->savednumlenbits;
477                    }
478                }
479            }
480        }
481    }
482}
483
484void jpc_init_t2state(jpc_enc_t *enc, int raflag)
485{
486/* It is assumed that band->numbps and cblk->numbps precomputed */
487
488    jpc_enc_tcmpt_t *comp;
489    jpc_enc_tcmpt_t *endcomps;
490    jpc_enc_rlvl_t *lvl;
491    jpc_enc_rlvl_t *endlvls;
492    jpc_enc_band_t *band;
493    jpc_enc_band_t *endbands;
494    jpc_enc_cblk_t *cblk;
495    jpc_enc_cblk_t *endcblks;
496    jpc_enc_pass_t *pass;
497    jpc_enc_pass_t *endpasses;
498    jpc_tagtreenode_t *leaf;
499    jpc_enc_tile_t *tile;
500    int prcno;
501    jpc_enc_prc_t *prc;
502
503    tile = enc->curtile;
504
505    endcomps = &tile->tcmpts[tile->numtcmpts];
506    for (comp = tile->tcmpts; comp != endcomps; ++comp) {
507        endlvls = &comp->rlvls[comp->numrlvls];
508        for (lvl = comp->rlvls; lvl != endlvls; ++lvl) {
509            if (!lvl->bands) {
510                continue;
511            }
512            endbands = &lvl->bands[lvl->numbands];
513            for (band = lvl->bands; band != endbands; ++band) {
514                if (!band->data) {
515                    continue;
516                }
517                for (prcno = 0, prc = band->prcs; prcno < lvl->numprcs; ++prcno, ++prc) {
518                    if (!prc->cblks) {
519                        continue;
520                    }
521                    jpc_tagtree_reset(prc->incltree);
522                    jpc_tagtree_reset(prc->nlibtree);
523                    endcblks = &prc->cblks[prc->numcblks];
524                    for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
525                        if (jas_stream_rewind(cblk->stream)) {
526                            assert(0);
527                        }
528                        cblk->curpass = (cblk->numpasses > 0) ? cblk->passes : 0;
529                        cblk->numencpasses = 0;
530                        cblk->numlenbits = 3;
531                        cblk->numimsbs = band->numbps - cblk->numbps;
532                        assert(cblk->numimsbs >= 0);
533                        leaf = jpc_tagtree_getleaf(prc->nlibtree, cblk - prc->cblks);
534                        jpc_tagtree_setvalue(prc->nlibtree, leaf, cblk->numimsbs);
535
536                        if (raflag) {
537                            endpasses = &cblk->passes[cblk->numpasses];
538                            for (pass = cblk->passes; pass != endpasses; ++pass) {
539                                pass->lyrno = -1;
540                                pass->lyrno = 0;
541                            }
542                        }
543                    }
544                }
545            }
546        }
547    }
548
549}
550
551jpc_pi_t *jpc_enc_pi_create(jpc_enc_cp_t *cp, jpc_enc_tile_t *tile)
552{
553    jpc_pi_t *pi;
554    int compno;
555    jpc_picomp_t *picomp;
556    jpc_pirlvl_t *pirlvl;
557    jpc_enc_tcmpt_t *tcomp;
558    int rlvlno;
559    jpc_enc_rlvl_t *rlvl;
560    int prcno;
561    int *prclyrno;
562
563    if (!(pi = jpc_pi_create0())) {
564        return 0;
565    }
566    pi->pktno = -1;
567    pi->numcomps = cp->numcmpts;
568    if (!(pi->picomps = jas_alloc2(pi->numcomps, sizeof(jpc_picomp_t)))) {
569        jpc_pi_destroy(pi);
570        return 0;
571    }
572    for (compno = 0, picomp = pi->picomps; compno < pi->numcomps; ++compno,
573      ++picomp) {
574        picomp->pirlvls = 0;
575    }
576
577    for (compno = 0, tcomp = tile->tcmpts, picomp = pi->picomps;
578      compno < pi->numcomps; ++compno, ++tcomp, ++picomp) {
579        picomp->numrlvls = tcomp->numrlvls;
580        if (!(picomp->pirlvls = jas_alloc2(picomp->numrlvls,
581          sizeof(jpc_pirlvl_t)))) {
582            jpc_pi_destroy(pi);
583            return 0;
584        }
585        for (rlvlno = 0, pirlvl = picomp->pirlvls; rlvlno <
586          picomp->numrlvls; ++rlvlno, ++pirlvl) {
587            pirlvl->prclyrnos = 0;
588        }
589        for (rlvlno = 0, pirlvl = picomp->pirlvls, rlvl = tcomp->rlvls;
590          rlvlno < picomp->numrlvls; ++rlvlno, ++pirlvl, ++rlvl) {
591/* XXX sizeof(long) should be sizeof different type */
592            pirlvl->numprcs = rlvl->numprcs;
593            if (rlvl->numprcs) {
594                if (!(pirlvl->prclyrnos = jas_alloc2(pirlvl->numprcs,
595                  sizeof(long)))) {
596                    jpc_pi_destroy(pi);
597                    return 0;
598                }
599            } else {
600                pirlvl->prclyrnos = 0;
601            }
602        }
603    }
604
605    pi->maxrlvls = 0;
606    for (compno = 0, tcomp = tile->tcmpts, picomp = pi->picomps;
607      compno < pi->numcomps; ++compno, ++tcomp, ++picomp) {
608        picomp->hsamp = cp->ccps[compno].sampgrdstepx;
609        picomp->vsamp = cp->ccps[compno].sampgrdstepy;
610        for (rlvlno = 0, pirlvl = picomp->pirlvls, rlvl = tcomp->rlvls;
611          rlvlno < picomp->numrlvls; ++rlvlno, ++pirlvl, ++rlvl) {
612            pirlvl->prcwidthexpn = rlvl->prcwidthexpn;
613            pirlvl->prcheightexpn = rlvl->prcheightexpn;
614            for (prcno = 0, prclyrno = pirlvl->prclyrnos;
615              prcno < pirlvl->numprcs; ++prcno, ++prclyrno) {
616                *prclyrno = 0;
617            }
618            pirlvl->numhprcs = rlvl->numhprcs;
619        }
620        if (pi->maxrlvls < tcomp->numrlvls) {
621            pi->maxrlvls = tcomp->numrlvls;
622        }
623    }
624
625    pi->numlyrs = tile->numlyrs;
626    pi->xstart = tile->tlx;
627    pi->ystart = tile->tly;
628    pi->xend = tile->brx;
629    pi->yend = tile->bry;
630
631    pi->picomp = 0;
632    pi->pirlvl = 0;
633    pi->x = 0;
634    pi->y = 0;
635    pi->compno = 0;
636    pi->rlvlno = 0;
637    pi->prcno = 0;
638    pi->lyrno = 0;
639    pi->xstep = 0;
640    pi->ystep = 0;
641
642    pi->pchgno = -1;
643
644    pi->defaultpchg.prgord = tile->prg;
645    pi->defaultpchg.compnostart = 0;
646    pi->defaultpchg.compnoend = pi->numcomps;
647    pi->defaultpchg.rlvlnostart = 0;
648    pi->defaultpchg.rlvlnoend = pi->maxrlvls;
649    pi->defaultpchg.lyrnoend = pi->numlyrs;
650    pi->pchg = 0;
651
652    pi->valid = 0;
653
654    return pi;
655}
656