766 lines
21 KiB
C
766 lines
21 KiB
C
|
/*
|
||
|
* 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 <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <setjmp.h>
|
||
|
#include <math.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#include "j2k.h"
|
||
|
#include "cio.h"
|
||
|
#include "tcd.h"
|
||
|
#include "int.h"
|
||
|
#include "jpip.h"
|
||
|
#include "jp2.h"
|
||
|
|
||
|
#define J2K_MS_SOC 0xff4f
|
||
|
#define J2K_MS_SOT 0xff90
|
||
|
#define J2K_MS_SOD 0xff93
|
||
|
#define J2K_MS_EOC 0xffd9
|
||
|
#define J2K_MS_SIZ 0xff51
|
||
|
#define J2K_MS_COD 0xff52
|
||
|
#define J2K_MS_COC 0xff53
|
||
|
#define J2K_MS_RGN 0xff5e
|
||
|
#define J2K_MS_QCD 0xff5c
|
||
|
#define J2K_MS_QCC 0xff5d
|
||
|
#define J2K_MS_POC 0xff5f
|
||
|
#define J2K_MS_TLM 0xff55
|
||
|
#define J2K_MS_PLM 0xff57
|
||
|
#define J2K_MS_PLT 0xff58
|
||
|
#define J2K_MS_PPM 0xff60
|
||
|
#define J2K_MS_PPT 0xff61
|
||
|
#define J2K_MS_SOP 0xff91
|
||
|
#define J2K_MS_EPH 0xff92
|
||
|
#define J2K_MS_CRG 0xff63
|
||
|
#define J2K_MS_COM 0xff64
|
||
|
|
||
|
#define J2K_STATE_MHSOC 0x0001
|
||
|
#define J2K_STATE_MHSIZ 0x0002
|
||
|
#define J2K_STATE_MH 0x0004
|
||
|
#define J2K_STATE_TPHSOT 0x0008
|
||
|
#define J2K_STATE_TPH 0x0010
|
||
|
#define J2K_STATE_MT 0x0020
|
||
|
|
||
|
jmp_buf j2k_error;
|
||
|
|
||
|
static int j2k_state;
|
||
|
static int j2k_curtileno;
|
||
|
static j2k_tcp_t j2k_default_tcp;
|
||
|
static unsigned char *j2k_eot;
|
||
|
|
||
|
static j2k_image_t *j2k_img;
|
||
|
static j2k_cp_t *j2k_cp;
|
||
|
|
||
|
static unsigned char **j2k_tile_data;
|
||
|
static int *j2k_tile_len;
|
||
|
|
||
|
static info_image_t img;
|
||
|
|
||
|
void j2k_clean() {
|
||
|
int tileno = 0;
|
||
|
int compno, resno, precno;
|
||
|
|
||
|
tcd_free(j2k_img,j2k_cp);
|
||
|
|
||
|
for (tileno=0;tileno<j2k_cp->tw*j2k_cp->th;tileno++) {
|
||
|
info_tile_t *tile_Idx = &img.tile[tileno];
|
||
|
|
||
|
for (compno=0;compno<img.Comp;compno++)
|
||
|
{
|
||
|
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];
|
||
|
free(prec_Idx->layer);
|
||
|
}
|
||
|
free(reso_Idx->prec);
|
||
|
}
|
||
|
free(compo_Idx->reso);
|
||
|
}
|
||
|
free(tile_Idx->compo);
|
||
|
}
|
||
|
free(img.tile);
|
||
|
free(img.marker);
|
||
|
}
|
||
|
|
||
|
void j2k_read_soc() {
|
||
|
j2k_state=J2K_STATE_MHSIZ;
|
||
|
}
|
||
|
|
||
|
void j2k_read_siz() {
|
||
|
int len, i;
|
||
|
len=cio_read(2);
|
||
|
|
||
|
// <INDEX>
|
||
|
img.marker[img.num_marker].type=J2K_MS_SIZ;
|
||
|
img.marker[img.num_marker].start_pos=cio_tell()-2;
|
||
|
img.marker[img.num_marker].len=len;
|
||
|
img.num_marker++;
|
||
|
// </INDEX>
|
||
|
|
||
|
|
||
|
cio_read(2); // Rsiz (capabilities)
|
||
|
j2k_img->x1=cio_read(4); // Xsiz
|
||
|
j2k_img->y1=cio_read(4); // Ysiz
|
||
|
j2k_img->x0=cio_read(4); // X0siz
|
||
|
j2k_img->y0=cio_read(4); // Y0siz
|
||
|
j2k_cp->tdx=cio_read(4); // XTsiz
|
||
|
j2k_cp->tdy=cio_read(4); // YTsiz
|
||
|
j2k_cp->tx0=cio_read(4); // XT0siz
|
||
|
j2k_cp->ty0=cio_read(4); // YTOsiz
|
||
|
j2k_img->numcomps=cio_read(2); // Csiz
|
||
|
j2k_img->comps=(j2k_comp_t*)malloc(j2k_img->numcomps*sizeof(j2k_comp_t));
|
||
|
for (i=0; i<j2k_img->numcomps; i++) {
|
||
|
int tmp, w, h;
|
||
|
tmp=cio_read(1);
|
||
|
j2k_img->comps[i].prec=(tmp&0x7f)+1;
|
||
|
j2k_img->comps[i].sgnd=tmp>>7;
|
||
|
j2k_img->comps[i].dx=cio_read(1);
|
||
|
j2k_img->comps[i].dy=cio_read(1);
|
||
|
w=int_ceildiv(j2k_img->x1-j2k_img->x0, j2k_img->comps[i].dx);
|
||
|
h=int_ceildiv(j2k_img->y1-j2k_img->y0, j2k_img->comps[i].dy);
|
||
|
j2k_img->comps[i].data=(int*)malloc(sizeof(int)*w*h);
|
||
|
}
|
||
|
j2k_cp->tw=int_ceildiv(j2k_img->x1-j2k_img->x0, j2k_cp->tdx);
|
||
|
j2k_cp->th=int_ceildiv(j2k_img->y1-j2k_img->y0, j2k_cp->tdy);
|
||
|
|
||
|
j2k_cp->tcps=(j2k_tcp_t*)calloc(sizeof(j2k_tcp_t), j2k_cp->tw*j2k_cp->th);
|
||
|
j2k_default_tcp.tccps=(j2k_tccp_t*)calloc(sizeof(j2k_tccp_t), j2k_img->numcomps);
|
||
|
for (i=0; i<j2k_cp->tw*j2k_cp->th; i++) {
|
||
|
j2k_cp->tcps[i].tccps=(j2k_tccp_t*)calloc(sizeof(j2k_tccp_t), j2k_img->numcomps);
|
||
|
}
|
||
|
j2k_tile_data=(unsigned char**)calloc(j2k_cp->tw*j2k_cp->th, sizeof(char*));
|
||
|
j2k_tile_len=(int*)calloc(j2k_cp->tw*j2k_cp->th, sizeof(int));
|
||
|
j2k_state=J2K_STATE_MH;
|
||
|
|
||
|
// <INDEX>
|
||
|
img.Im_w=j2k_img->x1-j2k_img->x0;
|
||
|
img.Im_h=j2k_img->y1-j2k_img->y0;
|
||
|
img.Tile_x=j2k_cp->tdx;
|
||
|
img.Tile_y=j2k_cp->tdy;
|
||
|
img.Comp=j2k_img->numcomps;
|
||
|
img.tw=j2k_cp->tw;
|
||
|
img.th=j2k_cp->th;
|
||
|
img.tile=(info_tile_t*)malloc((img.tw*img.th)*sizeof(info_tile_t));
|
||
|
//</INDEX>
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
void j2k_read_com() {
|
||
|
int len;
|
||
|
len=cio_read(2);
|
||
|
|
||
|
// <INDEX>
|
||
|
if (j2k_state==J2K_STATE_MH)
|
||
|
{
|
||
|
if (!img.marker_mul.num_COM)
|
||
|
img.marker_mul.COM=(info_marker_t*)malloc(sizeof(info_marker_t));
|
||
|
else
|
||
|
img.marker_mul.COM=realloc(img.marker_mul.COM,(1+img.marker_mul.num_COM)*sizeof(info_marker_t));
|
||
|
img.marker_mul.COM[img.marker_mul.num_COM].type=J2K_MS_COM;
|
||
|
img.marker_mul.COM[img.marker_mul.num_COM].start_pos=cio_tell()-2;
|
||
|
img.marker_mul.COM[img.marker_mul.num_COM].len=len;
|
||
|
img.marker_mul.num_COM++;
|
||
|
}
|
||
|
// </INDEX>
|
||
|
|
||
|
cio_skip(len-2);
|
||
|
}
|
||
|
|
||
|
void j2k_read_cox(int compno) {
|
||
|
int i;
|
||
|
j2k_tcp_t *tcp;
|
||
|
j2k_tccp_t *tccp;
|
||
|
tcp=j2k_state==J2K_STATE_TPH?&j2k_cp->tcps[j2k_curtileno]:&j2k_default_tcp;
|
||
|
tccp=&tcp->tccps[compno];
|
||
|
tccp->numresolutions=cio_read(1)+1;
|
||
|
|
||
|
img.Decomposition=tccp->numresolutions-1; // <INDEX>
|
||
|
|
||
|
tccp->cblkw=cio_read(1)+2;
|
||
|
tccp->cblkh=cio_read(1)+2;
|
||
|
tccp->cblksty=cio_read(1);
|
||
|
tccp->qmfbid=cio_read(1);
|
||
|
if (tccp->csty&J2K_CP_CSTY_PRT) {
|
||
|
for (i=0; i<tccp->numresolutions; i++) {
|
||
|
int tmp=cio_read(1);
|
||
|
tccp->prcw[i]=tmp&0xf;
|
||
|
tccp->prch[i]=tmp>>4;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void j2k_read_cod() {
|
||
|
int len, i, pos;
|
||
|
j2k_tcp_t *tcp;
|
||
|
tcp=j2k_state==J2K_STATE_TPH?&j2k_cp->tcps[j2k_curtileno]:&j2k_default_tcp;
|
||
|
len=cio_read(2);
|
||
|
|
||
|
// <INDEX>
|
||
|
if (j2k_state==J2K_STATE_MH)
|
||
|
{
|
||
|
if (!img.marker_mul.num_COD)
|
||
|
img.marker_mul.COD=(info_marker_t*)malloc(sizeof(info_marker_t));
|
||
|
else
|
||
|
img.marker_mul.COD=realloc(img.marker_mul.COD,(1+img.marker_mul.num_COD)*sizeof(info_marker_t));
|
||
|
img.marker_mul.COD[img.marker_mul.num_COD].type=J2K_MS_COD;
|
||
|
img.marker_mul.COD[img.marker_mul.num_COD].start_pos=cio_tell()-2;
|
||
|
img.marker_mul.COD[img.marker_mul.num_COD].len=len;
|
||
|
img.marker_mul.num_COD++;
|
||
|
}
|
||
|
// </INDEX>
|
||
|
|
||
|
|
||
|
tcp->csty=cio_read(1);
|
||
|
tcp->prg=cio_read(1);
|
||
|
tcp->numlayers=cio_read(2);
|
||
|
tcp->mct=cio_read(1);
|
||
|
pos=cio_tell();
|
||
|
for (i=0; i<j2k_img->numcomps; i++) {
|
||
|
tcp->tccps[i].csty=tcp->csty&J2K_CP_CSTY_PRT;
|
||
|
cio_seek(pos);
|
||
|
j2k_read_cox(i);
|
||
|
}
|
||
|
//<INDEX>
|
||
|
img.Prog=tcp->prg;
|
||
|
img.Layer=tcp->numlayers;
|
||
|
//</INDEX>
|
||
|
}
|
||
|
|
||
|
void j2k_read_coc() {
|
||
|
int len, compno;
|
||
|
j2k_tcp_t *tcp;
|
||
|
tcp=j2k_state==J2K_STATE_TPH?&j2k_cp->tcps[j2k_curtileno]:&j2k_default_tcp;
|
||
|
len=cio_read(2);
|
||
|
// <INDEX>
|
||
|
if (j2k_state==J2K_STATE_MH)
|
||
|
{
|
||
|
if (!img.marker_mul.num_COC)
|
||
|
img.marker_mul.COC=(info_marker_t*)malloc(sizeof(info_marker_t));
|
||
|
else
|
||
|
img.marker_mul.COC=realloc(img.marker_mul.COC,(1+img.marker_mul.num_COC)*sizeof(info_marker_t));
|
||
|
img.marker_mul.COC[img.marker_mul.num_COC].type=J2K_MS_COC;
|
||
|
img.marker_mul.COC[img.marker_mul.num_COC].start_pos=cio_tell()-2;
|
||
|
img.marker_mul.COC[img.marker_mul.num_COC].len=len;
|
||
|
img.marker_mul.num_COC++;
|
||
|
}
|
||
|
// </INDEX>
|
||
|
|
||
|
|
||
|
compno=cio_read(j2k_img->numcomps<=256?1:2);
|
||
|
tcp->tccps[compno].csty=cio_read(1);
|
||
|
j2k_read_cox(compno);
|
||
|
}
|
||
|
|
||
|
void j2k_read_qcx(int compno, int len) {
|
||
|
int tmp;
|
||
|
j2k_tcp_t *tcp;
|
||
|
j2k_tccp_t *tccp;
|
||
|
int bandno, numbands;
|
||
|
tcp=j2k_state==J2K_STATE_TPH?&j2k_cp->tcps[j2k_curtileno]:&j2k_default_tcp;
|
||
|
tccp=&tcp->tccps[compno];
|
||
|
tmp=cio_read(1);
|
||
|
tccp->qntsty=tmp&0x1f;
|
||
|
tccp->numgbits=tmp>>5;
|
||
|
numbands=tccp->qntsty==J2K_CCP_QNTSTY_SIQNT?1:(tccp->qntsty==J2K_CCP_QNTSTY_NOQNT?len-1:(len-1)/2);
|
||
|
for (bandno=0; bandno<numbands; bandno++) {
|
||
|
int expn, mant;
|
||
|
if (tccp->qntsty==J2K_CCP_QNTSTY_NOQNT) { // WHY STEPSIZES WHEN NOQNT ?
|
||
|
expn=cio_read(1)>>3;
|
||
|
mant=0;
|
||
|
} else {
|
||
|
tmp=cio_read(2);
|
||
|
expn=tmp>>11;
|
||
|
mant=tmp&0x7ff;
|
||
|
}
|
||
|
tccp->stepsizes[bandno].expn=expn;
|
||
|
tccp->stepsizes[bandno].mant=mant;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void j2k_read_qcd() {
|
||
|
int len, i, pos;
|
||
|
len=cio_read(2);
|
||
|
|
||
|
// <INDEX>
|
||
|
if (j2k_state==J2K_STATE_MH)
|
||
|
{
|
||
|
img.marker[img.num_marker].type=J2K_MS_QCD;
|
||
|
img.marker[img.num_marker].start_pos=cio_tell()-2;
|
||
|
img.marker[img.num_marker].len=len;
|
||
|
img.num_marker++;
|
||
|
}
|
||
|
// </INDEX>
|
||
|
|
||
|
|
||
|
pos=cio_tell();
|
||
|
for (i=0; i<j2k_img->numcomps; i++) {
|
||
|
cio_seek(pos);
|
||
|
j2k_read_qcx(i, len-2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void j2k_read_qcc() {
|
||
|
int len, compno;
|
||
|
len=cio_read(2);
|
||
|
|
||
|
// <INDEX>
|
||
|
if (j2k_state==J2K_STATE_MH)
|
||
|
{
|
||
|
if (!img.marker_mul.num_QCC)
|
||
|
img.marker_mul.QCC=(info_marker_t*)malloc(sizeof(info_marker_t));
|
||
|
else
|
||
|
img.marker_mul.QCC=realloc(img.marker_mul.QCC,(1+img.marker_mul.num_QCC)*sizeof(info_marker_t));
|
||
|
img.marker_mul.QCC[img.marker_mul.num_QCC].type=J2K_MS_QCC;
|
||
|
img.marker_mul.QCC[img.marker_mul.num_QCC].start_pos=cio_tell()-2;
|
||
|
img.marker_mul.QCC[img.marker_mul.num_QCC].len=len;
|
||
|
img.marker_mul.num_QCC++;
|
||
|
}
|
||
|
// </INDEX>
|
||
|
|
||
|
|
||
|
compno=cio_read(j2k_img->numcomps<=256?1:2);
|
||
|
j2k_read_qcx(compno, len-2-(j2k_img->numcomps<=256?1:2));
|
||
|
}
|
||
|
|
||
|
void j2k_read_poc() {
|
||
|
int len, numpchgs, i;
|
||
|
j2k_tcp_t *tcp;
|
||
|
fprintf(stderr, "WARNING: POC marker segment processing not fully implemented\n");
|
||
|
tcp=j2k_state==J2K_STATE_TPH?&j2k_cp->tcps[j2k_curtileno]:&j2k_default_tcp;
|
||
|
len=cio_read(2);
|
||
|
|
||
|
// <INDEX>
|
||
|
if (j2k_state==J2K_STATE_MH)
|
||
|
{
|
||
|
img.marker[img.num_marker].type=J2K_MS_POC;
|
||
|
img.marker[img.num_marker].start_pos=cio_tell()-2;
|
||
|
img.marker[img.num_marker].len=len;
|
||
|
img.num_marker++;
|
||
|
}
|
||
|
// </INDEX>
|
||
|
|
||
|
|
||
|
numpchgs=(len-2)/(5+2*(j2k_img->numcomps<=256?1:2));
|
||
|
for (i=0; i<numpchgs; i++) {
|
||
|
j2k_poc_t *poc;
|
||
|
poc=&tcp->pocs[i];
|
||
|
poc->resno0=cio_read(1);
|
||
|
poc->compno0=cio_read(j2k_img->numcomps<=256?1:2);
|
||
|
poc->layno1=cio_read(2);
|
||
|
poc->resno1=cio_read(1);
|
||
|
poc->compno1=cio_read(j2k_img->numcomps<=256?1:2);
|
||
|
poc->prg=cio_read(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void j2k_read_crg() {
|
||
|
int len;
|
||
|
len=cio_read(2);
|
||
|
|
||
|
// <INDEX>
|
||
|
if (j2k_state==J2K_STATE_MH)
|
||
|
{
|
||
|
img.marker[img.num_marker].type=J2K_MS_CRG;
|
||
|
img.marker[img.num_marker].start_pos=cio_tell()-2;
|
||
|
img.marker[img.num_marker].len=len;
|
||
|
img.num_marker++;
|
||
|
}
|
||
|
// </INDEX>
|
||
|
|
||
|
fprintf(stderr, "WARNING: CRG marker segment processing not implemented\n");
|
||
|
cio_skip(len-2);
|
||
|
}
|
||
|
|
||
|
void j2k_read_tlm() {
|
||
|
int len;
|
||
|
len=cio_read(2);
|
||
|
|
||
|
// <INDEX>
|
||
|
if (j2k_state==J2K_STATE_MH)
|
||
|
{
|
||
|
if (!img.marker_mul.num_TLM)
|
||
|
img.marker_mul.TLM=(info_marker_t*)malloc(sizeof(info_marker_t));
|
||
|
else
|
||
|
img.marker_mul.TLM=realloc(img.marker_mul.TLM,(1+img.marker_mul.num_TLM)*sizeof(info_marker_t));
|
||
|
img.marker_mul.TLM[img.marker_mul.num_TLM].type=J2K_MS_TLM;
|
||
|
img.marker_mul.TLM[img.marker_mul.num_TLM].start_pos=cio_tell()-2;
|
||
|
img.marker_mul.TLM[img.marker_mul.num_TLM].len=len;
|
||
|
img.marker_mul.num_TLM++;
|
||
|
}
|
||
|
// </INDEX>
|
||
|
|
||
|
fprintf(stderr, "WARNING: TLM marker segment processing not implemented\n");
|
||
|
cio_skip(len-2);
|
||
|
}
|
||
|
|
||
|
void j2k_read_plm() {
|
||
|
int len;
|
||
|
len=cio_read(2);
|
||
|
|
||
|
// <INDEX>
|
||
|
if (j2k_state==J2K_STATE_MH)
|
||
|
{
|
||
|
if (!img.marker_mul.num_PLM)
|
||
|
img.marker_mul.PLM=(info_marker_t*)malloc(sizeof(info_marker_t));
|
||
|
else
|
||
|
img.marker_mul.PLM=realloc(img.marker_mul.PLM,(1+img.marker_mul.num_PLM)*sizeof(info_marker_t));
|
||
|
img.marker_mul.PLM[img.marker_mul.num_PLM].type=J2K_MS_PLM;
|
||
|
img.marker_mul.PLM[img.marker_mul.num_PLM].start_pos=cio_tell()-2;
|
||
|
img.marker_mul.PLM[img.marker_mul.num_PLM].len=len;
|
||
|
img.marker_mul.num_PLM++;
|
||
|
}
|
||
|
// </INDEX>
|
||
|
|
||
|
fprintf(stderr, "WARNING: PLM marker segment processing not implemented\n");
|
||
|
cio_skip(len-2);
|
||
|
}
|
||
|
|
||
|
void j2k_read_plt() {
|
||
|
int len;
|
||
|
len=cio_read(2);
|
||
|
fprintf(stderr, "WARNING: PLT marker segment processing not implemented\n");
|
||
|
cio_skip(len-2);
|
||
|
}
|
||
|
|
||
|
void j2k_read_ppm() {
|
||
|
int len;
|
||
|
len=cio_read(2);
|
||
|
// <INDEX>
|
||
|
if (j2k_state==J2K_STATE_MH)
|
||
|
{
|
||
|
img.marker[img.num_marker].type=J2K_MS_PPM;
|
||
|
img.marker[img.num_marker].start_pos=cio_tell()-2;
|
||
|
img.marker[img.num_marker].len=len;
|
||
|
img.num_marker++;
|
||
|
}
|
||
|
// </INDEX>
|
||
|
|
||
|
fprintf(stderr, "WARNING: PPM marker segment processing not implemented\n");
|
||
|
cio_skip(len-2);
|
||
|
}
|
||
|
|
||
|
void j2k_read_ppt() {
|
||
|
int len;
|
||
|
len=cio_read(2);
|
||
|
fprintf(stderr, "WARNING: PPT marker segment processing not implemented\n");
|
||
|
cio_skip(len-2);
|
||
|
}
|
||
|
|
||
|
void j2k_read_sot() {
|
||
|
int len, tileno, totlen, partno, numparts, i;
|
||
|
j2k_tcp_t *tcp;
|
||
|
j2k_tccp_t *tmp;
|
||
|
len=cio_read(2);
|
||
|
tileno=cio_read(2);
|
||
|
//<INDEX>
|
||
|
if (!tileno) img.Main_head_end=cio_tell()-6; // Correction End = First byte of first SOT
|
||
|
img.tile[tileno].start_pos=cio_tell()-6;
|
||
|
img.tile[tileno].num_tile=tileno;
|
||
|
// </INDEX>
|
||
|
totlen=cio_read(4);
|
||
|
if (!totlen) totlen = cio_numbytesleft() + 8;
|
||
|
|
||
|
img.tile[tileno].end_pos=totlen+img.tile[tileno].start_pos; // <INDEX>
|
||
|
|
||
|
partno=cio_read(1);
|
||
|
numparts=cio_read(1);
|
||
|
j2k_curtileno=tileno;
|
||
|
j2k_eot=cio_getbp()-12+totlen;
|
||
|
j2k_state=J2K_STATE_TPH;
|
||
|
tcp=&j2k_cp->tcps[j2k_curtileno];
|
||
|
tmp=tcp->tccps;
|
||
|
*tcp=j2k_default_tcp;
|
||
|
tcp->tccps=tmp;
|
||
|
for (i=0; i<j2k_img->numcomps; i++) {
|
||
|
tcp->tccps[i]=j2k_default_tcp.tccps[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void j2k_read_sod() {
|
||
|
int len;
|
||
|
unsigned char *data;
|
||
|
img.tile[j2k_curtileno].end_header=cio_tell()-1; //<INDEX>
|
||
|
len=int_min(j2k_eot-cio_getbp(), cio_numbytesleft());
|
||
|
j2k_tile_len[j2k_curtileno]+=len;
|
||
|
data=(unsigned char*)realloc(j2k_tile_data[j2k_curtileno], j2k_tile_len[j2k_curtileno]);
|
||
|
memcpy(data, cio_getbp(), len);
|
||
|
j2k_tile_data[j2k_curtileno]=data;
|
||
|
cio_skip(len);
|
||
|
j2k_state=J2K_STATE_TPHSOT;
|
||
|
|
||
|
}
|
||
|
|
||
|
void j2k_read_rgn() {
|
||
|
int len, compno, roisty;
|
||
|
j2k_tcp_t *tcp;
|
||
|
tcp=j2k_state==J2K_STATE_TPH?&j2k_cp->tcps[j2k_curtileno]:&j2k_default_tcp;
|
||
|
len=cio_read(2);
|
||
|
|
||
|
// <INDEX>
|
||
|
if (j2k_state==J2K_STATE_MH)
|
||
|
{
|
||
|
if (!img.marker_mul.num_RGN)
|
||
|
img.marker_mul.RGN=(info_marker_t*)malloc(sizeof(info_marker_t));
|
||
|
else
|
||
|
img.marker_mul.RGN=realloc(img.marker_mul.RGN,(1+img.marker_mul.num_RGN)*sizeof(info_marker_t));
|
||
|
img.marker_mul.RGN[img.marker_mul.num_RGN].type=J2K_MS_RGN;
|
||
|
img.marker_mul.RGN[img.marker_mul.num_RGN].start_pos=cio_tell()-2;
|
||
|
img.marker_mul.RGN[img.marker_mul.num_RGN].len=len;
|
||
|
img.marker_mul.num_RGN++;
|
||
|
}
|
||
|
// </INDEX>
|
||
|
|
||
|
|
||
|
compno=cio_read(j2k_img->numcomps<=256?1:2);
|
||
|
roisty=cio_read(1);
|
||
|
tcp->tccps[compno].roishift=cio_read(1);
|
||
|
}
|
||
|
|
||
|
void j2k_read_eoc() {
|
||
|
int tileno;
|
||
|
tcd_init(j2k_img, j2k_cp, &img);
|
||
|
for (tileno=0; tileno<j2k_cp->tw*j2k_cp->th; tileno++) {
|
||
|
tcd_decode_tile(j2k_tile_data[tileno], j2k_tile_len[tileno], tileno, &img);
|
||
|
}
|
||
|
|
||
|
j2k_state=J2K_STATE_MT;
|
||
|
longjmp(j2k_error, 1);
|
||
|
|
||
|
}
|
||
|
|
||
|
void j2k_read_unk() {
|
||
|
fprintf(stderr, "warning: unknown marker\n");
|
||
|
}
|
||
|
|
||
|
int j2k_index_JPIP(char *Idx_file, char *J2K_file, int len){
|
||
|
FILE *dest;
|
||
|
char *index;
|
||
|
int pos_iptr, end_pos;
|
||
|
int len_cidx, pos_cidx;
|
||
|
int len_jp2c, pos_jp2c;
|
||
|
int len_fidx, pos_fidx;
|
||
|
|
||
|
dest=fopen(Idx_file, "wb");
|
||
|
if (!dest) {
|
||
|
fprintf(stderr,"Failed to open %s for reading !!\n",Idx_file);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// INDEX MODE JPIP
|
||
|
index=(char*)malloc(len);
|
||
|
cio_init(index, len);
|
||
|
jp2_write_jp();
|
||
|
jp2_write_ftyp();
|
||
|
|
||
|
jp2_write_jp2h(j2k_img);
|
||
|
jp2_write_dbtl(Idx_file);
|
||
|
|
||
|
pos_iptr=cio_tell();
|
||
|
cio_skip(24); // IPTR further !
|
||
|
|
||
|
pos_jp2c=cio_tell();
|
||
|
len_jp2c=jp2_write_jp2c(J2K_file);
|
||
|
|
||
|
pos_cidx=cio_tell();
|
||
|
len_cidx=jpip_write_cidx(pos_jp2c+8,img, j2k_cp); // Correction len_jp2C --> pos_jp2c+8
|
||
|
|
||
|
pos_fidx=cio_tell();
|
||
|
len_fidx=jpip_write_fidx(pos_jp2c, len_jp2c, pos_cidx, len_cidx);
|
||
|
|
||
|
end_pos=cio_tell();
|
||
|
cio_seek(pos_iptr);
|
||
|
jpip_write_iptr(pos_fidx,len_fidx);
|
||
|
cio_seek(end_pos);
|
||
|
|
||
|
fwrite(index, 1, cio_tell(), dest);
|
||
|
free(index);
|
||
|
|
||
|
fclose(dest);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
typedef struct {
|
||
|
int id;
|
||
|
int states;
|
||
|
void (*handler)();
|
||
|
} j2k_dec_mstabent_t;
|
||
|
|
||
|
j2k_dec_mstabent_t j2k_dec_mstab[]={
|
||
|
{J2K_MS_SOC, J2K_STATE_MHSOC, j2k_read_soc},
|
||
|
{J2K_MS_SOT, J2K_STATE_MH|J2K_STATE_TPHSOT, j2k_read_sot},
|
||
|
{J2K_MS_SOD, J2K_STATE_TPH, j2k_read_sod},
|
||
|
{J2K_MS_EOC, J2K_STATE_TPHSOT, j2k_read_eoc},
|
||
|
{J2K_MS_SIZ, J2K_STATE_MHSIZ, j2k_read_siz},
|
||
|
{J2K_MS_COD, J2K_STATE_MH|J2K_STATE_TPH, j2k_read_cod},
|
||
|
{J2K_MS_COC, J2K_STATE_MH|J2K_STATE_TPH, j2k_read_coc},
|
||
|
{J2K_MS_RGN, J2K_STATE_MH|J2K_STATE_TPH, j2k_read_rgn},
|
||
|
{J2K_MS_QCD, J2K_STATE_MH|J2K_STATE_TPH, j2k_read_qcd},
|
||
|
{J2K_MS_QCC, J2K_STATE_MH|J2K_STATE_TPH, j2k_read_qcc},
|
||
|
{J2K_MS_POC, J2K_STATE_MH|J2K_STATE_TPH, j2k_read_poc},
|
||
|
{J2K_MS_TLM, J2K_STATE_MH, j2k_read_tlm},
|
||
|
{J2K_MS_PLM, J2K_STATE_MH, j2k_read_plm},
|
||
|
{J2K_MS_PLT, J2K_STATE_TPH, j2k_read_plt},
|
||
|
{J2K_MS_PPM, J2K_STATE_MH, j2k_read_ppm},
|
||
|
{J2K_MS_PPT, J2K_STATE_TPH, j2k_read_ppt},
|
||
|
{J2K_MS_SOP, 0, 0},
|
||
|
{J2K_MS_CRG, J2K_STATE_MH, j2k_read_crg},
|
||
|
{J2K_MS_COM, J2K_STATE_MH|J2K_STATE_TPH, j2k_read_com},
|
||
|
{0, J2K_STATE_MH|J2K_STATE_TPH, j2k_read_unk}
|
||
|
};
|
||
|
|
||
|
j2k_dec_mstabent_t *j2k_dec_mstab_lookup(int id) {
|
||
|
j2k_dec_mstabent_t *e;
|
||
|
for (e=j2k_dec_mstab; e->id!=0; e++) {
|
||
|
if (e->id==id) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return e;
|
||
|
}
|
||
|
|
||
|
LIBJ2K_API int j2k_decode(unsigned char *src, int len, j2k_image_t **image, j2k_cp_t **cp) {
|
||
|
if (setjmp(j2k_error)) {
|
||
|
if (j2k_state!=J2K_STATE_MT) {
|
||
|
fprintf(stderr, "WARNING: incomplete bitstream\n");
|
||
|
return 0;
|
||
|
}
|
||
|
return cio_numbytes();
|
||
|
}
|
||
|
j2k_img=(j2k_image_t*)malloc(sizeof(j2k_image_t));
|
||
|
j2k_cp=(j2k_cp_t*)malloc(sizeof(j2k_cp_t));
|
||
|
*image=j2k_img;
|
||
|
*cp=j2k_cp;
|
||
|
j2k_state=J2K_STATE_MHSOC;
|
||
|
cio_init(src, len);
|
||
|
for (;;) {
|
||
|
j2k_dec_mstabent_t *e;
|
||
|
int id=cio_read(2);
|
||
|
if (id>>8!=0xff) {
|
||
|
fprintf(stderr, "%.8x: expected a marker instead of %x\n", cio_tell()-2, id);
|
||
|
return 0;
|
||
|
}
|
||
|
e=j2k_dec_mstab_lookup(id);
|
||
|
if (!(j2k_state & e->states)) {
|
||
|
fprintf(stderr, "%.8x: unexpected marker %x\n", cio_tell()-2, id);
|
||
|
return 0;
|
||
|
}
|
||
|
if (e->handler) {
|
||
|
(*e->handler)();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
#ifdef WIN32
|
||
|
#include <windows.h>
|
||
|
|
||
|
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
|
||
|
switch (ul_reason_for_call) {
|
||
|
case DLL_PROCESS_ATTACH:
|
||
|
case DLL_THREAD_ATTACH:
|
||
|
case DLL_THREAD_DETACH:
|
||
|
case DLL_PROCESS_DETACH:
|
||
|
break;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
extern info_image_t img;
|
||
|
|
||
|
|
||
|
int main(int argc, char **argv)
|
||
|
{
|
||
|
FILE *src;
|
||
|
int totlen;
|
||
|
char *j2kfile;
|
||
|
j2k_image_t *imgg;
|
||
|
j2k_cp_t *cp;
|
||
|
|
||
|
if (argc!=3)
|
||
|
{
|
||
|
fprintf(stderr,"\nERROR in entry : index_create J2K-file Idx-file\n\n");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
src=fopen(argv[1], "rb");
|
||
|
if (!src) {
|
||
|
fprintf(stderr,"Failed to open %s for reading !!\n",argv[1]);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// length of the codestream
|
||
|
fseek(src, 0, SEEK_END);
|
||
|
totlen=ftell(src);
|
||
|
fseek(src, 0, SEEK_SET);
|
||
|
|
||
|
j2kfile=(char*)malloc(totlen);
|
||
|
fread(j2kfile, 1, totlen, src);
|
||
|
|
||
|
img.marker=(info_marker_t*)malloc(32*sizeof(info_marker_t));
|
||
|
img.num_marker=0;
|
||
|
img.marker_mul.num_COD=0;
|
||
|
img.marker_mul.num_COC=0;
|
||
|
img.marker_mul.num_RGN=0;
|
||
|
img.marker_mul.num_QCC=0;
|
||
|
img.marker_mul.num_TLM=0;
|
||
|
img.marker_mul.num_PLM=0;
|
||
|
img.marker_mul.num_COM=0;
|
||
|
|
||
|
// decode
|
||
|
|
||
|
if (!j2k_decode(j2kfile, totlen, &imgg, &cp)) {
|
||
|
fprintf(stderr, "Index_creator: failed to decode image!\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
free(j2kfile);
|
||
|
|
||
|
fseek(src, 0, SEEK_SET);
|
||
|
img.codestream_size=totlen;
|
||
|
|
||
|
j2k_index_JPIP(argv[2],argv[1],totlen*2>30000?totlen*2:30000);
|
||
|
|
||
|
fclose(src);
|
||
|
|
||
|
j2k_clean();
|
||
|
return 1;
|
||
|
}
|