/* * Copyright (c) 2001-2002, David Janssens * Copyright (c) 2002-2004, Yannick Verschueren * Copyright (c) 2002-2004, 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 "tcd.h" #include "int.h" #include "t1.h" #include "t2.h" #include "dwt.h" #include "mct.h" #include #include #include #include #include #include #include static tcd_image_t tcd_image; static j2k_image_t *tcd_img; static j2k_cp_t *tcd_cp; static tcd_tile_t *tcd_tile; static j2k_tcp_t *tcd_tcp; static int tcd_tileno; static tcd_tile_t *tile; static tcd_tilecomp_t *tilec; static tcd_resolution_t *res; static tcd_band_t *band; static tcd_precinct_t *prc; static tcd_cblk_t *cblk; extern jmp_buf j2k_error; void tcd_dump(tcd_image_t * img, int curtileno) { int tileno, compno, resno, bandno, precno, cblkno; /* fprintf(stderr, "image {\n"); */ fprintf(stderr, " tw=%d, th=%d x0 %d x1 %d\n", img->tw, img->th, tcd_img->x0, tcd_img->x1); for (tileno = 0; tileno < 1; tileno++) { tcd_tile_t *tile = &tcd_image.tiles[curtileno]; /* fprintf(stderr, " tile {\n"); */ /* fprintf(stderr, " x0=%d, y0=%d, x1=%d, y1=%d, numcomps=%d\n", tile->x0, tile->y0, tile->x1, tile->y1, tile->numcomps); */ for (compno = 0; compno < tile->numcomps; compno++) { tcd_tilecomp_t *tilec = &tile->comps[compno]; /* fprintf(stderr, " tilec {\n"); */ /* fprintf(stderr, " x0=%d, y0=%d, x1=%d, y1=%d, numresolutions=%d\n", tilec->x0, tilec->y0, tilec->x1, tilec->y1, tilec->numresolutions); */ for (resno = 0; resno < tilec->numresolutions; resno++) { tcd_resolution_t *res = &tilec->resolutions[resno]; /* fprintf(stderr, "\n res {\n"); */ /* fprintf(stderr, " x0=%d, y0=%d, x1=%d, y1=%d, pw=%d, ph=%d, numbands=%d\n", res->x0, res->y0, res->x1, res->y1, res->pw, res->ph, res->numbands); */ for (bandno = 0; bandno < res->numbands; bandno++) { tcd_band_t *band = &res->bands[bandno]; /* fprintf(stderr, " band {\n"); */ /* fprintf(stderr, " x0=%d, y0=%d, x1=%d, y1=%d, stepsize=%d, numbps=%d\n", band->x0, band->y0, band->x1, band->y1, band->stepsize, band->numbps); */ for (precno = 0; precno < res->pw * res->ph; precno++) { tcd_precinct_t *prec = &band->precincts[precno]; /* fprintf(stderr, " prec {\n"); */ /* fprintf(stderr, " x0=%d, y0=%d, x1=%d, y1=%d, cw=%d, ch=%d\n", prec->x0, prec->y0, prec->x1, prec->y1, prec->cw, prec->ch); */ for (cblkno = 0; cblkno < prec->cw * prec->ch; cblkno++) { /* tcd_cblk_t *cblk=&prec->cblks[cblkno]; */ /* fprintf(stderr, " cblk {\n"); */ /* fprintf(stderr, " x0=%d, y0=%d, x1=%d, y1=%d\n", cblk->x0, cblk->y0, cblk->x1, cblk->y1); */ /* fprintf(stderr, " }\n"); */ } /* fprintf(stderr, " }\n"); */ } /* fprintf(stderr, " }\n"); */ } /* fprintf(stderr, " }\n"); */ } /* fprintf(stderr, " }\n"); */ } /* fprintf(stderr, " }\n"); */ } /* fprintf(stderr, "}\n"); */ } void tcd_malloc_encode(j2k_image_t * img, j2k_cp_t * cp, int curtileno) { int tileno, compno, resno, bandno, precno, cblkno; tcd_img = img; tcd_cp = cp; tcd_image.tw = cp->tw; tcd_image.th = cp->th; tcd_image.tiles = (tcd_tile_t *) malloc(sizeof(tcd_tile_t)); for (tileno = 0; tileno < 1; tileno++) { j2k_tcp_t *tcp = &cp->tcps[curtileno]; int j; /* cfr p59 ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ int p = curtileno % cp->tw; /* si numerotation matricielle .. */ int q = curtileno / cp->tw; /* .. coordonnees de la tile (q,p) q pour ligne et p pour colonne */ /* tcd_tile_t *tile=&tcd_image.tiles[tileno]; */ tile = tcd_image.tiles; /* 4 borders of the tile rescale on the image if necessary */ tile->x0 = int_max(cp->tx0 + p * cp->tdx, img->x0); tile->y0 = int_max(cp->ty0 + q * cp->tdy, img->y0); tile->x1 = int_min(cp->tx0 + (p + 1) * cp->tdx, img->x1); tile->y1 = int_min(cp->ty0 + (q + 1) * cp->tdy, img->y1); tile->numcomps = img->numcomps; /* tile->PPT=img->PPT; */ /* Modification of the RATE >> */ for (j = 0; j < tcp->numlayers; j++) { tcp->rates[j] = ceil(tile->numcomps * (tile->x1 - tile->x0) * (tile->y1 - tile->y0) * img->comps[0].prec / (tcp->rates[j] * 8 * img->comps[0].dx * img->comps[0].dy)); if (j && tcp->rates[j] < tcp->rates[j - 1] + 10) { tcp->rates[j] = tcp->rates[j - 1] + 20; } else { if (!j && tcp->rates[j] < 30) tcp->rates[j] = 30; } } /* << Modification of the RATE */ tile->comps = (tcd_tilecomp_t *) malloc(img->numcomps * sizeof(tcd_tilecomp_t)); for (compno = 0; compno < tile->numcomps; compno++) { j2k_tccp_t *tccp = &tcp->tccps[compno]; /* tcd_tilecomp_t *tilec=&tile->comps[compno]; */ tilec = &tile->comps[compno]; /* border of each tile component (global) */ tilec->x0 = int_ceildiv(tile->x0, img->comps[compno].dx); tilec->y0 = int_ceildiv(tile->y0, img->comps[compno].dy); tilec->x1 = int_ceildiv(tile->x1, img->comps[compno].dx); tilec->y1 = int_ceildiv(tile->y1, img->comps[compno].dy); tilec->data = (int *) malloc((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0) * sizeof(int)); tilec->numresolutions = tccp->numresolutions; tilec->resolutions = (tcd_resolution_t *) malloc(tilec->numresolutions * sizeof(tcd_resolution_t)); for (resno = 0; resno < tilec->numresolutions; resno++) { int pdx, pdy; int levelno = tilec->numresolutions - 1 - resno; int tlprcxstart, tlprcystart, brprcxend, brprcyend; int tlcbgxstart, tlcbgystart, brcbgxend, brcbgyend; int cbgwidthexpn, cbgheightexpn; int cblkwidthexpn, cblkheightexpn; /* tcd_resolution_t *res=&tilec->resolutions[resno]; */ res = &tilec->resolutions[resno]; /* border for each resolution level (global) */ res->x0 = int_ceildivpow2(tilec->x0, levelno); res->y0 = int_ceildivpow2(tilec->y0, levelno); res->x1 = int_ceildivpow2(tilec->x1, levelno); res->y1 = int_ceildivpow2(tilec->y1, levelno); res->numbands = resno == 0 ? 1 : 3; /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */ if (tccp->csty & J2K_CCP_CSTY_PRT) { pdx = tccp->prcw[resno]; pdy = tccp->prch[resno]; } else { pdx = 15; pdy = 15; } /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ tlprcxstart = int_floordivpow2(res->x0, pdx) << pdx; tlprcystart = int_floordivpow2(res->y0, pdy) << pdy; brprcxend = int_ceildivpow2(res->x1, pdx) << pdx; brprcyend = int_ceildivpow2(res->y1, pdy) << pdy; res->pw = (brprcxend - tlprcxstart) >> pdx; res->ph = (brprcyend - tlprcystart) >> pdy; if (resno == 0) { tlcbgxstart = tlprcxstart; tlcbgystart = tlprcystart; brcbgxend = brprcxend; brcbgyend = brprcyend; cbgwidthexpn = pdx; cbgheightexpn = pdy; } else { tlcbgxstart = int_ceildivpow2(tlprcxstart, 1); tlcbgystart = int_ceildivpow2(tlprcystart, 1); brcbgxend = int_ceildivpow2(brprcxend, 1); brcbgyend = int_ceildivpow2(brprcyend, 1); cbgwidthexpn = pdx - 1; cbgheightexpn = pdy - 1; } cblkwidthexpn = int_min(tccp->cblkw, cbgwidthexpn); cblkheightexpn = int_min(tccp->cblkh, cbgheightexpn); for (bandno = 0; bandno < res->numbands; bandno++) { int x0b, y0b, i; int gain, numbps; j2k_stepsize_t *ss; band = &res->bands[bandno]; band->bandno = resno == 0 ? 0 : bandno + 1; x0b = (band->bandno == 1) || (band->bandno == 3) ? 1 : 0; y0b = (band->bandno == 2) || (band->bandno == 3) ? 1 : 0; if (band->bandno == 0) { /* band border (global) */ band->x0 = int_ceildivpow2(tilec->x0, levelno); band->y0 = int_ceildivpow2(tilec->y0, levelno); band->x1 = int_ceildivpow2(tilec->x1, levelno); band->y1 = int_ceildivpow2(tilec->y1, levelno); } else { /* band border (global) */ band->x0 = int_ceildivpow2(tilec->x0 - (1 << levelno) * x0b, levelno + 1); band->y0 = int_ceildivpow2(tilec->y0 - (1 << levelno) * y0b, levelno + 1); band->x1 = int_ceildivpow2(tilec->x1 - (1 << levelno) * x0b, levelno + 1); band->y1 = int_ceildivpow2(tilec->y1 - (1 << levelno) * y0b, levelno + 1); } ss = &tccp->stepsizes[resno == 0 ? 0 : 3 * (resno - 1) + bandno + 1]; gain = tccp->qmfbid == 0 ? dwt_getgain_real(band->bandno) : dwt_getgain(band->bandno); numbps = img->comps[compno].prec + gain; band->stepsize = (int) floor((1.0 + ss->mant / 2048.0) * pow(2.0, numbps - ss->expn) * 8192.0); band->numbps = ss->expn + tccp->numgbits - 1; /* WHY -1 ? */ band->precincts = (tcd_precinct_t *) malloc(3 * res->pw * res->ph * sizeof(tcd_precinct_t)); for (i = 0; i < res->pw * res->ph * 3; i++) { band->precincts[i].imsbtree = NULL; band->precincts[i].incltree = NULL; } for (precno = 0; precno < res->pw * res->ph; precno++) { int tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend; int cbgxstart = tlcbgxstart + (precno % res->pw) * (1 << cbgwidthexpn); int cbgystart = tlcbgystart + (precno / res->pw) * (1 << cbgheightexpn); int cbgxend = cbgxstart + (1 << cbgwidthexpn); int cbgyend = cbgystart + (1 << cbgheightexpn); /* tcd_precinct_t *prc=&band->precincts[precno]; */ prc = &band->precincts[precno]; /* precinct size (global) */ prc->x0 = int_max(cbgxstart, band->x0); prc->y0 = int_max(cbgystart, band->y0); prc->x1 = int_min(cbgxend, band->x1); prc->y1 = int_min(cbgyend, band->y1); tlcblkxstart = int_floordivpow2(prc->x0, cblkwidthexpn) << cblkwidthexpn; tlcblkystart = int_floordivpow2(prc->y0, cblkheightexpn) << cblkheightexpn; brcblkxend = int_ceildivpow2(prc->x1, cblkwidthexpn) << cblkwidthexpn; brcblkyend = int_ceildivpow2(prc->y1, cblkheightexpn) << cblkheightexpn; prc->cw = (brcblkxend - tlcblkxstart) >> cblkwidthexpn; prc->ch = (brcblkyend - tlcblkystart) >> cblkheightexpn; prc->cblks = (tcd_cblk_t *) malloc((prc->cw * prc->ch) * sizeof(tcd_cblk_t)); prc->incltree = tgt_create(prc->cw, prc->ch); prc->imsbtree = tgt_create(prc->cw, prc->ch); for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { int cblkxstart = tlcblkxstart + (cblkno % prc->cw) * (1 << cblkwidthexpn); int cblkystart = tlcblkystart + (cblkno / prc->cw) * (1 << cblkheightexpn); int cblkxend = cblkxstart + (1 << cblkwidthexpn); int cblkyend = cblkystart + (1 << cblkheightexpn); cblk = &prc->cblks[cblkno]; /* code-block size (global) */ cblk->x0 = int_max(cblkxstart, prc->x0); cblk->y0 = int_max(cblkystart, prc->y0); cblk->x1 = int_min(cblkxend, prc->x1); cblk->y1 = int_min(cblkyend, prc->y1); } } } } } } /* tcd_dump(&tcd_image,curtileno); */ } void tcd_free_encode(j2k_image_t * img, j2k_cp_t * cp, int curtileno) { int tileno, compno, resno, bandno, precno; tcd_img = img; tcd_cp = cp; tcd_image.tw = cp->tw; tcd_image.th = cp->th; for (tileno = 0; tileno < 1; tileno++) { /* j2k_tcp_t *tcp=&cp->tcps[curtileno]; */ tile = tcd_image.tiles; for (compno = 0; compno < tile->numcomps; compno++) { tilec = &tile->comps[compno]; for (resno = 0; resno < tilec->numresolutions; resno++) { res = &tilec->resolutions[resno]; for (bandno = 0; bandno < res->numbands; bandno++) { band = &res->bands[bandno]; for (precno = 0; precno < res->pw * res->ph; precno++) { prc = &band->precincts[precno]; if (prc->incltree != NULL) tgt_destroy(prc->incltree); if (prc->imsbtree != NULL) tgt_destroy(prc->imsbtree); free(prc->cblks); } /* for (precno */ free(band->precincts); } /* for (bandno */ } /* for (resno */ free(tilec->resolutions); } /* for (compno */ free(tile->comps); } /* for (tileno */ free(tcd_image.tiles); } void tcd_init_encode(j2k_image_t * img, j2k_cp_t * cp, int curtileno) { int tileno, compno, resno, bandno, precno, cblkno; for (tileno = 0; tileno < 1; tileno++) { j2k_tcp_t *tcp = &cp->tcps[curtileno]; int j; // int previous_x0, previous_x1, previous_y0, previous_y1; /* cfr p59 ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ int p = curtileno % cp->tw; int q = curtileno / cp->tw; tile = tcd_image.tiles; /* 4 borders of the tile rescale on the image if necessary */ tile->x0 = int_max(cp->tx0 + p * cp->tdx, img->x0); tile->y0 = int_max(cp->ty0 + q * cp->tdy, img->y0); tile->x1 = int_min(cp->tx0 + (p + 1) * cp->tdx, img->x1); tile->y1 = int_min(cp->ty0 + (q + 1) * cp->tdy, img->y1); tile->numcomps = img->numcomps; /* tile->PPT=img->PPT; */ /* Modification of the RATE >> */ for (j = 0; j < tcp->numlayers; j++) { tcp->rates[j] = ceil(tile->numcomps * (tile->x1 - tile->x0) * (tile->y1 - tile->y0) * img->comps[0].prec / (tcp->rates[j] * 8 * img->comps[0].dx * img->comps[0].dy)); if (j && tcp->rates[j] < tcp->rates[j - 1] + 10) { tcp->rates[j] = tcp->rates[j - 1] + 20; } else { if (!j && tcp->rates[j] < 30) tcp->rates[j] = 30; } } /* << Modification of the RATE */ /* tile->comps=(tcd_tilecomp_t*)realloc(tile->comps,img->numcomps*sizeof(tcd_tilecomp_t)); */ for (compno = 0; compno < tile->numcomps; compno++) { j2k_tccp_t *tccp = &tcp->tccps[compno]; /* int realloc_op; */ tilec = &tile->comps[compno]; /* border of each tile component (global) */ tilec->x0 = int_ceildiv(tile->x0, img->comps[compno].dx); tilec->y0 = int_ceildiv(tile->y0, img->comps[compno].dy); tilec->x1 = int_ceildiv(tile->x1, img->comps[compno].dx); tilec->y1 = int_ceildiv(tile->y1, img->comps[compno].dy); tilec->data = (int *) malloc((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0) * sizeof(int)); tilec->numresolutions = tccp->numresolutions; /* tilec->resolutions=(tcd_resolution_t*)realloc(tilec->resolutions,tilec->numresolutions*sizeof(tcd_resolution_t)); */ for (resno = 0; resno < tilec->numresolutions; resno++) { int pdx, pdy; int levelno = tilec->numresolutions - 1 - resno; int tlprcxstart, tlprcystart, brprcxend, brprcyend; int tlcbgxstart, tlcbgystart, brcbgxend, brcbgyend; int cbgwidthexpn, cbgheightexpn; int cblkwidthexpn, cblkheightexpn; res = &tilec->resolutions[resno]; /* border for each resolution level (global) */ res->x0 = int_ceildivpow2(tilec->x0, levelno); res->y0 = int_ceildivpow2(tilec->y0, levelno); res->x1 = int_ceildivpow2(tilec->x1, levelno); res->y1 = int_ceildivpow2(tilec->y1, levelno); res->numbands = resno == 0 ? 1 : 3; /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */ if (tccp->csty & J2K_CCP_CSTY_PRT) { pdx = tccp->prcw[resno]; pdy = tccp->prch[resno]; } else { pdx = 15; pdy = 15; } /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ tlprcxstart = int_floordivpow2(res->x0, pdx) << pdx; tlprcystart = int_floordivpow2(res->y0, pdy) << pdy; brprcxend = int_ceildivpow2(res->x1, pdx) << pdx; brprcyend = int_ceildivpow2(res->y1, pdy) << pdy; res->pw = (brprcxend - tlprcxstart) >> pdx; res->ph = (brprcyend - tlprcystart) >> pdy; if (resno == 0) { tlcbgxstart = tlprcxstart; tlcbgystart = tlprcystart; brcbgxend = brprcxend; brcbgyend = brprcyend; cbgwidthexpn = pdx; cbgheightexpn = pdy; } else { tlcbgxstart = int_ceildivpow2(tlprcxstart, 1); tlcbgystart = int_ceildivpow2(tlprcystart, 1); brcbgxend = int_ceildivpow2(brprcxend, 1); brcbgyend = int_ceildivpow2(brprcyend, 1); cbgwidthexpn = pdx - 1; cbgheightexpn = pdy - 1; } cblkwidthexpn = int_min(tccp->cblkw, cbgwidthexpn); cblkheightexpn = int_min(tccp->cblkh, cbgheightexpn); for (bandno = 0; bandno < res->numbands; bandno++) { int x0b, y0b; int gain, numbps; j2k_stepsize_t *ss; band = &res->bands[bandno]; band->bandno = resno == 0 ? 0 : bandno + 1; x0b = (band->bandno == 1) || (band->bandno == 3) ? 1 : 0; y0b = (band->bandno == 2) || (band->bandno == 3) ? 1 : 0; if (band->bandno == 0) { /* band border */ band->x0 = int_ceildivpow2(tilec->x0, levelno); band->y0 = int_ceildivpow2(tilec->y0, levelno); band->x1 = int_ceildivpow2(tilec->x1, levelno); band->y1 = int_ceildivpow2(tilec->y1, levelno); } else { band->x0 = int_ceildivpow2(tilec->x0 - (1 << levelno) * x0b, levelno + 1); band->y0 = int_ceildivpow2(tilec->y0 - (1 << levelno) * y0b, levelno + 1); band->x1 = int_ceildivpow2(tilec->x1 - (1 << levelno) * x0b, levelno + 1); band->y1 = int_ceildivpow2(tilec->y1 - (1 << levelno) * y0b, levelno + 1); } ss = &tccp->stepsizes[resno == 0 ? 0 : 3 * (resno - 1) + bandno + 1]; gain = tccp->qmfbid == 0 ? dwt_getgain_real(band->bandno) : dwt_getgain(band->bandno); numbps = img->comps[compno].prec + gain; band->stepsize = (int) floor((1.0 + ss->mant / 2048.0) * pow(2.0, numbps - ss->expn) * 8192.0); band->numbps = ss->expn + tccp->numgbits - 1; /* WHY -1 ? */ for (precno = 0; precno < res->pw * res->ph; precno++) { int tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend; int cbgxstart = tlcbgxstart + (precno % res->pw) * (1 << cbgwidthexpn); int cbgystart = tlcbgystart + (precno / res->pw) * (1 << cbgheightexpn); int cbgxend = cbgxstart + (1 << cbgwidthexpn); int cbgyend = cbgystart + (1 << cbgheightexpn); prc = &band->precincts[precno]; /* precinct size (global) */ prc->x0 = int_max(cbgxstart, band->x0); prc->y0 = int_max(cbgystart, band->y0); prc->x1 = int_min(cbgxend, band->x1); prc->y1 = int_min(cbgyend, band->y1); tlcblkxstart = int_floordivpow2(prc->x0, cblkwidthexpn) << cblkwidthexpn; tlcblkystart = int_floordivpow2(prc->y0, cblkheightexpn) << cblkheightexpn; brcblkxend = int_ceildivpow2(prc->x1, cblkwidthexpn) << cblkwidthexpn; brcblkyend = int_ceildivpow2(prc->y1, cblkheightexpn) << cblkheightexpn; prc->cw = (brcblkxend - tlcblkxstart) >> cblkwidthexpn; prc->ch = (brcblkyend - tlcblkystart) >> cblkheightexpn; free(prc->cblks); prc->cblks = (tcd_cblk_t *) malloc(prc->cw * prc->ch * sizeof(tcd_cblk_t)); if (prc->incltree != NULL) tgt_destroy(prc->incltree); if (prc->imsbtree != NULL) tgt_destroy(prc->imsbtree); prc->incltree = tgt_create(prc->cw, prc->ch); prc->imsbtree = tgt_create(prc->cw, prc->ch); for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { int cblkxstart = tlcblkxstart + (cblkno % prc->cw) * (1 << cblkwidthexpn); int cblkystart = tlcblkystart + (cblkno / prc->cw) * (1 << cblkheightexpn); int cblkxend = cblkxstart + (1 << cblkwidthexpn); int cblkyend = cblkystart + (1 << cblkheightexpn); cblk = &prc->cblks[cblkno]; /* code-block size (global) */ cblk->x0 = int_max(cblkxstart, prc->x0); cblk->y0 = int_max(cblkystart, prc->y0); cblk->x1 = int_min(cblkxend, prc->x1); cblk->y1 = int_min(cblkyend, prc->y1); } } } } } } /* tcd_dump(&tcd_image,0); */ } void tcd_init(j2k_image_t * img, j2k_cp_t * cp) { int tileno, compno, resno, bandno, precno, cblkno, i; unsigned int x0=0 , y0=0, x1 = 0, y1 = 0, w, h, j, p, q; tcd_img = img; tcd_cp = cp; tcd_image.tw = cp->tw; tcd_image.th = cp->th; tcd_image.tiles = (tcd_tile_t *) malloc(cp->tw * cp->th * sizeof(tcd_tile_t)); /*for (tileno = 0; tileno < cp->tw * cp->th; tileno++) { j2k_tcp_t *tcp = &cp->tcps[tileno]; tcd_tile_t *tile = &tcd_image.tiles[tileno];*/ for (i = 0 ; i < cp->tileno_size ; i++){ j2k_tcp_t *tcp = &cp->tcps[cp->tileno[i]]; tcd_tile_t *tile = &tcd_image.tiles[cp->tileno[i]]; tileno = cp->tileno[i]; // int previous_x0, previous_x1, previous_y0, previous_y1; /* cfr p59 ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ p = tileno % cp->tw; /* si numerotation matricielle .. */ q = tileno / cp->tw; /* .. coordonnees de la tile (q,p) q pour ligne et p pour colonne */ /* 4 borders of the tile rescale on the image if necessary */ tile->x0 = int_max(cp->tx0 + p * cp->tdx, img->x0); tile->y0 = int_max(cp->ty0 + q * cp->tdy, img->y0); tile->x1 = int_min(cp->tx0 + (p + 1) * cp->tdx, img->x1); tile->y1 = int_min(cp->ty0 + (q + 1) * cp->tdy, img->y1); tile->numcomps = img->numcomps; tile->comps = (tcd_tilecomp_t *) malloc(img->numcomps * sizeof(tcd_tilecomp_t)); for (compno = 0; compno < tile->numcomps; compno++) { j2k_tccp_t *tccp = &tcp->tccps[compno]; tcd_tilecomp_t *tilec = &tile->comps[compno]; /* border of each tile component (global) */ tilec->x0 = int_ceildiv(tile->x0, img->comps[compno].dx); tilec->y0 = int_ceildiv(tile->y0, img->comps[compno].dy); tilec->x1 = int_ceildiv(tile->x1, img->comps[compno].dx); tilec->y1 = int_ceildiv(tile->y1, img->comps[compno].dy); tilec->data = (int *) malloc((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0) * sizeof(int)); tilec->numresolutions = tccp->numresolutions; tilec->resolutions = (tcd_resolution_t *) malloc(tilec->numresolutions * sizeof(tcd_resolution_t)); for (resno = 0; resno < tilec->numresolutions; resno++) { int pdx, pdy; int levelno = tilec->numresolutions - 1 - resno; int tlprcxstart, tlprcystart, brprcxend, brprcyend; int tlcbgxstart, tlcbgystart, brcbgxend, brcbgyend; int cbgwidthexpn, cbgheightexpn; int cblkwidthexpn, cblkheightexpn; tcd_resolution_t *res = &tilec->resolutions[resno]; /* border for each resolution level (global) */ res->x0 = int_ceildivpow2(tilec->x0, levelno); res->y0 = int_ceildivpow2(tilec->y0, levelno); res->x1 = int_ceildivpow2(tilec->x1, levelno); res->y1 = int_ceildivpow2(tilec->y1, levelno); res->numbands = resno == 0 ? 1 : 3; /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */ if (tccp->csty & J2K_CCP_CSTY_PRT) { pdx = tccp->prcw[resno]; pdy = tccp->prch[resno]; } else { pdx = 15; pdy = 15; } /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ tlprcxstart = int_floordivpow2(res->x0, pdx) << pdx; tlprcystart = int_floordivpow2(res->y0, pdy) << pdy; brprcxend = int_ceildivpow2(res->x1, pdx) << pdx; brprcyend = int_ceildivpow2(res->y1, pdy) << pdy; res->pw = (brprcxend - tlprcxstart) >> pdx; res->ph = (brprcyend - tlprcystart) >> pdy; if (resno == 0) { tlcbgxstart = tlprcxstart; tlcbgystart = tlprcystart; brcbgxend = brprcxend; brcbgyend = brprcyend; cbgwidthexpn = pdx; cbgheightexpn = pdy; } else { tlcbgxstart = int_ceildivpow2(tlprcxstart, 1); tlcbgystart = int_ceildivpow2(tlprcystart, 1); brcbgxend = int_ceildivpow2(brprcxend, 1); brcbgyend = int_ceildivpow2(brprcyend, 1); cbgwidthexpn = pdx - 1; cbgheightexpn = pdy - 1; } cblkwidthexpn = int_min(tccp->cblkw, cbgwidthexpn); cblkheightexpn = int_min(tccp->cblkh, cbgheightexpn); for (bandno = 0; bandno < res->numbands; bandno++) { int x0b, y0b; int gain, numbps; j2k_stepsize_t *ss; tcd_band_t *band = &res->bands[bandno]; band->bandno = resno == 0 ? 0 : bandno + 1; x0b = (band->bandno == 1) || (band->bandno == 3) ? 1 : 0; y0b = (band->bandno == 2) || (band->bandno == 3) ? 1 : 0; if (band->bandno == 0) { /* band border (global) */ band->x0 = int_ceildivpow2(tilec->x0, levelno); band->y0 = int_ceildivpow2(tilec->y0, levelno); band->x1 = int_ceildivpow2(tilec->x1, levelno); band->y1 = int_ceildivpow2(tilec->y1, levelno); } else { /* band border (global) */ band->x0 = int_ceildivpow2(tilec->x0 - (1 << levelno) * x0b, levelno + 1); band->y0 = int_ceildivpow2(tilec->y0 - (1 << levelno) * y0b, levelno + 1); band->x1 = int_ceildivpow2(tilec->x1 - (1 << levelno) * x0b, levelno + 1); band->y1 = int_ceildivpow2(tilec->y1 - (1 << levelno) * y0b, levelno + 1); } ss = &tccp->stepsizes[resno == 0 ? 0 : 3 * (resno - 1) + bandno + 1]; gain = tccp->qmfbid == 0 ? dwt_getgain_real(band->bandno) : dwt_getgain(band->bandno); numbps = img->comps[compno].prec + gain; band->stepsize = (int) floor((1.0 + ss->mant / 2048.0) * pow(2.0, numbps - ss->expn) * 8192.0); band->numbps = ss->expn + tccp->numgbits - 1; /* WHY -1 ? */ band->precincts = (tcd_precinct_t *) malloc(res->pw * res->ph * sizeof(tcd_precinct_t)); for (precno = 0; precno < res->pw * res->ph; precno++) { int tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend; int cbgxstart = tlcbgxstart + (precno % res->pw) * (1 << cbgwidthexpn); int cbgystart = tlcbgystart + (precno / res->pw) * (1 << cbgheightexpn); int cbgxend = cbgxstart + (1 << cbgwidthexpn); int cbgyend = cbgystart + (1 << cbgheightexpn); tcd_precinct_t *prc = &band->precincts[precno]; /* precinct size (global) */ prc->x0 = int_max(cbgxstart, band->x0); prc->y0 = int_max(cbgystart, band->y0); prc->x1 = int_min(cbgxend, band->x1); prc->y1 = int_min(cbgyend, band->y1); tlcblkxstart = int_floordivpow2(prc->x0, cblkwidthexpn) << cblkwidthexpn; tlcblkystart = int_floordivpow2(prc->y0, cblkheightexpn) << cblkheightexpn; brcblkxend = int_ceildivpow2(prc->x1, cblkwidthexpn) << cblkwidthexpn; brcblkyend = int_ceildivpow2(prc->y1, cblkheightexpn) << cblkheightexpn; prc->cw = (brcblkxend - tlcblkxstart) >> cblkwidthexpn; prc->ch = (brcblkyend - tlcblkystart) >> cblkheightexpn; prc->cblks = (tcd_cblk_t *) malloc(prc->cw * prc->ch * sizeof(tcd_cblk_t)); prc->incltree = tgt_create(prc->cw, prc->ch); prc->imsbtree = tgt_create(prc->cw, prc->ch); for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { int cblkxstart = tlcblkxstart + (cblkno % prc->cw) * (1 << cblkwidthexpn); int cblkystart = tlcblkystart + (cblkno / prc->cw) * (1 << cblkheightexpn); int cblkxend = cblkxstart + (1 << cblkwidthexpn); int cblkyend = cblkystart + (1 << cblkheightexpn); tcd_cblk_t *cblk = &prc->cblks[cblkno]; /* code-block size (global) */ cblk->x0 = int_max(cblkxstart, prc->x0); cblk->y0 = int_max(cblkystart, prc->y0); cblk->x1 = int_min(cblkxend, prc->x1); cblk->y1 = int_min(cblkyend, prc->y1); } } } } } } /* tcd_dump(&tcd_image,0); */ /* Allocate place to store the date decoded = fianl image */ /* Place limited by the tile really present in the codestream */ for (i = 0; i < img->numcomps; i++) { for (j = 0; j < cp->tileno_size; j++) { tileno = cp->tileno[j]; x0 = j == 0 ? tcd_image.tiles[tileno].x0 : int_min(x0 , tcd_image.tiles[tileno].x0); y0 = j == 0 ? tcd_image.tiles[tileno].y0 : int_min(y0 , tcd_image.tiles[tileno].y0); x1 = j == 0 ? tcd_image.tiles[tileno].x1 : int_max(x1 , tcd_image.tiles[tileno].x1); y1 = j == 0 ? tcd_image.tiles[tileno].y1 : int_max(y1 , tcd_image.tiles[tileno].y1); } w = int_ceildiv(x1 - x0, img->comps[i].dx); h = int_ceildiv(y1 - y0, img->comps[i].dy); img->comps[i].data = (int *) calloc(w * h,sizeof(int)); img->comps[i].w = w; img->comps[i].h = h; img->comps[i].x0 = x0; img->comps[i].y0 = y0; } } void tcd_makelayer_fixed(int layno, int final) { int compno, resno, bandno, precno, cblkno; int value; //, matrice[tcd_tcp->numlayers][tcd_tile->comps[0].numresolutions][3]; int matrice[10][10][3]; int i,j,k; /*matrice=(int*)malloc(tcd_tcp->numlayers*tcd_tile->comps[0].numresolutions*3*sizeof(int));*/ for (compno=0; compnonumcomps; compno++) { tcd_tilecomp_t *tilec=&tcd_tile->comps[compno]; for (i=0;inumlayers;i++) { for (j=0;jnumresolutions;j++) { for (k=0;k<3;k++) { matrice[i][j][k]=(int)(tcd_cp->matrice[i*tilec->numresolutions*3+j*3+k]*(float)(tcd_img->comps[compno].prec/16.0));}}} for (resno=0; resnonumresolutions; resno++) { tcd_resolution_t *res=&tilec->resolutions[resno]; for (bandno=0; bandnonumbands; bandno++) { tcd_band_t *band=&res->bands[bandno]; for (precno=0; precnopw*res->ph; precno++) { tcd_precinct_t *prc=&band->precincts[precno]; for (cblkno=0; cblknocw*prc->ch; cblkno++) { tcd_cblk_t *cblk=&prc->cblks[cblkno]; tcd_layer_t *layer=&cblk->layers[layno]; int n; int imsb=tcd_img->comps[compno].prec-cblk->numbps; /* number of bit-plan equal to zero */ /* Correction of the matrix of coefficient to include the IMSB information */ if (layno==0) { value=matrice[layno][resno][bandno]; if (imsb>=value) value=0; else value-=imsb; } else { value=matrice[layno][resno][bandno]-matrice[layno-1][resno][bandno]; if (imsb>=matrice[layno-1][resno][bandno]) { value-=(imsb-matrice[layno-1][resno][bandno]); if (value<0) value=0; } } if (layno==0) cblk->numpassesinlayers=0; n=cblk->numpassesinlayers; if (cblk->numpassesinlayers==0) { if (value!=0) n=3*value-2+cblk->numpassesinlayers; else n=cblk->numpassesinlayers; } else n=3*value+cblk->numpassesinlayers; layer->numpasses=n-cblk->numpassesinlayers; if (!layer->numpasses) continue; if (cblk->numpassesinlayers==0) { layer->len=cblk->passes[n-1].rate; layer->data=cblk->data; } else { layer->len=cblk->passes[n-1].rate-cblk->passes[cblk->numpassesinlayers-1].rate; layer->data=cblk->data+cblk->passes[cblk->numpassesinlayers-1].rate; } if (final) cblk->numpassesinlayers=n; } } } } } } void tcd_rateallocate_fixed() { int layno; for (layno=0; laynonumlayers; layno++) { tcd_makelayer_fixed(layno, 1); } } void tcd_makelayer(int layno, double thresh, int final) { int compno, resno, bandno, precno, cblkno, passno; for (compno = 0; compno < tcd_tile->numcomps; compno++) { tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; for (resno = 0; resno < tilec->numresolutions; resno++) { tcd_resolution_t *res = &tilec->resolutions[resno]; for (bandno = 0; bandno < res->numbands; bandno++) { tcd_band_t *band = &res->bands[bandno]; for (precno = 0; precno < res->pw * res->ph; precno++) { tcd_precinct_t *prc = &band->precincts[precno]; for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { tcd_cblk_t *cblk = &prc->cblks[cblkno]; tcd_layer_t *layer = &cblk->layers[layno]; int n; if (layno == 0) { cblk->numpassesinlayers = 0; } n = cblk->numpassesinlayers; for (passno = cblk->numpassesinlayers; passno < cblk->totalpasses; passno++) { int dr; double dd; tcd_pass_t *pass = &cblk->passes[passno]; if (n == 0) { dr = pass->rate; dd = pass->distortiondec; } else { dr = pass->rate - cblk->passes[n - 1].rate; dd = pass->distortiondec - cblk->passes[n - 1].distortiondec; } if (dr == 0) { if (dd != 0) n = passno + 1; continue; } if (dd / dr > thresh) n = passno + 1; } layer->numpasses = n - cblk->numpassesinlayers; if (!layer->numpasses) continue; if (cblk->numpassesinlayers == 0) { layer->len = cblk->passes[n - 1].rate; layer->data = cblk->data; layer->disto = cblk->passes[n - 1].distortiondec; } else { layer->len = cblk->passes[n - 1].rate - cblk->passes[cblk->numpassesinlayers - 1].rate; layer->data = cblk->data + cblk->passes[cblk->numpassesinlayers - 1].rate; layer->disto = cblk->passes[n - 1].distortiondec - cblk->passes[cblk->numpassesinlayers - 1].distortiondec; } if (final) cblk->numpassesinlayers = n; } } } } } } void tcd_rateallocate(unsigned char *dest, int len, info_image * info_IM) { int compno, resno, bandno, precno, cblkno, passno, layno; double min, max; min = DBL_MAX; max = 0; for (compno = 0; compno < tcd_tile->numcomps; compno++) { tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; for (resno = 0; resno < tilec->numresolutions; resno++) { tcd_resolution_t *res = &tilec->resolutions[resno]; for (bandno = 0; bandno < res->numbands; bandno++) { tcd_band_t *band = &res->bands[bandno]; for (precno = 0; precno < res->pw * res->ph; precno++) { tcd_precinct_t *prc = &band->precincts[precno]; for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { tcd_cblk_t *cblk = &prc->cblks[cblkno]; for (passno = 0; passno < cblk->totalpasses; passno++) { tcd_pass_t *pass = &cblk->passes[passno]; int dr; double dd, rdslope; if (passno == 0) { dr = pass->rate; dd = pass->distortiondec; } else { dr = pass->rate - cblk->passes[passno - 1].rate; dd = pass->distortiondec - cblk->passes[passno - 1].distortiondec; } if (dr == 0) { continue; } rdslope = dd / dr; if (rdslope < min) { min = rdslope; } if (rdslope > max) { max = rdslope; } } /* passno */ } /* cbklno */ } /* precno */ } /* bandno */ } /* resno */ } /* compno */ if (info_IM->index_on) { /* Threshold for Marcela Index */ info_IM->tile[tcd_tileno].thresh=(double*)malloc(tcd_tcp->numlayers*sizeof(double)); } for (layno = 0; layno < tcd_tcp->numlayers; layno++) { volatile double lo = min; volatile double hi = max; volatile int success = 0; volatile int maxlen = int_min(tcd_tcp->rates[layno], len); volatile double goodthresh; volatile int goodlen; volatile int i; for (i = 0; i < 32; i++) { volatile double thresh = (lo + hi) / 2; int l; tcd_makelayer(layno, thresh, 0); l = t2_encode_packets(tcd_img, tcd_cp, tcd_tileno, tcd_tile, layno + 1, dest, maxlen, info_IM); /* fprintf(stderr, "rate alloc: len=%d, max=%d\n", l, maxlen); */ if (l == -999) { lo = thresh; continue; } hi = thresh; success = 1; goodthresh = thresh; goodlen = l; } if (!success) { longjmp(j2k_error, 1); } if (info_IM->index_on) { /* Threshold for Marcela Index */ info_IM->tile[tcd_tileno].thresh[layno]=goodthresh; } tcd_makelayer(layno, goodthresh, 1); } } int tcd_encode_tile_pxm(int tileno, unsigned char *dest, int len, info_image * info_IM) { int compno; int l; clock_t time7; tcd_tile_t *tile; j2k_tcp_t *tcp = &tcd_cp->tcps[0]; j2k_tccp_t *tccp = &tcp->tccps[0]; tcd_tileno = tileno; tcd_tile = tcd_image.tiles; tcd_tcp = &tcd_cp->tcps[tileno]; tile = tcd_tile; /* INDEX >> "Precinct_nb_X et Precinct_nb_Y" */ if (info_IM->index_on) { tcd_tilecomp_t *tilec_idx = &tile->comps[0]; /* old parser version */ tcd_resolution_t *res_idx = &tilec_idx->resolutions[0]; /* old parser version */ info_IM->tile[tileno].pw = res_idx->pw; info_IM->tile[tileno].ph = res_idx->ph; info_IM->pw = res_idx->pw; /* old parser version */ info_IM->ph = res_idx->ph; /* old parser version */ info_IM->pdx = 1 << tccp->prcw[tccp->numresolutions - 1]; info_IM->pdy = 1 << tccp->prch[tccp->numresolutions - 1]; } /* << INDEX */ /*---------------TILE-------------------*/ time7 = clock(); for (compno = 0; compno < tile->numcomps; compno++) { FILE *src; char tmp[256]; int k; unsigned char elmt; int i, j; int tw, w; tcd_tilecomp_t *tilec = &tile->comps[compno]; int adjust = tcd_img->comps[compno].sgnd ? 0 : 1 << (tcd_img->comps[compno].prec - 1); int offset_x, offset_y; offset_x = int_ceildiv(tcd_img->x0, tcd_img->comps[compno].dx); offset_y = int_ceildiv(tcd_img->y0, tcd_img->comps[compno].dy); tw = tilec->x1 - tilec->x0; w = int_ceildiv(tcd_img->x1 - tcd_img->x0, tcd_img->comps[compno].dx); sprintf(tmp, "Compo%d", compno); /* component file */ src = fopen(tmp, "rb"); if (!src) { fprintf(stderr, "failed to open %s for reading\n", tmp); return 1; } /* read the Compo file to extract data of the tile */ k = 0; fseek(src, (tilec->x0 - offset_x) + (tilec->y0 - offset_y) * w, SEEK_SET); k = (tilec->x0 - offset_x) + (tilec->y0 - offset_y) * w; for (j = tilec->y0; j < tilec->y1; j++) { for (i = tilec->x0; i < tilec->x1; i++) { if (tcd_tcp->tccps[compno].qmfbid == 1) { elmt = fgetc(src); tilec->data[i - tilec->x0 + (j - tilec->y0) * tw] = elmt - adjust; k++; } else if (tcd_tcp->tccps[compno].qmfbid == 0) { elmt = fgetc(src); tilec->data[i - tilec->x0 + (j - tilec->y0) * tw] = (elmt - adjust) << 13; k++; } } fseek(src, (tilec->x0 - offset_x) + (j + 1 - offset_y) * w - k, SEEK_CUR); k = tilec->x0 - offset_x + (j + 1 - offset_y) * w; } fclose(src); } /*----------------MCT-------------------*/ if (tcd_tcp->mct) { if (tcd_tcp->tccps[0].qmfbid == 0) { mct_encode_real(tile->comps[0].data, tile->comps[1].data,tile->comps[2].data, (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0)); } else { mct_encode(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0)); } } /*----------------DWT---------------------*/ /* time3=clock(); */ for (compno = 0; compno < tile->numcomps; compno++) { tcd_tilecomp_t *tilec = &tile->comps[compno]; if (tcd_tcp->tccps[compno].qmfbid == 1) { dwt_encode(tilec->data, tilec->x1 - tilec->x0, tilec->y1 - tilec->y0, tilec, tilec->numresolutions - 1); } else if (tcd_tcp->tccps[compno].qmfbid == 0) { dwt_encode_real(tilec->data, tilec->x1 - tilec->x0, tilec->y1 - tilec->y0, tilec, tilec->numresolutions - 1); } } /*------------------TIER1-----------------*/ t1_init_luts(); t1_encode_cblks(tile, tcd_tcp); /*-----------RATE-ALLOCATE------------------*/ info_IM->index_write = 0; /* INDEX */ if (tcd_cp->disto_alloc) /* Normal Rate/distortion allocation */ tcd_rateallocate(dest, len, info_IM); else /* Fixed layer allocation */ tcd_rateallocate_fixed(); /*--------------TIER2------------------*/ info_IM->index_write = 1; /* INDEX */ l = t2_encode_packets(tcd_img, tcd_cp, tileno, tile, tcd_tcp->numlayers, dest, len, info_IM); /*---------------CLEAN-------------------*/ time7 = clock() - time7; printf("total: %ld.%.3ld s\n", time7 / CLOCKS_PER_SEC, (time7 % CLOCKS_PER_SEC) * 1000 / CLOCKS_PER_SEC); /* cleaning memory */ for (compno = 0; compno < tile->numcomps; compno++) { tilec = &tile->comps[compno]; free(tilec->data); } return l; } int tcd_encode_tile_pgx(int tileno, unsigned char *dest, int len, info_image * info_IM) { int compno; int l; clock_t time; tcd_tile_t *tile; j2k_tcp_t *tcp = &tcd_cp->tcps[0]; j2k_tccp_t *tccp = &tcp->tccps[0]; tcd_tileno = tileno; tcd_tile = tcd_image.tiles; tcd_tcp = &tcd_cp->tcps[tileno]; tile = tcd_tile; /* INDEX >> "Precinct_nb_X et Precinct_nb_Y" */ if (info_IM->index_on) { tcd_tilecomp_t *tilec_idx = &tile->comps[0]; tcd_resolution_t *res_idx = &tilec_idx->resolutions[0]; info_IM->tile[tileno].pw = res_idx->pw; info_IM->tile[tileno].ph = res_idx->ph; info_IM->pw = res_idx->pw; /* old parser version */ info_IM->ph = res_idx->ph; /* old parser version */ info_IM->pdx = 1 << tccp->prcw[tccp->numresolutions - 1]; info_IM->pdy = 1 << tccp->prch[tccp->numresolutions - 1]; } /* << INDEX */ /*---------------TILE-------------------*/ time = clock(); for (compno = 0; compno < tile->numcomps; compno++) { FILE *src; char tmp[256]; int k; int elmt; int i, j; int tw, w; tcd_tilecomp_t *tilec = &tile->comps[compno]; int adjust = tcd_img->comps[compno].sgnd ? 0 : 1 << (tcd_img->comps[compno].prec - 1); int offset_x, offset_y; offset_x = int_ceildiv(tcd_img->x0, tcd_img->comps[compno].dx); offset_y = int_ceildiv(tcd_img->y0, tcd_img->comps[compno].dy); tw = tilec->x1 - tilec->x0; w = int_ceildiv(tcd_img->x1 - tcd_img->x0, tcd_img->comps[compno].dx); sprintf(tmp, "bandtile%d", tileno / tcd_cp->tw + 1); /* bandtile file opening */ src = fopen(tmp, "rb"); if (!src) { fprintf(stderr, "failed to open %s for reading\n", tmp); return 1; } /* Extract data from bandtile file limited to the current tile */ k = 0; while (k < tilec->x0 - offset_x) { k++; fscanf(src, "%d", &elmt); } for (j = 0; j < tilec->y1 - tilec->y0; j++) { for (i = tilec->x0; i < tilec->x1; i++) { if (tcd_tcp->tccps[compno].qmfbid == 1) { fscanf(src, "%d", &elmt); tilec->data[i - tilec->x0 + (j) * tw] = elmt - adjust; k++; } else if (tcd_tcp->tccps[compno].qmfbid == 0) { fscanf(src, "%d", &elmt); tilec->data[i - tilec->x0 + (j) * tw] = (elmt - adjust) << 13; k++; } } while (k < tilec->x0 - offset_x + (j + 1) * w) { k++; fscanf(src, "%d", &elmt); } } fclose(src); } /*----------------MCT-------------------*/ if (tcd_tcp->mct) { if (tcd_tcp->tccps[0].qmfbid == 0) { mct_encode_real(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0)); } else { mct_encode(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0)); } } /*----------------DWT---------------------*/ for (compno = 0; compno < tile->numcomps; compno++) { tcd_tilecomp_t *tilec = &tile->comps[compno]; if (tcd_tcp->tccps[compno].qmfbid == 1) { dwt_encode(tilec->data, tilec->x1 - tilec->x0, tilec->y1 - tilec->y0, tilec, tilec->numresolutions - 1); } else if (tcd_tcp->tccps[compno].qmfbid == 0) { dwt_encode_real(tilec->data, tilec->x1 - tilec->x0, tilec->y1 - tilec->y0, tilec, tilec->numresolutions - 1); } } /*------------------TIER1-----------------*/ t1_init_luts(); t1_encode_cblks(tile, tcd_tcp); /*-----------RATE-ALLOCATE------------------*/ info_IM->index_write = 0; /* INDEX */ info_IM->index_write=0; /* INDEX */ if (tcd_cp->disto_alloc) /* Normal Rate/distortion allocation */ tcd_rateallocate(dest, len, info_IM); else /* Fixed layer allocation */ tcd_rateallocate_fixed(); /*--------------TIER2------------------*/ info_IM->index_write = 1; /* INDEX */ l = t2_encode_packets(tcd_img, tcd_cp, tileno, tile, tcd_tcp->numlayers, dest, len, info_IM); /*---------------CLEAN-------------------*/ time = clock() - time; printf("total: %ld.%.3ld s\n", time / CLOCKS_PER_SEC, (time % CLOCKS_PER_SEC) * 1000 / CLOCKS_PER_SEC); for (compno = 0; compno < tile->numcomps; compno++) { tilec = &tile->comps[compno]; free(tilec->data); } return l; } int tcd_decode_tile(unsigned char *src, int len, int tileno) { int l; int compno; int eof = 0; clock_t time; tcd_tile_t *tile; tcd_tileno = tileno; tcd_tile = &tcd_image.tiles[tileno]; tcd_tcp = &tcd_cp->tcps[tileno]; tile = tcd_tile; time = clock(); fprintf(stderr,"tile decoding time %d/%d: ", tileno + 1, tcd_cp->tw * tcd_cp->th); /*--------------TIER2------------------*/ l = t2_decode_packets(src, len, tcd_img, tcd_cp, tileno, tile); if (l == -999) { eof = 1; fprintf(stderr, "tcd_decode: incomplete bistream\n"); } /*------------------TIER1-----------------*/ t1_init_luts(); t1_decode_cblks(tile, tcd_tcp); /*----------------DWT---------------------*/ for (compno = 0; compno < tile->numcomps; compno++) { tcd_tilecomp_t *tilec = &tile->comps[compno]; if (tcd_cp->reduce_on == 1) { tcd_img->comps[compno].resno_decoded = tile->comps[compno].numresolutions - tcd_cp->reduce_value - 1; } if (tcd_tcp->tccps[compno].qmfbid == 1) { dwt_decode(tilec->data, tilec->x1 - tilec->x0, tilec->y1 - tilec->y0, tilec, tilec->numresolutions - 1, tilec->numresolutions - 1 - tcd_img->comps[compno].resno_decoded); } else { dwt_decode_real(tilec->data, tilec->x1 - tilec->x0, tilec->y1 - tilec->y0, tilec, tilec->numresolutions - 1, tilec->numresolutions - 1 - tcd_img->comps[compno].resno_decoded); } if (tile->comps[compno].numresolutions > 0) tcd_img->comps[compno].factor = tile->comps[compno].numresolutions - (tcd_img->comps[compno].resno_decoded + 1); } /*----------------MCT-------------------*/ if (tcd_tcp->mct) { if (tcd_tcp->tccps[0].qmfbid == 1) { mct_decode(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0)); } else { mct_decode_real(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0)); } } /*---------------TILE-------------------*/ for (compno = 0; compno < tile->numcomps; compno++) { tcd_tilecomp_t *tilec = &tile->comps[compno]; tcd_resolution_t *res = &tilec->resolutions[tcd_img->comps[compno].resno_decoded]; int adjust = tcd_img->comps[compno].sgnd ? 0 : 1 << (tcd_img->comps[compno].prec - 1); int min = tcd_img->comps[compno].sgnd ? - (1 << (tcd_img->comps[compno].prec - 1)) : 0; int max = tcd_img->comps[compno].sgnd ? (1 << (tcd_img->comps[compno].prec - 1)) - 1 : (1 << tcd_img->comps[compno].prec) - 1; int tw = tilec->x1 - tilec->x0; int w = tcd_img->comps[compno].w; int i, j; int offset_x = int_ceildivpow2(tcd_img->comps[compno].x0, tcd_img->comps[compno].factor); int offset_y = int_ceildivpow2(tcd_img->comps[compno].y0, tcd_img->comps[compno].factor); for (j = res->y0; j < res->y1; j++) { for (i = res->x0; i < res->x1; i++) { int v; if (tcd_tcp->tccps[compno].qmfbid == 1) { v = tilec->data[i - res->x0 + (j - res->y0) * tw]; } else { v = tilec->data[i - res->x0 + (j - res->y0) * tw] >> 13; } v += adjust; tcd_img->comps[compno].data[(i - offset_x) + (j - offset_y) * w] = int_clamp(v, min, max); } } } time = clock() - time; fprintf(stderr,"total: %ld.%.3ld s\n", time / CLOCKS_PER_SEC, (time % CLOCKS_PER_SEC) * 1000 / CLOCKS_PER_SEC); if (eof) { longjmp(j2k_error, 1); } return l; }