6eafa40b78304c2da26259fe9f3a5601f5612d8d
[openjpeg.git] / applications / jpip / libopenjpip / index_manager.c
1 /*
2  * $Id: index_manager.c 53 2011-05-09 16:55:39Z kaori $
3  *
4  * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
5  * Copyright (c) 2002-2011, Professor Benoit Macq
6  * Copyright (c) 2010-2011, Kaori Hagihara
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <math.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <string.h>
38
39 #include "bool.h"
40 #include "index_manager.h"
41 #include "box_manager.h"
42 #include "manfbox_manager.h"
43 #include "mhixbox_manager.h"
44 #include "codestream_manager.h"
45 #include "marker_manager.h"
46 #include "faixbox_manager.h"
47 #include "boxheader_manager.h"
48
49 #ifdef SERVER
50 #include "fcgi_stdio.h"
51 #define logstream FCGI_stdout
52 #else
53 #define FCGI_stdout stdout
54 #define FCGI_stderr stderr
55 #define logstream stderr
56 #endif //SERVER
57
58 /**
59  * chekc JP2 box indexing
60  *
61  * @param[in] toplev_boxlist top level box list
62  * @return                   if correct (true) or wrong (false)
63  */
64 bool check_JP2boxidx( boxlist_param_t *toplev_boxlist);
65
66 /**
67  * set code index parameters (parse cidx box)
68  * Annex I
69  *
70  * @param[in]  cidx_box pointer to the reference cidx_box
71  * @param[out] codeidx  pointer to index parameters
72  * @return              if succeeded (true) or failed (false)
73  */
74 bool set_cidxdata( box_param_t *cidx_box, index_param_t *codeidx);
75
76 index_param_t * parse_jp2file( int fd)
77 {
78   index_param_t *jp2idx;
79   box_param_t *cidx;
80   metadatalist_param_t *metadatalist;
81   boxlist_param_t *toplev_boxlist;
82   struct stat sb;
83   
84   if( fstat( fd, &sb) == -1){
85     fprintf( FCGI_stdout, "Reason: Target broken (fstat error)\r\n");
86     return NULL;
87   }
88
89   if( !(toplev_boxlist = get_boxstructure( fd, 0, sb.st_size))){
90     fprintf( FCGI_stderr, "Error: Not correctl JP2 format\n");
91     return NULL;
92   }
93   
94   if( !check_JP2boxidx( toplev_boxlist)){
95     fprintf( FCGI_stderr, "Index format not supported\n");
96     delete_boxlist( &toplev_boxlist);
97     return NULL;
98   }
99
100   if( !(cidx = search_box( "cidx", toplev_boxlist))){
101     fprintf( FCGI_stderr, "Box cidx not found\n");
102     delete_boxlist( &toplev_boxlist);
103     return NULL;
104   }
105
106   jp2idx = (index_param_t *)malloc( sizeof(index_param_t));
107   
108   if( !set_cidxdata( cidx, jp2idx)){
109     fprintf( FCGI_stderr, "Error: Not correctl format in cidx box\n");
110     free(jp2idx);
111     delete_boxlist( &toplev_boxlist);
112     return NULL;
113   }
114   delete_boxlist( &toplev_boxlist);
115   
116   metadatalist = const_metadatalist( fd);
117   jp2idx->metadatalist = metadatalist;
118
119 #ifndef SERVER
120     fprintf( logstream, "local log: code index created\n");
121 #endif
122   
123   return jp2idx;
124 }
125
126 void print_index( index_param_t index)
127 {
128   int i;
129
130   fprintf( logstream, "index info:\n");
131   fprintf( logstream, "\tCodestream  Offset: %#llx\n", index.offset);
132   fprintf( logstream, "\t            Length: %#llx\n", index.length);
133   fprintf( logstream, "\tMain header Length: %#llx\n", index.mhead_length);
134   
135   print_SIZ( index.SIZ);
136   print_COD( index.COD);
137   
138   fprintf( logstream, "Tile part information: \n");
139   print_faixbox( index.tilepart);
140
141   fprintf( logstream, "Tile header information: \n");
142   for( i=0; i<index.SIZ.XTnum*index.SIZ.YTnum ;i++)
143     print_mhixbox( index.tileheader[i]);
144
145   fprintf( logstream, "Precinct packet information: \n");
146   for( i=0; i<index.SIZ.Csiz; i++){
147     fprintf( logstream, "Component %d\n", i);
148     print_faixbox( index.precpacket[i]);
149   }
150
151   print_allmetadata( index.metadatalist);
152 }
153
154 void print_SIZ( SIZmarker_param_t SIZ)
155 {
156   int i;
157
158   fprintf( logstream, "\tImage and Tile SIZ parameters\n");
159   fprintf( logstream, "\t              Rsiz: %#x\n", SIZ.Rsiz);
160   fprintf( logstream, "\t        Xsiz, Ysiz: (%d,%d) = (%#x, %#x)\n", SIZ.Xsiz, SIZ.Ysiz, SIZ.Xsiz, SIZ.Ysiz);
161   fprintf( logstream, "\t      XOsiz, YOsiz: (%d,%d) = (%#x, %#x)\n", SIZ.XOsiz, SIZ.YOsiz, SIZ.XOsiz, SIZ.YOsiz);
162   fprintf( logstream, "\t      XTsiz, YTsiz: (%d,%d) = (%#x, %#x)\n", SIZ.XTsiz, SIZ.YTsiz, SIZ.XTsiz, SIZ.YTsiz);
163   fprintf( logstream, "\t    XTOsiz, YTOsiz: (%d,%d) = (%#x, %#x)\n", SIZ.XTOsiz, SIZ.YTOsiz, SIZ.XTOsiz, SIZ.YTOsiz);
164   fprintf( logstream, "\t    XTnum, YTnum: (%d,%d)\n", SIZ.XTnum, SIZ.YTnum);
165   fprintf( logstream, "\t Num of Components: %d\n", SIZ.Csiz);
166   
167   for( i=0; i<SIZ.Csiz; i++)
168     fprintf( logstream, "\t[%d] (Ssiz, XRsiz, YRsiz): (%d, %d, %d) = (%#x, %#x, %#x)\n", i, SIZ.Ssiz[i], SIZ.XRsiz[i], SIZ.YRsiz[i], SIZ.Ssiz[i], SIZ.XRsiz[i], SIZ.YRsiz[i]);
169 }
170
171 void print_COD( CODmarker_param_t COD)
172 {
173   int i;
174
175   fprintf( logstream, "\tCoding style default COD parameters\n");
176   fprintf( logstream, "\t Progression order: %d [ LRCP=0, RLCP=1, RPCL=2, PCRL=3, CPRL=4]\n", COD.prog_order);
177   fprintf( logstream, "\t     Num of layers: %d\n", COD.numOflayers);
178   fprintf( logstream, "\t Decomposition lvl: %d\n", COD.numOfdecomp);
179   
180   for( i=0; i<=((COD.Scod & 0x01) ? COD.numOfdecomp:0); i++){
181     fprintf( logstream, "\t  [%d] XPsiz, YPsiz: (%d,%d) = (%#x, %#x)\n",i, COD.XPsiz[i], COD.YPsiz[i], COD.XPsiz[i], COD.YPsiz[i]);
182   }
183 }
184
185 void delete_index( index_param_t **index)
186 {
187   int i;
188
189   delete_metadatalist( &((*index)->metadatalist));
190
191   delete_COD( (*index)->COD);
192   
193   delete_faixbox( &((*index)->tilepart));
194
195   for( i=0; i< (*index)->SIZ.XTnum*(*index)->SIZ.YTnum ;i++)
196     delete_mhixbox( &((*index)->tileheader[i]));
197   free( (*index)->tileheader);
198   
199   for( i=0; i<(*index)->SIZ.Csiz; i++)
200     delete_faixbox( &((*index)->precpacket[i]));
201   free( (*index)->precpacket);
202   
203   free(*index);
204 }
205
206 void delete_COD( CODmarker_param_t COD)
207 {
208   if( COD.XPsiz)    free( COD.XPsiz);
209   if( COD.YPsiz)    free( COD.YPsiz);
210 }
211
212 bool check_JP2boxidx( boxlist_param_t *toplev_boxlist)
213 {
214   box_param_t *iptr, *fidx, *prxy;
215   box_param_t *cidx, *jp2c;
216
217   iptr = search_box( "iptr", toplev_boxlist);
218   fidx = search_box( "fidx", toplev_boxlist);
219   cidx = search_box( "cidx", toplev_boxlist);
220   jp2c = search_box( "jp2c", toplev_boxlist);
221   prxy = gene_childboxbyType( fidx, 0, "prxy");
222
223   Byte8_t off = fetch_DBox8bytebigendian( iptr, 0);
224   if( off != fidx->offset)
225     fprintf( FCGI_stderr, "Reference File Index box offset in Index Finder box not correct\n");
226
227   Byte8_t len = fetch_DBox8bytebigendian( iptr, 8);
228   if( len != fidx->length)
229     fprintf( FCGI_stderr, "Reference File Index box length in Index Finder box not correct\n");
230
231  
232   int pos = 0;
233   Byte8_t ooff = fetch_DBox8bytebigendian( prxy, pos);
234   if( ooff != jp2c->offset)
235     fprintf( FCGI_stderr, "Reference jp2c offset in prxy box not correct\n");
236   pos += 8;
237
238   boxheader_param_t *obh = gene_childboxheader( prxy, pos);
239   if( obh->length != jp2c->length || strncmp( obh->type, "jp2c",4)!=0)
240     fprintf( FCGI_stderr, "Reference jp2c header in prxy box not correct\n");
241   pos += obh->headlen;
242   free(obh);
243   
244   Byte_t ni = fetch_DBox1byte( prxy, pos);
245   if( ni != 1){
246     fprintf( FCGI_stderr, "Multiple indexes not supported\n");
247     return false;
248   }  
249   pos += 1;
250   
251   Byte8_t ioff = fetch_DBox8bytebigendian( prxy, pos);
252   if( ioff != cidx->offset)
253     fprintf( FCGI_stderr, "Reference cidx offset in prxy box not correct\n");
254   pos += 8;
255
256   boxheader_param_t *ibh = gene_childboxheader( prxy, pos);
257   if( ibh->length != cidx->length || strncmp( ibh->type, "cidx",4)!=0)
258     fprintf( FCGI_stderr, "Reference cidx header in prxy box not correct\n");
259   pos += ibh->headlen;
260   free(ibh);
261   
262   free(prxy);
263
264   return true;
265 }
266
267 /**
268  * set code index parameters from cptr box
269  * I.3.2.2 Codestream Finder box
270  *
271  * @param[in]  cidx_box pointer to the reference cidx_box
272  * @param[out] jp2idx   pointer to index parameters
273  * @return              if succeeded (true) or failed (false)
274  */
275 bool set_cptrdata( box_param_t *cidx_box, index_param_t *jp2idx);
276
277 /**
278  * set code index parameters from mhix box for main header
279  * I.3.2.4.3 Header Index Table box
280  *
281  * @param[in]  cidx_box   pointer to the reference cidx_box
282  * @param[in]  codestream codestream parameters
283  * @param[out] jp2idx     pointer to index parameters
284  * @return                if succeeded (true) or failed (false)
285  */
286 bool set_mainmhixdata( box_param_t *cidx_box, codestream_param_t codestream, index_param_t *jp2idx);
287
288 /**
289  * set code index parameters from tpix box
290  * I.3.2.4.4 Tile-part Index Table box
291  *
292  * @param[in]  cidx_box   pointer to the reference cidx_box
293  * @param[out] jp2idx     pointer to index parameters
294  * @return                if succeeded (true) or failed (false)
295  */
296 bool set_tpixdata( box_param_t *cidx_box, index_param_t *jp2idx);
297
298 /**
299  * set code index parameters from thix box
300  * I.3.2.4.5 Tile Header Index Table box
301  *
302  * @param[in]  cidx_box   pointer to the reference cidx_box
303  * @param[out] jp2idx     pointer to index parameters
304  * @return                if succeeded (true) or failed (false)
305  */
306 bool set_thixdata( box_param_t *cidx_box, index_param_t *jp2idx);
307
308 /**
309  * set code index parameters from ppix box
310  * I.3.2.4.6 Precinct Packet Index Table box
311  *
312  * @param[in]  cidx_box   pointer to the reference cidx_box
313  * @param[out] jp2idx     pointer to index parameters
314  * @return                if succeeded (true) or failed (false)
315  */
316 bool set_ppixdata( box_param_t *cidx_box, index_param_t *jp2idx);
317
318 bool set_cidxdata( box_param_t *cidx_box, index_param_t *jp2idx)
319 {
320   box_param_t *manf_box;
321   manfbox_param_t *manf;
322   codestream_param_t codestream;
323
324   set_cptrdata( cidx_box, jp2idx);
325
326   codestream = set_codestream( cidx_box->fd, jp2idx->offset, jp2idx->length);
327
328   manf_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "manf");
329   manf = gene_manfbox( manf_box);
330
331   if( !search_boxheader( "mhix", manf)){
332     fprintf( FCGI_stderr, "Error: mhix box not present in manfbox\n");
333     free(jp2idx);
334     return false;
335   }
336   set_mainmhixdata( cidx_box, codestream, jp2idx);
337
338   if( !search_boxheader( "tpix", manf)){
339     fprintf( FCGI_stderr, "Error: tpix box not present in manfbox\n");
340     free(jp2idx);
341     return false;
342   }
343   set_tpixdata( cidx_box, jp2idx);
344
345   if( !search_boxheader( "thix", manf)){
346     fprintf( FCGI_stderr, "Error: thix box not present in manfbox\n");
347     free(jp2idx);
348     return false;
349   }
350   set_thixdata( cidx_box, jp2idx);
351
352   if( !search_boxheader( "ppix", manf)){
353     fprintf( FCGI_stderr, "Error: ppix box not present in manfbox\n");
354     free(jp2idx);
355     return false;
356   }
357   set_ppixdata( cidx_box, jp2idx);
358
359   delete_manfbox( &manf);
360   free( manf_box);
361
362   return true;
363 }
364
365 bool set_cptrdata( box_param_t *cidx_box, index_param_t *jp2idx)
366 {
367   box_param_t *box;   //!< cptr box
368   Byte2_t dr, cont;
369
370   if( !(box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "cptr")))
371     return false;
372   
373   // DR: Data Reference. 
374   // If 0, the codestream or its Fragment Table box exists in the current file
375   if(( dr = fetch_DBox2bytebigendian( box, 0))){
376     fprintf( FCGI_stderr, "Error: Codestream not present in current file\n");
377     free( box);
378     return false;  
379   }
380   
381   // CONT: Container Type
382   // If 0, the entire codestream appears as a contiguous range of
383   // bytes within its file or resource.
384   if(( cont = fetch_DBox2bytebigendian( box, 2))){
385     fprintf( FCGI_stderr, "Error: Can't cope with fragmented codestreams yet\n");
386     free( box);
387     return false;  
388   }
389     
390   jp2idx->offset = fetch_DBox8bytebigendian( box, 4);
391   jp2idx->length = fetch_DBox8bytebigendian( box, 12);
392
393   free( box);
394
395   return true;
396 }
397
398
399 /**
400  * set SIZ marker information
401  * A.5 Fixed information marker segment
402  * A.5.1 Image and tile size (SIZ)
403  *
404  * @param[in]  sizmkidx   pointer to SIZ marker index in mhix box
405  * @param[in]  codestream codestream parameters
406  * @param[out] SIZ        SIZ marker parameters pointer
407  * @return                if succeeded (true) or failed (false)
408  */
409 bool set_SIZmkrdata( markeridx_param_t *sizmkidx, codestream_param_t codestream, SIZmarker_param_t *SIZ);
410
411 /**
412  * set code index parameters from COD marker in codestream
413  * A.6 Functional marker segments
414  * A.6.1 Coding style default (COD)
415  *
416  * @param[in]  codmkidx   pointer to COD marker index in mhix box
417  * @param[in]  codestream codestream parameters
418  * @param[out] COD        COD marker parameters pointer
419  * @return                if succeeded (true) or failed (false)
420  */
421 bool set_CODmkrdata( markeridx_param_t *codmkidx, codestream_param_t codestream, CODmarker_param_t *COD);
422
423 bool set_mainmhixdata( box_param_t *cidx_box, codestream_param_t codestream, index_param_t *jp2idx)
424 {
425   box_param_t *mhix_box;
426   mhixbox_param_t *mhix;
427   markeridx_param_t *sizmkidx;
428   markeridx_param_t *codmkidx;
429
430   if( !(mhix_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "mhix")))
431     return false;
432
433   jp2idx->mhead_length = fetch_DBox8bytebigendian( mhix_box, 0);
434
435   mhix = gene_mhixbox( mhix_box);
436   free( mhix_box);
437
438   sizmkidx = search_markeridx( 0xff51, mhix);
439   set_SIZmkrdata( sizmkidx, codestream, &(jp2idx->SIZ));
440
441   codmkidx = search_markeridx( 0xff52, mhix);
442   set_CODmkrdata( codmkidx, codestream, &(jp2idx->COD));
443
444   delete_mhixbox( &mhix);
445
446   return true;
447 }
448
449 bool set_tpixdata( box_param_t *cidx_box, index_param_t *jp2idx)
450 {
451   box_param_t *tpix_box;   //!< tpix box
452   box_param_t *faix_box;   //!< faix box
453   
454   if( !(tpix_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "tpix"))){
455     fprintf( FCGI_stderr, "Error: tpix box not present in cidx box\n");
456     return false;
457   }
458
459   if( !(faix_box = gene_boxbyType( tpix_box->fd, get_DBoxoff( tpix_box), get_DBoxlen( tpix_box), "faix"))){
460     fprintf( FCGI_stderr, "Error: faix box not present in tpix box\n");
461     return false;
462   }
463
464   jp2idx->tilepart = gene_faixbox( faix_box);
465   
466   free( tpix_box);
467   free( faix_box);
468
469   return true;
470 }
471
472 bool set_thixdata( box_param_t *cidx_box, index_param_t *jp2idx)
473 {
474   box_param_t *thix_box, *manf_box, *mhix_box;
475   manfbox_param_t *manf;
476   boxheader_param_t *ptr;
477   mhixbox_param_t *mhix;
478   Byte8_t pos, mhixseqoff;
479   Byte2_t tile_no;
480   
481   if( !(thix_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "thix"))){
482     fprintf( FCGI_stderr, "Error: thix box not present in cidx box\n");
483     return false;
484   }
485   
486   if( !(manf_box = gene_boxbyType( thix_box->fd, get_DBoxoff( thix_box), get_DBoxlen( thix_box), "manf"))){
487     fprintf( FCGI_stderr, "Error: manf box not present in thix box\n");
488     free( thix_box);
489     return false;
490   }
491   
492   manf = gene_manfbox( manf_box);
493   ptr = manf->first;
494   mhixseqoff = manf_box->offset+manf_box->length;
495   pos = 0;
496   tile_no = 0;
497   jp2idx->tileheader = (mhixbox_param_t **)malloc( jp2idx->SIZ.XTnum*jp2idx->SIZ.YTnum*sizeof(mhixbox_param_t *));
498     
499   while( ptr){
500     if( !(mhix_box = gene_boxbyType( thix_box->fd, mhixseqoff+pos, get_DBoxlen( thix_box)-manf_box->length-pos, "mhix"))){
501       fprintf( FCGI_stderr, "Error: mhix box not present in thix box\n");
502       delete_manfbox( &manf);
503       free( manf_box);
504       free( thix_box);
505       return false;
506     }
507     mhix = gene_mhixbox( mhix_box);
508
509     pos += mhix_box->length;
510     ptr = ptr->next;
511
512     free( mhix_box);
513     jp2idx->tileheader[tile_no++] = mhix;
514   }
515
516   delete_manfbox( &manf);
517   free( manf_box);
518   free( thix_box);
519
520   return true;
521 }
522
523 bool set_ppixdata( box_param_t *cidx_box, index_param_t *jp2idx)
524 {
525   box_param_t *ppix_box, *faix_box, *manf_box;
526   manfbox_param_t *manf;     //!< manf
527   boxheader_param_t *bh;     //!< box headers
528   faixbox_param_t *faix;     //!< faix
529   Byte8_t inbox_offset;
530   int comp_idx;
531
532   if( !(ppix_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "ppix"))){
533     fprintf( FCGI_stderr, "Error: ppix box not present in cidx box\n");
534     return false;
535   }
536
537   inbox_offset = get_DBoxoff( ppix_box);
538   if( !(manf_box = gene_boxbyType( ppix_box->fd, inbox_offset, get_DBoxlen( ppix_box), "manf"))){
539     fprintf( FCGI_stderr, "Error: manf box not present in ppix box\n");
540     free( ppix_box);
541     return false;
542   }
543
544   free( ppix_box);
545
546   manf = gene_manfbox( manf_box);
547   bh = search_boxheader( "faix", manf);
548   inbox_offset = manf_box->offset + manf_box->length;
549   
550   free( manf_box);
551
552   jp2idx->precpacket = (faixbox_param_t **)malloc( jp2idx->SIZ.Csiz*sizeof(faixbox_param_t *));
553
554   for( comp_idx=0; bh!=NULL; bh=bh->next, comp_idx++){
555     if( jp2idx->SIZ.Csiz <= comp_idx ){
556       fprintf( FCGI_stderr, "Error: num of faix boxes is not identical to num of components in ppix box\n");
557       return false;
558     }
559
560     if( !(faix_box = gene_boxbyOffset( cidx_box->fd, inbox_offset))){
561       fprintf( FCGI_stderr, "Error: faix box not present in ppix box\n");
562       return false;
563     }
564   
565     faix = gene_faixbox( faix_box);
566     jp2idx->precpacket[comp_idx] = faix;
567
568     inbox_offset = faix_box->offset + faix_box->length;
569     free( faix_box);   
570   }
571   
572   delete_manfbox( &manf);
573
574   return true;
575 }
576
577
578 bool set_SIZmkrdata( markeridx_param_t *sizmkidx, codestream_param_t codestream, SIZmarker_param_t *SIZ)
579 {
580   marker_param_t sizmkr;
581   int i;
582
583   sizmkr = set_marker( codestream, sizmkidx->code, sizmkidx->offset, sizmkidx->length);
584
585   SIZ->Lsiz = fetch_marker2bytebigendian( sizmkr, 0);
586
587   if( sizmkidx->length != SIZ->Lsiz){
588     fprintf( FCGI_stderr, "Error: marker %#x index is not correct\n", sizmkidx->code);
589     return false;
590   }
591   
592   SIZ->Rsiz   = fetch_marker2bytebigendian( sizmkr, 2);
593   SIZ->Xsiz   = fetch_marker4bytebigendian( sizmkr, 4);
594   SIZ->Ysiz   = fetch_marker4bytebigendian( sizmkr, 8);
595   SIZ->XOsiz  = fetch_marker4bytebigendian( sizmkr, 12);
596   SIZ->YOsiz  = fetch_marker4bytebigendian( sizmkr, 16);
597   SIZ->XTsiz  = fetch_marker4bytebigendian( sizmkr, 20);
598   SIZ->YTsiz  = fetch_marker4bytebigendian( sizmkr, 24);
599   SIZ->XTOsiz = fetch_marker4bytebigendian( sizmkr, 28);
600   SIZ->YTOsiz = fetch_marker4bytebigendian( sizmkr, 32);
601   SIZ->Csiz   = fetch_marker2bytebigendian( sizmkr, 36);
602
603   SIZ->XTnum  = ( SIZ->Xsiz-SIZ->XTOsiz+SIZ->XTsiz-1)/SIZ->XTsiz;
604   SIZ->YTnum  = ( SIZ->Ysiz-SIZ->YTOsiz+SIZ->YTsiz-1)/SIZ->YTsiz;
605   
606   for( i=0; i<(int)SIZ->Csiz; i++){
607     SIZ->Ssiz[i]  = fetch_marker1byte( sizmkr, 38+i*3);
608     SIZ->XRsiz[i] = fetch_marker1byte( sizmkr, 39+i*3);
609     SIZ->YRsiz[i] = fetch_marker1byte( sizmkr, 40+i*3);
610   }
611   return true;
612 }
613
614 bool set_CODmkrdata( markeridx_param_t *codmkidx, codestream_param_t codestream, CODmarker_param_t *COD)
615 {
616   marker_param_t codmkr;
617   int i;
618
619   codmkr = set_marker( codestream, codmkidx->code, codmkidx->offset, codmkidx->length);
620
621   COD->Lcod = fetch_marker2bytebigendian( codmkr, 0);
622
623   if( codmkidx->length != COD->Lcod){
624     fprintf( FCGI_stderr, "Error: marker %#x index is not correct\n", codmkidx->code);
625     return false;
626   }
627
628   COD->Scod   = fetch_marker1byte( codmkr, 2);
629   COD->prog_order  = fetch_marker1byte( codmkr, 3);
630   COD->numOflayers = fetch_marker2bytebigendian( codmkr, 4);
631   COD->numOfdecomp = fetch_marker1byte( codmkr, 7);
632   
633   if(COD->Scod & 0x01){
634     COD->XPsiz = (Byte4_t *)malloc( (COD->numOfdecomp+1)*sizeof(Byte4_t));
635     COD->YPsiz = (Byte4_t *)malloc( (COD->numOfdecomp+1)*sizeof(Byte4_t));
636
637     for( i=0; i<=COD->numOfdecomp; i++){
638       //precinct size
639       COD->XPsiz[i] = pow( 2, fetch_marker1byte( codmkr, 12+i) & 0x0F);
640       COD->YPsiz[i] = pow( 2,(fetch_marker1byte( codmkr, 12+i) & 0xF0) >> 4);
641     }
642   }
643   else{
644     COD->XPsiz = (Byte4_t *)malloc( sizeof(Byte4_t));
645     COD->YPsiz = (Byte4_t *)malloc( sizeof(Byte4_t));
646
647     COD->XPsiz[0] = COD->YPsiz[0] = pow(2,15);
648   }
649   return true;
650 }
651
652
653 Byte4_t max( Byte4_t n1, Byte4_t n2);
654 Byte4_t min( Byte4_t n1, Byte4_t n2);
655
656 range_param_t get_tile_range( Byte4_t Osiz, Byte4_t siz, Byte4_t TOsiz, Byte4_t Tsiz, Byte4_t tile_XYid, int level);
657
658 range_param_t get_tile_Xrange( SIZmarker_param_t SIZ, Byte4_t tile_id, int level)
659 {
660   return get_tile_range( SIZ.XOsiz, SIZ.Xsiz, SIZ.XTOsiz, SIZ.XTsiz, tile_id%SIZ.XTnum, level);
661 }
662
663 range_param_t get_tile_Yrange( SIZmarker_param_t SIZ, Byte4_t tile_id, int level)
664 {
665   return get_tile_range( SIZ.YOsiz, SIZ.Ysiz, SIZ.YTOsiz, SIZ.YTsiz, tile_id/SIZ.XTnum, level);
666 }
667
668 range_param_t get_tile_range( Byte4_t Osiz, Byte4_t siz, Byte4_t TOsiz, Byte4_t Tsiz, Byte4_t tile_XYid, int level)
669 {
670   range_param_t range;
671   int n;
672
673   range.minvalue = max( Osiz, TOsiz+tile_XYid*Tsiz);
674   range.maxvalue = min( siz,  TOsiz+(tile_XYid+1)*Tsiz);
675
676   for( n=0; n<level; n++){
677     range.minvalue = ceil(range.minvalue/2.0);
678     range.maxvalue = ceil(range.maxvalue/2.0);
679   }
680   return range;
681 }
682
683 Byte4_t get_tile_XSiz( SIZmarker_param_t SIZ, Byte4_t tile_id, int level)
684 {
685   range_param_t tile_Xrange;
686
687   tile_Xrange = get_tile_Xrange( SIZ, tile_id, level);
688   return tile_Xrange.maxvalue - tile_Xrange.minvalue;
689 }
690
691 Byte4_t get_tile_YSiz( SIZmarker_param_t SIZ, Byte4_t tile_id, int level)
692 {
693   range_param_t tile_Yrange;
694
695   tile_Yrange = get_tile_Yrange( SIZ, tile_id, level);
696   return tile_Yrange.maxvalue - tile_Yrange.minvalue;
697 }
698
699 Byte4_t max( Byte4_t n1, Byte4_t n2)
700 {
701   if( n1 < n2)
702     return n2;
703   else
704     return n1;
705 }
706
707 Byte4_t min( Byte4_t n1, Byte4_t n2)
708 {
709   if( n1 < n2)
710     return n1;
711   else
712     return n2;
713 }
714
715 bool isJPTfeasible( index_param_t index)
716 {
717   if( 1 < get_nmax( index.tilepart))
718     return true;
719   else
720     return false;
721 }