blob: 14a44bea0e57f8d55ab1d1e01b0416f421e15d62 [file] [log] [blame]
/*
* 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;
}
}