2 * Copyright (c) 2001-2003, David Janssens
\r
3 * Copyright (c) 2002-2003, Yannick Verschueren
\r
4 * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
\r
5 * Copyright (c) 2005, Hervé Drolon, FreeImage Team
\r
6 * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
\r
7 * All rights reserved.
\r
9 * Redistribution and use in source and binary forms, with or without
\r
10 * modification, are permitted provided that the following conditions
\r
12 * 1. Redistributions of source code must retain the above copyright
\r
13 * notice, this list of conditions and the following disclaimer.
\r
14 * 2. Redistributions in binary form must reproduce the above copyright
\r
15 * notice, this list of conditions and the following disclaimer in the
\r
16 * documentation and/or other materials provided with the distribution.
\r
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
\r
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
\r
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
\r
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
\r
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
\r
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
\r
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
\r
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
\r
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
\r
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
\r
28 * POSSIBILITY OF SUCH DAMAGE.
\r
31 #include "opj_includes.h"
\r
33 /** @defgroup PI PI - Implementation of a packet iterator */
\r
36 /** @name Local static functions */
\r
40 Get next packet in layer-resolution-component-precinct order.
\r
41 @param pi packet iterator to modify
\r
42 @return returns false if pi pointed to the last packet or else returns true
\r
44 static bool pi_next_lrcp(opj_pi_iterator_t * pi);
\r
46 Get next packet in resolution-layer-component-precinct order.
\r
47 @param pi packet iterator to modify
\r
48 @return returns false if pi pointed to the last packet or else returns true
\r
50 static bool pi_next_rlcp(opj_pi_iterator_t * pi);
\r
52 Get next packet in resolution-precinct-component-layer order.
\r
53 @param pi packet iterator to modify
\r
54 @return returns false if pi pointed to the last packet or else returns true
\r
56 static bool pi_next_rpcl(opj_pi_iterator_t * pi);
\r
58 Get next packet in precinct-component-resolution-layer order.
\r
59 @param pi packet iterator to modify
\r
60 @return returns false if pi pointed to the last packet or else returns true
\r
62 static bool pi_next_pcrl(opj_pi_iterator_t * pi);
\r
64 Get next packet in component-precinct-resolution-layer order.
\r
65 @param pi packet iterator to modify
\r
66 @return returns false if pi pointed to the last packet or else returns true
\r
68 static bool pi_next_cprl(opj_pi_iterator_t * pi);
\r
75 ==========================================================
\r
77 ==========================================================
\r
80 static bool pi_next_lrcp(opj_pi_iterator_t * pi) {
\r
81 opj_pi_comp_t *comp = NULL;
\r
82 opj_pi_resolution_t *res = NULL;
\r
86 comp = &pi->comps[pi->compno];
\r
87 res = &comp->resolutions[pi->resno];
\r
93 for (pi->layno = 0; pi->layno < pi->poc.layno1; pi->layno++) {
\r
94 for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1;
\r
96 for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) {
\r
97 comp = &pi->comps[pi->compno];
\r
98 if (pi->resno >= comp->numresolutions) {
\r
101 res = &comp->resolutions[pi->resno];
\r
102 for (pi->precno = 0; pi->precno < res->pw * res->ph; pi->precno++) {
\r
103 index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
\r
104 if (!pi->include[index]) {
\r
105 pi->include[index] = 1;
\r
117 static bool pi_next_rlcp(opj_pi_iterator_t * pi) {
\r
118 opj_pi_comp_t *comp = NULL;
\r
119 opj_pi_resolution_t *res = NULL;
\r
123 comp = &pi->comps[pi->compno];
\r
124 res = &comp->resolutions[pi->resno];
\r
130 for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) {
\r
131 for (pi->layno = 0; pi->layno < pi->poc.layno1; pi->layno++) {
\r
132 for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) {
\r
133 comp = &pi->comps[pi->compno];
\r
134 if (pi->resno >= comp->numresolutions) {
\r
137 res = &comp->resolutions[pi->resno];
\r
138 for (pi->precno = 0; pi->precno < res->pw * res->ph; pi->precno++) {
\r
139 index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
\r
140 if (!pi->include[index]) {
\r
141 pi->include[index] = 1;
\r
153 static bool pi_next_rpcl(opj_pi_iterator_t * pi) {
\r
154 opj_pi_comp_t *comp = NULL;
\r
155 opj_pi_resolution_t *res = NULL;
\r
165 for (compno = 0; compno < pi->numcomps; compno++) {
\r
166 comp = &pi->comps[compno];
\r
167 for (resno = 0; resno < comp->numresolutions; resno++) {
\r
169 res = &comp->resolutions[resno];
\r
170 dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno));
\r
171 dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno));
\r
172 pi->dx = !pi->dx ? dx : int_min(pi->dx, dx);
\r
173 pi->dy = !pi->dy ? dy : int_min(pi->dy, dy);
\r
178 for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) {
\r
179 for (pi->y = pi->ty0; pi->y < pi->ty1; pi->y += pi->dy - (pi->y % pi->dy)) {
\r
180 for (pi->x = pi->tx0; pi->x < pi->tx1; pi->x += pi->dx - (pi->x % pi->dx)) {
\r
181 for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) {
\r
187 comp = &pi->comps[pi->compno];
\r
188 if (pi->resno >= comp->numresolutions) {
\r
191 res = &comp->resolutions[pi->resno];
\r
192 levelno = comp->numresolutions - 1 - pi->resno;
\r
193 trx0 = int_ceildiv(pi->tx0, comp->dx << levelno);
\r
194 try0 = int_ceildiv(pi->ty0, comp->dy << levelno);
\r
195 trx1 = int_ceildiv(pi->tx1, comp->dx << levelno);
\r
196 try1 = int_ceildiv(pi->ty1, comp->dy << levelno);
\r
197 rpx = res->pdx + levelno;
\r
198 rpy = res->pdy + levelno;
\r
199 if ((!(pi->x % (comp->dx << rpx) == 0) || (pi->x == pi->tx0 && (trx0 << levelno) % (1 << rpx)))) {
\r
202 if ((!(pi->y % (comp->dy << rpy) == 0) || (pi->y == pi->ty0 && (try0 << levelno) % (1 << rpx)))) {
\r
206 if ((res->pw==0)||(res->pw==0)) continue;
\r
208 if ((trx0==trx1)||(try0==try1)) continue;
\r
210 prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx)
\r
211 - int_floordivpow2(trx0, res->pdx);
\r
212 prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy)
\r
213 - int_floordivpow2(try0, res->pdy);
\r
214 pi->precno = prci + prcj * res->pw;
\r
215 for (pi->layno = 0; pi->layno < pi->poc.layno1; pi->layno++) {
\r
216 index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
\r
217 if (!pi->include[index]) {
\r
218 pi->include[index] = 1;
\r
231 static bool pi_next_pcrl(opj_pi_iterator_t * pi) {
\r
232 opj_pi_comp_t *comp = NULL;
\r
233 opj_pi_resolution_t *res = NULL;
\r
237 comp = &pi->comps[pi->compno];
\r
244 for (compno = 0; compno < pi->numcomps; compno++) {
\r
245 comp = &pi->comps[compno];
\r
246 for (resno = 0; resno < comp->numresolutions; resno++) {
\r
248 res = &comp->resolutions[resno];
\r
249 dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno));
\r
250 dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno));
\r
251 pi->dx = !pi->dx ? dx : int_min(pi->dx, dx);
\r
252 pi->dy = !pi->dy ? dy : int_min(pi->dy, dy);
\r
257 for (pi->y = pi->ty0; pi->y < pi->ty1; pi->y += pi->dy - (pi->y % pi->dy)) {
\r
258 for (pi->x = pi->tx0; pi->x < pi->tx1; pi->x += pi->dx - (pi->x % pi->dx)) {
\r
259 for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) {
\r
260 comp = &pi->comps[pi->compno];
\r
261 for (pi->resno = pi->poc.resno0; pi->resno < int_min(pi->poc.resno1, comp->numresolutions); pi->resno++) {
\r
267 res = &comp->resolutions[pi->resno];
\r
268 levelno = comp->numresolutions - 1 - pi->resno;
\r
269 trx0 = int_ceildiv(pi->tx0, comp->dx << levelno);
\r
270 try0 = int_ceildiv(pi->ty0, comp->dy << levelno);
\r
271 trx1 = int_ceildiv(pi->tx1, comp->dx << levelno);
\r
272 try1 = int_ceildiv(pi->ty1, comp->dy << levelno);
\r
273 rpx = res->pdx + levelno;
\r
274 rpy = res->pdy + levelno;
\r
275 if ((!(pi->x % (comp->dx << rpx) == 0) || (pi->x == pi->tx0 && (trx0 << levelno) % (1 << rpx)))) {
\r
278 if ((!(pi->y % (comp->dy << rpy) == 0) || (pi->y == pi->ty0 && (try0 << levelno) % (1 << rpx)))) {
\r
282 if ((res->pw==0)||(res->pw==0)) continue;
\r
284 if ((trx0==trx1)||(try0==try1)) continue;
\r
286 prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx)
\r
287 - int_floordivpow2(trx0, res->pdx);
\r
288 prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy)
\r
289 - int_floordivpow2(try0, res->pdy);
\r
290 pi->precno = prci + prcj * res->pw;
\r
291 for (pi->layno = 0; pi->layno < pi->poc.layno1; pi->layno++) {
\r
292 index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
\r
293 if (!pi->include[index]) {
\r
294 pi->include[index] = 1;
\r
307 static bool pi_next_cprl(opj_pi_iterator_t * pi) {
\r
308 opj_pi_comp_t *comp = NULL;
\r
309 opj_pi_resolution_t *res = NULL;
\r
313 comp = &pi->comps[pi->compno];
\r
319 for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) {
\r
321 comp = &pi->comps[pi->compno];
\r
324 for (resno = 0; resno < comp->numresolutions; resno++) {
\r
326 res = &comp->resolutions[resno];
\r
327 dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno));
\r
328 dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno));
\r
329 pi->dx = !pi->dx ? dx : int_min(pi->dx, dx);
\r
330 pi->dy = !pi->dy ? dy : int_min(pi->dy, dy);
\r
332 for (pi->y = pi->ty0; pi->y < pi->ty1; pi->y += pi->dy - (pi->y % pi->dy)) {
\r
333 for (pi->x = pi->tx0; pi->x < pi->tx1; pi->x += pi->dx - (pi->x % pi->dx)) {
\r
334 for (pi->resno = pi->poc.resno0; pi->resno < int_min(pi->poc.resno1, comp->numresolutions); pi->resno++) {
\r
340 res = &comp->resolutions[pi->resno];
\r
341 levelno = comp->numresolutions - 1 - pi->resno;
\r
342 trx0 = int_ceildiv(pi->tx0, comp->dx << levelno);
\r
343 try0 = int_ceildiv(pi->ty0, comp->dy << levelno);
\r
344 trx1 = int_ceildiv(pi->tx1, comp->dx << levelno);
\r
345 try1 = int_ceildiv(pi->ty1, comp->dy << levelno);
\r
346 rpx = res->pdx + levelno;
\r
347 rpy = res->pdy + levelno;
\r
348 if ((!(pi->x % (comp->dx << rpx) == 0) || (pi->x == pi->tx0 && (trx0 << levelno) % (1 << rpx)))) {
\r
351 if ((!(pi->y % (comp->dy << rpy) == 0) || (pi->y == pi->ty0 && (try0 << levelno) % (1 << rpx)))) {
\r
355 if ((res->pw==0)||(res->pw==0)) continue;
\r
357 if ((trx0==trx1)||(try0==try1)) continue;
\r
359 prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx)
\r
360 - int_floordivpow2(trx0, res->pdx);
\r
361 prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy)
\r
362 - int_floordivpow2(try0, res->pdy);
\r
363 pi->precno = prci + prcj * res->pw;
\r
364 for (pi->layno = 0; pi->layno < pi->poc.layno1; pi->layno++) {
\r
365 index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
\r
366 if (!pi->include[index]) {
\r
367 pi->include[index] = 1;
\r
381 ==========================================================
\r
382 Packet iterator interface
\r
383 ==========================================================
\r
386 opj_pi_iterator_t *pi_create(opj_image_t *image, opj_cp_t *cp, int tileno) {
\r
388 int compno, resno, pino;
\r
390 opj_pi_iterator_t *pi = NULL;
\r
391 opj_tcp_t *tcp = NULL;
\r
392 opj_tccp_t *tccp = NULL;
\r
395 tcp = &cp->tcps[tileno];
\r
397 array_size = (tcp->numpocs + 1) * sizeof(opj_pi_iterator_t);
\r
398 pi = (opj_pi_iterator_t *) opj_malloc(array_size);
\r
400 /* TODO: throw an error */
\r
404 for (pino = 0; pino < tcp->numpocs + 1; pino++) { /* change */
\r
405 p = tileno % cp->tw;
\r
406 q = tileno / cp->tw;
\r
408 pi[pino].tx0 = int_max(cp->tx0 + p * cp->tdx, image->x0);
\r
409 pi[pino].ty0 = int_max(cp->ty0 + q * cp->tdy, image->y0);
\r
410 pi[pino].tx1 = int_min(cp->tx0 + (p + 1) * cp->tdx, image->x1);
\r
411 pi[pino].ty1 = int_min(cp->ty0 + (q + 1) * cp->tdy, image->y1);
\r
412 pi[pino].numcomps = image->numcomps;
\r
414 array_size = image->numcomps * sizeof(opj_pi_comp_t);
\r
415 pi[pino].comps = (opj_pi_comp_t *) opj_malloc(array_size);
\r
416 if(!pi[pino].comps) {
\r
417 /* TODO: throw an error */
\r
418 pi_destroy(pi, cp, tileno);
\r
421 memset(pi[pino].comps, 0, array_size);
\r
423 for (compno = 0; compno < pi->numcomps; compno++) {
\r
424 int tcx0, tcy0, tcx1, tcy1;
\r
425 opj_pi_comp_t *comp = &pi[pino].comps[compno];
\r
426 tccp = &tcp->tccps[compno];
\r
427 comp->dx = image->comps[compno].dx;
\r
428 comp->dy = image->comps[compno].dy;
\r
429 comp->numresolutions = tccp->numresolutions;
\r
431 array_size = comp->numresolutions * sizeof(opj_pi_resolution_t);
\r
432 comp->resolutions = (opj_pi_resolution_t *) opj_malloc(array_size);
\r
433 if(!comp->resolutions) {
\r
434 /* TODO: throw an error */
\r
435 pi_destroy(pi, cp, tileno);
\r
439 tcx0 = int_ceildiv(pi->tx0, comp->dx);
\r
440 tcy0 = int_ceildiv(pi->ty0, comp->dy);
\r
441 tcx1 = int_ceildiv(pi->tx1, comp->dx);
\r
442 tcy1 = int_ceildiv(pi->ty1, comp->dy);
\r
443 if (comp->numresolutions > maxres) {
\r
444 maxres = comp->numresolutions;
\r
447 for (resno = 0; resno < comp->numresolutions; resno++) {
\r
449 int rx0, ry0, rx1, ry1;
\r
450 int px0, py0, px1, py1;
\r
451 opj_pi_resolution_t *res = &comp->resolutions[resno];
\r
452 if (tccp->csty & J2K_CCP_CSTY_PRT) {
\r
453 res->pdx = tccp->prcw[resno];
\r
454 res->pdy = tccp->prch[resno];
\r
459 levelno = comp->numresolutions - 1 - resno;
\r
460 rx0 = int_ceildivpow2(tcx0, levelno);
\r
461 ry0 = int_ceildivpow2(tcy0, levelno);
\r
462 rx1 = int_ceildivpow2(tcx1, levelno);
\r
463 ry1 = int_ceildivpow2(tcy1, levelno);
\r
464 px0 = int_floordivpow2(rx0, res->pdx) << res->pdx;
\r
465 py0 = int_floordivpow2(ry0, res->pdy) << res->pdy;
\r
466 px1 = int_ceildivpow2(rx1, res->pdx) << res->pdx;
\r
467 py1 = int_ceildivpow2(ry1, res->pdy) << res->pdy;
\r
468 res->pw = (rx0==rx1)?0:((px1 - px0) >> res->pdx);
\r
469 res->ph = (ry0==ry1)?0:((py1 - py0) >> res->pdy);
\r
473 tccp = &tcp->tccps[0];
\r
474 pi[pino].step_p = 1;
\r
475 pi[pino].step_c = 100 * pi[pino].step_p;
\r
476 pi[pino].step_r = image->numcomps * pi[pino].step_c;
\r
477 pi[pino].step_l = maxres * pi[pino].step_r;
\r
480 array_size = image->numcomps * maxres * tcp->numlayers * 100 * sizeof(short int);
\r
481 pi[pino].include = (short int *) opj_malloc(array_size);
\r
482 if(!pi[pino].include) {
\r
483 /* TODO: throw an error */
\r
484 pi_destroy(pi, cp, tileno);
\r
489 pi[pino].include = pi[pino - 1].include;
\r
492 if (tcp->POC == 0) {
\r
493 pi[pino].first = 1;
\r
494 pi[pino].poc.resno0 = 0;
\r
495 pi[pino].poc.compno0 = 0;
\r
496 pi[pino].poc.layno1 = tcp->numlayers;
\r
497 pi[pino].poc.resno1 = maxres;
\r
498 pi[pino].poc.compno1 = image->numcomps;
\r
499 pi[pino].poc.prg = tcp->prg;
\r
501 pi[pino].first = 1;
\r
502 pi[pino].poc.resno0 = tcp->pocs[pino].resno0;
\r
503 pi[pino].poc.compno0 = tcp->pocs[pino].compno0;
\r
504 pi[pino].poc.layno1 = tcp->pocs[pino].layno1;
\r
505 pi[pino].poc.resno1 = tcp->pocs[pino].resno1;
\r
506 pi[pino].poc.compno1 = tcp->pocs[pino].compno1;
\r
507 pi[pino].poc.prg = tcp->pocs[pino].prg;
\r
514 void pi_destroy(opj_pi_iterator_t *pi, opj_cp_t *cp, int tileno) {
\r
516 opj_tcp_t *tcp = &cp->tcps[tileno];
\r
518 for (pino = 0; pino < tcp->numpocs + 1; pino++) {
\r
519 if(pi[pino].comps) {
\r
520 for (compno = 0; compno < pi->numcomps; compno++) {
\r
521 opj_pi_comp_t *comp = &pi[pino].comps[compno];
\r
522 if(comp->resolutions) {
\r
523 opj_free(comp->resolutions);
\r
526 opj_free(pi[pino].comps);
\r
530 opj_free(pi->include);
\r
536 bool pi_next(opj_pi_iterator_t * pi) {
\r
537 switch (pi->poc.prg) {
\r
539 return pi_next_lrcp(pi);
\r
541 return pi_next_rlcp(pi);
\r
543 return pi_next_rpcl(pi);
\r
545 return pi_next_pcrl(pi);
\r
547 return pi_next_cprl(pi);
\r