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