/* * Copyright (c) 2001-2002, David Janssens * Copyright (c) 2003, Yannick Verschueren * Copyright (c) 2003, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "t2.h" #include "tcd.h" #include "bio.h" #include "j2k.h" #include "pi.h" #include "tgt.h" #include "int.h" #include "cio.h" #include #include #include #include #define RESTART 0x04 extern jmp_buf j2k_error; int t2_getcommacode() { int n; for (n=0; bio_read(1); n++) {} return n; } int t2_getnumpasses() { int n; if (!bio_read(1)) return 1; if (!bio_read(1)) return 2; if ((n=bio_read(2))!=3) return 3+n; if ((n=bio_read(5))!=31) return 6+n; return 37+bio_read(7); } void t2_init_seg(tcd_seg_t *seg, int cblksty) { seg->numpasses=0; seg->len=0; seg->maxpasses=cblksty&J2K_CCP_CBLKSTY_TERMALL?1:100; } int t2_decode_packet(unsigned char *src, int len, tcd_tile_t *tile, j2k_cp_t * cp, j2k_tcp_t *tcp, int compno, int resno, int precno, int layno, info_layer_t *layer_Idx) { int bandno, cblkno; tcd_tilecomp_t *tilec = &tile->comps[compno]; tcd_resolution_t *res = &tilec->resolutions[resno]; unsigned char *c = src; unsigned char *d = c; int e; int present; if (layno == 0) { for (bandno = 0; bandno < res->numbands; bandno++) { tcd_band_t *band = &res->bands[bandno]; tcd_precinct_t *prc = &band->precincts[precno]; tgt_reset(prc->incltree); tgt_reset(prc->imsbtree); for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { tcd_cblk_t *cblk = &prc->cblks[cblkno]; cblk->numsegs = 0; } } } /* INDEX */ layer_Idx->len_header = 0; /* When the marker PPT/PPM is used the packet header are store in PPT/PPM marker This part deal with this caracteristic step 1: Read packet header in the saved structure step 2: (futher) return to codestream for decoding */ if (cp->ppm == 1) /* PPM */ { c = cp->ppm_data; d = c; bio_init_dec(c, 1000); } else { if (tcp->ppt == 1) /* PPT */ { c = tcp->ppt_data; d = c; bio_init_dec(c, 1000); } else /* Normal Case */ { if (tcp->csty & J2K_CP_CSTY_SOP) { if ((*c) != 255 || (*(c+1) != 145)) {printf("Error : expected SOP marker [1]!!!\n");} c += 6; } bio_init_dec(c, src + len - c); layer_Idx->len_header = -6; } } present = bio_read(1); if (!present) { bio_inalign(); /* Normal case */ c += bio_numbytes(); if (tcp->csty & J2K_CP_CSTY_EPH) { if ((*c) != 255 || (*(c+1) != 146)) {printf("Error : expected EPH marker [1]!!!\n");} c += 2; } /* INDEX */ layer_Idx->len_header += (c-d); /* PPT and PPM dealing */ if (cp->ppm == 1) /* PPM */ { cp->ppm_data = c; return 0; } if (tcp->ppt == 1) /* PPT */ { tcp->ppt_data = c; return 0; } return c - src; } for (bandno=0; bandnonumbands; bandno++) { tcd_band_t *band = &res->bands[bandno]; tcd_precinct_t *prc = &band->precincts[precno]; for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { int included, increment, n; tcd_cblk_t *cblk = &prc->cblks[cblkno]; tcd_seg_t *seg; if (!cblk->numsegs) { included = tgt_decode(prc->incltree, cblkno, layno+1); } else { included = bio_read(1); } if (!included) { cblk->numnewpasses = 0; continue; } if (!cblk->numsegs) { int i, numimsbs; for (i = 0; !tgt_decode(prc->imsbtree, cblkno, i); i++) {} numimsbs = i-1; cblk->numbps = band->numbps - numimsbs; cblk->numlenbits = 3; } cblk->numnewpasses = t2_getnumpasses(); increment = t2_getcommacode(); cblk->numlenbits += increment; if (!cblk->numsegs) { seg = &cblk->segs[0]; t2_init_seg(seg, tcp->tccps[compno].cblksty); } else { seg = &cblk->segs[cblk->numsegs - 1]; if (seg->numpasses == seg->maxpasses) { t2_init_seg(++seg, tcp->tccps[compno].cblksty); } } n = cblk->numnewpasses; do { seg->numnewpasses = int_min(seg->maxpasses-seg->numpasses, n); seg->newlen = bio_read(cblk->numlenbits + int_floorlog2(seg->numnewpasses)); n -= seg->numnewpasses; if (n > 0) { t2_init_seg(++seg, tcp->tccps[compno].cblksty); } } while (n > 0); } } if(bio_inalign()) return -999; c += bio_numbytes(); if (tcp->csty & J2K_CP_CSTY_EPH) { /* EPH marker */ if ((*c) != 255 || (*(c+1) != 146)) {printf("Error : expected EPH marker [2]!!!\n"); } c += 2; } /* INDEX */ layer_Idx->len_header += (c-d); /* PPT Step 2 : see above for details */ if (cp->ppm == 1) { cp->ppm_data = c; /* Update pointer */ /* INDEX */ layer_Idx->len_header = c-d; c = src; d = c; if (tcp->csty & J2K_CP_CSTY_SOP) { if ((*c) != 255 || (*(c+1) != 145)) {printf("Error : expected SOP marker [2] !!!\n"); } c += 6; } bio_init_dec(c, src + len - c); } else { if (tcp->ppt == 1) { tcp->ppt_data = c; /* Update pointer */ /* INDEX */ layer_Idx->len_header = c-d; c = src; d = c; if (tcp->csty & J2K_CP_CSTY_SOP) /* SOP marker */ { if ((*c) != 255 || (*(c+1) != 145)) {printf("Error : expected SOP marker [2] !!!\n"); } c += 6; } bio_init_dec(c, src + len - c); } } for (bandno = 0; bandno < res->numbands; bandno++) { tcd_band_t *band = &res->bands[bandno]; tcd_precinct_t *prc = &band->precincts[precno]; for (cblkno = 0; cblkno < prc->cw*prc->ch; cblkno++) { tcd_cblk_t *cblk = &prc->cblks[cblkno]; tcd_seg_t *seg; if (!cblk->numnewpasses) continue; if (!cblk->numsegs) { seg = &cblk->segs[cblk->numsegs++]; cblk->len = 0; } else { seg = &cblk->segs[cblk->numsegs-1]; if (seg->numpasses == seg->maxpasses) { seg++; cblk->numsegs++; } } do { if (c + seg->newlen > src + len) return -999; memcpy(cblk->data + cblk->len, c, seg->newlen); if (seg->numpasses == 0) { seg->data = cblk->data + cblk->len; } c += seg->newlen; cblk->len += seg->newlen; seg->len += seg->newlen; seg->numpasses += seg->numnewpasses; cblk->numnewpasses -= seg->numnewpasses; if (cblk->numnewpasses > 0) { seg++; cblk->numsegs++; } } while (cblk->numnewpasses > 0); } } /* */ e = c-d; layer_Idx->len = e; /* */ return c-src; } void t2_init_info_packets(info_image_t *img, j2k_cp_t *cp) { int compno, tileno, resno, precno, layno; for(compno = 0; compno < img->Comp; compno++) { for(tileno = 0; tileno < img->tw*img->th; tileno++) { info_tile_t *tile_Idx = &img->tile[tileno]; info_compo_t *compo_Idx = &tile_Idx->compo[compno]; for(resno = 0; resno < img->Decomposition + 1 ; resno++) { info_reso_t *reso_Idx = &compo_Idx->reso[resno]; for (precno = 0; precno < img->tile[tileno].pw * img->tile[tileno].ph; precno++) { info_prec_t *prec_Idx = &reso_Idx->prec[precno]; for(layno = 0; layno < img->Layer ; layno++) { info_layer_t *layer_Idx = &prec_Idx->layer[layno]; layer_Idx->offset = 0; /* start position */ layer_Idx->len_header = 0; /* length */ } } } } } } int t2_decode_packets(unsigned char *src, int len, j2k_image_t *img, j2k_cp_t *cp, int tileno, tcd_tile_t *tile, info_image_t *imgg) { unsigned char *c = src; pi_iterator_t *pi; int pino, compno,e; int partno; info_tile_part_t *tile_part; int position; int length_read; info_tile_t *tile_Idx; info_compo_t *compo_Idx; info_reso_t *reso_Idx; info_prec_t *prec_Idx; info_layer_t *layer_Idx; t2_init_info_packets(imgg, cp); /* Initialize the packets information : LEN and OFFSET to 0 */ tile_Idx = &imgg->tile[tileno]; tile_Idx->num_packet = 0; pi = pi_create(img, cp, tileno); partno = 0; tile_part = &tile_Idx->tile_parts[partno]; position = tile_part->end_header + 1; length_read = 0; for (pino = 0; pino <= cp->tcps[tileno].numpocs; pino++) { while (pi_next(&pi[pino])) { compo_Idx = &tile_Idx->compo[pi[pino].compno]; reso_Idx = &compo_Idx->reso[pi[pino].resno]; prec_Idx = &reso_Idx->prec[pi[pino].precno]; layer_Idx = &prec_Idx->layer[pi[pino].layno]; layer_Idx->offset = position; layer_Idx->offset_header = position; e = t2_decode_packet(c, src+len-c, tile, cp, &cp->tcps[tileno], pi[pino].compno, pi[pino].resno, pi[pino].precno, pi[pino].layno,layer_Idx); if (e == -999) { break; } else c += e; position += e; /* Update position in case of multiple tile-parts for a tile >> */ length_read += e; if (length_read >= (tile_part->end_pos - tile_part->end_header)) { partno++; tile_part = &tile_Idx->tile_parts[partno]; position = tile_part->end_header + 1; length_read = 0; } /* << end_update */ tile_Idx->num_packet++; } // FREE space memory taken by pi for (compno = 0; compno < pi[pino].numcomps; compno++) { free(pi[pino].comps[compno].resolutions); } free(pi[pino].comps); } free(pi[0].include); free(pi); if (e==-999) return e; else { imgg->num_packet_max=int_max(imgg->num_packet_max,tile_Idx->num_packet); return c-src; } }