| /* |
| * 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 <stdio.h> |
| #include <setjmp.h> |
| #include <string.h> |
| #include <stdlib.h> |
| |
| #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; 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++) { |
| 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); |
| } |
| } |
| /* <INDEX> */ |
| e = c-d; |
| layer_Idx->len = e; |
| /* </INDEX> */ |
| |
| 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; |
| } |
| } |