openjpeg/src/bin/fltk/flviewer/read_jpeg2000.cxx

3515 lines
73 KiB
C++

#include <config.h>
/*
* author(s) and license
*/
/*
* Part 1 JPEG 2000 Image Core Coding System (J2K, JP2)
* 15444-1annexi.pdf: new JP2 file format
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#ifdef _WIN32
#include <windows.h>
#include <io.h>
#define snprintf sprintf_s
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#define sprintf _scprintf
#define strdup _strdup
#else /* not _WIN32 */
#define __STDC_FORMAT_MACROS
#include <stdint.h>
#include <stddef.h>
#endif /* _WIN32 */
#include <FL/Fl.H>
#include <FL/Fl_Tree.H>
#include <FL/Fl_Pixmap.H>
#include <FL/fl_utf8.h>
#include "opj_inttypes.h"
#include "opj_stdint.h"
#include "viewerdefs.hh"
#include "tree.hh"
//-----------------------------------
//WARNING: SHOW_PACKETS may need a very long time to be shown:
//#define SHOW_PACKETS
#define TREE_LABEL_SIZE 11
unsigned char box_name[33];
//-----------------------------------
//#define DEBUG_MAIN
//#define READ_ALL_SOT_MARKERS
//#define PSOT_LENG_FROM_BUF_END
//#define DEBUG_DEFAULT_TEST
//#define DEBUG_BOXHEADER
//#define DEBUG_BOXHEADER8
//#define COLLECT_CURV
//#define DEBUG_CURV
//#define DEBUG_XYZ
//#define DEBUG_ICC_PROFILE
//#define DEBUG_DESC
//#define DEBUG_JP2C
//#define SHOW_COM
//#define QUANT_AS_STRING
//#define SHOW_SIZE_VALUE
//#define SHOW_PCLR_ENTRY
//#define DEBUG_JP2C_END
//#define SHOW_XML
//#define SHOW_UUID_DATA
//---------------- FORWARD ----------------
//read_ihdr(), read_bpcc()
static unsigned short nr_components;
//read_ppt()
static unsigned int ppt, ppt_store, ppt_len;
//read_ppm()
static unsigned int ppm_prev;
static unsigned int ppm_store;
//read_poc()
static unsigned char has_POC;
static unsigned int numpocs;
//read_siz()
static short extended_cap, Csiz;
static int one_tile_only;
//read_cod()
static short entropy_coder, use_sop_marker, use_eph_marker;
static short max_precincts, user_defined_precincts;
static unsigned short irreversible_transform, reversible_transform,
transform;
//-------------- end FORWARD --------------
static jp2_color_t jp2_color;
static char item_name[MAX_ITEMBUF+2];
static const char *L_document_xpm[] =
{
"11 11 3 1",
". c None",
"x c #d8d8f8",
"@ c #202060",
".@@@@@@....",
".@xxx@.@...",
".@xxx@..@..",
".@xxx@@@@@.",
".@xxxxxxx@.",
".@xxxxxxx@.",
".@xxxxxxx@.",
".@xxxxxxx@.",
".@xxxxxxx@.",
".@xxxxxxx@.",
".@@@@@@@@@."
};
static Fl_Pixmap L_documentpixmap(L_document_xpm);
/*-----------------
COM: Comment and extension marker
COC: Coding style component marker
COD: Coding style default maker
EPH: End of packet marker
EOI: End of image marker (EOC: end of codestream )
PLM: Packet length, main header marker
PLT: Packet length, tile-part header marker
POD: Progression order change (POC), default marker
PPM: Packed packet headers, main header marker
PPT: Packed packet headers, tile-part header marker
QCC: Quantization component marker
QCD: Quantization default marker
RGN: Region of interest marker
SIZ: Size of image marker
SOC: Start of image (codestream) marker
SOP: Start of packet marker
SOT: Start of tile marker
TLM: Tile length marker
Part 2:
DCO: Variable DC offset
VMS: Visual masking
DFS: Downsampling factor style
ADS: Arbitrary decomposition style
CBD: Component bit depth
MCT: Multiple component transformation definition
MCC: Multiple component collection
MIC: Multiple component intermediate collection
NLT: Non-linearity point transformation
ARN: Arbitrary region of interest marker: obsolete?
Part 2, Part 10:
ATK: Arbitrary transformation kernels
------------------*/
#define J2K_SOC 0xff4f
#define J2K_SIZ 0xff51
#define J2K_COD 0xff52
#define J2K_COC 0xff53
#define J2K_TLM 0xff55
#define J2K_PLM 0xff57
#define J2K_PLT 0xff58
#define J2K_QCD 0xff5c
#define J2K_QCC 0xff5d
#define J2K_RGN 0xff5e
#define J2K_POC 0xff5f
#define J2K_PPM 0xff60
#define J2K_PPT 0xff61
#define J2K_CRG 0xff63
#define J2K_COM 0xff64
#define J2K_SEC 0xff65
#define J2K_EPB 0xff66
#define J2K_ESD 0xff67
#define J2K_EPC 0xff68
#define J2K_RED 0xff69
/*------- Part 2 ---------*/
#define J2K_DCO 0xff70
#define J2K_VMS 0xff71
#define J2K_DFS 0xff72
#define J2K_ADS 0xff73
#define J2K_MCT 0xff74
#define J2K_MCC 0xff75
#define J2K_NLT 0xff76
#define J2K_MIC 0xff77
#define J2K_CBD 0xff78
#define J2K_ATK 0xff79
//ARN
/*----------------------*/
#define J2K_SOT 0xff90
#define J2K_SOP 0xff91
#define J2K_EPH 0xff92
#define J2K_SOD 0xff93
#define J2K_INSEC 0xff94
#define J2K_EOC 0xffd9
static const char *reg_text[]=
{
" General use (binary values)",
" General use (ISO 8859-1 (latin-1) values)",
" Reserved use",
NULL
};
static const char *enumcs_text(int i)
{
static const char *cs_text[]=
{
"Bi-level",
"YCbCr(1)",
"",
"YCbCr(2)",
"YCbCr(3)",
"",
"",
"",
"",
"PhotoCD",
"",
"CMY",
"CMYK",
"YCCK",
"CIELab",
"Bi-level(2)",
"sRGB",
"greyscale",
"sYCC",
"CIEJab",
"e-sRGB",
"ROMM-RGB",
"YPbPr(1125/60)",
"YPbPr(1250/50)",
"e-sYCC",
NULL
};
if(i < 0 || i > 24) return "Unknown";
return cs_text[i];
}//enumcs_text()
static void init()
{
nr_components = 0;
ppt = ppt_store = ppt_len = 0;
ppm_prev = ppm_store = 0;
has_POC = 0;
numpocs = 0;
extended_cap = 0;
Csiz = 0;
one_tile_only = 0;
entropy_coder = use_sop_marker = use_eph_marker = 0;
max_precincts = user_defined_precincts = 0;
irreversible_transform = reversible_transform = transform = 0;
}
unsigned int get4(const unsigned char *b)
{
return (b[0]<<24)|(b[1]<<16)|(b[2]<<8)|b[3];
}
unsigned int get2(const unsigned char *b)
{
return (b[0]<<8)|b[1];
}
uint64_t get8(const unsigned char *b)
{
uint64_t v;
unsigned int v2;
v = (uint64_t)get4(b); v2 = get4(b+4);
return ((v<<32) | v2);
}
unsigned int get_size(const unsigned char *b, unsigned int size)
{
unsigned int i, v = b[0];
#ifdef SHOW_SIZE_VALUE
fprintf(stderr,"\n=== get_size(%u) ===\n\n",size);
#endif
for(i = 1; i < size; ++i)
{
v = (v<<8) | b[i];
}
return v;
}
static void apply_cdef(jp2_cdef_info_t *info, unsigned short n)
{
unsigned short i, j, last;
for(i = 0; i < n; ++i)
{
if(info[i].asoc != 65535 && info[i].typ != 65535) continue;
last = n - 1;
for(j = i; j < last; ++j)
{
info[j] = info[j+1];
}
--n;
}
FLViewer_set_max_components(n);
}
static void read_curv_type(unsigned char *tag)
{
#ifdef DEBUG_CURV
unsigned char *start;
#endif
#ifdef COLLECT_CURV
unsigned int i,
unsigned short v;
#endif
unsigned int n;
tag += 4;//reserved
n = get4(tag); tag += 4;
#ifdef DEBUG_CURV
start = tag;
fprintf(stderr," curv size[%u]\n",n);
#endif
if(n == 1)
{
#ifdef DEBUG_CURV
/* gamma */
unsigned short v = get2(tag);
fprintf(stderr," curv[0]gamma(%u.%d)\n",(v>>8),v & 0xff);
#endif
return;
}
#ifdef COLLECT_CURV
for(i = 0; i < n; ++i)
{
v = get2(tag); tag += 2;
fprintf(stderr," curv[%u] %u\n",i,v);
}
#elif DEBUG_CURV
i = 0;
v = get2(tag); tag += 2;
fprintf(stderr," curv[%d] %u\n",i,v);
v = get2(tag); tag += 2;
fprintf(stderr," curv[%d] %u\n",i+1,v);
i = n/2; tag = start + i*2;
v = get2(tag); tag += 2;
fprintf(stderr," curv[%d] %u\n",i,v);
v = get2(tag); tag += 2;
fprintf(stderr," curv[%d] %u\n",i+1,v);
i = n - 2; tag = start + i * 2;
v = get2(tag); tag += 2;
fprintf(stderr," curv[%d] %u\n",i,v);
v = get2(tag); tag += 2;
fprintf(stderr," curv[%d] %u\n",i+1,v);
#endif
}
static void read_XYZ_type(unsigned char *tag)
{
#ifdef DEBUG_XYZ
unsigned int a,b,c;
#endif
tag += 4;//reserved
#ifdef DEBUG_XYZ
a = get4(tag); b = get4(tag+4); c = get4(tag+8);
fprintf(stderr," XYZ(%u.%u, %u.%u, %u.%u)",
a>>16,a & 0xff,a>>16,a & 0xff,a>>16,a & 0xff);
#endif
}
/* Is NOT ascii text, but UTF8 text */
static void read_desc_type(unsigned char *tag, unsigned int size)
{
#ifdef DEBUG_DESC
unsigned int i;
fputs(" DESC(", stderr);
for(i = 0; i < size; ++i)
{
if(tag[i] == '/') fputs("\n/", stderr);
else
if( !iscntrl(tag[i])) fprintf(stderr,"%c",tag[i]);
}
fputs(")", stderr);
#endif //DEBUG_DESC
}
static void add_sub_item()
{
Fl_Tree_Item *sub = tree->add(item_name);
sub->usericon(&L_documentpixmap);
}
static void read_icc_profile(unsigned char *s, const char *name_src)
{
char sign[5], proclass[5];
char cspace[5], pcs[5], platsign[5];
unsigned char *version;
unsigned char *profile_start, *profile_end, *tag;
int profile_len, siz;
unsigned cmmtype, da0, da1;
unsigned int proflags, rendintent;
unsigned int ciex,ciey,ciez;
unsigned int nt, i;
unsigned short year,month,day,hour,min,sec;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/ICC profile box",name_buf);
add_sub_item();
profile_start = s;
profile_len = get4(s); s += 4;
profile_end = s + profile_len;
cmmtype = get4(s); s += 4;
version = s; s += 4;
proclass[4] = 0; memcpy(proclass, s, 4); s += 4;
cspace[4] = 0; memcpy(cspace, s, 4); s += 4;
pcs[4] = 0; memcpy(pcs, s, 4); s += 4;
year = get2(s); s += 2; month = get2(s); s += 2; day = get2(s); s += 2;
hour = get2(s); s += 2; min = get2(s); s += 2; sec = get2(s); s += 2;
sign[4] = 0; memcpy(sign, s, 4); s += 4;
platsign[4] = 0; memcpy(platsign, s, 4); s += 4;
proflags = get4(s); s += 4;
s += 4;/* device manufacturer */
s += 4;/* device model */
da0 = get4(s); s += 4; da1 = get4(s); s += 4;
rendintent = get4(s); s += 4;
ciex = get4(s); s += 4; ciey = get4(s); s += 4; ciez = get4(s); s += 4;
s += 4;/* creator */
s += 16;/* ID */
snprintf(item_name, MAX_ITEMBUF, "%s/cmmtype(%#x)",name_buf,cmmtype);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/version(%u.%u.%u.0)",name_buf,
version[0],version[1],version[2]);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/class(%s)",name_buf,proclass);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/color-space(%s)",name_buf,cspace);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/profile-connection-space(%s)",
name_buf,pcs);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/date(%u.%u.%u) time(%u:%u:%u)",
name_buf,
day,month,year,hour,min,sec);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/signature(%s)",name_buf,sign);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/platform-signature(%s)",
name_buf,platsign);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF,
"%s/profile-flags(%#x) [0] %u [1] %u [2:15] %u",
name_buf,proflags,proflags & 1,proflags & 2, proflags & 0xfffc);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/device-attr(%u) white(%u)",
name_buf, da0,(da1&1));
add_sub_item();
snprintf(item_name, MAX_ITEMBUF,
"%s/negative(%u) matte(%u) transparent(%u)",
name_buf,(da1&2),(da1&4),(da1&8));
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/rendering-intent(%#x)",name_buf,
rendintent);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/CIE: x(%u.%u) y(%u.%u) z(%u.%u)",
name_buf, (ciex>>16),ciex&0xffff,(ciey>>16),ciey&0xffff,(ciez>>16),
ciez&0xffff);
add_sub_item();
s = profile_start + 128;
nt = get4(s); s += 4;
for(i = 0; i < nt; ++i)
{
unsigned int off;
memcpy(sign, s, 4); s += 4;
off = get4(s); s += 4;
siz = get4(s); s += 4;
tag = profile_start + off;
#ifdef DEBUG_ICC_PROFILE
fprintf(stderr,"[%u] signature(%s) size[%d]\n",i,sign,siz);
#endif
//issue328-Ninja.jp2 :
if(s + siz > profile_end || tag > profile_end)
{
fprintf(stderr, "\nflviewer/read_jpeg2000.cxx:%d:\n"
"\t=== ICC Profile seems to be chopped. RETURN. ===\n\n",__LINE__);
return;
}
if(memcmp(sign, "cprt", 4) == 0)
{
//#ifdef DEBUG_ICC
char buf[32];
int j, k = 0;
memset(buf, 0, 32);
for(j = 4; j < siz; ++j)
{
if(iscntrl(tag[j])) continue;
buf[k] = tag[j]; ++k;
if(k == 31) break;
}
snprintf(item_name, MAX_ITEMBUF, "%s/%s",name_buf,buf);
add_sub_item();
//#endif
}
else
if(memcmp(sign, "desc", 4) == 0)
{
//fprintf(stderr,"%s:%d:\n\tTRACE\n",__FILE__,__LINE__);
read_desc_type(tag + 4, siz - 4);
}
else
{
unsigned char buf[5];
buf[4] = 0; memcpy(buf, tag, 4); tag += 4;
if(memcmp(buf, "curv", 4) == 0)
{
//fprintf(stderr,"%s:%d:\n\tTRACE\n",__FILE__,__LINE__);
read_curv_type(tag);
}
else
if(memcmp(buf, "XYZ ", 4) == 0)
{
//fprintf(stderr,"%s:%d:\n\tTRACE\n",__FILE__,__LINE__);
read_XYZ_type(tag);
}
else
if(memcmp(buf, "desc", 4) == 0)
{
//fprintf(stderr,"%s:%d:\n\tTRACE\n",__FILE__,__LINE__);
read_desc_type(tag, siz-4);
}
else
{
/*-----------
fprintf(stderr," %s\n", buf);
-------------*/
}
}
#ifdef DEBUG_ICC_PROFILE
fprintf(stderr,"\n");
#endif
}
}/* read_icc_profile() */
uint64_t read_boxheader(unsigned char *box, unsigned char *dend,
unsigned int *out_siz)
{
uint64_t len;
len = (uint64_t)get4(box);
memcpy(box_name, box + 4, 4); box_name[4] = 0; *out_siz = 8; // 4 + 4
#ifdef DEBUG_BOXHEADER
fprintf(stderr,"\tREAD[1]BOX_NAME(%s) BOX_LEN(%" PRIu64 ")\n",
box_name,len);
#endif
if(len == 0) return (uint64_t)(dend - box);//last box
if(len > 1) return len;
if(sizeof(uint64_t) == 8)
{
len = get8(box+8); *out_siz = 16; // 4 + 4 + 8
}
else
{
fprintf(stderr,"%s:%d:\n\tread_boxheader ==> can not read 8 bytes."
" STOP.\n",__FILE__,__LINE__);
len = 0; *out_siz = 16; // 4 + 4 + 8
}
#ifdef DEBUG_BOXHEADER8
fprintf(stderr,"\tREAD[2] BOX_LEN(%" PRIu64 ")\n",
len);
#endif
return len;
}
static unsigned short read_siz(unsigned char *s, const char *name_src)
{
unsigned int len, x, y, x0, y0,xt,yt, xt0,yt0;
unsigned short r, c, i, xr, yr, prec, depth, sign;
int tile_w, tile_h, image_w, image_h;
int max_tiles;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Image and tile size marker",
name_buf);
add_sub_item();
len = get2(s); s += 2;//Lsiz = 38 + 3 * Csiz
r = get2(s); s += 2;//Rsiz
snprintf(item_name, MAX_ITEMBUF, "%s/Rsiz(%d)",name_buf,r);
add_sub_item();
x = get4(s); s += 4;//Xsiz
snprintf(item_name, MAX_ITEMBUF, "%s/Xsiz(%u)",name_buf,x);
add_sub_item();
y = get4(s); s += 4;//Ysiz
snprintf(item_name, MAX_ITEMBUF, "%s/Ysiz(%u)",name_buf,y);
add_sub_item();
x0 = get4(s); s += 4;//XOsiz
snprintf(item_name, MAX_ITEMBUF, "%s/X0siz(%u)",name_buf,x0);
add_sub_item();
y0 = get4(s); s += 4;//YOsiz
snprintf(item_name, MAX_ITEMBUF, "%s/Y0siz(%u)",name_buf,y0);
add_sub_item();
xt = get4(s); s += 4;//XTsiz
snprintf(item_name, MAX_ITEMBUF, "%s/XTsiz(%u)",name_buf,xt);
add_sub_item();
yt = get4(s); s += 4;//YTsiz
snprintf(item_name, MAX_ITEMBUF, "%s/YTsiz(%u)",name_buf,yt);
add_sub_item();
xt0 = get4(s); s += 4;//XTOsiz
snprintf(item_name, MAX_ITEMBUF, "%s/XT0siz(%u)",name_buf,xt0);
add_sub_item();
yt0 = get4(s); s += 4;//YTOsiz
snprintf(item_name, MAX_ITEMBUF, "%s/YT0siz(%u)",name_buf,yt0);
add_sub_item();
c = get2(s); s += 2;//Csiz
snprintf(item_name, MAX_ITEMBUF, "%s/Csiz(%d)",name_buf,c);
add_sub_item();
Csiz = c;
FLViewer_set_max_components(c);
image_w = x - x0; image_h = y - y0;
tile_w = xt - xt0; tile_h = yt - yt0;
if(tile_w <= 0 || tile_h <= 0)
{
//This definitely is a bug.
max_tiles = 0;
}
else
{
int nr;
max_tiles = image_w/tile_w;
if(image_w%tile_w) ++max_tiles;
nr = image_h/tile_h;
if(image_h%tile_h) ++nr;
max_tiles *= nr;
}
FLViewer_set_max_tiles(max_tiles);
if(r >= 32768) extended_cap = 1; else extended_cap = 0;
snprintf(item_name, MAX_ITEMBUF, "%s/Ext. Capabilities(%d)",
name_buf,extended_cap);
add_sub_item();
#ifdef DEBUG_SIZ
fprintf(stderr,"%s:%d:\n\tread_siz\n\tlen(%u)\n"
"\tcapabilities(%u)[extended: %d]\n\tx(%u : %u) y(%u : %u)"
"\n\txt(%u : %u) yt(%u : %u)\n\tIMAGE w(%d) h(%d) TILE w(%d) h(%d)\n"
"\tCsiz(%hd)\n",__FILE_,__LINE__,len,r, extended_cap, x0,x, y0,y,
xt0,xt, yt0,yt, image_w,image_h,tile_w,tile_h,Csiz);
#endif
for(i = 0; i < c; ++i)
{
prec = s[0]; ++s;
depth = (prec & 0x7f) + 1;
sign = ((prec & 0x80)?1:0);//Ssiz
xr = s[0]; ++s;//XRsiz
yr = s[0]; ++s;//YRsiz
snprintf(item_name,
MAX_ITEMBUF, "%s/comp[%d] signed(%u) prec(%u) hsep(%u) vsep(%u)",
name_buf,i,sign,depth,xr,yr);
add_sub_item();
}
one_tile_only = (image_w == tile_w && image_h == tile_h);
snprintf(item_name, MAX_ITEMBUF, "%s/OneTileOnly(%d)",
name_buf,one_tile_only);
add_sub_item();
ppm_store = 0; ppm_prev = 0;
return len;
}//read_siz()
static unsigned short read_cod(unsigned char *s, const char *name_src)
{
unsigned char *cur;
const char *cs = "";
unsigned short len, max_len, nr_layers;
unsigned short Scod, prog_order, multi_comp_transform;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Coding style default marker",
name_buf);
add_sub_item();
cur = s;
max_len = get2(cur); cur += 2;
Scod = cur[0]; ++cur;//Table A-13
prog_order = cur[0]; ++cur;//Table A-16
nr_layers = get2(cur); cur += 2;
multi_comp_transform = cur[0]; ++cur;
if(nr_layers > 65534)
{
return max_len;
}
FLViewer_set_max_layers(nr_layers);
entropy_coder = use_sop_marker = use_eph_marker = 0;
if(Scod & 1) entropy_coder = 1;
if(Scod & 2) use_sop_marker = 1;
if(Scod & 4) use_eph_marker = 1;
if(prog_order == 0) cs = "LRCP";
else
if(prog_order == 1) cs = "RLCP";
else
if(prog_order == 2) cs = "RPCL";
else
if(prog_order == 3) cs = "PCRL";
else
if(prog_order == 4) cs = "CPRL";
else
cs = "Unknown";
snprintf(item_name, MAX_ITEMBUF, "%s/prog_order(%hu)%s", name_buf,
prog_order, cs);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/nr_layers(%u)", name_buf,
nr_layers );
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/multi_comp_transform(%hu)", name_buf,
multi_comp_transform );
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/entropy_coder(%hd)", name_buf,
entropy_coder );
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/use_sop_marker(%hd)", name_buf,
use_sop_marker);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/use_eph_marker(%hd)", name_buf,
use_eph_marker);
add_sub_item();
max_precincts = user_defined_precincts = 0;
if(max_len < 13)
{
max_precincts = 1; // A.2
snprintf(item_name, MAX_ITEMBUF, "%s/max_precincts(1)", name_buf);
add_sub_item();
}
else
{
user_defined_precincts = 1;
snprintf(item_name, MAX_ITEMBUF, "%s/user_defined_precincts(1)", name_buf);
add_sub_item();
}
{
unsigned int i;
unsigned char code_block_width ,code_block_height,
code_block_style, nr_decomp_levels;
/*--------------------------------------------------
A -- Progression order
B-- Number of layers
C -- Multiple component transformation
A B C | D E F G H Ii .. In D -- Number of decomposition levels
| E -- Code-block width
SGcod | SPcod F -- Code-block height
G -- Code-block style
H -- Transformation
Ii through In -- Precinct size
----------------------------------------------------*/
/* SPcod:
*/
nr_decomp_levels = cur[0] + 1; ++cur;
code_block_width = cur[0]; ++cur;
code_block_height = cur[0]; ++cur;
code_block_style = cur[0]; ++cur;
transform = cur[0]; ++cur;
if(nr_decomp_levels == 0 || code_block_width == 0 || code_block_height == 0)
{
return max_len;
}
FLViewer_set_max_reduction((int)nr_decomp_levels);
snprintf(item_name, MAX_ITEMBUF, "%s/nr_decomp_levels(%hu)", name_buf,
nr_decomp_levels);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/code_block_width(%d)", name_buf,
code_block_width);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/code_block_height(%u)", name_buf,
code_block_height);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/code_block_style(%d)", name_buf,
code_block_style);
add_sub_item();
irreversible_transform = reversible_transform = 0;
if(transform == 0)
{
irreversible_transform = 1;
snprintf(item_name, MAX_ITEMBUF, "%s/transformation(0) (9-7 irreversible)",
name_buf);
add_sub_item();
}
else
if(transform == 1)
{
reversible_transform = 1;
snprintf(item_name, MAX_ITEMBUF, "%s/transformation(1) (5-3 reversible)",
name_buf);
add_sub_item();
}
else
{
snprintf(item_name, MAX_ITEMBUF, "%s/transformation(%hu)", name_buf,
transform);
add_sub_item();
}
if(max_len == 12)
{
unsigned short j;
for(j = 0; j < nr_decomp_levels; ++j)
{
snprintf(item_name, MAX_ITEMBUF, "%s/[%d] precinct w(%d) h(%d)",
name_buf, j,15,15);
add_sub_item();
}
return max_len;
}
len = 12;
i = 0;
while(len < max_len && (len + nr_decomp_levels) < max_len)
{
len += nr_decomp_levels;
if(len > max_len)
{
return max_len;
}
if((Scod & 1))// Table A-21
{
unsigned short j, v;
for(j = 0; j < nr_decomp_levels; ++j)
{
v = cur[0]; ++cur;
snprintf(item_name, MAX_ITEMBUF, "%s/[%d] precinct w(%d) h(%u)",
name_buf, j,(v&0xf), (v>>4));
add_sub_item();
}
}
else
{
unsigned short j;
for(j = 0; j < nr_decomp_levels; ++j)
{
snprintf(item_name, MAX_ITEMBUF, "%s/[%d] precinct w(%d) h(%d)",
name_buf,j,15,15);
add_sub_item();
}
}
++i;
}
}
return max_len;
}// read_cod()
static unsigned short read_coc(unsigned char *s, const char *name_src)
{
unsigned short len, Scoc;
unsigned short A, B, C, D, E;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Coding style component marker",
name_buf);
add_sub_item();
len = get2(s); s += 2;
Scoc = s[0]; ++s;//csty
snprintf(item_name, MAX_ITEMBUF, "%s/Scoc(%hu)", name_buf,Scoc);
add_sub_item();
A = s[0] + 1; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/nr_decomp_levels(%hu)", name_buf,A);
add_sub_item();
B = s[0] + 2; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/code-block-width(%hu)", name_buf,B);
add_sub_item();
C = s[0] + 2; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/code-block-height(%hu)", name_buf,C);
add_sub_item();
D = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/code-block-style(%hu)", name_buf,D);
add_sub_item();
E = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/transformation(%hu)", name_buf,E);
add_sub_item();
if(Scoc == 0)
{
unsigned short i;
for(i = 0; i < A; ++i)
{
snprintf(item_name, MAX_ITEMBUF, "%s/Precinct[%d] Width(15) Height(15)",
name_buf,i );
add_sub_item();
}
}
else
if(Scoc & 1)
{
unsigned short i, K;
for(i = 0; i < A; ++i)
{
K = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/Precinct[%d] Width(%d) Height(%u)",
name_buf,i,(K & 0xf), (K >> 4) );
add_sub_item();
}
}
return len;
}//read_coc()
static unsigned short read_rgn(unsigned char *s, const char *name_src)
{
unsigned short len, Crgn, Srgn, SPrgn;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Region-of-interest marker",name_buf);
add_sub_item();
len = get2(s); s += 2;
Crgn = get_size(s, (Csiz < 257?1:2) );
snprintf(item_name, MAX_ITEMBUF, "%s/Component Index(%hu)",name_buf,Crgn);
add_sub_item();
Srgn = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/ROI style(%hu)",name_buf,Srgn);
add_sub_item();
SPrgn = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/Implicit ROI shift(%hu)",
name_buf,SPrgn);
add_sub_item();
return len;
}//read_rgn()
static unsigned short read_plm(unsigned char *s, const char *name_src)
{
unsigned short len;
short siz;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Packet length marker",name_buf);
add_sub_item();
len = get2(s); s += 2;
siz = (short)len;
++s; //Zplm
siz -= 3;
while(siz > 0)
{
unsigned int i, Nplm, packet_len = 0;
unsigned short v;
Nplm = get4(s); s += 4; siz -= 4;
snprintf(item_name, MAX_ITEMBUF, "%s/Index of marker segment(%u)",
name_buf,Nplm);
add_sub_item();
for(i = 0; i < Nplm; ++i)
{
v = s[0]; ++s; --siz;
packet_len = (packet_len << 7) + v;
// if((v & 0x80) == 0) packet_len = 0; //New packet
snprintf(item_name, MAX_ITEMBUF, "%s/Packet[%u] length(%u)",
name_buf,i,packet_len);
add_sub_item();
if((v & 0x80) == 0) packet_len = 0; //New packet
}
}
return len;
}//read_plm()
static unsigned short read_qcc(unsigned char *s, const char *name_src)
{
unsigned short len, Cqcc, Sqcc;
unsigned short header_size, num_bands;
unsigned short qntsty;
// unsigned short numgbits;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Quantization component marker",
name_buf);
add_sub_item();
len = get2(s); s += 2;
header_size = len - 2 - 1;
if(Csiz < 257)
{
Cqcc = s[0]; ++s;
}
else
{
Cqcc = get2(s); s += 2;
}
Sqcc = s[0]; ++s;
qntsty = Sqcc & 0x1f; //numgbits = Sqcc >> 5;
if(qntsty == 1)
{
num_bands = 1;
}
else
if(qntsty == 0)
{
num_bands = header_size;
}
else
{
num_bands = header_size/2;
}
snprintf(item_name, MAX_ITEMBUF, "%s/Cqcc(%d) Sqcc(%d) numbands(%d)",
name_buf, Cqcc, Sqcc, num_bands);
add_sub_item();
if(qntsty == 0)
{
unsigned short i, v;
for(i = 0; i < num_bands; ++i)
{
v = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/Band[%d] Exponent(%u) Mantissa(%d)",
name_buf,i,(v>>3), 0);
add_sub_item();
}
}
else
{
unsigned short i, v;
for(i = 0; i < num_bands; ++i)
{
v = get2(s); s += 2;
snprintf(item_name, MAX_ITEMBUF, "%s/Band[%d] Exponent(%u) Mantissa(%d)",
name_buf,i,(v>>11), (v & 0x7ff));
add_sub_item();
}
}
return len;
}//read_qcc()
static unsigned short read_poc(unsigned char *s, const char *name_src)
{
unsigned short len, numpchgs, i, old_poc;
unsigned short RSpoc, CSpoc;
unsigned short LYEpoc, REpoc, CEpoc;
unsigned short Ppoc;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Progression order change marker",
name_buf);
add_sub_item();
len = get2(s); s += 2;
old_poc = has_POC ? numpocs + 1 : 0;
has_POC = 1;
numpchgs = (len - 2) / (5 + 2 * (Csiz < 257 ? 1 : 2));
if( numpchgs >= 32 ) numpchgs = 0;
for(i = old_poc; i < numpchgs + old_poc; ++i)
{
RSpoc = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/poc[%i] RSpoc(%hu)",name_buf,i,RSpoc);
add_sub_item();
if(Csiz < 257)
{
CSpoc = s[0]; ++s;
}
else
{
CSpoc = get2(s); s += 2;
}
snprintf(item_name, MAX_ITEMBUF, "%s/poc[%i] CSpoc(%hu)",name_buf,i,CSpoc);
add_sub_item();
LYEpoc = get2(s); s += 2;
snprintf(item_name, MAX_ITEMBUF, "%s/poc[%i] LYEpoc(%hu)",name_buf,i,LYEpoc);
add_sub_item();
REpoc = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/poc[%i] REpoc(%hu)",name_buf,i,REpoc);
add_sub_item();
if(Csiz < 257)
{
CEpoc = s[0]; ++s;
}
else
{
CEpoc = get2(s); s += 2;
}
snprintf(item_name, MAX_ITEMBUF, "%s/poc[%i] CEpoc(%hu)",name_buf,i,CEpoc);
add_sub_item();
Ppoc = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/poc[%i] Ppoc(%hu)",name_buf,i,Ppoc);
add_sub_item();
}
numpocs = numpchgs + old_poc - 1;
return len;
}//read_poc()
static unsigned short read_tlm(unsigned char *s, const char *name_src)
{
unsigned short len;
unsigned short Ztlm, Stlm;
unsigned int ST, SP, dSP, i, tile_tlm, Ttlm, Ptlm;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Tile-part lengths marker",name_buf);
add_sub_item();
len = get2(s); s += 2;
Ztlm = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/Ztlm(%hu)",name_buf,Ztlm);
add_sub_item();
Stlm = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/Stlm(%hu)",name_buf,Stlm);
add_sub_item();
ST = ((Stlm >> 4) & 0x01) + ((Stlm >> 4) & 0x02);
SP = (Stlm >> 6) & 0x01;
dSP = (SP ? 4 : 2);
tile_tlm = (len - 4) / ((SP + 1) * 2 + ST);
for(i = 0; i < tile_tlm; ++i)
{
Ttlm = get_size(s, ST); s += ST;
Ptlm = get_size(s, dSP); s += dSP;
snprintf(item_name, MAX_ITEMBUF, "%s/Tlm[%u] Ttlm(%u) Ptlm(%u)",
name_buf,i,Ttlm,Ptlm);
add_sub_item();
}
return len;
}//read_tlm()
unsigned char *read_resc(unsigned char *s, unsigned char *box_end,
const char *name_src)
{
char name_buf[MAX_ITEMBUF];
unsigned short vcn, vcd, hcn, hcd, vce, hce;
strcpy(name_buf, (char*)name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Capture resolution box",name_buf);
add_sub_item();
vcn = get2(s); s += 2;
vcd = get2(s); s += 2;
hcn = get2(s); s += 2;
hcd = get2(s); s += 2;
vce = s[0]; ++s;
hce = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/vcn(%hu) vcd(%hu)", name_buf,vcn,vcd);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/hcn(%hu) hcd(%hu)", name_buf,hcn,hcd);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/vce(%hu) hce(%hu)", name_buf,vce,hce);
add_sub_item();
return s;
}//read_resc()
unsigned char *read_resd(unsigned char *s, unsigned char *box_end,
const char *name_src)
{
char name_buf[MAX_ITEMBUF];
unsigned short vdn, vdd, hdn, hdd, vde, hde;
strcpy(name_buf, (char*)name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Default display resolution box",
name_buf);
add_sub_item();
vdn = get2(s); s += 2;
vdd = get2(s); s += 2;
hdn = get2(s); s += 2;
hdd = get2(s); s += 2;
vde = s[0]; ++s;
hde = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/vdn(%hu) vdd(%hu)", name_buf,vdn,vdd);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/hdn(%hu) hdd(%hu)", name_buf,hdn,hdd);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/vde(%hu) hde(%hu)", name_buf,vde,hde);
add_sub_item();
return s;
}//read_resd()
unsigned char *read_res(unsigned char *s, unsigned char *box_end,
unsigned char *dend, const unsigned char *name_src)
{
char name_buf[MAX_ITEMBUF];
uint64_t box_len;
unsigned int hstep;
strcpy(name_buf, (char*)name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Resolution box",name_buf);
add_sub_item();
box_len = read_boxheader(s, dend, &hstep);
if(box_len == 0) return dend;
snprintf(item_name, MAX_ITEMBUF, "%s/%s", name_buf,(char*)box_name);
if(memcmp(box_name, "resc", 4) == 0)
{
Fl_Tree_Item *sup = tree->add(item_name);
s = read_resc(s + hstep, s + box_len, item_name);
sup->close();
box_len = read_boxheader(s, dend, &hstep);
if(box_len == 0) return dend;
snprintf(item_name, MAX_ITEMBUF, "%s/%s", name_buf,(char*)box_name);
}
if(memcmp(box_name, "resd", 4) == 0)
{
Fl_Tree_Item *sup = tree->add(item_name);
s = read_resd(s + hstep, s + box_len, item_name);
sup->close();
}
return s;
}
unsigned char *read_ftyp(unsigned char *s, unsigned char *box_end,
const char *name_src)
{
int i, n;
char name_buf[MAX_ITEMBUF];
char buf[5], brand[5];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/File type box", name_buf);
add_sub_item();
brand[4] = 0; buf[4] = 0;
memcpy(brand, s, 4); s += 4;
// minv = get4(s);
s += 4;
snprintf(item_name, MAX_ITEMBUF, "%s/brand(%s)", name_buf,brand);
add_sub_item();
n = (int)((box_end - s)/4);
for(i = 0; i < n; ++i)
{
memcpy(buf, s, 4); s += 4;
if(*buf == 0) memset(buf, ' ', 4);
snprintf(item_name, MAX_ITEMBUF, "%s/CL(%s)", name_buf,buf);
add_sub_item();
}
return s;
}
unsigned char *read_ihdr(unsigned char *s, unsigned char *box_end,
const char *name_src)
{
char name_buf[MAX_ITEMBUF];
int w, h;
unsigned short nc, bpc, c, unkc, ipr, depth, sign;
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Image header box",name_buf);
add_sub_item();
h = get4(s); s += 4;
w = get4(s); s += 4;
nc = get2(s); s += 2;
bpc = s[0]; ++s;
depth = (bpc & 0x7f) + 1;
sign = (bpc & 0x80)?1:0;
c = s[0]; ++s;
unkc = s[0]; ++s;
ipr = s[0]; ++s;
#ifdef DEBUG_IHDR
fprintf(stderr,"read_ihdr\n\tw(%d) h(%d) nc(%u) bpc(%u)\n\tsigned(%u) "
"depth(%u)\n\tcompress(%u) unknown_c(%u) ipr(%u)\n",w, h,
nc,bpc, sign,depth,c, unkc, ipr);
#endif
snprintf(item_name, MAX_ITEMBUF, "%s/w(%d)", name_buf, w);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/h(%d)", name_buf, h);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/numcomps(%d)", name_buf, nc);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/bpc(%d)", name_buf, bpc);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/depth(%d)", name_buf, depth);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/signed(%d)", name_buf, sign);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/compress(%d)", name_buf, c);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/unkc(%d)", name_buf, unkc);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/ipr(%d)", name_buf, ipr);
add_sub_item();
nr_components = nc;
return s;
}/* read_ihdr() */
unsigned char *read_bpcc(unsigned char *s, unsigned char *box_end,
const char *name_src)
{
unsigned char *v;
char name_buf[MAX_ITEMBUF];
unsigned short i;
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Bits per component box",name_buf);
add_sub_item();
v = s;
for(i = 0; i < nr_components; ++i)
{
snprintf(item_name, MAX_ITEMBUF, "%s/[%d]bpcc(%u)", name_buf,
i,v[0]);
add_sub_item();
++v;
}
return (s + nr_components);
}
unsigned char *read_colr(unsigned char *s, unsigned char *box_end,
const char *name_src)
{
char name_buf[MAX_ITEMBUF];
unsigned int meth, prec, approx, enumcs = 0;
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Colour specification box",name_buf);
add_sub_item();
meth = s[0]; ++s;
prec = s[0]; ++s;
approx = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/meth(%u)",name_buf,meth);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/prec(%u)",name_buf,prec);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF, "%s/approx(%u)",name_buf,approx);
add_sub_item();
if(meth == 1)/* enumerated colorspace */
{
const char *cs;
enumcs = get4(s); s += 4;
cs = enumcs_text(enumcs);
snprintf(item_name, MAX_ITEMBUF, "%s/enumcs(%u: %s)",
name_buf,enumcs,cs);
add_sub_item();
if(enumcs == 14) //CIELab
{
s = box_end;
}
}
else /* Profile */
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/ICC",name_buf);
sup = tree->add(item_name);
read_icc_profile(s, item_name);
sup->close();
s = box_end;//skip ICC Profile
}
assert(box_end == s);
if( !jp2_color.has_colr)
{
jp2_color.meth = meth;
jp2_color.precedence = prec;
jp2_color.approx = approx;
jp2_color.enumcs = enumcs;
jp2_color.has_colr = 1;
}
return s;
}//read_colr()
unsigned char *read_cdef(unsigned char *s, unsigned char *box_end,
const char *name_src)
{
jp2_cdef_info_t *cdef_info;
char name_buf[MAX_ITEMBUF];
unsigned short i, n, c, typ, asoc;
//
// Part 1, I.5.3.6: 'There shall be at most one Channel Definition box
// inside a JP2 Header box.'
//
if(jp2_color.has_cdef)
{
return box_end;
}
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Channel definition box",name_buf);
add_sub_item();
n = get2(s); s += 2;
cdef_info = (jp2_cdef_info_t*)malloc(n * sizeof(jp2_cdef_info_t));
if(cdef_info == NULL)
{
fprintf(stderr,"read_jpeg2000.cx:%d:\n\tmemory_out\n",__LINE__);
return box_end;
}
jp2_color.has_cdef = 1;
for(i = 0; i < n; ++i)
{
c = get2(s); s += 2;
typ = get2(s); s += 2;
asoc = get2(s); s += 2;
snprintf(item_name, MAX_ITEMBUF, "%s/[%d] c(%d) typ(%d) asoc(%d)",
name_buf, i, c, typ, asoc);
add_sub_item();
cdef_info[i].cn = c; cdef_info[i].typ = typ; cdef_info[i].asoc = asoc;
}
apply_cdef(cdef_info, n);
free(cdef_info);
return s;
}//read_cdef()
unsigned char *read_pclr(unsigned char *s, unsigned char *box_end,
unsigned int *out_channels, const char *name_src)
{
char name_buf[MAX_ITEMBUF];
unsigned char *prec;
unsigned int *entries;
int size;
unsigned short nr_entries, nr_channels;
unsigned short i, j;
int count;
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Palette box",name_buf);
add_sub_item();
nr_entries = get2(s); s += 2; /* NE */
nr_channels = s[0]; ++s; /* NPC */
count = 11;//8+3
*out_channels = nr_channels;
i = nr_channels * nr_entries;
entries = (unsigned int*)calloc(i, sizeof(unsigned int));
if(entries == NULL)
{
fprintf(stderr,"read_jpeg2000.cx:%d:\n\tmemory_out\n",__LINE__);
return box_end;
}
prec = (unsigned char*)calloc(nr_channels, 1);
if(prec == NULL)
{
fprintf(stderr,"read_jpeg2000.cx:%d:\n\tmemory_out\n",__LINE__);
free(entries);
return box_end;
}
for(i = 0; i < nr_channels; ++i)
{
prec[i] = s[0]; ++s; /* Bi */
++count;
snprintf(item_name, MAX_ITEMBUF, "%s/[%d] signed(%d) depth(%u)",
name_buf, i, ((prec[i]&0x80)?1:0), (prec[i]&0x7f) + 1 );
add_sub_item();
}
for(j = 0; j < nr_entries; ++j)
{
#ifdef SHOW_PCLR_ENTRY
fprintf(stderr," entry[%03u]",j);
#endif
for(i = 0; i < nr_channels; ++i)
{
size = ((prec[i]&0x7f) + 1 + 7)/8;
entries[j*nr_channels + i] = get_size(s, size); s += size; /* Cji */
count += size;
#ifdef SHOW_PCLR_ENTRY
fprintf(stderr,"%u ", entries[j*nr_channels + i]);
#endif
}
#ifdef SHOW_PCLR_ENTRY
fputs("\n",stderr);
#endif
}
free(prec); free(entries);
return box_end;
}/* read_pclr() */
unsigned char *read_cmap(unsigned char *s, unsigned char *box_end,
unsigned int nr_channels, const char *name_src)
{
char name_buf[MAX_ITEMBUF];
unsigned short i, cmp;
unsigned char mtyp, pcol;
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Component mapping box",name_buf);
add_sub_item();
for(i = 0; i < nr_channels; ++i)
{
cmp = get2(s); s += 2;
mtyp = s[0]; ++s;
pcol = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/[%d] cmp(%u) mtyp(%u) pcol(%u)",
name_buf, i,cmp,mtyp,pcol);
add_sub_item();
}
return s;
}/* read_cmap() */
unsigned char *read_jp2h(unsigned char *s, unsigned char *box_end,
unsigned char *dend, const char *name_src)
{
uint64_t box_len;
unsigned int hstep, nr_channels = 0;
int pos = -1;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/JP2 header box",name_buf);
add_sub_item();
while(s < box_end)
{
++pos;
box_len = read_boxheader(s, dend, &hstep);
if(box_len == 0) return dend;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] %s",name_buf,pos,
(char*)box_name);
if(memcmp(box_name, "ihdr", 4) == 0)
{
Fl_Tree_Item *sup;
sup = tree->add(item_name);
s = read_ihdr(s + hstep, s + box_len, item_name);
sup->close();
continue;
}
if(memcmp(box_name, "bpcc", 4) == 0)
{
Fl_Tree_Item *sup;
sup = tree->add(item_name);
s = read_bpcc(s + hstep, s + box_len, item_name);
sup->close();
continue;
}
if(memcmp(box_name, "colr", 4) == 0)
{
Fl_Tree_Item *sup;
sup = tree->add(item_name);
s = read_colr(s + hstep, s + box_len, item_name);
sup->close();
continue;
}
if(memcmp(box_name, "cdef", 4) == 0)
{
Fl_Tree_Item *sup;
sup = tree->add(item_name);
s = read_cdef(s + hstep, s + box_len, item_name);
sup->close();
continue;
}
if(memcmp(box_name, "pclr", 4) == 0)
{
Fl_Tree_Item *sup;
sup = tree->add(item_name);
s = read_pclr(s + hstep, s + box_len, &nr_channels, item_name);
sup->close();
continue;
}
if(memcmp(box_name, "cmap", 4) == 0)
{
Fl_Tree_Item *sup;
sup = tree->add(item_name);
s = read_cmap(s + hstep, s + box_len, nr_channels, item_name);
sup->close();
continue;
}
if(memcmp(box_name, "res ", 4) == 0)
{
Fl_Tree_Item *sup;
sup = tree->add(item_name);
s = read_res(s + hstep, s + box_len, dend, (unsigned char*)item_name);
sup->close();
continue;
}
if(memcmp(box_name, "xml ", 4) == 0
|| memcmp(box_name, "XML ", 4) == 0)
{
Fl_Tree_Item *sup, *sub;
char *buf = NULL;
char iname[MAX_ITEMBUF];
snprintf(iname, MAX_ITEMBUF, "[%03d] XML", ++pos);
sup = tree->add(iname);
snprintf(item_name, MAX_ITEMBUF, "%s/xml1", iname);
sub = tree->add(item_name);
s = read_xml(s + hstep, s + box_len, dend, &buf);
sub->label(buf);
sup->close();
free(buf); --pos;
continue;
}
{
Fl_Tree_Item *sup;
char iname[MAX_ITEMBUF];
snprintf(iname, MAX_ITEMBUF, "[%03d] %s", ++pos, (char*)box_name);
sup = tree->add(iname);
snprintf(item_name, MAX_ITEMBUF, "%s/Not handled. Skipped.", iname);
add_sub_item();
sup->close();
}
s += box_len;
}
return box_end;
}//read_jp2h()
unsigned short read_plt(unsigned char *s, const char *name_src)
{
unsigned short len, Zplt;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF,
"%s/Packet length, tile-part header marker", name_buf);
add_sub_item();
len = get2(s); s += 2;
Zplt = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF,
"%s/Zplt(%hu) len(%hu)", name_buf,Zplt,len);
add_sub_item();
return len;
}// read_plt()
static unsigned short read_ppm(unsigned char *s, const char *name_src)
{
unsigned short max_len, len, Zppm;
unsigned int Nppm, i, j;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Packed packet headers marker (Main)", name_buf);
add_sub_item();
max_len = get2(s); s += 2;
len = max_len - 3;
Zppm = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/Zppm(%hu)", name_buf,Zppm);
add_sub_item();
while(len > 0)
{
if(ppm_prev)
{
Nppm = ppm_prev;
}
else
{
Nppm = get4(s); s += 4;
snprintf(item_name, MAX_ITEMBUF, "%s/Nppm(%u)", name_buf,Nppm);
add_sub_item();
}
j = ppm_store;
for(i = Nppm; i > 0; --i)
{
++s; ++j;
if(--len == 0) break;
}
ppm_prev = i - 1;
ppm_store = j;
}//while(len > 0)
return max_len;
}//read_ppm()
static unsigned short read_ppt(unsigned char *s, const char *name_src)
{
unsigned short len, Zppt;
unsigned int i, j;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Packed packet headers marker (Tile part)", name_buf);
add_sub_item();
len = get2(s); s += 2;
Zppt = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/Zppt(%hu)", name_buf,Zppt);
add_sub_item();
ppt = 1;
if(Zppt == 0)//First marker
{
ppt_store = 0; ppt_len = len - 3;
}
else
{
ppt_len = len - 3 + ppt_store;
}
j = ppt_store;
for(i = len - 3; i > 0; --i)
{
++s;
++j;
}
ppt_store = j;
return len;
}//read_ppt()
#ifdef SHOW_PACKETS
static unsigned short read_sop(unsigned char *s, const char *name_src)
{
unsigned short len, Nsop;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Start of packet marker", name_buf);
add_sub_item();
len = get2(s); s += 2;
Nsop = get2(s); s += 2;
snprintf(item_name, MAX_ITEMBUF, "%s/Packet sequence number(%hu)", name_buf,Nsop);
add_sub_item();
return len;
}//read_sop()
#endif //SHOW_PACKETS
static unsigned short read_crg(unsigned char *s, const char *name_src)
{
unsigned short len, i, v;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Component registration marker", name_buf);
add_sub_item();
len = get2(s); s += 2;
for(i = 0; i < Csiz; ++i)
{
v = get2(s); s += 2;
snprintf(item_name, MAX_ITEMBUF, "%s/Xcrg[%d] %hu", name_buf,i,v);
add_sub_item();
}
for(i = 0; i < Csiz; ++i)
{
v = get2(s); s += 2;
snprintf(item_name, MAX_ITEMBUF, "%s/YXcrg[%d] %hu", name_buf,i,v);
add_sub_item();
}
return len;
}//read_crg()
static unsigned short read_com(unsigned char *s, const char *name_src)
{
Fl_Tree_Item *sub;
char *txt;
unsigned short len;
unsigned int r, i, n;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Comment marker", name_buf);
add_sub_item();
len = get2(s); s += 2;
r = get2(s); s += 2;
n = len - 4;
txt = (char*)calloc(1, n + 8);
if(txt == NULL) return len;
strcpy(txt, " ");
memcpy(txt+4, s, n);
if(r > 1) i = 2; else i = r;
snprintf(item_name, MAX_ITEMBUF, "%s/com1", name_buf);
sub = tree->add(item_name);
sub->label(reg_text[i]);
snprintf(item_name, MAX_ITEMBUF, "%s/com2", name_buf);
sub = tree->add(item_name);
sub->label(txt);
#ifdef SHOW_COM
fprintf(stderr,"%s:%d:\n\tCOM\n\tR[%u]%s\n\tT(%s)\n",__FILE__,__LINE__,
i,reg_text[i],txt);
#endif
free(txt);
return len;
}//read_com()
static unsigned char *read_sot(unsigned char *s, unsigned char *box_end,
unsigned char *dend, const char *name_src)
{
unsigned char *start;
unsigned short tile_nr;
#ifdef READ_ALL_SOT_MARKERS
unsigned short len;
#endif
uint64_t Psot;
unsigned char TPsot, TNsot;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Start of tile-part marker",name_buf);
add_sub_item();
start = s;
#ifdef READ_ALL_SOT_MARKERS
len = get2(s); s += 2;
#else
s += 2;
#endif
tile_nr = get2(s); s += 2;
snprintf(item_name, MAX_ITEMBUF,"%s/TileNr(%d)",name_buf,tile_nr);
add_sub_item();
Psot = (uint64_t)get4(s); s += 4;
TPsot = s[0]; ++s;
TNsot = s[0]; ++s;
#ifdef PSOT_LENG_FROM_BUF_END
if(Psot == 0)
{
Psot = (uint64_t)(dend - s);
snprintf(item_name, MAX_ITEMBUF,"%s/Psot(%" PRIu64 ")",name_buf,Psot);
add_sub_item();
}//EOC, EOI
#else /* not PSOT_LENG_FROM_BUF_END */
if(Psot == 0)
{
Psot = (uint64_t)(box_end - s);
snprintf(item_name, MAX_ITEMBUF,"%s/Psot(%" PRIu64 ")",name_buf,Psot);
add_sub_item();
}
#endif /* PSOT_LENG_FROM_BUF_END */
#ifdef READ_ALL_SOT_MARKERS
s = start + len;
#else
s = start + Psot - 2;
#endif
snprintf(item_name, MAX_ITEMBUF,"%s/TPsot(%d)",name_buf, TPsot);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF,"%s/TNsot(%d)",name_buf, TNsot);
add_sub_item();
return s;
}//read_sot()
static unsigned short read_qcd(unsigned char *s, const char *name_src)
{
#ifdef QUANT_AS_STRING
const char *cs = "";
#endif
unsigned short max_len, i;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Quantization default marker",name_buf);
add_sub_item();
max_len = get2(s); s += 2;
for(i = 0; i < Csiz; ++i)
{
unsigned short sqcd, v, bits;
sqcd = s[0]; ++s;
v = (sqcd & 0x1f); bits = (sqcd>>5);
#ifdef QUANT_AS_STRING
if(v == 0) cs = "no";//No quantization
else
if(v == 1) cs = "implicit";//Scalar derived
else
if(v == 2) cs = "explicit";//Scalar expounded
else
cs = "unknown";
snprintf(item_name, MAX_ITEMBUF, "%s/Sqcd[%d] quant(%s) bits(%hu)", name_buf,
i,cs,bits);
#else
snprintf(item_name, MAX_ITEMBUF, "%s/Sqcd[%d] q(%hu) b(%hu)", name_buf,
i,v,bits);
#endif
add_sub_item();
}
return max_len;
}//read_qcd();
static unsigned short read_epb(unsigned char *s, const char *name_src)
{
unsigned int ldp, p;
unsigned short len, v;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
len = get2(s); s += 2;
snprintf(item_name, MAX_ITEMBUF, "%s/Error protection block", name_buf);
add_sub_item();
v = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/style(%hu)", name_buf, v);
add_sub_item();
ldp = get4(s); s += 4;
snprintf(item_name, MAX_ITEMBUF, "%s/length_of_data(%u)", name_buf, ldp);
add_sub_item();
p = get4(s); s += 4;
snprintf(item_name, MAX_ITEMBUF, "%s/parameters(%u)", name_buf, p);
add_sub_item();
return len;
}//read_epb()
static unsigned short read_epc(unsigned char *s, const char *name_src)
{
unsigned int cl;
unsigned short len, crc, epc;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
len = get2(s); s += 2;
snprintf(item_name, MAX_ITEMBUF, "%s/Error protection capacity", name_buf);
add_sub_item();
crc = get2(s); s += 2;
snprintf(item_name, MAX_ITEMBUF, "%s/Parity crc(%hu)", name_buf, crc);
add_sub_item();
cl = get4(s); s += 4;
snprintf(item_name, MAX_ITEMBUF, "%s/codestrem_len(%u)", name_buf, cl);
add_sub_item();
epc = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/parameter(%hu)", name_buf, epc);
add_sub_item();
return len;
}//read_epc()
static unsigned short read_esd(unsigned char *s, const char *name_src)
{
unsigned short len, v;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
len = get2(s); s += 2;
snprintf(item_name, MAX_ITEMBUF, "%s/Error sensitivity descriptor", name_buf);
add_sub_item();
if(Csiz < 257)
{
v = s[0]; ++s;
}
else
{
v = get2(s); s += 2;
}
snprintf(item_name, MAX_ITEMBUF, "%s/component(%hu)", name_buf, v);
add_sub_item();
v = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/usage(%hu)", name_buf, v);
add_sub_item();
return len;
}//read_esd()
static unsigned short read_red(unsigned char *s, const char *name_src)
{
unsigned short len, v;
char name_buf[MAX_ITEMBUF];
strcpy(name_buf, name_src);
len = get2(s); s += 2;
snprintf(item_name, MAX_ITEMBUF, "%s/Residual errors descriptor", name_buf);
add_sub_item();
v = s[0]; ++s;
snprintf(item_name, MAX_ITEMBUF, "%s/usage(%hu)", name_buf, v);
add_sub_item();
return len;
}//read_red()
unsigned char *test_marker(unsigned char *s, unsigned char *box_end,
unsigned int type)
{
unsigned int len;
unsigned char prefix, suffix;
suffix = type & 0xff;
s += 2;
/* 0x30 : 0x3f ==> reserved, no parameters */
if(suffix >= 0x30 && suffix <= 0x3f) return s;
len = get2(s); s += len;
if(s >= box_end)
{
fprintf(stderr,"\t1:MARKER %#x is unknown.\n",type);
return s;//box_end;
}
type = get2(s);
if(s + 2 >= box_end)
{
fprintf(stderr,"\t2:MARKER %#x is unknown. STOP.\n",type);
return box_end;
}
prefix = (type>>8) & 0xff; suffix = type & 0xff;
if(prefix == 0xff) return s;
fprintf(stderr,"\t3:NEXT MARKER %#x is unknown. STOP.\n",type);
return box_end;
}
unsigned char *read_jp2c(unsigned char *s, unsigned char *box_end,
unsigned char *dend, const char *name_src)
{
unsigned char *stop;
#ifdef DEBUG_JP2C
unsigned char *start0 = s;
#endif
unsigned int type, next_type, len;
int pos = -1;
int eoc_found = 0, sod_found = 0;
char name_buf[MAX_ITEMBUF];
char iname[MAX_ITEMBUF+2];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Contiguous codestream box",name_buf);
add_sub_item();
while(s < box_end)
{
type = get2(s);
++pos;
#ifdef DEBUG_JP2C
fprintf(stderr,"[%03d] marker(%#x) position(%ld)\n",pos,type,(long)(s-start0));
#endif
s += 2; len = 0;
switch(type)
{
case J2K_SOC:
{
Fl_Tree_Item *sup;
snprintf(iname, MAX_ITEMBUF,"%s/[%03d] SOC",name_buf,pos);
sup = tree->add(iname);
snprintf(item_name,
MAX_ITEMBUF, "%s/Start of codestream marker", iname);
add_sub_item();
sup->close();
continue;
}
case J2K_SOT:
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] SOT", name_buf,pos);
sup = tree->add(item_name);
s = read_sot(s, box_end, dend, item_name);
sup->close();
continue;
}
case J2K_SOD:
{
Fl_Tree_Item *sup;
snprintf(iname, MAX_ITEMBUF,"%s/[%03d] SOD",name_buf,pos);
sup = tree->add(iname);
snprintf(item_name, MAX_ITEMBUF, "%s/Start of data marker",iname);
add_sub_item();
sup->close();
sod_found = 1;
next_type = get2(s);
if(next_type == J2K_SOT || next_type == J2K_SOP)
{
continue;
}
s = dend - 2;
continue;
}
case J2K_EOC:
{
Fl_Tree_Item *sup;
snprintf(iname, MAX_ITEMBUF,"%s/[%03d] EOC",name_buf,pos);
sup = tree->add(iname);
snprintf(item_name, MAX_ITEMBUF,"%s/End of codestream marker",iname);
add_sub_item();
sup->close();
eoc_found = 1;
continue;
}
case J2K_SIZ:
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF,"%s/[%03d] SIZ",name_buf,pos);
sup = tree->add(item_name);
s += read_siz(s, item_name);
sup->close();
continue;
}
case J2K_COD:
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF,"%s/[%03d] COD", name_buf,pos);
sup = tree->add(item_name);
s += read_cod(s, item_name);
sup->close();
continue;
}
case J2K_COC:
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] COC", name_buf,pos);
sup = tree->add(item_name);
s += read_coc(s, item_name);
sup->close();
continue;
}
case J2K_RGN:
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] RGN", name_buf,pos);
sup = tree->add(item_name);
s += read_rgn(s, item_name);
sup->close();
continue;
}
case J2K_QCD:
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF,"%s/[%03d] QCD", name_buf,pos);
sup = tree->add(item_name);
s += read_qcd(s, item_name);
sup->close();
continue;
}
case J2K_QCC:
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] QCC", name_buf,pos);
sup = tree->add(item_name);
s += read_qcc(s, item_name);
sup->close();
continue;
}
case J2K_POC://POD
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] POC", name_buf,pos);
sup = tree->add(item_name);
s += read_poc(s, item_name);
sup->close();
continue;
}
case J2K_TLM:
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] COC", name_buf,pos);
sup = tree->add(item_name);
s += read_tlm(s, item_name);
sup->close();
continue;
}
case J2K_PLM:
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] PLM", name_buf,pos);
sup = tree->add(item_name);
s += read_plm(s, item_name);
sup->close();
continue;
}
case J2K_PLT:
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] PLT", name_buf,pos);
sup = tree->add(item_name);
s += read_plt(s, item_name);
sup->close();
continue;
}
case J2K_PPM:
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] PPM", name_buf,pos);
sup = tree->add(item_name);
s += read_ppm(s, item_name);
sup->close();
continue;
}
case J2K_PPT:
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] PPT", name_buf,pos);
sup = tree->add(item_name);
s += read_ppt(s, item_name);
sup->close();
continue;
}
case J2K_SOP:
{
#ifdef SHOW_PACKETS
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] SOP", name_buf,pos);
sup = tree->add(item_name);
s += read_sop(s, item_name);
sup->close();
#endif
stop = box_end - 2;
next_type = 0;
while(s < stop)
{
if(s[0] == 0xff)
{
next_type = get2(s);
if(next_type == J2K_EPH) break;
}
++s;
}
continue;
}
case J2K_EPH:
{
#ifdef SHOW_PACKETS
Fl_Tree_Item *sup;
snprintf(iname, MAX_ITEMBUF, "%s/[%03d] EPH", name_buf,pos);
sup = tree->add(iname);
snprintf(item_name, MAX_ITEMBUF, "%s/End of packet marker", iname);
add_sub_item();
sup->close();
#endif
stop = box_end - 2; next_type = 0;
while(s < stop)
{
if(s[0] == 0xff)
{
next_type = get2(s);
if(next_type == J2K_SOP || next_type == J2K_SOT) break;
}
++s;
}
continue;
}
case J2K_CRG:
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] CRG", name_buf,pos);
sup = tree->add(item_name);
s += read_crg(s, item_name);
sup->close();
continue;
}
case J2K_COM://CME
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] COM", name_buf,pos);
sup = tree->add(item_name);
s += read_com(s, item_name);
sup->close();
continue;
}
case J2K_EPC://JPWL
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] EPC", name_buf,pos);
sup = tree->add(item_name);
s += read_epc(s, item_name);
sup->close();
continue;
}
case J2K_EPB://JPWL
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] EPB", name_buf,pos);
sup = tree->add(item_name);
s += read_epb(s, item_name);
sup->close();
continue;
}
case J2K_ESD://JPWL
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] ESD", name_buf,pos);
sup = tree->add(item_name);
s += read_esd(s, item_name);
sup->close();
continue;
}
case J2K_RED://JPWL
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] RED", name_buf,pos);
sup = tree->add(item_name);
s += read_red(s, item_name);
sup->close();
continue;
}
case J2K_SEC://JPSEC
{
Fl_Tree_Item *item;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] SEC", name_buf,pos);
item = tree->add(item_name);
item->usericon(&L_documentpixmap);
len = get2(s); s += len;
continue;
}
case J2K_INSEC://JPSEC
{
Fl_Tree_Item *item;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] INSEC", name_buf,pos);
item = tree->add(item_name);
item->usericon(&L_documentpixmap);
len = get2(s); s += len;
continue;
}
/*---------- Part 2, Extensions ---------------*/
case J2K_DCO:
{
Fl_Tree_Item *item;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] dco", name_buf,pos);
item = tree->add(item_name);
item->usericon(&L_documentpixmap);
len = get2(s); s += len;
continue;
}
case J2K_VMS:
{
Fl_Tree_Item *item;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] vms", name_buf,pos);
item = tree->add(item_name);
item->usericon(&L_documentpixmap);
len = get2(s); s += len;
continue;
}
case J2K_DFS:
{
Fl_Tree_Item *item;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] dfs", name_buf,pos);
item = tree->add(item_name);
item->usericon(&L_documentpixmap);
len = get2(s); s += len;
continue;
}
case J2K_ADS:
{
Fl_Tree_Item *item;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] ads", name_buf,pos);
item = tree->add(item_name);
item->usericon(&L_documentpixmap);
len = get2(s); s += len;
continue;
}
case J2K_MCT:
{
Fl_Tree_Item *item;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] mct", name_buf,pos);
item = tree->add(item_name);
item->usericon(&L_documentpixmap);
len = get2(s); s += len;
continue;
}
case J2K_MCC:
{
Fl_Tree_Item *item;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] mcc", name_buf,pos);
item = tree->add(item_name);
item->usericon(&L_documentpixmap);
len = get2(s); s += len;
continue;
}
case J2K_NLT:
{
Fl_Tree_Item *item;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] nlt", name_buf,pos);
item = tree->add(item_name);
item->usericon(&L_documentpixmap);
len = get2(s); s += len;
continue;
}
case J2K_CBD:
{
Fl_Tree_Item *item;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] cbd", name_buf,pos);
item = tree->add(item_name);
item->usericon(&L_documentpixmap);
len = get2(s); s += len;
continue;
}
case J2K_ATK://jp3d
{
Fl_Tree_Item *item;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] atk", name_buf,pos);
item = tree->add(item_name);
item->usericon(&L_documentpixmap);
len = get2(s); s += len;
continue;
}
case J2K_MIC:
{
Fl_Tree_Item *item;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] mic", name_buf,pos);
item = tree->add(item_name);
item->usericon(&L_documentpixmap);
len = get2(s); s += len;
continue;
}
/*--------------- end Part 2 ----------------*/
default:
{
Fl_Tree_Item *item;
snprintf(iname, MAX_ITEMBUF, "%s/[%03d] Unknown marker 0x%x",
name_buf,pos,type);
item = tree->add(iname);
item->usericon(&L_documentpixmap);
#ifdef DEBUG_DEFAULT_TEST
fprintf(stderr,"test_marker:box_end(%p) - s(%p) ==> %ld\n",
(void*)box_end,(void*)s,(long)(box_end - s));
#endif
s = test_marker(s, box_end, type);
}
break;
}
}
if(sod_found && ! eoc_found)
{
Fl_Tree_Item *sup;
snprintf(iname, MAX_ITEMBUF,"%s/[%03d] EOC",name_buf,pos);
sup = tree->add(iname);
snprintf(item_name, MAX_ITEMBUF,"%s/End of codestream marker",iname);
add_sub_item();
sup->close();
}
if((box_end - s) == 0) return box_end;
#ifdef DEBUG_JP2C_END
fprintf(stderr,"\n%s:%d:END OF READ_JP2C\n"
"\ts(%p) - box_end(%p) ==> %d\n",__FILE__,__LINE__,
(void*)s,(void*)box_end, (int)(s - box_end) );
fprintf(stderr,"\tBOX_END[-1:-7] %02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
box_end[-1],box_end[-2],box_end[-3],box_end[-4],
box_end[-5],box_end[-6],box_end[-7]);
fprintf(stderr,"\tDEND[-1:-7] %02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
dend[-1],dend[-2],dend[-3],dend[-4],dend[-5],dend[-6],dend[-7]);
#endif
if(s <= box_end)
{
#ifdef DEBUG_JP2C_END
fprintf(stderr,"EXIT read_jp2c\n\tbox_end - s ==> %lu\n",
(unsigned long)(box_end - s));
fprintf(stderr,"\tbox_end(%p)\n\tbuf_end(%p)\n",(void*)box_end,
(void*)dend);
#endif
return box_end;
}
#ifdef DEBUG_JP2C_END
fprintf(stderr,"EXIT read_jp2c\n\tdend(%p) - s(%p) ==> %lu\n",
(void*)dend,(void*)s,(unsigned long)(dend - s));
fprintf(stderr,"\tWARNING: s(%p) > box_end(%p) ==> %lu\n",
(void*)s,(void*)box_end,(unsigned long)(s - box_end));
#endif
return box_end;
}// read_jp2c()
unsigned char *read_jp2i(unsigned char *s, unsigned char *box_end,
unsigned char *dend, const char *name_src)
{
snprintf(item_name, MAX_ITEMBUF, "%s/Intellectual property box", name_src);
add_sub_item();
return box_end;
}//read_jp2i()
unsigned char *read_xml(unsigned char *s, unsigned char *box_end,
unsigned char *dend, char **out_buf)
{
char *b;
size_t len;
assert(box_end <= dend);
len = (box_end - s);
b = (char*)calloc(1, len+8);
if(b == NULL) return box_end;
//FIXME memcpy(b, (char*)s, len); b[len] = 0;
fl_utf8toa((char*)s, (unsigned int)len, b, (unsigned int)len);
#ifdef SHOW_XML
fprintf(stderr,"\n%s:%d:\n\tXML(%s)\n\n",__FILE__,__LINE__,b);
#endif
//FIXME to short output
b[32] = 0;
*out_buf = b;
return box_end;
}//read_xml()
unsigned char *read_url(unsigned char *s, unsigned char *box_end,
unsigned char *dend, const char *name_src)
{
unsigned int flag, src_len, dst_len;
unsigned short vers;
char name_buf[MAX_ITEMBUF];
char dst[2048];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/Data Entry URL box",name_buf);
add_sub_item();
vers = (unsigned short)s[0]; ++s;
flag = get_size(s, 3); s += 3;
src_len = (unsigned int)strlen((char*)s);
dst_len = fl_utf8toa((char*)s, src_len, dst, 2047);
snprintf(item_name, MAX_ITEMBUF,"%s/DE vers(%hu) flag(%u) url[%u](%s)",
name_buf, vers,flag,dst_len,dst);
add_sub_item();
return box_end;
}
unsigned char *read_ulst(unsigned char *s, unsigned char *box_end,
unsigned char *dend, const char *name_src)
{
char name_buf[MAX_ITEMBUF];
unsigned char buf[13];
unsigned int i, n, id;
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/UUID List box",name_buf);
buf[12] = 0;
n = get2(s); s += 2;
for(i = 0; i < n; ++i)
{
id = get4(s); s += 4; memcpy(buf, s, 12); s += 12;
snprintf(item_name, MAX_ITEMBUF, "%s/[%u]ID(%u%s)",name_buf,i,id,buf);
add_sub_item();
}
return box_end;
}
unsigned char *read_uuid(unsigned char *s, unsigned char *box_end,
unsigned char *dend, const char *name_src)
{
unsigned int len;
char name_buf[MAX_ITEMBUF];
char data[2048];
char dst[2048];
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF,
"%s/Universal unique identifier box", name_buf);
add_sub_item();
snprintf(item_name, MAX_ITEMBUF,
"%s/ID(%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
name_buf,
s[0], s[1], s[2], s[3],
s[4], s[5],
s[6], s[7],
s[8], s[9],
s[10], s[11], s[12], s[13], s[14], s[15] );
s += 16;
add_sub_item();
memset(data, 0, 2048);
memset(dst, 0, 2048);
len = (unsigned int)(box_end - s);
if(len > 0)
{
if(len > 2047) len = 2047;
memcpy(data, s, len); data[len] = 0;
fl_utf8toa((char*)data, len, dst, len);
#ifdef SHOW_UUID_DATA
dst[len] = 0;
fprintf(stderr,"%s:%d:\n\tDATA(%s)\n",__FILE__,__LINE__,dst);
#else
dst[32] = 0;
#endif
}
snprintf(item_name, MAX_ITEMBUF, "%s/data(%s)",name_buf,dst);
add_sub_item();
return box_end;
}
unsigned char *read_uinf(unsigned char *s, unsigned char *box_end,
unsigned char *dend, const char *name_src)
{
uint64_t box_len;
unsigned int hstep;
char name_buf[MAX_ITEMBUF];
int pos = -1;
strcpy(name_buf, name_src);
snprintf(item_name, MAX_ITEMBUF, "%s/UUID Info box",name_buf);
add_sub_item();
box_len = read_boxheader(s, dend, &hstep);
if(memcmp(box_name, "ulst", 4) == 0)
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] uinf", name_buf, ++pos);
sup = tree->add(item_name);
s = read_ulst(s + hstep, s + box_len, dend, item_name);
sup->close();
box_len = read_boxheader(s, dend, &hstep);
}
if(memcmp(box_name, "url ", 4) == 0)
{
Fl_Tree_Item *sup;
snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] url", name_buf, ++pos);
sup = tree->add(item_name);
(void)read_url(s + hstep, s + box_len, dend, item_name);
sup->close();
}
return box_end;
}
static void test_ftyp(FTYPInfo *info, unsigned char *s,
unsigned char *box_end)
{
int i, n;
unsigned char buf[5];
buf[4] = 0;
memcpy(buf, s, 4); s += 4;
#ifdef DEBUG_TEST_FTYP
fprintf(stderr,"%s:%d:\n\tFTYP BRAND(%s)\n",__FILE__,__LINE__,(char*)buf);
#endif
if(strcasecmp((char*)buf, "jp2 ") == 0)
info->brand_jp2 = 1;
else
if(strcasecmp((char*)buf, "jpx ") == 0)
info->brand_jpx = 1;
else
if(strcasecmp((char*)buf, "jpm ") == 0)
info->brand_jpm = 1;
info->minv = get4(s); s += 4;
n = (int)((box_end - s)/4);
for(i = 0; i < n; ++i)
{
memcpy(buf, s, 4); s += 4;
#ifdef DEBUG_TEST_FTYP
fprintf(stderr,"%s:%d:\n\tFTYP CL[%d]%s\n",__FILE__,__LINE__,i,(char*)buf);
#endif
if(strcasecmp((char*)buf, "jp2 ") == 0)
info->compat_jp2 = 1;
else
if(strcasecmp((char*)buf, "jp21") == 0)
info->compat_jp21 = 1;
else
if(strcasecmp((char*)buf, "jpx ") == 0)
info->compat_jpx = 1;
else
if(strcasecmp((char*)buf, "jpxb") == 0)
info->compat_jpxb = 1;
else
if(strcasecmp((char*)buf, "jpm ") == 0)
info->compat_jpm = 1;
}
}/* test_ftyp() */
int JPEG2000_test_ftyp(const char *fname, unsigned char *s, uint64_t size,
FTYPInfo *info)
{
unsigned char *dend;
const char *cs;
uint64_t box_len;
unsigned int hstep, found = 0;
memset(info, 0, sizeof(struct ftyp_info));
dend = s + size;
if(memcmp(s, JP2_RFC3745_MAGIC, 12) == 0)
{
info->magic_len = 12;
}
else
if(memcmp(s, JP2_MAGIC, 4) == 0)
{
info->magic_len = 4;
}
else
if(memcmp(s, J2K_CODESTREAM_MAGIC, 4) == 0)
{
info->is_j2k = 1;
info->decod_format = J2K_CFMT;
return 1;
}
else
return 0;
s += info->magic_len;
while(s < dend)
{
box_len = read_boxheader(s, dend, &hstep);
if( box_len == 0) break;
if(memcmp(box_name, "ftyp", 4) == 0)
{
test_ftyp(info, s + hstep, s + box_len);
found = 1;
break;
}
s += box_len;
}//while(
if(found == 0)
{
fprintf(stderr,"\nJPX_read_ftyp: no ftyp box found. STOP.\n\n");
return 0;
}
if((cs = strrchr(fname, '.')) != NULL)
{
++cs;
if(strncasecmp(cs, "jpt", 3) == 0)
{
info->decod_format = JPT_CFMT;
info->is_jpt = 1;
return 1;
}
}
info->decod_format = JP2_CFMT;
if(info->brand_jpx)
{
info->is_jpx = 1;
return 1;
}
if(info->brand_jp2)
{
info->is_jp2 = 1;
return 1;
}
if(info->brand_jpm)
{
info->is_jpm = 1;
return 1;
}
return 0;
}//JPEG2000_test_ftyp()
int JPEG2000_build_tree(const char *read_idf)
{
unsigned char *src, *s, *box_end, *dend;
const char *basename;
uint64_t box_len;
#ifdef HAVE_FSEEKO
off_t src_len;
#elif HAVE_FSEEKI64
int64_t src_len;
#else
long src_len;
#endif
unsigned int hstep;
int pos = -1;
unsigned short is_codestream = 0, is_mj2 = 0, is_jpx = 0, is_jpm = 0;
FILE *reader;
char sup_name[MAX_ITEMBUF+2];
if((reader = fopen(read_idf, "rb")) == NULL) return 0;
(void)fread(box_name, 1, 12, reader);
rewind(reader);
if(memcmp(box_name, JP2_RFC3745_MAGIC, 12) == 0)
{
box_len = (uint64_t)12;
strcpy((char*)box_name, "jP ");
}
else
if(memcmp(box_name, JP2_MAGIC, 4) == 0)
{
box_len = (uint64_t)4;
strcpy((char*)box_name, "jP ");
}
else
if(memcmp(box_name, J2K_CODESTREAM_MAGIC, 4) == 0)
{
box_len = (uint64_t)0; *box_name = 0;
is_codestream = 1;
}
else
{
fprintf(stderr, "NOT A JPEG2000 FILE: %s\n",read_idf);
fclose(reader);
return 0;
}
#ifdef _WIN32
basename = strrchr(read_idf, '\\');
#else
basename = strrchr(read_idf, '/');
#endif
if(basename) ++basename; else basename = read_idf;
if(tree != NULL)
{
tree->clear();
}
box_name[4] = 0;
#ifdef HAVE_FSEEKO
fseeko(reader, 0, SEEK_END);
#elif HAVE_FSEEKI64
_fseeki64(reader, 0, SEEK_END);
#else
fseek(reader, 0, SEEK_END);
#endif
#ifdef HAVE_FSEEKO
src_len = ftello(reader);
#elif HAVE_FSEEKI64
src_len = _ftelli64(reader);
#else
src_len = ftell(reader);
#endif
#ifdef HAVE_FSEEKO
fseeko(reader, 0, SEEK_SET);
#elif HAVE_FSEEKI64
_fseeki64(reader, 0, SEEK_SET);
#else
fseek(reader, 0, SEEK_SET);
#endif
src = (unsigned char*) malloc(src_len+4);
if(src == NULL)
{
fprintf(stderr,"read_jpeg2000.cx:%d:\n\tmemory_out\n",__LINE__);
fclose(reader);
return 0;
}
(void)fread(src, 1, src_len, reader);
fclose(reader);
reader = NULL;
init();
memset(&jp2_color, 0, sizeof(jp2_color_t));
s = src + (ptrdiff_t)box_len;
dend = src + (ptrdiff_t)src_len;
memset(src+(ptrdiff_t)src_len,'1',4);
if(is_codestream)
{
Fl_Tree_Item *sup;
snprintf(sup_name, MAX_ITEMBUF, "[%03d] jp2c", ++pos);
sup = tree->add(sup_name);
//-------------- J2K -----------------
s = read_jp2c(s, dend, dend, sup_name);
//-------------- J2K -----------------
sup->close();
}
else
{
box_len = read_boxheader(s, dend, &hstep);
if(box_len == 0) { s = dend; goto end_mark; }
box_end = s + (ptrdiff_t)box_len;
if(box_end >= dend) { s = dend; goto end_mark; }
if(memcmp(box_name, "ftyp", 4) == 0)
{
unsigned char brand[5];
brand[4] = 0;
memcpy(brand, s+hstep, 4);
if(memcmp(brand, "mjp2", 4) == 0)
is_mj2 = 1;
else
if(memcmp(brand, "jpx ", 4) == 0)
is_jpx = 1;
else
if(memcmp(brand, "jpm ", 4) == 0)
is_jpm = 1;
}
if(is_mj2)
{
//------------------------
read_mj2(s, dend);
//------------------------
goto end_mark;
}
if(is_jpx)
{
//------------------------
read_jpx(src, s, dend);
//------------------------
goto end_mark;
}
if(is_jpm)
{
//------------------------
read_jpm(src, s, dend);
//------------------------
goto end_mark;
}
//------- JP2, JPM -------
while(s < dend)
{
box_len = read_boxheader(s, dend, &hstep);
if(box_len == 0) { s = dend; break; }
if((uint64_t)(dend - s) < box_len)
box_end = dend;
else
box_end = s + (ptrdiff_t)box_len;
if(memcmp(box_name, "ftyp", 4) == 0)
{
Fl_Tree_Item *sup;
snprintf(sup_name, MAX_ITEMBUF, "[%03d] ftyp", ++pos);
sup = tree->add(sup_name);
s = read_ftyp(s + hstep, s + box_len, sup_name);
sup->close();
continue;
}
if(memcmp(box_name, "jp2h", 4) == 0)
{
Fl_Tree_Item *sup;
snprintf(sup_name, MAX_ITEMBUF, "[%03d] jp2h", ++pos);
sup = tree->add(sup_name);
s = read_jp2h(s + hstep, s + box_len, dend, sup_name);
sup->close();
continue;
}
if(memcmp(box_name, "jp2c", 4) == 0)
{
Fl_Tree_Item *sup;
snprintf(sup_name, MAX_ITEMBUF, "[%03d] jp2c", ++pos);
sup = tree->add(sup_name);
/*----------------------------------------------------------*/
s = read_jp2c(s + hstep, s + box_len, dend, sup_name);
/*----------------------------------------------------------*/
assert(s == box_end);
sup->close();
continue;
}
if(memcmp(box_name, "jp2i", 4) == 0)
{
Fl_Tree_Item *sup;
snprintf(sup_name, MAX_ITEMBUF, "[%03d] jp2i", ++pos);
sup = tree->add(sup_name);
s = read_jp2i(s + hstep, s + box_len, dend, sup_name);
sup->close();
continue;
}
if(memcmp(box_name, "xml ", 4) == 0
|| memcmp(box_name, "XML ", 4) == 0)
{
Fl_Tree_Item *sup, *sub;
char *buf = NULL;
char name[MAX_ITEMBUF+1];
snprintf(name, MAX_ITEMBUF, "[%03d] XML", ++pos);
sup = tree->add(name);
snprintf(sup_name, MAX_ITEMBUF, "%s/xml1", name);
sub = tree->add(sup_name);
s = read_xml(s + hstep, s + box_len, dend, &buf);
sub->label(buf);
sup->close();
free(buf);
continue;
}
if(memcmp(box_name, "uuid", 4) == 0)
{
Fl_Tree_Item *sup;
snprintf(sup_name, MAX_ITEMBUF, "[%03d] uuid", ++pos);
sup = tree->add(sup_name);
s = read_uuid(s + hstep, s + box_len, dend, sup_name);
sup->close();
continue;
}
if(memcmp(box_name, "uinf", 4) == 0)
{
Fl_Tree_Item *sup;
snprintf(sup_name, MAX_ITEMBUF, "[%03d] uinf", ++pos);
sup = tree->add(sup_name);
s = read_uinf(s + hstep, s + box_len, dend, sup_name);
sup->close();
continue;
}
{
Fl_Tree_Item *sup;
snprintf(sup_name, MAX_ITEMBUF, "[%03d] %s", ++pos, (char*)box_name);
sup = tree->add(sup_name);
snprintf(item_name, MAX_ITEMBUF, "%s/Not handled. Skipped.", sup_name);
add_sub_item();
sup->close();
}
#ifdef PRINTF_UNKNOWN_BOX
fprintf(stderr,"%s:%d:\n\tTRACE Unknown Box name(%s) len(%ld)\n"
"\tbox_end - s(%ld) dend - s(%ld)\n",__FILE__,__LINE__,
(char*)box_name,box_len,(long)(box_end - s),(long)(dend - s) );
#endif
s = box_end;
}//while(
}
end_mark:
free(src);
snprintf(sup_name, MAX_ITEMBUF, "%s (%" PRId64 " Byte)", basename,
(int64_t)src_len);
tree->root_label(sup_name);
tree->labelsize(TREE_LABEL_SIZE);
tree->redraw();
return 1;
}// JPEG2000_build_tree()