/* * $Id: index_manager.c 53 2011-05-09 16:55:39Z kaori $ * * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium * Copyright (c) 2002-2011, Professor Benoit Macq * Copyright (c) 2010-2011, Kaori Hagihara * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "bool.h" #include "index_manager.h" #include "box_manager.h" #include "manfbox_manager.h" #include "mhixbox_manager.h" #include "codestream_manager.h" #include "marker_manager.h" #include "faixbox_manager.h" #include "boxheader_manager.h" #ifdef SERVER #include "fcgi_stdio.h" #define logstream FCGI_stdout #else #define FCGI_stdout stdout #define FCGI_stderr stderr #define logstream stderr #endif //SERVER /** * chekc JP2 box indexing * * @param[in] toplev_boxlist top level box list * @return if correct (true) or wrong (false) */ bool check_JP2boxidx( boxlist_param_t *toplev_boxlist); /** * set code index parameters (parse cidx box) * Annex I * * @param[in] cidx_box pointer to the reference cidx_box * @param[out] codeidx pointer to index parameters * @return if succeeded (true) or failed (false) */ bool set_cidxdata( box_param_t *cidx_box, index_param_t *codeidx); index_param_t * parse_jp2file( int fd) { index_param_t *jp2idx; box_param_t *cidx; metadatalist_param_t *metadatalist; boxlist_param_t *toplev_boxlist; struct stat sb; if( fstat( fd, &sb) == -1){ fprintf( FCGI_stdout, "Reason: Target broken (fstat error)\r\n"); return NULL; } if( !(toplev_boxlist = get_boxstructure( fd, 0, sb.st_size))){ fprintf( FCGI_stderr, "Error: Not correctl JP2 format\n"); return NULL; } if( !check_JP2boxidx( toplev_boxlist)){ fprintf( FCGI_stderr, "Index format not supported\n"); delete_boxlist( &toplev_boxlist); return NULL; } if( !(cidx = search_box( "cidx", toplev_boxlist))){ fprintf( FCGI_stderr, "Box cidx not found\n"); delete_boxlist( &toplev_boxlist); return NULL; } jp2idx = (index_param_t *)malloc( sizeof(index_param_t)); if( !set_cidxdata( cidx, jp2idx)){ fprintf( FCGI_stderr, "Error: Not correctl format in cidx box\n"); free(jp2idx); delete_boxlist( &toplev_boxlist); return NULL; } delete_boxlist( &toplev_boxlist); metadatalist = const_metadatalist( fd); jp2idx->metadatalist = metadatalist; #ifndef SERVER fprintf( logstream, "local log: code index created\n"); #endif return jp2idx; } void print_index( index_param_t index) { int i; fprintf( logstream, "index info:\n"); fprintf( logstream, "\tCodestream Offset: %#llx\n", index.offset); fprintf( logstream, "\t Length: %#llx\n", index.length); fprintf( logstream, "\tMain header Length: %#llx\n", index.mhead_length); fprintf( logstream, "\t Rsiz: %#x\n", index.Rsiz); fprintf( logstream, "\t Xsiz, Ysiz: (%d,%d) = (%#x, %#x)\n", index.Xsiz, index.Ysiz, index.Xsiz, index.Ysiz); fprintf( logstream, "\t XOsiz, YOsiz: (%d,%d) = (%#x, %#x)\n", index.XOsiz, index.YOsiz, index.XOsiz, index.YOsiz); fprintf( logstream, "\t XTsiz, YTsiz: (%d,%d) = (%#x, %#x)\n", index.XTsiz, index.YTsiz, index.XTsiz, index.YTsiz); fprintf( logstream, "\t XTOsiz, YTOsiz: (%d,%d) = (%#x, %#x)\n", index.XTOsiz, index.YTOsiz, index.XTOsiz, index.YTOsiz); fprintf( logstream, "\t XTnum, YTnum: (%d,%d)\n", index.XTnum, index.YTnum); fprintf( logstream, "\t Num of Components: %d\n", index.Csiz); for( i=0; imetadatalist)); delete_faixbox( &((*index)->tilepart)); free(*index); } bool check_JP2boxidx( boxlist_param_t *toplev_boxlist) { box_param_t *iptr, *fidx, *prxy; box_param_t *cidx, *jp2c; iptr = search_box( "iptr", toplev_boxlist); fidx = search_box( "fidx", toplev_boxlist); cidx = search_box( "cidx", toplev_boxlist); jp2c = search_box( "jp2c", toplev_boxlist); prxy = gene_childboxbyType( fidx, 0, "prxy"); Byte8_t off = fetch_DBox8bytebigendian( iptr, 0); if( off != fidx->offset) fprintf( FCGI_stderr, "Reference File Index box offset in Index Finder box not correct\n"); Byte8_t len = fetch_DBox8bytebigendian( iptr, 8); if( len != fidx->length) fprintf( FCGI_stderr, "Reference File Index box length in Index Finder box not correct\n"); int pos = 0; Byte8_t ooff = fetch_DBox8bytebigendian( prxy, pos); if( ooff != jp2c->offset) fprintf( FCGI_stderr, "Reference jp2c offset in prxy box not correct\n"); pos += 8; boxheader_param_t *obh = gene_childboxheader( prxy, pos); if( obh->length != jp2c->length || strncmp( obh->type, "jp2c",4)!=0) fprintf( FCGI_stderr, "Reference jp2c header in prxy box not correct\n"); pos += obh->headlen; free(obh); Byte_t ni = fetch_DBox1byte( prxy, pos); if( ni != 1){ fprintf( FCGI_stderr, "Multiple indexes not supported\n"); return false; } pos += 1; Byte8_t ioff = fetch_DBox8bytebigendian( prxy, pos); if( ioff != cidx->offset) fprintf( FCGI_stderr, "Reference cidx offset in prxy box not correct\n"); pos += 8; boxheader_param_t *ibh = gene_childboxheader( prxy, pos); if( ibh->length != cidx->length || strncmp( ibh->type, "cidx",4)!=0) fprintf( FCGI_stderr, "Reference cidx header in prxy box not correct\n"); pos += ibh->headlen; free(ibh); free(prxy); return true; } /** * set code index parameters from cptr box * I.3.2.2 Codestream Finder box * * @param[in] cidx_box pointer to the reference cidx_box * @param[out] jp2idx pointer to index parameters * @return if succeeded (true) or failed (false) */ bool set_cptrdata( box_param_t *cidx_box, index_param_t *jp2idx); /** * set code index parameters from mhix box for main header * I.3.2.4.3 Header Index Table box * * @param[in] cidx_box pointer to the reference cidx_box * @param[in] codestream codestream parameters * @param[out] jp2idx pointer to index parameters * @return if succeeded (true) or failed (false) */ bool set_mainmhixdata( box_param_t *cidx_box, codestream_param_t codestream, index_param_t *jp2idx); /** * set code index parameters from tpix box * I.3.2.4.4 Tile-part Index Table box * * @param[in] cidx_box pointer to the reference cidx_box * @param[out] jp2idx pointer to index parameters * @return if succeeded (true) or failed (false) */ bool set_tpixdata( box_param_t *cidx_box, index_param_t *jp2idx); /** * set code index parameters from thix box * I.3.2.4.5 Tile Header Index Table box * * @param[in] cidx_box pointer to the reference cidx_box * @param[out] jp2idx pointer to index parameters * @return if succeeded (true) or failed (false) */ bool set_thixdata( box_param_t *cidx_box, index_param_t *jp2idx); bool set_cidxdata( box_param_t *cidx_box, index_param_t *jp2idx) { box_param_t *manf_box; manfbox_param_t *manf; codestream_param_t codestream; set_cptrdata( cidx_box, jp2idx); codestream = set_codestream( cidx_box->fd, jp2idx->offset, jp2idx->length); manf_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "manf"); manf = gene_manfbox( manf_box); if( !search_boxheader( "mhix", manf)){ fprintf( FCGI_stderr, "Error: mhix box not present in manfbox\n"); free(jp2idx); return false; } set_mainmhixdata( cidx_box, codestream, jp2idx); if( !search_boxheader( "tpix", manf)){ fprintf( FCGI_stderr, "Error: tpix box not present in manfbox\n"); free(jp2idx); return false; } set_tpixdata( cidx_box, jp2idx); #ifdef NO_NEED_YET if( !search_boxheader( "thix", manf)){ fprintf( FCGI_stderr, "Error: thix box not present in manfbox\n"); return false; } set_thixdata( cidx_box, jp2idx); #endif delete_manfbox( &manf); free( manf_box); return true; } bool set_cptrdata( box_param_t *cidx_box, index_param_t *jp2idx) { box_param_t *box; //!< cptr box Byte2_t dr, cont; if( !(box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "cptr"))) return false; // DR: Data Reference. // If 0, the codestream or its Fragment Table box exists in the current file if(( dr = fetch_DBox2bytebigendian( box, 0))){ fprintf( FCGI_stderr, "Error: Codestream not present in current file\n"); free( box); return false; } // CONT: Container Type // If 0, the entire codestream appears as a contiguous range of // bytes within its file or resource. if(( cont = fetch_DBox2bytebigendian( box, 2))){ fprintf( FCGI_stderr, "Error: Can't cope with fragmented codestreams yet\n"); free( box); return false; } jp2idx->offset = fetch_DBox8bytebigendian( box, 4); jp2idx->length = fetch_DBox8bytebigendian( box, 12); free( box); return true; } /** * set code index parameters from SIZ marker in codestream * A.5 Fixed information marker segment * A.5.1 Image and tile size (SIZ) * * @param[in] sizmkidx pointer to SIZ marker index in mhix box * @param[in] codestream codestream parameters * @param[out] jp2idx pointer to index parameters * @return if succeeded (true) or failed (false) */ bool set_SIZmkrdata( markeridx_param_t *sizmkidx, codestream_param_t codestream, index_param_t *jp2idx); bool set_mainmhixdata( box_param_t *cidx_box, codestream_param_t codestream, index_param_t *jp2idx) { box_param_t *mhix_box; mhixbox_param_t *mhix; markeridx_param_t *sizmkidx; if( !(mhix_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "mhix"))) return false; jp2idx->mhead_length = fetch_DBox8bytebigendian( mhix_box, 0); mhix = gene_mhixbox( mhix_box); free( mhix_box); sizmkidx = search_markeridx( 0xff51, mhix); set_SIZmkrdata( sizmkidx, codestream, jp2idx); delete_mhixbox( &mhix); return true; } bool set_tpixdata( box_param_t *cidx_box, index_param_t *jp2idx) { box_param_t *tpix_box; //!< tpix box box_param_t *faix_box; //!< faix box if( !(tpix_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "tpix"))) return false; if( !(faix_box = gene_boxbyType( tpix_box->fd, get_DBoxoff( tpix_box), get_DBoxlen( tpix_box), "faix"))) return false; jp2idx->tilepart = gene_faixbox( faix_box); free( tpix_box); free( faix_box); return true; } bool set_thixdata( box_param_t *cidx_box, index_param_t *jp2idx) { box_param_t *thix_box, *manf_box, *mhix_box; manfbox_param_t *manf; boxheader_param_t *ptr; mhixbox_param_t *mhix; Byte8_t pos, mhixseqoff; if( !(thix_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "thix"))) return false; if( !(manf_box = gene_boxbyType( thix_box->fd, get_DBoxoff( thix_box), get_DBoxlen( thix_box), "manf"))){ free( thix_box); return false; } manf = gene_manfbox( manf_box); ptr = manf->first; mhixseqoff = manf_box->offset+manf_box->length; pos = 0; while( ptr){ mhix_box = gene_boxbyType( thix_box->fd, mhixseqoff+pos, get_DBoxlen( thix_box)-manf_box->length-pos, "mhix"); mhix = gene_mhixbox( mhix_box); pos += mhix_box->length; ptr = ptr->next; free( mhix_box); delete_mhixbox( &mhix); } delete_manfbox( &manf); free( manf_box); free( thix_box); return true; } bool set_SIZmkrdata( markeridx_param_t *sizmkidx, codestream_param_t codestream, index_param_t *jp2idx) { marker_param_t sizmkr; int i; sizmkr = set_marker( codestream, sizmkidx->code, sizmkidx->offset, sizmkidx->length); if( sizmkidx->length != fetch_marker2bytebigendian( sizmkr, 0)){ fprintf( FCGI_stderr, "Error: marker %#x index is not correct\n", sizmkidx->code); return false; } jp2idx->Rsiz = fetch_marker2bytebigendian( sizmkr, 2); jp2idx->Xsiz = fetch_marker4bytebigendian( sizmkr, 4); jp2idx->Ysiz = fetch_marker4bytebigendian( sizmkr, 8); jp2idx->XOsiz = fetch_marker4bytebigendian( sizmkr, 12); jp2idx->YOsiz = fetch_marker4bytebigendian( sizmkr, 16); jp2idx->XTsiz = fetch_marker4bytebigendian( sizmkr, 20); jp2idx->YTsiz = fetch_marker4bytebigendian( sizmkr, 24); jp2idx->XTOsiz = fetch_marker4bytebigendian( sizmkr, 28); jp2idx->YTOsiz = fetch_marker4bytebigendian( sizmkr, 32); jp2idx->Csiz = fetch_marker2bytebigendian( sizmkr, 36); jp2idx->XTnum = ( jp2idx->Xsiz-jp2idx->XTOsiz+jp2idx->XTsiz-1)/jp2idx->XTsiz; jp2idx->YTnum = ( jp2idx->Ysiz-jp2idx->YTOsiz+jp2idx->YTsiz-1)/jp2idx->YTsiz; for( i=0; i<(int)jp2idx->Csiz; i++){ jp2idx->Ssiz[i] = fetch_marker1byte( sizmkr, 38+i*3); jp2idx->XRsiz[i] = fetch_marker1byte( sizmkr, 39+i*3); jp2idx->YRsiz[i] = fetch_marker1byte( sizmkr, 40+i*3); } return true; } Byte4_t max( Byte4_t n1, Byte4_t n2); Byte4_t min( Byte4_t n1, Byte4_t n2); range_param_t get_tile_range( Byte4_t Osiz, Byte4_t siz, Byte4_t TOsiz, Byte4_t Tsiz, Byte4_t tile_id, int level); range_param_t get_tile_Xrange( index_param_t index, Byte4_t tile_xid, int level) { return get_tile_range( index.XOsiz, index.Xsiz, index.XTOsiz, index.XTsiz, tile_xid, level); } range_param_t get_tile_Yrange( index_param_t index, Byte4_t tile_yid, int level) { return get_tile_range( index.YOsiz, index.Ysiz, index.YTOsiz, index.YTsiz, tile_yid, level); } range_param_t get_tile_range( Byte4_t Osiz, Byte4_t siz, Byte4_t TOsiz, Byte4_t Tsiz, Byte4_t tile_id, int level) { range_param_t range; int n; range.minvalue = max( Osiz, TOsiz+tile_id*Tsiz); range.maxvalue = min( siz, TOsiz+(tile_id+1)*Tsiz); for( n=0; n