2004-07-07 10:24:36 +02:00
/*
2014-04-03 17:30:57 +02:00
* The copyright in this software is being made available under the 2 - clauses
* BSD License , included below . This software may be subject to other third
* party and contributor rights , including patent rights , and no such rights
* are granted under this license .
*
* Copyright ( c ) 2002 - 2014 , Universite catholique de Louvain ( UCL ) , Belgium
* Copyright ( c ) 2002 - 2014 , Professor Benoit Macq
2007-01-15 10:55:40 +01:00
* Copyright ( c ) 2001 - 2003 , David Janssens
* Copyright ( c ) 2002 - 2003 , Yannick Verschueren
2014-04-03 17:30:57 +02:00
* Copyright ( c ) 2003 - 2007 , Francois - Olivier Devaux
* Copyright ( c ) 2003 - 2014 , Antonin Descampe
2007-01-15 10:55:40 +01:00
* Copyright ( c ) 2005 , Herve Drolon , FreeImage Team
2011-09-09 16:49:08 +02:00
* Copyright ( c ) 2010 - 2011 , Kaori Hagihara
2014-04-03 17:30:57 +02:00
* Copyright ( c ) 2008 , 2011 - 2012 , Centre National d ' Etudes Spatiales ( CNES ) , FR
2012-11-15 16:22:29 +01:00
* Copyright ( c ) 2012 , CS Systemes d ' Information , France
2005-12-02 14:34:15 +01:00
* 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 "opj_includes.h"
2005-12-08 10:38:47 +01:00
/** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */
/*@{*/
2012-11-16 09:29:43 +01:00
# define OPJ_BOX_SIZE 1024
2011-09-19 15:36:07 +02:00
2005-12-08 10:38:47 +01:00
/** @name Local static functions */
/*@{*/
2006-01-20 17:53:05 +01:00
/*static void jp2_write_url(opj_cio_t *cio, char *Idx_file);*/
2011-09-19 15:36:07 +02:00
/**
* Reads a IHDR box - Image Header box
*
* @ param p_image_header_data pointer to actual data ( already read from file )
* @ param jp2 the jpeg2000 file codec .
* @ param p_image_header_size the size of the image header
* @ param p_manager the user event manager .
*
2012-08-09 15:22:25 +02:00
* @ return true if the image header is valid , false else .
2011-09-19 15:36:07 +02:00
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_read_ihdr ( opj_jp2_t * jp2 ,
2012-08-09 15:22:25 +02:00
OPJ_BYTE * p_image_header_data ,
2012-08-10 12:34:40 +02:00
OPJ_UINT32 p_image_header_size ,
2012-08-09 15:22:25 +02:00
opj_event_mgr_t * p_manager ) ;
2011-09-19 15:36:07 +02:00
2012-05-14 11:37:36 +02:00
/**
* Writes the Image Header box - Image Header box .
*
* @ param jp2 jpeg2000 file codec .
* @ param p_nb_bytes_written pointer to store the nb of bytes written by the function .
2012-08-30 18:56:31 +02:00
*
2012-05-14 11:37:36 +02:00
* @ return the data being copied .
*/
2012-10-25 16:16:19 +02:00
static OPJ_BYTE * opj_jp2_write_ihdr ( opj_jp2_t * jp2 ,
2012-08-13 11:27:58 +02:00
OPJ_UINT32 * p_nb_bytes_written ) ;
2012-05-14 11:37:36 +02:00
/**
* Writes the Bit per Component box .
*
* @ param jp2 jpeg2000 file codec .
* @ param p_nb_bytes_written pointer to store the nb of bytes written by the function .
2012-08-30 18:56:31 +02:00
*
2012-05-14 11:37:36 +02:00
* @ return the data being copied .
*/
2012-10-25 16:16:19 +02:00
static OPJ_BYTE * opj_jp2_write_bpcc ( opj_jp2_t * jp2 ,
2012-08-13 11:31:24 +02:00
OPJ_UINT32 * p_nb_bytes_written ) ;
2012-05-14 11:37:36 +02:00
2011-09-19 15:36:07 +02:00
/**
* Reads a Bit per Component box .
*
* @ param p_bpc_header_data pointer to actual data ( already read from file )
* @ param jp2 the jpeg2000 file codec .
* @ param p_bpc_header_size the size of the bpc header
* @ param p_manager the user event manager .
*
* @ return true if the bpc header is valid , fale else .
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_read_bpcc ( opj_jp2_t * jp2 ,
2012-08-10 11:53:28 +02:00
OPJ_BYTE * p_bpc_header_data ,
2012-08-10 12:34:40 +02:00
OPJ_UINT32 p_bpc_header_size ,
2012-08-10 11:53:28 +02:00
opj_event_mgr_t * p_manager ) ;
2011-09-19 15:36:07 +02:00
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_read_cdef ( opj_jp2_t * jp2 ,
2012-08-10 12:19:11 +02:00
OPJ_BYTE * p_cdef_header_data ,
2011-09-19 15:36:07 +02:00
OPJ_UINT32 p_cdef_header_size ,
2012-08-10 12:19:11 +02:00
opj_event_mgr_t * p_manager ) ;
2012-08-13 12:10:25 +02:00
static void opj_jp2_apply_cdef ( opj_image_t * image , opj_jp2_color_t * color ) ;
2014-11-03 15:12:01 +01:00
/**
* Writes the Channel Definition box .
*
* @ param jp2 jpeg2000 file codec .
* @ param p_nb_bytes_written pointer to store the nb of bytes written by the function .
*
* @ return the data being copied .
*/
static OPJ_BYTE * opj_jp2_write_cdef ( opj_jp2_t * jp2 ,
OPJ_UINT32 * p_nb_bytes_written ) ;
2012-05-14 11:37:36 +02:00
/**
* Writes the Colour Specification box .
*
* @ param jp2 jpeg2000 file codec .
* @ param p_nb_bytes_written pointer to store the nb of bytes written by the function .
2012-08-30 18:56:31 +02:00
*
2012-05-14 11:37:36 +02:00
* @ return the data being copied .
*/
2012-10-25 16:16:19 +02:00
static OPJ_BYTE * opj_jp2_write_colr ( opj_jp2_t * jp2 ,
2012-08-13 11:35:16 +02:00
OPJ_UINT32 * p_nb_bytes_written ) ;
2012-05-14 11:37:36 +02:00
/**
* Writes a FTYP box - File type box
*
* @ param cio the stream to write data to .
* @ param jp2 the jpeg2000 file codec .
* @ param p_manager the user event manager .
2012-08-30 18:56:31 +02:00
*
2012-10-05 11:20:05 +02:00
* @ return true if writing was successful .
2012-05-14 11:37:36 +02:00
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_write_ftyp ( opj_jp2_t * jp2 ,
2012-08-13 11:39:51 +02:00
opj_stream_private_t * cio ,
opj_event_mgr_t * p_manager ) ;
2012-05-14 11:37:36 +02:00
2011-09-19 15:36:07 +02:00
/**
* Reads a a FTYP box - File type box
*
* @ param p_header_data the data contained in the FTYP box .
* @ param jp2 the jpeg2000 file codec .
* @ param p_header_size the size of the data contained in the FTYP box .
* @ param p_manager the user event manager .
*
* @ return true if the FTYP box is valid .
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_read_ftyp ( opj_jp2_t * jp2 ,
2012-08-10 12:22:51 +02:00
OPJ_BYTE * p_header_data ,
2012-05-14 11:37:36 +02:00
OPJ_UINT32 p_header_size ,
2012-08-10 12:22:51 +02:00
opj_event_mgr_t * p_manager ) ;
2011-09-19 15:36:07 +02:00
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_skip_jp2c ( opj_jp2_t * jp2 ,
2012-08-13 11:44:40 +02:00
opj_stream_private_t * cio ,
opj_event_mgr_t * p_manager ) ;
2012-03-15 11:23:20 +01:00
2011-09-19 15:36:07 +02:00
/**
* Reads the Jpeg2000 file Header box - JP2 Header box ( warning , this is a super box ) .
*
* @ param p_header_data the data contained in the file header box .
* @ param jp2 the jpeg2000 file codec .
* @ param p_header_size the size of the data contained in the file header box .
* @ param p_manager the user event manager .
*
* @ return true if the JP2 Header box was successfully reconized .
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_read_jp2h ( opj_jp2_t * jp2 ,
2012-08-10 11:43:28 +02:00
OPJ_BYTE * p_header_data ,
OPJ_UINT32 p_header_size ,
opj_event_mgr_t * p_manager ) ;
2011-09-19 15:36:07 +02:00
2012-05-14 19:17:53 +02:00
/**
* Writes the Jpeg2000 codestream Header box - JP2C Header box . This function must be called AFTER the coding has been done .
*
* @ param cio the stream to write data to .
* @ param jp2 the jpeg2000 file codec .
* @ param p_manager user event manager .
*
2012-10-05 11:20:05 +02:00
* @ return true if writing was successful .
2012-05-14 19:17:53 +02:00
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_write_jp2c ( opj_jp2_t * jp2 ,
2012-08-13 11:57:09 +02:00
opj_stream_private_t * cio ,
opj_event_mgr_t * p_manager ) ;
2012-05-14 19:17:53 +02:00
2012-10-29 14:27:39 +01:00
# ifdef USE_JPIP
2012-10-29 11:12:03 +01:00
/**
* Write index Finder box
* @ param cio the stream to write to .
* @ param jp2 the jpeg2000 file codec .
* @ param p_manager user event manager .
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jpip_write_iptr ( opj_jp2_t * jp2 ,
2012-10-29 11:12:03 +01:00
opj_stream_private_t * cio ,
opj_event_mgr_t * p_manager ) ;
/**
* Write index Finder box
* @ param cio the stream to write to .
* @ param jp2 the jpeg2000 file codec .
* @ param p_manager user event manager .
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jpip_write_cidx ( opj_jp2_t * jp2 ,
2012-10-29 11:12:03 +01:00
opj_stream_private_t * cio ,
opj_event_mgr_t * p_manager ) ;
/**
* Write file Index ( superbox )
* @ param cio the stream to write to .
* @ param jp2 the jpeg2000 file codec .
* @ param p_manager user event manager .
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jpip_write_fidx ( opj_jp2_t * jp2 ,
2012-10-29 11:12:03 +01:00
opj_stream_private_t * cio ,
opj_event_mgr_t * p_manager ) ;
2012-10-29 14:27:39 +01:00
# endif /* USE_JPIP */
2012-10-29 11:12:03 +01:00
2011-09-19 15:36:07 +02:00
/**
* Reads a jpeg2000 file signature box .
*
* @ param p_header_data the data contained in the signature box .
* @ param jp2 the jpeg2000 file codec .
* @ param p_header_size the size of the data contained in the signature box .
* @ param p_manager the user event manager .
*
* @ return true if the file signature box is valid .
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_read_jp ( opj_jp2_t * jp2 ,
2012-08-10 12:34:40 +02:00
OPJ_BYTE * p_header_data ,
OPJ_UINT32 p_header_size ,
opj_event_mgr_t * p_manager ) ;
2012-08-10 12:27:17 +02:00
2012-08-13 12:03:57 +02:00
/**
* Writes a jpeg2000 file signature box .
*
* @ param cio the stream to write data to .
* @ param jp2 the jpeg2000 file codec .
* @ param p_manager the user event manager .
2012-08-30 18:56:31 +02:00
*
2012-10-05 11:20:05 +02:00
* @ return true if writing was successful .
2012-08-13 12:03:57 +02:00
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_write_jp ( opj_jp2_t * jp2 ,
2012-08-13 12:03:57 +02:00
opj_stream_private_t * cio ,
opj_event_mgr_t * p_manager ) ;
2010-10-24 22:28:22 +02:00
/**
Apply collected palette data
2010-12-08 12:06:41 +01:00
@ param color Collector for profile , cdef and pclr data
2012-08-30 18:56:31 +02:00
@ param image
2010-10-24 22:28:22 +02:00
*/
2012-08-13 12:10:25 +02:00
static void opj_jp2_apply_pclr ( opj_image_t * image , opj_jp2_color_t * color ) ;
static void opj_jp2_free_pclr ( opj_jp2_color_t * color ) ;
2010-10-24 22:28:22 +02:00
/**
2012-08-30 18:56:31 +02:00
* Collect palette data
*
* @ param jp2 JP2 handle
* @ param p_pclr_header_data FIXME DOC
* @ param p_pclr_header_size FIXME DOC
* @ param p_manager
*
* @ return Returns true if successful , returns false otherwise
2010-10-24 22:28:22 +02:00
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_read_pclr ( opj_jp2_t * jp2 ,
2012-08-10 12:19:11 +02:00
OPJ_BYTE * p_pclr_header_data ,
OPJ_UINT32 p_pclr_header_size ,
opj_event_mgr_t * p_manager ) ;
2011-09-19 15:36:07 +02:00
2010-10-24 22:28:22 +02:00
/**
2012-08-30 18:56:31 +02:00
* Collect component mapping data
*
* @ param jp2 JP2 handle
* @ param p_cmap_header_data FIXME DOC
* @ param p_cmap_header_size FIXME DOC
* @ param p_manager FIXME DOC
*
* @ return Returns true if successful , returns false otherwise
2010-10-24 22:28:22 +02:00
*/
2011-09-19 15:36:07 +02:00
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_read_cmap ( opj_jp2_t * jp2 ,
2012-08-10 12:19:11 +02:00
OPJ_BYTE * p_cmap_header_data ,
OPJ_UINT32 p_cmap_header_size ,
opj_event_mgr_t * p_manager ) ;
2011-09-19 15:36:07 +02:00
/**
* Reads the Color Specification box .
*
* @ param p_colr_header_data pointer to actual data ( already read from file )
* @ param jp2 the jpeg2000 file codec .
* @ param p_colr_header_size the size of the color header
* @ param p_manager the user event manager .
*
* @ return true if the bpc header is valid , fale else .
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_read_colr ( opj_jp2_t * jp2 ,
2012-08-10 12:19:11 +02:00
OPJ_BYTE * p_colr_header_data ,
OPJ_UINT32 p_colr_header_size ,
opj_event_mgr_t * p_manager ) ;
2011-09-19 15:36:07 +02:00
2005-12-08 10:38:47 +01:00
/*@}*/
/*@}*/
2005-12-02 14:34:15 +01:00
2012-03-15 11:23:20 +01:00
/**
2012-10-05 11:20:05 +02:00
* Sets up the procedures to do on writing header after the codestream .
* Developpers wanting to extend the library can add their own writing procedures .
2012-03-15 11:23:20 +01:00
*/
2012-10-25 16:16:19 +02:00
static void opj_jp2_setup_end_header_writing ( opj_jp2_t * jp2 ) ;
2012-03-15 11:23:20 +01:00
2011-09-19 15:36:07 +02:00
/**
* Sets up the procedures to do on reading header after the codestream .
2012-10-05 11:20:05 +02:00
* Developpers wanting to extend the library can add their own writing procedures .
2011-09-19 15:36:07 +02:00
*/
2012-10-25 16:16:19 +02:00
static void opj_jp2_setup_end_header_reading ( opj_jp2_t * jp2 ) ;
2011-09-19 15:36:07 +02:00
/**
* Reads a jpeg2000 file header structure .
*
* @ param jp2 the jpeg2000 file header structure .
2012-08-30 18:56:31 +02:00
* @ param stream the stream to read data from .
2011-09-19 15:36:07 +02:00
* @ param p_manager the user event manager .
*
* @ return true if the box is valid .
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_read_header_procedure ( opj_jp2_t * jp2 ,
2012-08-10 12:55:10 +02:00
opj_stream_private_t * stream ,
opj_event_mgr_t * p_manager ) ;
2011-09-19 15:36:07 +02:00
/**
* Excutes the given procedures on the given codec .
*
* @ param p_procedure_list the list of procedures to execute
* @ param jp2 the jpeg2000 file codec to execute the procedures on .
2012-08-10 12:55:10 +02:00
* @ param stream the stream to execute the procedures on .
2011-09-19 15:36:07 +02:00
* @ param p_manager the user manager .
*
* @ return true if all the procedures were successfully executed .
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_exec ( opj_jp2_t * jp2 ,
2012-08-10 12:55:10 +02:00
opj_procedure_list_t * p_procedure_list ,
opj_stream_private_t * stream ,
opj_event_mgr_t * p_manager ) ;
2011-09-19 15:36:07 +02:00
/**
* Reads a box header . The box is the way data is packed inside a jpeg2000 file structure .
*
* @ param cio the input stream to read data from .
* @ param box the box structure to fill .
* @ param p_number_bytes_read pointer to an int that will store the number of bytes read from the stream ( shoul usually be 2 ) .
* @ param p_manager user event manager .
*
* @ return true if the box is reconized , false otherwise
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_read_boxhdr ( opj_jp2_box_t * box ,
2012-08-10 13:00:40 +02:00
OPJ_UINT32 * p_number_bytes_read ,
opj_stream_private_t * cio ,
opj_event_mgr_t * p_manager ) ;
2011-09-19 15:36:07 +02:00
2012-03-15 11:23:20 +01:00
/**
* Sets up the validation , i . e . adds the procedures to lauch to make sure the codec parameters
* are valid . Developpers wanting to extend the library can add their own validation procedures .
*/
2012-10-25 16:16:19 +02:00
static void opj_jp2_setup_encoding_validation ( opj_jp2_t * jp2 ) ;
2012-03-15 11:23:20 +01:00
/**
2012-10-05 11:20:05 +02:00
* Sets up the procedures to do on writing header . Developpers wanting to extend the library can add their own writing procedures .
2012-03-15 11:23:20 +01:00
*/
2012-10-25 16:16:19 +02:00
static void opj_jp2_setup_header_writing ( opj_jp2_t * jp2 ) ;
2012-03-15 11:23:20 +01:00
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_default_validation ( opj_jp2_t * jp2 ,
2012-08-10 12:55:10 +02:00
opj_stream_private_t * cio ,
opj_event_mgr_t * p_manager ) ;
2012-03-15 11:23:20 +01:00
2011-09-19 15:36:07 +02:00
/**
* Finds the image execution function related to the given box id .
*
* @ param p_id the id of the handler to fetch .
*
* @ return the given handler or NULL if it could not be found .
*/
2012-08-10 12:55:10 +02:00
static const opj_jp2_header_handler_t * opj_jp2_img_find_handler ( OPJ_UINT32 p_id ) ;
/**
* Finds the execution function related to the given box id .
*
* @ param p_id the id of the handler to fetch .
*
* @ return the given handler or NULL if it could not be found .
*/
static const opj_jp2_header_handler_t * opj_jp2_find_handler ( OPJ_UINT32 p_id ) ;
2011-09-19 15:36:07 +02:00
const opj_jp2_header_handler_t jp2_header [ ] =
{
2012-08-10 12:34:40 +02:00
{ JP2_JP , opj_jp2_read_jp } ,
2012-08-10 12:24:09 +02:00
{ JP2_FTYP , opj_jp2_read_ftyp } ,
2012-08-10 11:43:28 +02:00
{ JP2_JP2H , opj_jp2_read_jp2h }
2011-09-19 15:36:07 +02:00
} ;
const opj_jp2_header_handler_t jp2_img_header [ ] =
{
2012-08-10 11:47:56 +02:00
{ JP2_IHDR , opj_jp2_read_ihdr } ,
2012-08-10 12:19:11 +02:00
{ JP2_COLR , opj_jp2_read_colr } ,
2012-08-10 11:53:28 +02:00
{ JP2_BPCC , opj_jp2_read_bpcc } ,
2012-08-10 12:19:11 +02:00
{ JP2_PCLR , opj_jp2_read_pclr } ,
{ JP2_CMAP , opj_jp2_read_cmap } ,
{ JP2_CDEF , opj_jp2_read_cdef }
2011-09-19 15:36:07 +02:00
} ;
/**
* Reads a box header . The box is the way data is packed inside a jpeg2000 file structure . Data is read from a character string
*
* @ param box the box structure to fill .
2012-08-30 18:56:31 +02:00
* @ param p_data the character string to read data from .
2011-09-19 15:36:07 +02:00
* @ param p_number_bytes_read pointer to an int that will store the number of bytes read from the stream ( shoul usually be 2 ) .
* @ param p_box_max_size the maximum number of bytes in the box .
2012-08-30 18:56:31 +02:00
* @ param p_manager FIXME DOC
2011-09-19 15:36:07 +02:00
*
* @ return true if the box is reconized , false otherwise
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_read_boxhdr_char ( opj_jp2_box_t * box ,
2012-08-10 12:55:10 +02:00
OPJ_BYTE * p_data ,
OPJ_UINT32 * p_number_bytes_read ,
OPJ_UINT32 p_box_max_size ,
opj_event_mgr_t * p_manager ) ;
2011-09-19 15:36:07 +02:00
/**
* Sets up the validation , i . e . adds the procedures to lauch to make sure the codec parameters
* are valid . Developpers wanting to extend the library can add their own validation procedures .
*/
2012-10-25 16:16:19 +02:00
static void opj_jp2_setup_decoding_validation ( opj_jp2_t * jp2 ) ;
2011-09-19 15:36:07 +02:00
/**
* Sets up the procedures to do on reading header .
2012-10-05 11:20:05 +02:00
* Developpers wanting to extend the library can add their own writing procedures .
2011-09-19 15:36:07 +02:00
*/
2012-10-25 16:16:19 +02:00
static void opj_jp2_setup_header_reading ( opj_jp2_t * jp2 ) ;
2011-09-19 15:36:07 +02:00
2005-12-02 14:34:15 +01:00
/* ----------------------------------------------------------------------- */
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_read_boxhdr ( opj_jp2_box_t * box ,
2013-03-17 19:16:03 +01:00
OPJ_UINT32 * p_number_bytes_read ,
opj_stream_private_t * cio ,
opj_event_mgr_t * p_manager )
2011-09-19 15:36:07 +02:00
{
/* read header from file */
2012-10-24 14:49:28 +02:00
OPJ_BYTE l_data_header [ 8 ] ;
2011-09-19 15:36:07 +02:00
2012-03-02 16:53:14 +01:00
/* preconditions */
2011-09-19 15:36:07 +02:00
assert ( cio ! = 00 ) ;
assert ( box ! = 00 ) ;
assert ( p_number_bytes_read ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
2014-03-03 16:47:23 +01:00
* p_number_bytes_read = ( OPJ_UINT32 ) opj_stream_read_data ( cio , l_data_header , 8 , p_manager ) ;
2011-09-19 15:36:07 +02:00
if ( * p_number_bytes_read ! = 8 ) {
return OPJ_FALSE ;
}
/* process read data */
opj_read_bytes ( l_data_header , & ( box - > length ) , 4 ) ;
opj_read_bytes ( l_data_header + 4 , & ( box - > type ) , 4 ) ;
2013-03-17 19:16:03 +01:00
2014-03-03 16:47:23 +01:00
if ( box - > length = = 0 ) /* last box */
2013-03-17 19:16:03 +01:00
{
2014-03-03 16:47:23 +01:00
const OPJ_OFF_T bleft = opj_stream_get_number_byte_left ( cio ) ;
box - > length = ( OPJ_UINT32 ) bleft ;
assert ( ( OPJ_OFF_T ) box - > length = = bleft ) ;
return OPJ_TRUE ;
2013-03-17 19:16:03 +01:00
}
2011-09-19 15:36:07 +02:00
2012-03-02 16:53:14 +01:00
/* do we have a "special very large box ?" */
/* read then the XLBox */
2011-09-19 15:36:07 +02:00
if ( box - > length = = 1 ) {
OPJ_UINT32 l_xl_part_size ;
2014-03-03 16:47:23 +01:00
OPJ_UINT32 l_nb_bytes_read = ( OPJ_UINT32 ) opj_stream_read_data ( cio , l_data_header , 8 , p_manager ) ;
2011-09-19 15:36:07 +02:00
if ( l_nb_bytes_read ! = 8 ) {
if ( l_nb_bytes_read > 0 ) {
* p_number_bytes_read + = l_nb_bytes_read ;
}
return OPJ_FALSE ;
}
2013-03-17 19:16:03 +01:00
* p_number_bytes_read = 16 ;
2011-09-19 15:36:07 +02:00
opj_read_bytes ( l_data_header , & l_xl_part_size , 4 ) ;
if ( l_xl_part_size ! = 0 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Cannot handle box sizes higher than 2^32 \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
2013-03-17 19:16:03 +01:00
opj_read_bytes ( l_data_header + 4 , & ( box - > length ) , 4 ) ;
2011-09-19 15:36:07 +02:00
}
2013-03-17 19:16:03 +01:00
return OPJ_TRUE ;
2011-09-19 15:36:07 +02:00
}
2006-01-20 17:53:05 +01:00
#if 0
2005-12-02 14:34:15 +01:00
static void jp2_write_url ( opj_cio_t * cio , char * Idx_file ) {
2012-10-24 14:49:28 +02:00
OPJ_UINT32 i ;
2005-12-08 10:38:47 +01:00
opj_jp2_box_t box ;
box . init_pos = cio_tell ( cio ) ;
cio_skip ( cio , 4 ) ;
cio_write ( cio , JP2_URL , 4 ) ; /* DBTL */
cio_write ( cio , 0 , 1 ) ; /* VERS */
cio_write ( cio , 0 , 3 ) ; /* FLAG */
if ( Idx_file ) {
for ( i = 0 ; i < strlen ( Idx_file ) ; i + + ) {
cio_write ( cio , Idx_file [ i ] , 1 ) ;
}
}
box . length = cio_tell ( cio ) - box . init_pos ;
cio_seek ( cio , box . init_pos ) ;
cio_write ( cio , box . length , 4 ) ; /* L */
cio_seek ( cio , box . init_pos + box . length ) ;
2004-07-07 10:24:36 +02:00
}
2006-01-20 17:53:05 +01:00
# endif
2004-07-07 10:24:36 +02:00
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_read_ihdr ( opj_jp2_t * jp2 ,
2012-08-09 15:22:25 +02:00
OPJ_BYTE * p_image_header_data ,
2012-08-10 12:34:40 +02:00
OPJ_UINT32 p_image_header_size ,
2012-08-10 11:47:56 +02:00
opj_event_mgr_t * p_manager )
2011-09-19 15:36:07 +02:00
{
2012-03-02 16:53:14 +01:00
/* preconditions */
2011-09-19 15:36:07 +02:00
assert ( p_image_header_data ! = 00 ) ;
assert ( jp2 ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
if ( p_image_header_size ! = 14 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Bad image header box (bad size) \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
opj_read_bytes ( p_image_header_data , & ( jp2 - > h ) , 4 ) ; /* HEIGHT */
p_image_header_data + = 4 ;
opj_read_bytes ( p_image_header_data , & ( jp2 - > w ) , 4 ) ; /* WIDTH */
p_image_header_data + = 4 ;
2012-08-09 15:22:25 +02:00
opj_read_bytes ( p_image_header_data , & ( jp2 - > numcomps ) , 2 ) ; /* NC */
2011-09-19 15:36:07 +02:00
p_image_header_data + = 2 ;
/* allocate memory for components */
2014-09-16 17:48:04 +02:00
jp2 - > comps = ( opj_jp2_comps_t * ) opj_calloc ( jp2 - > numcomps , sizeof ( opj_jp2_comps_t ) ) ;
2011-09-19 15:36:07 +02:00
if ( jp2 - > comps = = 0 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Not enough memory to handle image header (ihdr) \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
opj_read_bytes ( p_image_header_data , & ( jp2 - > bpc ) , 1 ) ; /* BPC */
+ + p_image_header_data ;
opj_read_bytes ( p_image_header_data , & ( jp2 - > C ) , 1 ) ; /* C */
+ + p_image_header_data ;
2012-03-02 16:53:14 +01:00
/* Should be equal to 7 cf. chapter about image header box of the norm */
2011-09-19 15:36:07 +02:00
if ( jp2 - > C ! = 7 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_INFO , " JP2 IHDR box: compression type indicate that the file is not a conforming JP2 file (%d) \n " , jp2 - > C ) ;
2011-09-19 15:36:07 +02:00
}
opj_read_bytes ( p_image_header_data , & ( jp2 - > UnkC ) , 1 ) ; /* UnkC */
+ + p_image_header_data ;
opj_read_bytes ( p_image_header_data , & ( jp2 - > IPR ) , 1 ) ; /* IPR */
+ + p_image_header_data ;
return OPJ_TRUE ;
}
2012-10-25 16:16:19 +02:00
OPJ_BYTE * opj_jp2_write_ihdr ( opj_jp2_t * jp2 ,
2012-08-30 18:56:31 +02:00
OPJ_UINT32 * p_nb_bytes_written
2012-08-13 11:27:58 +02:00
)
2012-05-14 11:37:36 +02:00
{
2012-10-24 14:49:28 +02:00
OPJ_BYTE * l_ihdr_data , * l_current_ihdr_ptr ;
2012-05-14 11:37:36 +02:00
2012-09-10 11:04:47 +02:00
/* preconditions */
2012-05-14 11:37:36 +02:00
assert ( jp2 ! = 00 ) ;
assert ( p_nb_bytes_written ! = 00 ) ;
/* default image header is 22 bytes wide */
2014-09-16 17:48:04 +02:00
l_ihdr_data = ( OPJ_BYTE * ) opj_calloc ( 1 , 22 ) ;
2012-05-14 11:37:36 +02:00
if ( l_ihdr_data = = 00 ) {
return 00 ;
}
l_current_ihdr_ptr = l_ihdr_data ;
opj_write_bytes ( l_current_ihdr_ptr , 22 , 4 ) ; /* write box size */
l_current_ihdr_ptr + = 4 ;
opj_write_bytes ( l_current_ihdr_ptr , JP2_IHDR , 4 ) ; /* IHDR */
l_current_ihdr_ptr + = 4 ;
opj_write_bytes ( l_current_ihdr_ptr , jp2 - > h , 4 ) ; /* HEIGHT */
l_current_ihdr_ptr + = 4 ;
opj_write_bytes ( l_current_ihdr_ptr , jp2 - > w , 4 ) ; /* WIDTH */
l_current_ihdr_ptr + = 4 ;
opj_write_bytes ( l_current_ihdr_ptr , jp2 - > numcomps , 2 ) ; /* NC */
l_current_ihdr_ptr + = 2 ;
opj_write_bytes ( l_current_ihdr_ptr , jp2 - > bpc , 1 ) ; /* BPC */
+ + l_current_ihdr_ptr ;
opj_write_bytes ( l_current_ihdr_ptr , jp2 - > C , 1 ) ; /* C : Always 7 */
+ + l_current_ihdr_ptr ;
opj_write_bytes ( l_current_ihdr_ptr , jp2 - > UnkC , 1 ) ; /* UnkC, colorspace unknown */
+ + l_current_ihdr_ptr ;
opj_write_bytes ( l_current_ihdr_ptr , jp2 - > IPR , 1 ) ; /* IPR, no intellectual property */
+ + l_current_ihdr_ptr ;
* p_nb_bytes_written = 22 ;
return l_ihdr_data ;
}
2012-10-25 16:16:19 +02:00
OPJ_BYTE * opj_jp2_write_bpcc ( opj_jp2_t * jp2 ,
2012-08-30 18:56:31 +02:00
OPJ_UINT32 * p_nb_bytes_written
2012-08-13 11:33:00 +02:00
)
2012-05-14 11:37:36 +02:00
{
2012-10-24 14:49:28 +02:00
OPJ_UINT32 i ;
2012-05-14 11:37:36 +02:00
/* room for 8 bytes for box and 1 byte for each component */
2014-03-07 15:14:31 +01:00
OPJ_UINT32 l_bpcc_size = 8 + jp2 - > numcomps ;
2012-10-24 14:49:28 +02:00
OPJ_BYTE * l_bpcc_data , * l_current_bpcc_ptr ;
2012-05-14 11:37:36 +02:00
2012-09-10 11:04:47 +02:00
/* preconditions */
2012-05-14 11:37:36 +02:00
assert ( jp2 ! = 00 ) ;
assert ( p_nb_bytes_written ! = 00 ) ;
2014-09-16 17:48:04 +02:00
l_bpcc_data = ( OPJ_BYTE * ) opj_calloc ( 1 , l_bpcc_size ) ;
2012-05-14 11:37:36 +02:00
if ( l_bpcc_data = = 00 ) {
return 00 ;
}
l_current_bpcc_ptr = l_bpcc_data ;
opj_write_bytes ( l_current_bpcc_ptr , l_bpcc_size , 4 ) ; /* write box size */
l_current_bpcc_ptr + = 4 ;
opj_write_bytes ( l_current_bpcc_ptr , JP2_BPCC , 4 ) ; /* BPCC */
l_current_bpcc_ptr + = 4 ;
for ( i = 0 ; i < jp2 - > numcomps ; + + i ) {
opj_write_bytes ( l_current_bpcc_ptr , jp2 - > comps [ i ] . bpcc , 1 ) ; /* write each component information */
+ + l_current_bpcc_ptr ;
}
* p_nb_bytes_written = l_bpcc_size ;
return l_bpcc_data ;
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_read_bpcc ( opj_jp2_t * jp2 ,
2012-08-10 12:55:10 +02:00
OPJ_BYTE * p_bpc_header_data ,
OPJ_UINT32 p_bpc_header_size ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager
2012-08-10 12:55:10 +02:00
)
2011-09-19 15:36:07 +02:00
{
OPJ_UINT32 i ;
2012-03-02 16:53:14 +01:00
/* preconditions */
2011-09-19 15:36:07 +02:00
assert ( p_bpc_header_data ! = 00 ) ;
assert ( jp2 ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
2012-10-24 14:49:28 +02:00
if ( jp2 - > bpc ! = 255 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_WARNING , " A BPCC header box is available although BPC given by the IHDR box (%d) indicate components bit depth is constant \n " , jp2 - > bpc ) ;
2012-10-24 14:49:28 +02:00
}
2011-09-19 15:36:07 +02:00
2012-03-02 16:53:14 +01:00
/* and length is relevant */
2011-09-19 15:36:07 +02:00
if ( p_bpc_header_size ! = jp2 - > numcomps ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Bad BPCC header box (bad size) \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
2012-03-02 16:53:14 +01:00
/* read info for each component */
2011-09-19 15:36:07 +02:00
for ( i = 0 ; i < jp2 - > numcomps ; + + i ) {
opj_read_bytes ( p_bpc_header_data , & jp2 - > comps [ i ] . bpcc , 1 ) ; /* read each BPCC component */
+ + p_bpc_header_data ;
}
return OPJ_TRUE ;
}
2014-11-03 15:12:01 +01:00
static OPJ_BYTE * opj_jp2_write_cdef ( opj_jp2_t * jp2 , OPJ_UINT32 * p_nb_bytes_written )
{
/* room for 8 bytes for box, 2 for n */
OPJ_UINT32 l_cdef_size = 10 ;
OPJ_BYTE * l_cdef_data , * l_current_cdef_ptr ;
OPJ_UINT32 l_value ;
OPJ_UINT16 i ;
/* preconditions */
assert ( jp2 ! = 00 ) ;
assert ( p_nb_bytes_written ! = 00 ) ;
assert ( jp2 - > color . jp2_cdef ! = 00 ) ;
assert ( jp2 - > color . jp2_cdef - > info ! = 00 ) ;
assert ( jp2 - > color . jp2_cdef - > n > 0U ) ;
2014-11-24 22:31:09 +01:00
l_cdef_size + = 6U * jp2 - > color . jp2_cdef - > n ;
2014-11-03 15:12:01 +01:00
l_cdef_data = ( OPJ_BYTE * ) opj_malloc ( l_cdef_size ) ;
if ( l_cdef_data = = 00 ) {
return 00 ;
}
l_current_cdef_ptr = l_cdef_data ;
opj_write_bytes ( l_current_cdef_ptr , l_cdef_size , 4 ) ; /* write box size */
l_current_cdef_ptr + = 4 ;
opj_write_bytes ( l_current_cdef_ptr , JP2_CDEF , 4 ) ; /* BPCC */
l_current_cdef_ptr + = 4 ;
l_value = jp2 - > color . jp2_cdef - > n ;
opj_write_bytes ( l_current_cdef_ptr , l_value , 2 ) ; /* N */
l_current_cdef_ptr + = 2 ;
for ( i = 0U ; i < jp2 - > color . jp2_cdef - > n ; + + i ) {
l_value = jp2 - > color . jp2_cdef - > info [ i ] . cn ;
opj_write_bytes ( l_current_cdef_ptr , l_value , 2 ) ; /* Cni */
l_current_cdef_ptr + = 2 ;
l_value = jp2 - > color . jp2_cdef - > info [ i ] . typ ;
opj_write_bytes ( l_current_cdef_ptr , l_value , 2 ) ; /* Typi */
l_current_cdef_ptr + = 2 ;
l_value = jp2 - > color . jp2_cdef - > info [ i ] . asoc ;
opj_write_bytes ( l_current_cdef_ptr , l_value , 2 ) ; /* Asoci */
l_current_cdef_ptr + = 2 ;
}
* p_nb_bytes_written = l_cdef_size ;
return l_cdef_data ;
}
2011-09-19 15:36:07 +02:00
2012-10-25 16:16:19 +02:00
OPJ_BYTE * opj_jp2_write_colr ( opj_jp2_t * jp2 ,
2012-08-30 18:56:31 +02:00
OPJ_UINT32 * p_nb_bytes_written
2012-08-13 11:35:16 +02:00
)
2012-05-14 11:37:36 +02:00
{
/* room for 8 bytes for box 3 for common data and variable upon profile*/
2012-10-24 14:49:28 +02:00
OPJ_UINT32 l_colr_size = 11 ;
OPJ_BYTE * l_colr_data , * l_current_colr_ptr ;
2014-11-03 15:12:01 +01:00
2012-09-10 11:04:47 +02:00
/* preconditions */
2012-05-14 11:37:36 +02:00
assert ( jp2 ! = 00 ) ;
assert ( p_nb_bytes_written ! = 00 ) ;
2012-12-03 14:04:43 +01:00
assert ( jp2 - > meth = = 1 | | jp2 - > meth = = 2 ) ;
2012-05-14 11:37:36 +02:00
2012-12-03 14:04:43 +01:00
switch ( jp2 - > meth ) {
2012-05-14 11:37:36 +02:00
case 1 :
2012-12-03 14:04:43 +01:00
l_colr_size + = 4 ; /* EnumCS */
2012-05-14 11:37:36 +02:00
break ;
case 2 :
2012-12-03 14:04:43 +01:00
assert ( jp2 - > color . icc_profile_len ) ; /* ICC profile */
l_colr_size + = jp2 - > color . icc_profile_len ;
2012-05-14 11:37:36 +02:00
break ;
default :
return 00 ;
}
2014-09-16 17:48:04 +02:00
l_colr_data = ( OPJ_BYTE * ) opj_calloc ( 1 , l_colr_size ) ;
2012-05-14 11:37:36 +02:00
if ( l_colr_data = = 00 ) {
return 00 ;
}
l_current_colr_ptr = l_colr_data ;
opj_write_bytes ( l_current_colr_ptr , l_colr_size , 4 ) ; /* write box size */
l_current_colr_ptr + = 4 ;
opj_write_bytes ( l_current_colr_ptr , JP2_COLR , 4 ) ; /* BPCC */
l_current_colr_ptr + = 4 ;
opj_write_bytes ( l_current_colr_ptr , jp2 - > meth , 1 ) ; /* METH */
+ + l_current_colr_ptr ;
opj_write_bytes ( l_current_colr_ptr , jp2 - > precedence , 1 ) ; /* PRECEDENCE */
+ + l_current_colr_ptr ;
opj_write_bytes ( l_current_colr_ptr , jp2 - > approx , 1 ) ; /* APPROX */
+ + l_current_colr_ptr ;
2012-12-03 14:04:43 +01:00
if ( jp2 - > meth = = 1 ) { /* Meth value is restricted to 1 or 2 (Table I.9 of part 1) */
opj_write_bytes ( l_current_colr_ptr , jp2 - > enumcs , 4 ) ; } /* EnumCS */
else {
if ( jp2 - > meth = = 2 ) { /* ICC profile */
OPJ_UINT32 i ;
for ( i = 0 ; i < jp2 - > color . icc_profile_len ; + + i ) {
opj_write_bytes ( l_current_colr_ptr , jp2 - > color . icc_profile_buf [ i ] , 1 ) ;
+ + l_current_colr_ptr ;
}
}
2012-05-14 11:37:36 +02:00
}
* p_nb_bytes_written = l_colr_size ;
return l_colr_data ;
}
2012-08-13 12:10:25 +02:00
void opj_jp2_free_pclr ( opj_jp2_color_t * color )
2010-10-05 12:33:15 +02:00
{
2010-12-08 12:06:41 +01:00
opj_free ( color - > jp2_pclr - > channel_sign ) ;
opj_free ( color - > jp2_pclr - > channel_size ) ;
opj_free ( color - > jp2_pclr - > entries ) ;
2010-10-05 12:33:15 +02:00
2010-12-08 12:06:41 +01:00
if ( color - > jp2_pclr - > cmap ) opj_free ( color - > jp2_pclr - > cmap ) ;
2010-10-05 12:33:15 +02:00
2010-12-08 12:06:41 +01:00
opj_free ( color - > jp2_pclr ) ; color - > jp2_pclr = NULL ;
2010-10-05 12:33:15 +02:00
}
2014-02-26 12:05:31 +01:00
static OPJ_BOOL opj_jp2_check_color ( opj_image_t * image , opj_jp2_color_t * color , opj_event_mgr_t * p_manager )
{
OPJ_UINT16 i ;
/* testcase 4149.pdf.SIGSEGV.cf7.3501 */
if ( color - > jp2_cdef ) {
opj_jp2_cdef_info_t * info = color - > jp2_cdef - > info ;
OPJ_UINT16 n = color - > jp2_cdef - > n ;
2014-10-21 14:54:08 +02:00
OPJ_UINT32 nr_channels = image - > numcomps ; /* FIXME image->numcomps == jp2->numcomps before color is applied ??? */
/* cdef applies to cmap channels if any */
if ( color - > jp2_pclr & & color - > jp2_pclr - > cmap ) {
nr_channels = ( OPJ_UINT32 ) color - > jp2_pclr - > nr_channels ;
}
2014-02-26 12:05:31 +01:00
for ( i = 0 ; i < n ; i + + ) {
2014-10-30 19:26:10 +01:00
if ( info [ i ] . cn > = nr_channels ) {
opj_event_msg ( p_manager , EVT_ERROR , " Invalid component index %d (>= %d). \n " , info [ i ] . cn , nr_channels ) ;
2014-02-26 12:05:31 +01:00
return OPJ_FALSE ;
}
2014-10-30 19:26:10 +01:00
if ( info [ i ] . asoc > 0 & & ( OPJ_UINT32 ) ( info [ i ] . asoc - 1 ) > = nr_channels ) {
opj_event_msg ( p_manager , EVT_ERROR , " Invalid component index %d (>= %d). \n " , info [ i ] . asoc - 1 , nr_channels ) ;
2014-02-26 12:05:31 +01:00
return OPJ_FALSE ;
}
}
2014-10-21 14:54:08 +02:00
/* issue 397 */
/* ISO 15444-1 states that if cdef is present, it shall contain a complete list of channel definitions. */
while ( nr_channels > 0 )
{
for ( i = 0 ; i < n ; + + i ) {
if ( ( OPJ_UINT32 ) info [ i ] . cn = = ( nr_channels - 1U ) ) {
break ;
}
}
if ( i = = n ) {
opj_event_msg ( p_manager , EVT_ERROR , " Incomplete channel definitions. \n " ) ;
return OPJ_FALSE ;
}
- - nr_channels ;
}
2014-02-26 12:05:31 +01:00
}
/* testcases 451.pdf.SIGSEGV.f4c.3723, 451.pdf.SIGSEGV.5b5.3723 and
66 ea31acbb0f23a2bbc91f64d69a03f5_signal_sigsegv_13937c0_7030_5725 . pdf */
if ( color - > jp2_pclr & & color - > jp2_pclr - > cmap ) {
OPJ_UINT16 nr_channels = color - > jp2_pclr - > nr_channels ;
opj_jp2_cmap_comp_t * cmap = color - > jp2_pclr - > cmap ;
OPJ_BOOL * pcol_usage , is_sane = OPJ_TRUE ;
/* verify that all original components match an existing one */
for ( i = 0 ; i < nr_channels ; i + + ) {
if ( cmap [ i ] . cmp > = image - > numcomps ) {
opj_event_msg ( p_manager , EVT_ERROR , " Invalid component index %d (>= %d). \n " , cmap [ i ] . cmp , image - > numcomps ) ;
is_sane = OPJ_FALSE ;
}
}
pcol_usage = opj_calloc ( nr_channels , sizeof ( OPJ_BOOL ) ) ;
if ( ! pcol_usage ) {
opj_event_msg ( p_manager , EVT_ERROR , " Unexpected OOM. \n " ) ;
return OPJ_FALSE ;
}
/* verify that no component is targeted more than once */
for ( i = 0 ; i < nr_channels ; i + + ) {
2014-03-05 10:45:04 +01:00
OPJ_UINT16 pcol = cmap [ i ] . pcol ;
assert ( cmap [ i ] . mtyp = = 0 | | cmap [ i ] . mtyp = = 1 ) ;
2014-02-26 12:05:31 +01:00
if ( pcol > = nr_channels ) {
opj_event_msg ( p_manager , EVT_ERROR , " Invalid component/palette index for direct mapping %d. \n " , pcol ) ;
is_sane = OPJ_FALSE ;
}
2014-03-05 10:45:04 +01:00
else if ( pcol_usage [ pcol ] & & cmap [ i ] . mtyp = = 1 ) {
2014-02-26 12:05:31 +01:00
opj_event_msg ( p_manager , EVT_ERROR , " Component %d is mapped twice. \n " , pcol ) ;
is_sane = OPJ_FALSE ;
}
2014-03-05 10:45:04 +01:00
else if ( cmap [ i ] . mtyp = = 0 & & cmap [ i ] . pcol ! = 0 ) {
/* I.5.3.5 PCOL: If the value of the MTYP field for this channel is 0, then
* the value of this field shall be 0. */
opj_event_msg ( p_manager , EVT_ERROR , " Direct use at #%d however pcol=%d. \n " , i , pcol ) ;
is_sane = OPJ_FALSE ;
}
2014-02-26 12:05:31 +01:00
else
pcol_usage [ pcol ] = OPJ_TRUE ;
}
/* verify that all components are targeted at least once */
for ( i = 0 ; i < nr_channels ; i + + ) {
2014-03-05 10:45:04 +01:00
if ( ! pcol_usage [ i ] & & cmap [ i ] . mtyp ! = 0 ) {
2014-02-26 12:05:31 +01:00
opj_event_msg ( p_manager , EVT_ERROR , " Component %d doesn't have a mapping. \n " , i ) ;
is_sane = OPJ_FALSE ;
}
}
2015-07-12 19:39:30 +02:00
/* Issue 235/447 weird cmap */
if ( 1 & & is_sane & & ( image - > numcomps = = 1U ) ) {
for ( i = 0 ; i < nr_channels ; i + + ) {
if ( ! pcol_usage [ i ] ) {
is_sane = 0U ;
opj_event_msg ( p_manager , EVT_WARNING , " Component mapping seems wrong. Trying to correct. \n " , i ) ;
break ;
}
}
if ( ! is_sane ) {
is_sane = OPJ_TRUE ;
for ( i = 0 ; i < nr_channels ; i + + ) {
cmap [ i ] . mtyp = 1U ;
cmap [ i ] . pcol = ( OPJ_BYTE ) i ;
}
}
}
2014-02-26 12:05:31 +01:00
opj_free ( pcol_usage ) ;
if ( ! is_sane ) {
return OPJ_FALSE ;
}
}
return OPJ_TRUE ;
}
2014-03-02 11:16:54 +01:00
/* file9.jp2 */
2012-08-13 12:10:25 +02:00
void opj_jp2_apply_pclr ( opj_image_t * image , opj_jp2_color_t * color )
2010-10-05 12:33:15 +02:00
{
opj_image_comp_t * old_comps , * new_comps ;
2011-10-05 18:27:16 +02:00
OPJ_BYTE * channel_size , * channel_sign ;
OPJ_UINT32 * entries ;
2010-10-05 12:33:15 +02:00
opj_jp2_cmap_comp_t * cmap ;
2011-10-05 18:27:16 +02:00
OPJ_INT32 * src , * dst ;
OPJ_UINT32 j , max ;
OPJ_UINT16 i , nr_channels , cmp , pcol ;
OPJ_INT32 k , top_k ;
2010-10-05 12:33:15 +02:00
2010-12-08 12:06:41 +01:00
channel_size = color - > jp2_pclr - > channel_size ;
channel_sign = color - > jp2_pclr - > channel_sign ;
entries = color - > jp2_pclr - > entries ;
cmap = color - > jp2_pclr - > cmap ;
nr_channels = color - > jp2_pclr - > nr_channels ;
2010-10-05 12:33:15 +02:00
old_comps = image - > comps ;
new_comps = ( opj_image_comp_t * )
2011-10-05 18:27:16 +02:00
opj_malloc ( nr_channels * sizeof ( opj_image_comp_t ) ) ;
2014-09-19 12:26:35 +02:00
if ( ! new_comps ) {
/* FIXME no error code for opj_jp2_apply_pclr */
/* FIXME event manager error callback */
return ;
}
2011-10-05 18:27:16 +02:00
for ( i = 0 ; i < nr_channels ; + + i ) {
pcol = cmap [ i ] . pcol ; cmp = cmap [ i ] . cmp ;
2010-10-05 12:33:15 +02:00
2011-10-05 18:27:16 +02:00
/* Direct use */
2014-03-05 10:45:04 +01:00
if ( cmap [ i ] . mtyp = = 0 ) {
assert ( pcol = = 0 ) ;
new_comps [ i ] = old_comps [ cmp ] ;
} else {
assert ( i = = pcol ) ;
new_comps [ pcol ] = old_comps [ cmp ] ;
}
2011-10-05 18:27:16 +02:00
/* Palette mapping: */
2014-03-05 10:45:04 +01:00
new_comps [ i ] . data = ( OPJ_INT32 * )
2012-10-24 14:49:28 +02:00
opj_malloc ( old_comps [ cmp ] . w * old_comps [ cmp ] . h * sizeof ( OPJ_INT32 ) ) ;
2014-09-19 12:26:35 +02:00
if ( ! new_comps [ i ] . data ) {
opj_free ( new_comps ) ;
new_comps = NULL ;
/* FIXME no error code for opj_jp2_apply_pclr */
/* FIXME event manager error callback */
return ;
}
2014-03-05 10:45:04 +01:00
new_comps [ i ] . prec = channel_size [ i ] ;
new_comps [ i ] . sgnd = channel_sign [ i ] ;
2011-10-05 18:27:16 +02:00
}
2010-10-05 12:33:15 +02:00
2010-12-08 12:06:41 +01:00
top_k = color - > jp2_pclr - > nr_entries - 1 ;
2010-10-05 12:33:15 +02:00
2011-10-05 18:27:16 +02:00
for ( i = 0 ; i < nr_channels ; + + i ) {
/* Palette mapping: */
cmp = cmap [ i ] . cmp ; pcol = cmap [ i ] . pcol ;
src = old_comps [ cmp ] . data ;
2014-03-05 10:45:04 +01:00
assert ( src ) ;
2011-10-05 18:27:16 +02:00
max = new_comps [ pcol ] . w * new_comps [ pcol ] . h ;
2014-03-05 10:45:04 +01:00
/* Direct use: */
if ( cmap [ i ] . mtyp = = 0 ) {
assert ( cmp = = 0 ) ;
dst = new_comps [ i ] . data ;
assert ( dst ) ;
for ( j = 0 ; j < max ; + + j ) {
dst [ j ] = src [ j ] ;
}
}
else {
assert ( i = = pcol ) ;
dst = new_comps [ pcol ] . data ;
assert ( dst ) ;
for ( j = 0 ; j < max ; + + j ) {
/* The index */
if ( ( k = src [ j ] ) < 0 ) k = 0 ; else if ( k > top_k ) k = top_k ;
/* The colour */
2014-03-07 15:14:31 +01:00
dst [ j ] = ( OPJ_INT32 ) entries [ k * nr_channels + pcol ] ;
2014-03-05 10:45:04 +01:00
}
}
2011-10-05 18:27:16 +02:00
}
2010-10-05 12:33:15 +02:00
max = image - > numcomps ;
2011-10-05 18:27:16 +02:00
for ( i = 0 ; i < max ; + + i ) {
if ( old_comps [ i ] . data ) opj_free ( old_comps [ i ] . data ) ;
}
2010-10-05 12:33:15 +02:00
opj_free ( old_comps ) ;
image - > comps = new_comps ;
image - > numcomps = nr_channels ;
2012-08-13 12:10:25 +02:00
opj_jp2_free_pclr ( color ) ;
2010-10-05 12:33:15 +02:00
} /* apply_pclr() */
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_read_pclr ( opj_jp2_t * jp2 ,
2012-08-10 12:55:10 +02:00
OPJ_BYTE * p_pclr_header_data ,
OPJ_UINT32 p_pclr_header_size ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager
2012-08-10 12:55:10 +02:00
)
2012-08-10 12:19:11 +02:00
{
2011-09-19 15:36:07 +02:00
opj_jp2_pclr_t * jp2_pclr ;
OPJ_BYTE * channel_size , * channel_sign ;
OPJ_UINT32 * entries ;
OPJ_UINT16 nr_entries , nr_channels ;
OPJ_UINT16 i , j ;
OPJ_UINT32 l_value ;
2014-02-25 14:28:37 +01:00
OPJ_BYTE * orig_header_data = p_pclr_header_data ;
2011-09-19 15:36:07 +02:00
2012-03-02 16:53:14 +01:00
/* preconditions */
2011-09-19 15:36:07 +02:00
assert ( p_pclr_header_data ! = 00 ) ;
assert ( jp2 ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
2012-10-24 14:49:28 +02:00
( void ) p_pclr_header_size ;
2011-09-19 15:36:07 +02:00
if ( jp2 - > color . jp2_pclr )
return OPJ_FALSE ;
2014-02-25 14:28:37 +01:00
if ( p_pclr_header_size < 3 )
return OPJ_FALSE ;
2011-09-19 15:36:07 +02:00
opj_read_bytes ( p_pclr_header_data , & l_value , 2 ) ; /* NE */
p_pclr_header_data + = 2 ;
nr_entries = ( OPJ_UINT16 ) l_value ;
2014-11-21 00:47:09 +01:00
if ( ( nr_entries = = 0U ) | | ( nr_entries > 1024U ) ) {
opj_event_msg ( p_manager , EVT_ERROR , " Invalid PCLR box. Reports %d entries \n " , ( int ) nr_entries ) ;
return OPJ_FALSE ;
}
2011-09-19 15:36:07 +02:00
opj_read_bytes ( p_pclr_header_data , & l_value , 1 ) ; /* NPC */
+ + p_pclr_header_data ;
nr_channels = ( OPJ_UINT16 ) l_value ;
2014-11-21 00:47:09 +01:00
if ( nr_channels = = 0U ) {
opj_event_msg ( p_manager , EVT_ERROR , " Invalid PCLR box. Reports 0 palette columns \n " ) ;
return OPJ_FALSE ;
}
2011-09-19 15:36:07 +02:00
2014-11-21 00:47:09 +01:00
if ( p_pclr_header_size < 3 + ( OPJ_UINT32 ) nr_channels )
2014-02-25 14:28:37 +01:00
return OPJ_FALSE ;
2014-03-07 15:14:31 +01:00
entries = ( OPJ_UINT32 * ) opj_malloc ( ( size_t ) nr_channels * nr_entries * sizeof ( OPJ_UINT32 ) ) ;
2012-11-13 17:59:03 +01:00
if ( ! entries )
return OPJ_FALSE ;
2011-09-19 15:36:07 +02:00
channel_size = ( OPJ_BYTE * ) opj_malloc ( nr_channels ) ;
2012-11-13 17:59:03 +01:00
if ( ! channel_size )
{
opj_free ( entries ) ;
return OPJ_FALSE ;
}
2011-09-19 15:36:07 +02:00
channel_sign = ( OPJ_BYTE * ) opj_malloc ( nr_channels ) ;
2012-11-13 17:59:03 +01:00
if ( ! channel_sign )
{
opj_free ( entries ) ;
opj_free ( channel_size ) ;
return OPJ_FALSE ;
}
2011-09-19 15:36:07 +02:00
jp2_pclr = ( opj_jp2_pclr_t * ) opj_malloc ( sizeof ( opj_jp2_pclr_t ) ) ;
2012-11-13 17:59:03 +01:00
if ( ! jp2_pclr )
{
opj_free ( entries ) ;
opj_free ( channel_size ) ;
opj_free ( channel_sign ) ;
return OPJ_FALSE ;
}
2011-09-19 15:36:07 +02:00
jp2_pclr - > channel_sign = channel_sign ;
jp2_pclr - > channel_size = channel_size ;
jp2_pclr - > entries = entries ;
jp2_pclr - > nr_entries = nr_entries ;
2012-08-10 13:21:48 +02:00
jp2_pclr - > nr_channels = ( OPJ_BYTE ) l_value ;
2011-09-19 15:36:07 +02:00
jp2_pclr - > cmap = NULL ;
jp2 - > color . jp2_pclr = jp2_pclr ;
for ( i = 0 ; i < nr_channels ; + + i ) {
opj_read_bytes ( p_pclr_header_data , & l_value , 1 ) ; /* Bi */
+ + p_pclr_header_data ;
2014-03-03 16:47:23 +01:00
channel_size [ i ] = ( OPJ_BYTE ) ( ( l_value & 0x7f ) + 1 ) ;
channel_sign [ i ] = ( l_value & 0x80 ) ? 1 : 0 ;
2011-09-19 15:36:07 +02:00
}
for ( j = 0 ; j < nr_entries ; + + j ) {
for ( i = 0 ; i < nr_channels ; + + i ) {
2014-03-07 15:14:31 +01:00
OPJ_UINT32 bytes_to_read = ( OPJ_UINT32 ) ( ( channel_size [ i ] + 7 ) > > 3 ) ;
2012-05-29 15:55:49 +02:00
2014-02-25 14:28:37 +01:00
if ( bytes_to_read > sizeof ( OPJ_UINT32 ) )
bytes_to_read = sizeof ( OPJ_UINT32 ) ;
2014-10-06 23:05:32 +02:00
if ( ( ptrdiff_t ) p_pclr_header_size < ( ptrdiff_t ) ( p_pclr_header_data - orig_header_data ) + ( ptrdiff_t ) bytes_to_read )
2014-02-25 14:28:37 +01:00
return OPJ_FALSE ;
2012-05-29 15:55:49 +02:00
opj_read_bytes ( p_pclr_header_data , & l_value , bytes_to_read ) ; /* Cji */
p_pclr_header_data + = bytes_to_read ;
2011-09-19 15:36:07 +02:00
* entries = ( OPJ_UINT32 ) l_value ;
entries + + ;
}
}
return OPJ_TRUE ;
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_read_cmap ( opj_jp2_t * jp2 ,
2012-08-10 12:55:10 +02:00
OPJ_BYTE * p_cmap_header_data ,
OPJ_UINT32 p_cmap_header_size ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager
2012-08-10 12:55:10 +02:00
)
2011-09-19 15:36:07 +02:00
{
opj_jp2_cmap_comp_t * cmap ;
OPJ_BYTE i , nr_channels ;
OPJ_UINT32 l_value ;
2012-03-02 16:53:14 +01:00
/* preconditions */
2011-09-19 15:36:07 +02:00
assert ( jp2 ! = 00 ) ;
assert ( p_cmap_header_data ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
2012-11-13 17:59:03 +01:00
( void ) p_cmap_header_size ;
2011-09-19 15:36:07 +02:00
/* Need nr_channels: */
if ( jp2 - > color . jp2_pclr = = NULL ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Need to read a PCLR box before the CMAP box. \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
/* Part 1, I.5.3.5: 'There shall be at most one Component Mapping box
* inside a JP2 Header box ' :
*/
if ( jp2 - > color . jp2_pclr - > cmap ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Only one CMAP box is allowed. \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
nr_channels = jp2 - > color . jp2_pclr - > nr_channels ;
2014-02-25 14:28:37 +01:00
if ( p_cmap_header_size < ( OPJ_UINT32 ) nr_channels * 4 ) {
opj_event_msg ( p_manager , EVT_ERROR , " Insufficient data for CMAP box. \n " ) ;
return OPJ_FALSE ;
}
2011-09-19 15:36:07 +02:00
cmap = ( opj_jp2_cmap_comp_t * ) opj_malloc ( nr_channels * sizeof ( opj_jp2_cmap_comp_t ) ) ;
2012-11-13 17:59:03 +01:00
if ( ! cmap )
return OPJ_FALSE ;
2011-09-19 15:36:07 +02:00
for ( i = 0 ; i < nr_channels ; + + i ) {
opj_read_bytes ( p_cmap_header_data , & l_value , 2 ) ; /* CMP^i */
p_cmap_header_data + = 2 ;
cmap [ i ] . cmp = ( OPJ_UINT16 ) l_value ;
opj_read_bytes ( p_cmap_header_data , & l_value , 1 ) ; /* MTYP^i */
+ + p_cmap_header_data ;
cmap [ i ] . mtyp = ( OPJ_BYTE ) l_value ;
opj_read_bytes ( p_cmap_header_data , & l_value , 1 ) ; /* PCOL^i */
+ + p_cmap_header_data ;
cmap [ i ] . pcol = ( OPJ_BYTE ) l_value ;
}
jp2 - > color . jp2_pclr - > cmap = cmap ;
return OPJ_TRUE ;
}
2012-08-13 12:10:25 +02:00
void opj_jp2_apply_cdef ( opj_image_t * image , opj_jp2_color_t * color )
2010-10-05 12:33:15 +02:00
{
opj_jp2_cdef_info_t * info ;
2012-10-26 11:39:52 +02:00
OPJ_UINT16 i , n , cn , asoc , acn ;
2014-10-30 19:26:04 +01:00
2010-12-08 12:06:41 +01:00
info = color - > jp2_cdef - > info ;
n = color - > jp2_cdef - > n ;
2014-10-30 19:26:04 +01:00
for ( i = 0 ; i < n ; + + i )
{
/* WATCH: acn = asoc - 1 ! */
asoc = info [ i ] . asoc ;
cn = info [ i ] . cn ;
if ( cn > = image - > numcomps )
{
fprintf ( stderr , " cn=%d, numcomps=%d \n " , cn , image - > numcomps ) ;
continue ;
}
if ( asoc = = 0 | | asoc = = 65535 )
{
image - > comps [ cn ] . alpha = info [ i ] . typ ;
continue ;
}
acn = ( OPJ_UINT16 ) ( asoc - 1 ) ;
if ( acn > = image - > numcomps )
{
fprintf ( stderr , " acn=%d, numcomps=%d \n " , acn , image - > numcomps ) ;
continue ;
}
/* Swap only if color channel */
if ( ( cn ! = acn ) & & ( info [ i ] . typ = = 0 ) )
2011-10-05 18:27:16 +02:00
{
opj_image_comp_t saved ;
2014-10-30 19:26:04 +01:00
OPJ_UINT16 j ;
2011-10-05 18:27:16 +02:00
memcpy ( & saved , & image - > comps [ cn ] , sizeof ( opj_image_comp_t ) ) ;
memcpy ( & image - > comps [ cn ] , & image - > comps [ acn ] , sizeof ( opj_image_comp_t ) ) ;
memcpy ( & image - > comps [ acn ] , & saved , sizeof ( opj_image_comp_t ) ) ;
2014-10-30 19:26:04 +01:00
/* Swap channels in following channel definitions, don't bother with j <= i that are already processed */
2014-11-24 22:31:09 +01:00
for ( j = ( OPJ_UINT16 ) ( i + 1U ) ; j < n ; + + j )
2014-10-30 19:26:04 +01:00
{
if ( info [ j ] . cn = = cn ) {
info [ j ] . cn = acn ;
}
else if ( info [ j ] . cn = = acn ) {
info [ j ] . cn = cn ;
}
/* asoc is related to color index. Do not update. */
}
2011-10-05 18:27:16 +02:00
}
2014-10-30 19:26:04 +01:00
2014-02-26 12:03:55 +01:00
image - > comps [ cn ] . alpha = info [ i ] . typ ;
2011-10-05 18:27:16 +02:00
}
2014-10-30 19:26:04 +01:00
2010-12-08 12:06:41 +01:00
if ( color - > jp2_cdef - > info ) opj_free ( color - > jp2_cdef - > info ) ;
2014-10-30 19:26:04 +01:00
2010-12-08 12:06:41 +01:00
opj_free ( color - > jp2_cdef ) ; color - > jp2_cdef = NULL ;
2014-10-30 19:26:04 +01:00
2010-10-05 12:33:15 +02:00
} /* jp2_apply_cdef() */
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_read_cdef ( opj_jp2_t * jp2 ,
2012-08-10 12:55:10 +02:00
OPJ_BYTE * p_cdef_header_data ,
OPJ_UINT32 p_cdef_header_size ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager
2012-08-10 12:55:10 +02:00
)
2011-09-19 15:36:07 +02:00
{
opj_jp2_cdef_info_t * cdef_info ;
2012-10-24 14:49:28 +02:00
OPJ_UINT16 i ;
2011-09-19 15:36:07 +02:00
OPJ_UINT32 l_value ;
2012-03-02 16:53:14 +01:00
/* preconditions */
2011-09-19 15:36:07 +02:00
assert ( jp2 ! = 00 ) ;
assert ( p_cdef_header_data ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
2012-10-24 14:49:28 +02:00
( void ) p_cdef_header_size ;
2011-09-19 15:36:07 +02:00
/* Part 1, I.5.3.6: 'The shall be at most one Channel Definition box
* inside a JP2 Header box . ' */
if ( jp2 - > color . jp2_cdef ) return OPJ_FALSE ;
2014-02-25 14:28:37 +01:00
if ( p_cdef_header_size < 2 ) {
opj_event_msg ( p_manager , EVT_ERROR , " Insufficient data for CDEF box. \n " ) ;
return OPJ_FALSE ;
}
2011-09-19 15:47:35 +02:00
opj_read_bytes ( p_cdef_header_data , & l_value , 2 ) ; /* N */
p_cdef_header_data + = 2 ;
2011-09-19 15:36:07 +02:00
if ( ( OPJ_UINT16 ) l_value = = 0 ) { /* szukw000: FIXME */
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Number of channel description is equal to zero in CDEF box. \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
2014-02-25 14:28:37 +01:00
if ( p_cdef_header_size < 2 + ( OPJ_UINT32 ) ( OPJ_UINT16 ) l_value * 6 ) {
2014-02-26 12:21:18 +01:00
opj_event_msg ( p_manager , EVT_ERROR , " Insufficient data for CDEF box. \n " ) ;
return OPJ_FALSE ;
}
2011-09-19 15:36:07 +02:00
cdef_info = ( opj_jp2_cdef_info_t * ) opj_malloc ( l_value * sizeof ( opj_jp2_cdef_info_t ) ) ;
2012-11-13 17:59:03 +01:00
if ( ! cdef_info )
return OPJ_FALSE ;
2011-09-19 15:36:07 +02:00
jp2 - > color . jp2_cdef = ( opj_jp2_cdef_t * ) opj_malloc ( sizeof ( opj_jp2_cdef_t ) ) ;
2012-11-13 17:59:03 +01:00
if ( ! jp2 - > color . jp2_cdef )
{
opj_free ( cdef_info ) ;
return OPJ_FALSE ;
}
2011-09-19 15:36:07 +02:00
jp2 - > color . jp2_cdef - > info = cdef_info ;
jp2 - > color . jp2_cdef - > n = ( OPJ_UINT16 ) l_value ;
for ( i = 0 ; i < jp2 - > color . jp2_cdef - > n ; + + i ) {
opj_read_bytes ( p_cdef_header_data , & l_value , 2 ) ; /* Cn^i */
p_cdef_header_data + = 2 ;
cdef_info [ i ] . cn = ( OPJ_UINT16 ) l_value ;
opj_read_bytes ( p_cdef_header_data , & l_value , 2 ) ; /* Typ^i */
p_cdef_header_data + = 2 ;
cdef_info [ i ] . typ = ( OPJ_UINT16 ) l_value ;
opj_read_bytes ( p_cdef_header_data , & l_value , 2 ) ; /* Asoc^i */
p_cdef_header_data + = 2 ;
cdef_info [ i ] . asoc = ( OPJ_UINT16 ) l_value ;
}
return OPJ_TRUE ;
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_read_colr ( opj_jp2_t * jp2 ,
2012-08-10 12:55:10 +02:00
OPJ_BYTE * p_colr_header_data ,
OPJ_UINT32 p_colr_header_size ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager
2012-08-10 12:55:10 +02:00
)
2011-09-19 15:36:07 +02:00
{
OPJ_UINT32 l_value ;
2012-03-02 16:53:14 +01:00
/* preconditions */
2011-09-19 15:36:07 +02:00
assert ( jp2 ! = 00 ) ;
assert ( p_colr_header_data ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
if ( p_colr_header_size < 3 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Bad COLR header box (bad size) \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
/* Part 1, I.5.3.3 : 'A conforming JP2 reader shall ignore all Colour
* Specification boxes after the first . '
*/
if ( jp2 - > color . jp2_has_colr ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_INFO , " A conforming JP2 reader shall ignore all Colour Specification boxes after the first, so we ignore this one. \n " ) ;
2011-09-19 15:36:07 +02:00
p_colr_header_data + = p_colr_header_size ;
return OPJ_TRUE ;
}
opj_read_bytes ( p_colr_header_data , & jp2 - > meth , 1 ) ; /* METH */
+ + p_colr_header_data ;
opj_read_bytes ( p_colr_header_data , & jp2 - > precedence , 1 ) ; /* PRECEDENCE */
+ + p_colr_header_data ;
opj_read_bytes ( p_colr_header_data , & jp2 - > approx , 1 ) ; /* APPROX */
+ + p_colr_header_data ;
if ( jp2 - > meth = = 1 ) {
2014-02-26 12:22:34 +01:00
if ( p_colr_header_size < 7 ) {
opj_event_msg ( p_manager , EVT_ERROR , " Bad COLR header box (bad size: %d) \n " , p_colr_header_size ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
2014-02-26 12:22:34 +01:00
if ( p_colr_header_size > 7 ) {
/* testcase Altona_Technical_v20_x4.pdf */
opj_event_msg ( p_manager , EVT_WARNING , " Bad COLR header box (bad size: %d) \n " , p_colr_header_size ) ;
}
2011-09-19 15:36:07 +02:00
opj_read_bytes ( p_colr_header_data , & jp2 - > enumcs , 4 ) ; /* EnumCS */
2013-03-17 19:27:41 +01:00
jp2 - > color . jp2_has_colr = 1 ;
2011-09-19 15:36:07 +02:00
}
else if ( jp2 - > meth = = 2 ) {
2012-03-02 16:53:14 +01:00
/* ICC profile */
2012-10-24 14:49:28 +02:00
OPJ_INT32 it_icc_value = 0 ;
2014-03-07 15:14:31 +01:00
OPJ_INT32 icc_len = ( OPJ_INT32 ) p_colr_header_size - 3 ;
2011-09-19 15:36:07 +02:00
2014-03-07 15:14:31 +01:00
jp2 - > color . icc_profile_len = ( OPJ_UINT32 ) icc_len ;
2014-09-16 17:48:04 +02:00
jp2 - > color . icc_profile_buf = ( OPJ_BYTE * ) opj_calloc ( 1 , ( size_t ) icc_len ) ;
2012-11-13 17:59:03 +01:00
if ( ! jp2 - > color . icc_profile_buf )
{
jp2 - > color . icc_profile_len = 0 ;
return OPJ_FALSE ;
}
2011-09-19 15:36:07 +02:00
for ( it_icc_value = 0 ; it_icc_value < icc_len ; + + it_icc_value )
{
opj_read_bytes ( p_colr_header_data , & l_value , 1 ) ; /* icc values */
+ + p_colr_header_data ;
jp2 - > color . icc_profile_buf [ it_icc_value ] = ( OPJ_BYTE ) l_value ;
}
2013-03-17 19:27:41 +01:00
jp2 - > color . jp2_has_colr = 1 ;
2011-09-19 15:36:07 +02:00
}
2013-03-17 19:27:41 +01:00
else if ( jp2 - > meth > 2 )
{
2014-10-03 21:52:20 +02:00
/* ISO/IEC 15444-1:2004 (E), Table I.9 Legal METH values:
2013-03-17 19:27:41 +01:00
conforming JP2 reader shall ignore the entire Colour Specification box . */
opj_event_msg ( p_manager , EVT_INFO , " COLR BOX meth value is not a regular value (%d), "
" so we will ignore the entire Colour Specification box. \n " , jp2 - > meth ) ;
}
return OPJ_TRUE ;
2011-09-19 15:36:07 +02:00
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_decode ( opj_jp2_t * jp2 ,
2012-08-09 16:46:11 +02:00
opj_stream_private_t * p_stream ,
opj_image_t * p_image ,
opj_event_mgr_t * p_manager )
2011-10-05 18:27:16 +02:00
{
2011-10-12 16:42:21 +02:00
if ( ! p_image )
return OPJ_FALSE ;
2011-10-05 18:27:16 +02:00
/* J2K decoding */
2012-08-09 17:16:33 +02:00
if ( ! opj_j2k_decode ( jp2 - > j2k , p_stream , p_image , p_manager ) ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Failed to decode the codestream in the JP2 file \n " ) ;
2011-10-05 18:27:16 +02:00
return OPJ_FALSE ;
}
2012-08-30 18:56:31 +02:00
2012-08-09 16:28:35 +02:00
if ( ! jp2 - > ignore_pclr_cmap_cdef ) {
2014-02-26 12:05:31 +01:00
if ( ! opj_jp2_check_color ( p_image , & ( jp2 - > color ) , p_manager ) ) {
return OPJ_FALSE ;
}
2011-10-05 18:27:16 +02:00
2012-08-09 16:28:35 +02:00
/* Set Image Color Space */
if ( jp2 - > enumcs = = 16 )
2012-11-15 13:58:32 +01:00
p_image - > color_space = OPJ_CLRSPC_SRGB ;
2012-08-09 16:28:35 +02:00
else if ( jp2 - > enumcs = = 17 )
2012-11-15 13:58:32 +01:00
p_image - > color_space = OPJ_CLRSPC_GRAY ;
2012-08-09 16:28:35 +02:00
else if ( jp2 - > enumcs = = 18 )
2012-11-15 13:58:32 +01:00
p_image - > color_space = OPJ_CLRSPC_SYCC ;
2014-02-26 12:24:38 +01:00
else if ( jp2 - > enumcs = = 24 )
p_image - > color_space = OPJ_CLRSPC_EYCC ;
2012-08-09 16:28:35 +02:00
else
2012-11-15 13:58:32 +01:00
p_image - > color_space = OPJ_CLRSPC_UNKNOWN ;
2012-08-09 16:28:35 +02:00
if ( jp2 - > color . jp2_pclr ) {
/* Part 1, I.5.3.4: Either both or none : */
if ( ! jp2 - > color . jp2_pclr - > cmap )
2012-08-13 12:10:25 +02:00
opj_jp2_free_pclr ( & ( jp2 - > color ) ) ;
2012-08-09 16:28:35 +02:00
else
2012-08-13 12:10:25 +02:00
opj_jp2_apply_pclr ( p_image , & ( jp2 - > color ) ) ;
2012-08-09 16:28:35 +02:00
}
2014-10-30 19:26:10 +01:00
/* Apply the color space if needed */
if ( jp2 - > color . jp2_cdef ) {
opj_jp2_apply_cdef ( p_image , & ( jp2 - > color ) ) ;
}
2012-08-09 16:28:35 +02:00
if ( jp2 - > color . icc_profile_buf ) {
p_image - > icc_profile_buf = jp2 - > color . icc_profile_buf ;
p_image - > icc_profile_len = jp2 - > color . icc_profile_len ;
jp2 - > color . icc_profile_buf = NULL ;
}
}
2011-10-05 18:27:16 +02:00
return OPJ_TRUE ;
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_write_jp2h ( opj_jp2_t * jp2 ,
2012-08-13 11:24:15 +02:00
opj_stream_private_t * stream ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager
2012-08-13 11:24:15 +02:00
)
2012-05-14 11:37:36 +02:00
{
2014-11-03 15:12:01 +01:00
opj_jp2_img_header_writer_handler_t l_writers [ 4 ] ;
2012-05-14 11:37:36 +02:00
opj_jp2_img_header_writer_handler_t * l_current_writer ;
2012-10-24 14:49:28 +02:00
OPJ_INT32 i , l_nb_pass ;
2012-05-14 11:37:36 +02:00
/* size of data for super box*/
2014-03-07 15:14:31 +01:00
OPJ_UINT32 l_jp2h_size = 8 ;
2012-11-15 14:13:36 +01:00
OPJ_BOOL l_result = OPJ_TRUE ;
2012-05-14 11:37:36 +02:00
/* to store the data of the super box */
2012-10-24 14:49:28 +02:00
OPJ_BYTE l_jp2h_data [ 8 ] ;
2012-05-14 11:37:36 +02:00
2012-09-10 11:04:47 +02:00
/* preconditions */
2012-08-13 11:24:15 +02:00
assert ( stream ! = 00 ) ;
2012-05-14 11:37:36 +02:00
assert ( jp2 ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
memset ( l_writers , 0 , sizeof ( l_writers ) ) ;
if ( jp2 - > bpc = = 255 ) {
l_nb_pass = 3 ;
2012-08-13 11:27:58 +02:00
l_writers [ 0 ] . handler = opj_jp2_write_ihdr ;
2012-08-13 11:31:24 +02:00
l_writers [ 1 ] . handler = opj_jp2_write_bpcc ;
2012-08-13 11:35:16 +02:00
l_writers [ 2 ] . handler = opj_jp2_write_colr ;
2012-05-14 11:37:36 +02:00
}
else {
l_nb_pass = 2 ;
2012-08-13 11:27:58 +02:00
l_writers [ 0 ] . handler = opj_jp2_write_ihdr ;
2012-08-13 11:35:16 +02:00
l_writers [ 1 ] . handler = opj_jp2_write_colr ;
2012-05-14 11:37:36 +02:00
}
2014-11-03 15:12:01 +01:00
if ( jp2 - > color . jp2_cdef ! = NULL ) {
l_writers [ l_nb_pass ] . handler = opj_jp2_write_cdef ;
l_nb_pass + + ;
}
2012-05-14 11:37:36 +02:00
/* write box header */
/* write JP2H type */
opj_write_bytes ( l_jp2h_data + 4 , JP2_JP2H , 4 ) ;
l_current_writer = l_writers ;
for ( i = 0 ; i < l_nb_pass ; + + i ) {
l_current_writer - > m_data = l_current_writer - > handler ( jp2 , & ( l_current_writer - > m_size ) ) ;
if ( l_current_writer - > m_data = = 00 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Not enough memory to hold JP2 Header data \n " ) ;
2012-05-14 11:37:36 +02:00
l_result = OPJ_FALSE ;
break ;
}
l_jp2h_size + = l_current_writer - > m_size ;
+ + l_current_writer ;
}
if ( ! l_result ) {
l_current_writer = l_writers ;
for ( i = 0 ; i < l_nb_pass ; + + i ) {
if ( l_current_writer - > m_data ! = 00 ) {
opj_free ( l_current_writer - > m_data ) ;
}
+ + l_current_writer ;
}
return OPJ_FALSE ;
}
/* write super box size */
opj_write_bytes ( l_jp2h_data , l_jp2h_size , 4 ) ;
/* write super box data on stream */
2012-08-13 11:24:15 +02:00
if ( opj_stream_write_data ( stream , l_jp2h_data , 8 , p_manager ) ! = 8 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Stream error while writing JP2 Header box \n " ) ;
2012-05-14 11:37:36 +02:00
l_result = OPJ_FALSE ;
}
if ( l_result ) {
l_current_writer = l_writers ;
for ( i = 0 ; i < l_nb_pass ; + + i ) {
2012-08-13 11:24:15 +02:00
if ( opj_stream_write_data ( stream , l_current_writer - > m_data , l_current_writer - > m_size , p_manager ) ! = l_current_writer - > m_size ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Stream error while writing JP2 Header box \n " ) ;
2012-05-14 11:37:36 +02:00
l_result = OPJ_FALSE ;
break ;
}
+ + l_current_writer ;
}
}
l_current_writer = l_writers ;
/* cleanup */
for ( i = 0 ; i < l_nb_pass ; + + i ) {
if ( l_current_writer - > m_data ! = 00 ) {
opj_free ( l_current_writer - > m_data ) ;
}
+ + l_current_writer ;
}
return l_result ;
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_write_ftyp ( opj_jp2_t * jp2 ,
2012-05-14 11:37:36 +02:00
opj_stream_private_t * cio ,
opj_event_mgr_t * p_manager )
{
2012-10-24 14:49:28 +02:00
OPJ_UINT32 i ;
OPJ_UINT32 l_ftyp_size = 16 + 4 * jp2 - > numcl ;
OPJ_BYTE * l_ftyp_data , * l_current_data_ptr ;
2012-11-15 14:13:36 +01:00
OPJ_BOOL l_result ;
2012-05-14 11:37:36 +02:00
2012-09-10 11:04:47 +02:00
/* preconditions */
2012-05-14 11:37:36 +02:00
assert ( cio ! = 00 ) ;
assert ( jp2 ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
2014-09-16 17:48:04 +02:00
l_ftyp_data = ( OPJ_BYTE * ) opj_calloc ( 1 , l_ftyp_size ) ;
2012-05-14 11:37:36 +02:00
if ( l_ftyp_data = = 00 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Not enough memory to handle ftyp data \n " ) ;
2012-05-14 11:37:36 +02:00
return OPJ_FALSE ;
}
l_current_data_ptr = l_ftyp_data ;
opj_write_bytes ( l_current_data_ptr , l_ftyp_size , 4 ) ; /* box size */
l_current_data_ptr + = 4 ;
opj_write_bytes ( l_current_data_ptr , JP2_FTYP , 4 ) ; /* FTYP */
l_current_data_ptr + = 4 ;
opj_write_bytes ( l_current_data_ptr , jp2 - > brand , 4 ) ; /* BR */
l_current_data_ptr + = 4 ;
opj_write_bytes ( l_current_data_ptr , jp2 - > minversion , 4 ) ; /* MinV */
l_current_data_ptr + = 4 ;
for ( i = 0 ; i < jp2 - > numcl ; i + + ) {
opj_write_bytes ( l_current_data_ptr , jp2 - > cl [ i ] , 4 ) ; /* CL */
}
l_result = ( opj_stream_write_data ( cio , l_ftyp_data , l_ftyp_size , p_manager ) = = l_ftyp_size ) ;
if ( ! l_result )
{
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Error while writing ftyp data to stream \n " ) ;
2012-05-14 11:37:36 +02:00
}
opj_free ( l_ftyp_data ) ;
return l_result ;
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_write_jp2c ( opj_jp2_t * jp2 ,
2012-05-14 19:17:53 +02:00
opj_stream_private_t * cio ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager )
2012-05-14 19:17:53 +02:00
{
2012-08-10 13:21:48 +02:00
OPJ_OFF_T j2k_codestream_exit ;
OPJ_BYTE l_data_header [ 8 ] ;
2012-05-14 19:17:53 +02:00
2012-09-10 11:04:47 +02:00
/* preconditions */
2012-05-14 19:17:53 +02:00
assert ( jp2 ! = 00 ) ;
assert ( cio ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
assert ( opj_stream_has_seek ( cio ) ) ;
j2k_codestream_exit = opj_stream_tell ( cio ) ;
2012-08-10 13:21:48 +02:00
opj_write_bytes ( l_data_header ,
( OPJ_UINT32 ) ( j2k_codestream_exit - jp2 - > j2k_codestream_offset ) ,
4 ) ; /* size of codestream */
2012-05-14 19:17:53 +02:00
opj_write_bytes ( l_data_header + 4 , JP2_JP2C , 4 ) ; /* JP2C */
if ( ! opj_stream_seek ( cio , jp2 - > j2k_codestream_offset , p_manager ) ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Failed to seek in the stream. \n " ) ;
2012-05-14 19:17:53 +02:00
return OPJ_FALSE ;
}
if ( opj_stream_write_data ( cio , l_data_header , 8 , p_manager ) ! = 8 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Failed to seek in the stream. \n " ) ;
2012-05-14 19:17:53 +02:00
return OPJ_FALSE ;
}
if ( ! opj_stream_seek ( cio , j2k_codestream_exit , p_manager ) ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Failed to seek in the stream. \n " ) ;
2012-05-14 19:17:53 +02:00
return OPJ_FALSE ;
}
return OPJ_TRUE ;
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_write_jp ( opj_jp2_t * jp2 ,
2012-08-13 12:03:57 +02:00
opj_stream_private_t * cio ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager )
2012-05-14 11:37:36 +02:00
{
/* 12 bytes will be read */
2012-10-24 14:49:28 +02:00
OPJ_BYTE l_signature_data [ 12 ] ;
2012-05-14 11:37:36 +02:00
2012-09-10 11:04:47 +02:00
/* preconditions */
2012-05-14 11:37:36 +02:00
assert ( cio ! = 00 ) ;
assert ( jp2 ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
/* write box length */
opj_write_bytes ( l_signature_data , 12 , 4 ) ;
/* writes box type */
opj_write_bytes ( l_signature_data + 4 , JP2_JP , 4 ) ;
/* writes magic number*/
opj_write_bytes ( l_signature_data + 8 , 0x0d0a870a , 4 ) ;
if ( opj_stream_write_data ( cio , l_signature_data , 12 , p_manager ) ! = 12 ) {
return OPJ_FALSE ;
}
return OPJ_TRUE ;
}
2005-12-02 14:34:15 +01:00
/* ----------------------------------------------------------------------- */
/* JP2 decoder interface */
/* ----------------------------------------------------------------------- */
2012-10-25 16:16:19 +02:00
void opj_jp2_setup_decoder ( opj_jp2_t * jp2 , opj_dparameters_t * parameters )
2011-09-21 18:37:45 +02:00
{
2011-09-19 15:36:07 +02:00
/* setup the J2K codec */
2012-08-09 17:08:33 +02:00
opj_j2k_setup_decoder ( jp2 - > j2k , parameters ) ;
2011-09-19 15:36:07 +02:00
2011-09-21 18:37:45 +02:00
/* further JP2 initializations go here */
2011-09-19 15:36:07 +02:00
jp2 - > color . jp2_has_colr = 0 ;
2012-08-09 16:28:35 +02:00
jp2 - > ignore_pclr_cmap_cdef = parameters - > flags & OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG ;
2011-09-19 15:36:07 +02:00
}
/* ----------------------------------------------------------------------- */
2005-12-02 14:34:15 +01:00
/* JP2 encoder interface */
/* ----------------------------------------------------------------------- */
2014-09-19 12:26:35 +02:00
OPJ_BOOL opj_jp2_setup_encoder ( opj_jp2_t * jp2 ,
2012-08-30 18:56:31 +02:00
opj_cparameters_t * parameters ,
opj_image_t * image ,
opj_event_mgr_t * p_manager )
{
2014-11-03 15:12:01 +01:00
OPJ_UINT32 i ;
2014-03-07 15:14:31 +01:00
OPJ_UINT32 depth_0 ;
OPJ_UINT32 sign ;
2014-11-03 15:12:01 +01:00
OPJ_UINT32 alpha_count ;
2014-11-18 19:30:44 +01:00
OPJ_UINT32 color_channels = 0U ;
OPJ_UINT32 alpha_channel = 0U ;
2014-11-03 15:12:01 +01:00
2005-12-08 10:38:47 +01:00
if ( ! jp2 | | ! parameters | | ! image )
2014-09-19 12:26:35 +02:00
return OPJ_FALSE ;
2005-12-08 10:38:47 +01:00
/* setup the J2K codec */
/* ------------------- */
2007-01-03 16:41:50 +01:00
/* Check if number of components respects standard */
if ( image - > numcomps < 1 | | image - > numcomps > 16384 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Invalid number of components specified while setting up JP2 encoder \n " ) ;
2014-09-19 12:26:35 +02:00
return OPJ_FALSE ;
2007-01-03 16:41:50 +01:00
}
2014-09-19 12:26:35 +02:00
if ( opj_j2k_setup_encoder ( jp2 - > j2k , parameters , image , p_manager ) = = OPJ_FALSE ) {
return OPJ_FALSE ;
}
2005-12-08 10:38:47 +01:00
/* setup the JP2 codec */
/* ------------------- */
/* Profile box */
jp2 - > brand = JP2_JP2 ; /* BR */
jp2 - > minversion = 0 ; /* MinV */
jp2 - > numcl = 1 ;
2012-10-24 14:49:28 +02:00
jp2 - > cl = ( OPJ_UINT32 * ) opj_malloc ( jp2 - > numcl * sizeof ( OPJ_UINT32 ) ) ;
2014-09-19 12:26:35 +02:00
if ( ! jp2 - > cl ) {
jp2 - > cl = NULL ;
opj_event_msg ( p_manager , EVT_ERROR , " Not enough memory when setup the JP2 encoder \n " ) ;
return OPJ_FALSE ;
}
2005-12-08 10:38:47 +01:00
jp2 - > cl [ 0 ] = JP2_JP2 ; /* CL0 : JP2 */
/* Image Header box */
jp2 - > numcomps = image - > numcomps ; /* NC */
jp2 - > comps = ( opj_jp2_comps_t * ) opj_malloc ( jp2 - > numcomps * sizeof ( opj_jp2_comps_t ) ) ;
2014-09-19 12:26:35 +02:00
if ( ! jp2 - > comps ) {
jp2 - > comps = NULL ;
opj_event_msg ( p_manager , EVT_ERROR , " Not enough memory when setup the JP2 encoder \n " ) ;
/* Memory of jp2->cl will be freed by opj_jp2_destroy */
return OPJ_FALSE ;
}
2012-11-13 17:59:03 +01:00
2005-12-08 10:38:47 +01:00
jp2 - > h = image - > y1 - image - > y0 ; /* HEIGHT */
jp2 - > w = image - > x1 - image - > x0 ; /* WIDTH */
/* BPC */
depth_0 = image - > comps [ 0 ] . prec - 1 ;
sign = image - > comps [ 0 ] . sgnd ;
jp2 - > bpc = depth_0 + ( sign < < 7 ) ;
for ( i = 1 ; i < image - > numcomps ; i + + ) {
2014-03-07 15:14:31 +01:00
OPJ_UINT32 depth = image - > comps [ i ] . prec - 1 ;
2005-12-08 10:38:47 +01:00
sign = image - > comps [ i ] . sgnd ;
if ( depth_0 ! = depth )
jp2 - > bpc = 255 ;
}
jp2 - > C = 7 ; /* C : Always 7 */
jp2 - > UnkC = 0 ; /* UnkC, colorspace specified in colr box */
jp2 - > IPR = 0 ; /* IPR, no intellectual property */
/* BitsPerComponent box */
for ( i = 0 ; i < image - > numcomps ; i + + ) {
jp2 - > comps [ i ] . bpcc = image - > comps [ i ] . prec - 1 + ( image - > comps [ i ] . sgnd < < 7 ) ;
}
2012-05-14 11:37:36 +02:00
/* Colour Specification box */
2012-12-03 14:04:43 +01:00
if ( image - > icc_profile_len ) {
jp2 - > meth = 2 ;
jp2 - > enumcs = 0 ;
}
else {
jp2 - > meth = 1 ;
if ( image - > color_space = = 1 )
jp2 - > enumcs = 16 ; /* sRGB as defined by IEC 61966-2-1 */
else if ( image - > color_space = = 2 )
jp2 - > enumcs = 17 ; /* greyscale */
else if ( image - > color_space = = 3 )
jp2 - > enumcs = 18 ; /* YUV */
}
2014-11-03 15:12:01 +01:00
/* Channel Definition box */
/* FIXME not provided by parameters */
/* We try to do what we can... */
alpha_count = 0U ;
for ( i = 0 ; i < image - > numcomps ; i + + ) {
if ( image - > comps [ i ] . alpha ! = 0 ) {
alpha_count + + ;
alpha_channel = i ;
}
}
if ( alpha_count = = 1U ) { /* no way to deal with more than 1 alpha channel */
switch ( jp2 - > enumcs ) {
case 16 :
case 18 :
color_channels = 3 ;
break ;
case 17 :
color_channels = 1 ;
break ;
default :
alpha_count = 0U ;
break ;
}
if ( alpha_count = = 0U ) {
opj_event_msg ( p_manager , EVT_WARNING , " Alpha channel specified but unknown enumcs. No cdef box will be created. \n " ) ;
} else if ( image - > numcomps < ( color_channels + 1 ) ) {
opj_event_msg ( p_manager , EVT_WARNING , " Alpha channel specified but not enough image components for an automatic cdef box creation. \n " ) ;
alpha_count = 0U ;
} else if ( ( OPJ_UINT32 ) alpha_channel < color_channels ) {
opj_event_msg ( p_manager , EVT_WARNING , " Alpha channel position conflicts with color channel. No cdef box will be created. \n " ) ;
alpha_count = 0U ;
}
} else if ( alpha_count > 1 ) {
opj_event_msg ( p_manager , EVT_WARNING , " Multiple alpha channels specified. No cdef box will be created. \n " ) ;
}
if ( alpha_count = = 1U ) { /* if here, we know what we can do */
jp2 - > color . jp2_cdef = ( opj_jp2_cdef_t * ) opj_malloc ( sizeof ( opj_jp2_cdef_t ) ) ;
if ( ! jp2 - > color . jp2_cdef ) {
opj_event_msg ( p_manager , EVT_ERROR , " Not enough memory to setup the JP2 encoder \n " ) ;
return OPJ_FALSE ;
}
/* no memset needed, all values will be overwritten except if jp2->color.jp2_cdef->info allocation fails, */
/* in which case jp2->color.jp2_cdef->info will be NULL => valid for destruction */
jp2 - > color . jp2_cdef - > info = ( opj_jp2_cdef_info_t * ) opj_malloc ( image - > numcomps * sizeof ( opj_jp2_cdef_info_t ) ) ;
if ( ! jp2 - > color . jp2_cdef - > info ) {
/* memory will be freed by opj_jp2_destroy */
opj_event_msg ( p_manager , EVT_ERROR , " Not enough memory to setup the JP2 encoder \n " ) ;
return OPJ_FALSE ;
}
jp2 - > color . jp2_cdef - > n = ( OPJ_UINT16 ) image - > numcomps ; /* cast is valid : image->numcomps [1,16384] */
for ( i = 0U ; i < color_channels ; i + + ) {
jp2 - > color . jp2_cdef - > info [ i ] . cn = ( OPJ_UINT16 ) i ; /* cast is valid : image->numcomps [1,16384] */
jp2 - > color . jp2_cdef - > info [ i ] . typ = 0U ;
jp2 - > color . jp2_cdef - > info [ i ] . asoc = ( OPJ_UINT16 ) ( i + 1U ) ; /* No overflow + cast is valid : image->numcomps [1,16384] */
}
for ( ; i < image - > numcomps ; i + + ) {
if ( image - > comps [ i ] . alpha ! = 0 ) { /* we'll be here exactly once */
jp2 - > color . jp2_cdef - > info [ i ] . cn = ( OPJ_UINT16 ) i ; /* cast is valid : image->numcomps [1,16384] */
jp2 - > color . jp2_cdef - > info [ i ] . typ = 1U ; /* Opacity channel */
jp2 - > color . jp2_cdef - > info [ i ] . asoc = 0U ; /* Apply alpha channel to the whole image */
} else {
/* Unknown channel */
jp2 - > color . jp2_cdef - > info [ i ] . cn = ( OPJ_UINT16 ) i ; /* cast is valid : image->numcomps [1,16384] */
jp2 - > color . jp2_cdef - > info [ i ] . typ = 65535U ;
jp2 - > color . jp2_cdef - > info [ i ] . asoc = 65535U ;
}
}
}
2012-12-03 14:04:43 +01:00
2005-12-08 10:38:47 +01:00
jp2 - > precedence = 0 ; /* PRECEDENCE */
jp2 - > approx = 0 ; /* APPROX */
2012-10-29 11:12:03 +01:00
jp2 - > jpip_on = parameters - > jpip_on ;
2014-09-19 12:26:35 +02:00
return OPJ_TRUE ;
2005-12-02 14:34:15 +01:00
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_encode ( opj_jp2_t * jp2 ,
2012-08-30 18:56:31 +02:00
opj_stream_private_t * stream ,
2012-08-13 11:24:15 +02:00
opj_event_mgr_t * p_manager )
2012-05-14 13:04:59 +02:00
{
2012-11-16 09:29:43 +01:00
return opj_j2k_encode ( jp2 - > j2k , stream , p_manager ) ;
2012-05-14 13:04:59 +02:00
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_end_decompress ( opj_jp2_t * jp2 ,
2012-08-13 11:24:15 +02:00
opj_stream_private_t * cio ,
opj_event_mgr_t * p_manager
)
2011-09-19 15:36:07 +02:00
{
2012-03-02 16:53:14 +01:00
/* preconditions */
2011-09-19 15:36:07 +02:00
assert ( jp2 ! = 00 ) ;
assert ( cio ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
/* customization of the end encoding */
2012-08-10 12:55:10 +02:00
opj_jp2_setup_end_header_reading ( jp2 ) ;
2011-09-19 15:36:07 +02:00
/* write header */
2012-08-10 12:55:10 +02:00
if ( ! opj_jp2_exec ( jp2 , jp2 - > m_procedure_list , cio , p_manager ) ) {
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
2012-08-16 13:51:34 +02:00
return opj_j2k_end_decompress ( jp2 - > j2k , cio , p_manager ) ;
2011-09-19 15:36:07 +02:00
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_end_compress ( opj_jp2_t * jp2 ,
2012-08-13 11:24:15 +02:00
opj_stream_private_t * cio ,
opj_event_mgr_t * p_manager
)
2012-03-15 11:23:20 +01:00
{
/* preconditions */
assert ( jp2 ! = 00 ) ;
assert ( cio ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
/* customization of the end encoding */
2012-10-05 11:20:05 +02:00
opj_jp2_setup_end_header_writing ( jp2 ) ;
2012-03-15 11:23:20 +01:00
2012-08-16 13:51:34 +02:00
if ( ! opj_j2k_end_compress ( jp2 - > j2k , cio , p_manager ) ) {
2012-03-15 11:23:20 +01:00
return OPJ_FALSE ;
}
/* write header */
2012-08-10 12:55:10 +02:00
return opj_jp2_exec ( jp2 , jp2 - > m_procedure_list , cio , p_manager ) ;
2012-03-15 11:23:20 +01:00
}
2012-10-25 16:16:19 +02:00
void opj_jp2_setup_end_header_writing ( opj_jp2_t * jp2 )
2012-03-15 11:23:20 +01:00
{
/* preconditions */
assert ( jp2 ! = 00 ) ;
2012-10-29 14:27:39 +01:00
# ifdef USE_JPIP
2012-10-29 11:12:03 +01:00
if ( jp2 - > jpip_on )
opj_procedure_list_add_procedure ( jp2 - > m_procedure_list , ( opj_procedure ) opj_jpip_write_iptr ) ;
2012-10-29 14:27:39 +01:00
# endif
2012-08-13 11:57:09 +02:00
opj_procedure_list_add_procedure ( jp2 - > m_procedure_list , ( opj_procedure ) opj_jp2_write_jp2c ) ;
2012-03-15 11:23:20 +01:00
/* DEVELOPER CORNER, add your custom procedures */
2012-10-29 14:27:39 +01:00
# ifdef USE_JPIP
2012-10-29 11:12:03 +01:00
if ( jp2 - > jpip_on )
{
opj_procedure_list_add_procedure ( jp2 - > m_procedure_list , ( opj_procedure ) opj_jpip_write_cidx ) ;
opj_procedure_list_add_procedure ( jp2 - > m_procedure_list , ( opj_procedure ) opj_jpip_write_fidx ) ;
}
2012-10-29 14:27:39 +01:00
# endif
2012-03-15 11:23:20 +01:00
}
2012-10-25 16:16:19 +02:00
void opj_jp2_setup_end_header_reading ( opj_jp2_t * jp2 )
2011-09-19 15:36:07 +02:00
{
2012-03-02 16:53:14 +01:00
/* preconditions */
2011-09-19 15:36:07 +02:00
assert ( jp2 ! = 00 ) ;
2012-08-10 12:55:10 +02:00
opj_procedure_list_add_procedure ( jp2 - > m_procedure_list , ( opj_procedure ) opj_jp2_read_header_procedure ) ;
2011-09-19 15:36:07 +02:00
/* DEVELOPER CORNER, add your custom procedures */
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_default_validation ( opj_jp2_t * jp2 ,
2012-08-10 12:55:10 +02:00
opj_stream_private_t * cio ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager
2012-08-10 12:55:10 +02:00
)
2012-03-15 11:23:20 +01:00
{
2012-11-15 14:13:36 +01:00
OPJ_BOOL l_is_valid = OPJ_TRUE ;
2012-10-24 14:49:28 +02:00
OPJ_UINT32 i ;
2012-03-15 11:23:20 +01:00
/* preconditions */
assert ( jp2 ! = 00 ) ;
assert ( cio ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
/* JPEG2000 codec validation */
/* STATE checking */
/* make sure the state is at 0 */
l_is_valid & = ( jp2 - > jp2_state = = JP2_STATE_NONE ) ;
/* make sure not reading a jp2h ???? WEIRD */
l_is_valid & = ( jp2 - > jp2_img_state = = JP2_IMG_STATE_NONE ) ;
/* POINTER validation */
/* make sure a j2k codec is present */
l_is_valid & = ( jp2 - > j2k ! = 00 ) ;
/* make sure a procedure list is present */
l_is_valid & = ( jp2 - > m_procedure_list ! = 00 ) ;
/* make sure a validation list is present */
l_is_valid & = ( jp2 - > m_validation_list ! = 00 ) ;
/* PARAMETER VALIDATION */
/* number of components */
l_is_valid & = ( jp2 - > numcl > 0 ) ;
/* width */
l_is_valid & = ( jp2 - > h > 0 ) ;
/* height */
l_is_valid & = ( jp2 - > w > 0 ) ;
/* precision */
for ( i = 0 ; i < jp2 - > numcomps ; + + i ) {
2014-12-22 16:00:12 +01:00
l_is_valid & = ( ( jp2 - > comps [ i ] . bpcc & 0x7FU ) < 38U ) ; /* 0 is valid, ignore sign for check */
2012-03-15 11:23:20 +01:00
}
/* METH */
l_is_valid & = ( ( jp2 - > meth > 0 ) & & ( jp2 - > meth < 3 ) ) ;
/* stream validation */
/* back and forth is needed */
l_is_valid & = opj_stream_has_seek ( cio ) ;
return l_is_valid ;
}
2011-09-19 15:36:07 +02:00
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_read_header_procedure ( opj_jp2_t * jp2 ,
2012-08-10 12:55:10 +02:00
opj_stream_private_t * stream ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager
2012-08-10 12:55:10 +02:00
)
2011-09-19 15:36:07 +02:00
{
opj_jp2_box_t box ;
OPJ_UINT32 l_nb_bytes_read ;
const opj_jp2_header_handler_t * l_current_handler ;
2015-07-12 19:39:30 +02:00
const opj_jp2_header_handler_t * l_current_handler_misplaced ;
2012-11-16 09:29:43 +01:00
OPJ_UINT32 l_last_data_size = OPJ_BOX_SIZE ;
2011-09-19 15:36:07 +02:00
OPJ_UINT32 l_current_data_size ;
2012-10-24 14:49:28 +02:00
OPJ_BYTE * l_current_data = 00 ;
2011-09-19 15:36:07 +02:00
2012-03-02 16:53:14 +01:00
/* preconditions */
2012-08-10 12:55:10 +02:00
assert ( stream ! = 00 ) ;
2011-09-19 15:36:07 +02:00
assert ( jp2 ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
2014-09-16 17:48:04 +02:00
l_current_data = ( OPJ_BYTE * ) opj_calloc ( 1 , l_last_data_size ) ;
2011-09-19 15:36:07 +02:00
if ( l_current_data = = 00 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Not enough memory to handle jpeg2000 file header \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
2012-08-10 13:00:40 +02:00
while ( opj_jp2_read_boxhdr ( & box , & l_nb_bytes_read , stream , p_manager ) ) {
2012-03-02 16:53:14 +01:00
/* is it the codestream box ? */
2011-09-19 15:36:07 +02:00
if ( box . type = = JP2_JP2C ) {
if ( jp2 - > jp2_state & JP2_STATE_HEADER ) {
jp2 - > jp2_state | = JP2_STATE_CODESTREAM ;
2012-08-22 20:45:31 +02:00
opj_free ( l_current_data ) ;
2011-09-19 15:36:07 +02:00
return OPJ_TRUE ;
}
else {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " bad placed jpeg codestream \n " ) ;
2011-09-19 15:36:07 +02:00
opj_free ( l_current_data ) ;
return OPJ_FALSE ;
}
}
else if ( box . length = = 0 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Cannot handle box of undefined sizes \n " ) ;
2011-09-19 15:36:07 +02:00
opj_free ( l_current_data ) ;
return OPJ_FALSE ;
}
2014-02-26 12:25:27 +01:00
/* testcase 1851.pdf.SIGSEGV.ce9.948 */
2014-10-06 23:05:21 +02:00
else if ( box . length < l_nb_bytes_read ) {
2014-02-26 12:25:27 +01:00
opj_event_msg ( p_manager , EVT_ERROR , " invalid box size %d (%x) \n " , box . length , box . type ) ;
opj_free ( l_current_data ) ;
return OPJ_FALSE ;
}
2011-09-19 15:36:07 +02:00
2012-08-10 12:55:10 +02:00
l_current_handler = opj_jp2_find_handler ( box . type ) ;
2015-07-12 19:39:30 +02:00
l_current_handler_misplaced = opj_jp2_img_find_handler ( box . type ) ;
2011-09-19 15:36:07 +02:00
l_current_data_size = box . length - l_nb_bytes_read ;
2015-07-12 19:39:30 +02:00
if ( ( l_current_handler ! = 00 ) | | ( l_current_handler_misplaced ! = 00 ) ) {
if ( l_current_handler = = 00 ) {
opj_event_msg ( p_manager , EVT_WARNING , " Found a misplaced '%c%c%c%c' box outside jp2h box \n " , ( OPJ_BYTE ) ( box . type > > 24 ) , ( OPJ_BYTE ) ( box . type > > 16 ) , ( OPJ_BYTE ) ( box . type > > 8 ) , ( OPJ_BYTE ) ( box . type > > 0 ) ) ;
if ( jp2 - > jp2_state & JP2_STATE_HEADER ) {
/* read anyway, we already have jp2h */
l_current_handler = l_current_handler_misplaced ;
} else {
opj_event_msg ( p_manager , EVT_WARNING , " JPEG2000 Header box not read yet, '%c%c%c%c' box will be ignored \n " , ( OPJ_BYTE ) ( box . type > > 24 ) , ( OPJ_BYTE ) ( box . type > > 16 ) , ( OPJ_BYTE ) ( box . type > > 8 ) , ( OPJ_BYTE ) ( box . type > > 0 ) ) ;
jp2 - > jp2_state | = JP2_STATE_UNKNOWN ;
if ( opj_stream_skip ( stream , l_current_data_size , p_manager ) ! = l_current_data_size ) {
opj_event_msg ( p_manager , EVT_ERROR , " Problem with skipping JPEG2000 box, stream error \n " ) ;
opj_free ( l_current_data ) ;
return OPJ_FALSE ;
}
continue ;
}
}
2014-10-06 23:05:21 +02:00
if ( ( OPJ_OFF_T ) l_current_data_size > opj_stream_get_number_byte_left ( stream ) ) {
/* do not even try to malloc if we can't read */
opj_event_msg ( p_manager , EVT_ERROR , " Invalid box size %d for box '%c%c%c%c'. Need %d bytes, %d bytes remaining \n " , box . length , ( OPJ_BYTE ) ( box . type > > 24 ) , ( OPJ_BYTE ) ( box . type > > 16 ) , ( OPJ_BYTE ) ( box . type > > 8 ) , ( OPJ_BYTE ) ( box . type > > 0 ) , l_current_data_size , ( OPJ_UINT32 ) opj_stream_get_number_byte_left ( stream ) ) ;
opj_free ( l_current_data ) ;
return OPJ_FALSE ;
}
2011-09-19 15:36:07 +02:00
if ( l_current_data_size > l_last_data_size ) {
2012-10-24 14:49:28 +02:00
OPJ_BYTE * new_current_data = ( OPJ_BYTE * ) opj_realloc ( l_current_data , l_current_data_size ) ;
2014-02-25 14:39:50 +01:00
if ( ! new_current_data ) {
2011-12-07 10:53:46 +01:00
opj_free ( l_current_data ) ;
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Not enough memory to handle jpeg2000 box \n " ) ;
2011-12-07 10:53:46 +01:00
return OPJ_FALSE ;
}
2012-10-24 14:49:28 +02:00
l_current_data = new_current_data ;
2011-09-19 15:36:07 +02:00
l_last_data_size = l_current_data_size ;
}
2014-03-03 16:47:23 +01:00
l_nb_bytes_read = ( OPJ_UINT32 ) opj_stream_read_data ( stream , l_current_data , l_current_data_size , p_manager ) ;
2011-09-19 15:36:07 +02:00
if ( l_nb_bytes_read ! = l_current_data_size ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Problem with reading JPEG2000 box, stream error \n " ) ;
2012-10-24 14:49:28 +02:00
opj_free ( l_current_data ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
if ( ! l_current_handler - > handler ( jp2 , l_current_data , l_current_data_size , p_manager ) ) {
opj_free ( l_current_data ) ;
return OPJ_FALSE ;
}
}
else {
2015-01-20 15:27:20 +01:00
if ( ! ( jp2 - > jp2_state & JP2_STATE_SIGNATURE ) ) {
opj_event_msg ( p_manager , EVT_ERROR , " Malformed JP2 file format: first box must be JPEG 2000 signature box \n " ) ;
opj_free ( l_current_data ) ;
return OPJ_FALSE ;
}
if ( ! ( jp2 - > jp2_state & JP2_STATE_FILE_TYPE ) ) {
opj_event_msg ( p_manager , EVT_ERROR , " Malformed JP2 file format: second box must be file type box \n " ) ;
opj_free ( l_current_data ) ;
return OPJ_FALSE ;
}
2011-09-19 15:36:07 +02:00
jp2 - > jp2_state | = JP2_STATE_UNKNOWN ;
2012-08-10 12:55:10 +02:00
if ( opj_stream_skip ( stream , l_current_data_size , p_manager ) ! = l_current_data_size ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Problem with skipping JPEG2000 box, stream error \n " ) ;
2011-09-19 15:36:07 +02:00
opj_free ( l_current_data ) ;
return OPJ_FALSE ;
}
}
2005-12-08 10:38:47 +01:00
}
2005-12-02 14:34:15 +01:00
2011-09-19 15:36:07 +02:00
opj_free ( l_current_data ) ;
2011-05-18 13:02:27 +02:00
return OPJ_TRUE ;
2004-07-07 10:24:36 +02:00
}
2011-09-19 15:36:07 +02:00
/**
* Excutes the given procedures on the given codec .
*
* @ param p_procedure_list the list of procedures to execute
* @ param jp2 the jpeg2000 file codec to execute the procedures on .
2012-08-10 12:55:10 +02:00
* @ param stream the stream to execute the procedures on .
2011-09-19 15:36:07 +02:00
* @ param p_manager the user manager .
*
* @ return true if all the procedures were successfully executed .
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_exec ( opj_jp2_t * jp2 ,
2012-08-10 12:55:10 +02:00
opj_procedure_list_t * p_procedure_list ,
opj_stream_private_t * stream ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager
2012-08-10 12:55:10 +02:00
)
2011-09-19 15:36:07 +02:00
{
2012-11-15 14:13:36 +01:00
OPJ_BOOL ( * * l_procedure ) ( opj_jp2_t * jp2 , opj_stream_private_t * , opj_event_mgr_t * ) = 00 ;
OPJ_BOOL l_result = OPJ_TRUE ;
2011-09-19 15:36:07 +02:00
OPJ_UINT32 l_nb_proc , i ;
2012-03-02 16:53:14 +01:00
/* preconditions */
2011-09-19 15:36:07 +02:00
assert ( p_procedure_list ! = 00 ) ;
assert ( jp2 ! = 00 ) ;
2012-08-10 12:55:10 +02:00
assert ( stream ! = 00 ) ;
2011-09-19 15:36:07 +02:00
assert ( p_manager ! = 00 ) ;
l_nb_proc = opj_procedure_list_get_nb_procedures ( p_procedure_list ) ;
2012-11-15 14:13:36 +01:00
l_procedure = ( OPJ_BOOL ( * * ) ( opj_jp2_t * jp2 , opj_stream_private_t * , opj_event_mgr_t * ) ) opj_procedure_list_get_first_procedure ( p_procedure_list ) ;
2011-09-19 15:36:07 +02:00
for ( i = 0 ; i < l_nb_proc ; + + i ) {
2012-08-10 12:55:10 +02:00
l_result = l_result & & ( * l_procedure ) ( jp2 , stream , p_manager ) ;
2011-09-19 15:36:07 +02:00
+ + l_procedure ;
}
2012-03-02 16:53:14 +01:00
/* and clear the procedure list at the end. */
2011-09-19 15:36:07 +02:00
opj_procedure_list_clear ( p_procedure_list ) ;
return l_result ;
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_start_compress ( opj_jp2_t * jp2 ,
2012-08-13 11:24:15 +02:00
opj_stream_private_t * stream ,
opj_image_t * p_image ,
opj_event_mgr_t * p_manager
)
2012-03-15 11:23:20 +01:00
{
/* preconditions */
assert ( jp2 ! = 00 ) ;
2012-08-13 11:24:15 +02:00
assert ( stream ! = 00 ) ;
2012-03-15 11:23:20 +01:00
assert ( p_manager ! = 00 ) ;
/* customization of the validation */
2012-08-13 11:44:40 +02:00
opj_jp2_setup_encoding_validation ( jp2 ) ;
2012-03-15 11:23:20 +01:00
/* validation of the parameters codec */
2012-08-13 11:24:15 +02:00
if ( ! opj_jp2_exec ( jp2 , jp2 - > m_validation_list , stream , p_manager ) ) {
2012-03-15 11:23:20 +01:00
return OPJ_FALSE ;
}
/* customization of the encoding */
2012-10-05 11:20:05 +02:00
opj_jp2_setup_header_writing ( jp2 ) ;
2012-03-15 11:23:20 +01:00
/* write header */
2012-08-13 11:24:15 +02:00
if ( ! opj_jp2_exec ( jp2 , jp2 - > m_procedure_list , stream , p_manager ) ) {
2012-03-15 11:23:20 +01:00
return OPJ_FALSE ;
}
2012-08-16 13:51:34 +02:00
return opj_j2k_start_compress ( jp2 - > j2k , stream , p_image , p_manager ) ;
2012-03-15 11:23:20 +01:00
}
2011-09-19 15:36:07 +02:00
2012-08-10 12:55:10 +02:00
const opj_jp2_header_handler_t * opj_jp2_find_handler ( OPJ_UINT32 p_id )
2011-09-19 15:36:07 +02:00
{
OPJ_UINT32 i , l_handler_size = sizeof ( jp2_header ) / sizeof ( opj_jp2_header_handler_t ) ;
for ( i = 0 ; i < l_handler_size ; + + i ) {
if ( jp2_header [ i ] . id = = p_id ) {
return & jp2_header [ i ] ;
}
}
return NULL ;
}
/**
* Finds the image execution function related to the given box id .
*
* @ param p_id the id of the handler to fetch .
*
* @ return the given handler or 00 if it could not be found .
*/
2012-08-10 12:55:10 +02:00
static const opj_jp2_header_handler_t * opj_jp2_img_find_handler ( OPJ_UINT32 p_id )
2011-09-19 15:36:07 +02:00
{
OPJ_UINT32 i , l_handler_size = sizeof ( jp2_img_header ) / sizeof ( opj_jp2_header_handler_t ) ;
for ( i = 0 ; i < l_handler_size ; + + i )
{
if ( jp2_img_header [ i ] . id = = p_id ) {
return & jp2_img_header [ i ] ;
}
}
return NULL ;
}
/**
* Reads a jpeg2000 file signature box .
*
* @ param p_header_data the data contained in the signature box .
* @ param jp2 the jpeg2000 file codec .
* @ param p_header_size the size of the data contained in the signature box .
* @ param p_manager the user event manager .
*
* @ return true if the file signature box is valid .
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_read_jp ( opj_jp2_t * jp2 ,
2012-08-10 12:34:40 +02:00
OPJ_BYTE * p_header_data ,
OPJ_UINT32 p_header_size ,
opj_event_mgr_t * p_manager
)
2011-09-19 15:36:07 +02:00
{
2012-10-24 14:49:28 +02:00
OPJ_UINT32 l_magic_number ;
2011-09-19 15:36:07 +02:00
2012-03-02 16:53:14 +01:00
/* preconditions */
2011-09-19 15:36:07 +02:00
assert ( p_header_data ! = 00 ) ;
assert ( jp2 ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
if ( jp2 - > jp2_state ! = JP2_STATE_NONE ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " The signature box must be the first box in the file. \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
/* assure length of data is correct (4 -> magic number) */
if ( p_header_size ! = 4 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Error with JP signature Box size \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
2012-03-02 16:53:14 +01:00
/* rearrange data */
2011-09-19 15:36:07 +02:00
opj_read_bytes ( p_header_data , & l_magic_number , 4 ) ;
if ( l_magic_number ! = 0x0d0a870a ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Error with JP Signature : bad magic number \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
jp2 - > jp2_state | = JP2_STATE_SIGNATURE ;
return OPJ_TRUE ;
}
/**
* Reads a a FTYP box - File type box
*
* @ param p_header_data the data contained in the FTYP box .
* @ param jp2 the jpeg2000 file codec .
* @ param p_header_size the size of the data contained in the FTYP box .
* @ param p_manager the user event manager .
*
* @ return true if the FTYP box is valid .
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_read_ftyp ( opj_jp2_t * jp2 ,
2012-08-10 12:24:09 +02:00
OPJ_BYTE * p_header_data ,
OPJ_UINT32 p_header_size ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager
2012-08-10 12:24:09 +02:00
)
2011-09-19 15:36:07 +02:00
{
OPJ_UINT32 i , l_remaining_bytes ;
2012-03-02 16:53:14 +01:00
/* preconditions */
2011-09-19 15:36:07 +02:00
assert ( p_header_data ! = 00 ) ;
assert ( jp2 ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
if ( jp2 - > jp2_state ! = JP2_STATE_SIGNATURE ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " The ftyp box must be the second box in the file. \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
/* assure length of data is correct */
if ( p_header_size < 8 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Error with FTYP signature Box size \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
opj_read_bytes ( p_header_data , & jp2 - > brand , 4 ) ; /* BR */
p_header_data + = 4 ;
opj_read_bytes ( p_header_data , & jp2 - > minversion , 4 ) ; /* MinV */
p_header_data + = 4 ;
l_remaining_bytes = p_header_size - 8 ;
/* the number of remaining bytes should be a multiple of 4 */
if ( ( l_remaining_bytes & 0x3 ) ! = 0 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Error with FTYP signature Box size \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
/* div by 4 */
jp2 - > numcl = l_remaining_bytes > > 2 ;
if ( jp2 - > numcl ) {
2014-09-16 17:48:04 +02:00
jp2 - > cl = ( OPJ_UINT32 * ) opj_calloc ( jp2 - > numcl , sizeof ( OPJ_UINT32 ) ) ;
2011-09-19 15:36:07 +02:00
if ( jp2 - > cl = = 00 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Not enough memory with FTYP Box \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
}
for ( i = 0 ; i < jp2 - > numcl ; + + i )
{
opj_read_bytes ( p_header_data , & jp2 - > cl [ i ] , 4 ) ; /* CLi */
p_header_data + = 4 ;
}
jp2 - > jp2_state | = JP2_STATE_FILE_TYPE ;
return OPJ_TRUE ;
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_skip_jp2c ( opj_jp2_t * jp2 ,
2012-08-13 11:44:40 +02:00
opj_stream_private_t * stream ,
opj_event_mgr_t * p_manager )
2012-03-15 11:23:20 +01:00
{
/* preconditions */
assert ( jp2 ! = 00 ) ;
2012-05-14 12:02:59 +02:00
assert ( stream ! = 00 ) ;
2012-03-15 11:23:20 +01:00
assert ( p_manager ! = 00 ) ;
2012-05-14 12:02:59 +02:00
jp2 - > j2k_codestream_offset = opj_stream_tell ( stream ) ;
2012-03-15 11:23:20 +01:00
2012-05-14 12:02:59 +02:00
if ( opj_stream_skip ( stream , 8 , p_manager ) ! = 8 ) {
2012-03-15 11:23:20 +01:00
return OPJ_FALSE ;
}
return OPJ_TRUE ;
}
2011-09-19 15:36:07 +02:00
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jpip_skip_iptr ( opj_jp2_t * jp2 ,
2012-10-29 11:12:03 +01:00
opj_stream_private_t * stream ,
opj_event_mgr_t * p_manager )
{
/* preconditions */
assert ( jp2 ! = 00 ) ;
assert ( stream ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
jp2 - > jpip_iptr_offset = opj_stream_tell ( stream ) ;
if ( opj_stream_skip ( stream , 24 , p_manager ) ! = 24 ) {
return OPJ_FALSE ;
}
return OPJ_TRUE ;
}
2011-09-19 15:36:07 +02:00
/**
* Reads the Jpeg2000 file Header box - JP2 Header box ( warning , this is a super box ) .
*
* @ param p_header_data the data contained in the file header box .
* @ param jp2 the jpeg2000 file codec .
* @ param p_header_size the size of the data contained in the file header box .
* @ param p_manager the user event manager .
*
* @ return true if the JP2 Header box was successfully reconized .
*/
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jp2_read_jp2h ( opj_jp2_t * jp2 ,
2012-08-10 11:43:28 +02:00
OPJ_BYTE * p_header_data ,
OPJ_UINT32 p_header_size ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager
2012-08-10 11:43:28 +02:00
)
2011-09-19 15:36:07 +02:00
{
OPJ_UINT32 l_box_size = 0 , l_current_data_size = 0 ;
opj_jp2_box_t box ;
const opj_jp2_header_handler_t * l_current_handler ;
2014-10-21 14:35:16 +02:00
OPJ_BOOL l_has_ihdr = 0 ;
2011-09-19 15:36:07 +02:00
2012-03-02 16:53:14 +01:00
/* preconditions */
2011-09-19 15:36:07 +02:00
assert ( p_header_data ! = 00 ) ;
assert ( jp2 ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
/* make sure the box is well placed */
if ( ( jp2 - > jp2_state & JP2_STATE_FILE_TYPE ) ! = JP2_STATE_FILE_TYPE ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " The box must be the first box in the file. \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
jp2 - > jp2_img_state = JP2_IMG_STATE_NONE ;
/* iterate while remaining data */
while ( p_header_size > 0 ) {
2012-08-10 12:55:10 +02:00
if ( ! opj_jp2_read_boxhdr_char ( & box , p_header_data , & l_box_size , p_header_size , p_manager ) ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Stream error while reading JP2 Header box \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
if ( box . length > p_header_size ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Stream error while reading JP2 Header box: box length is inconsistent. \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
2012-08-10 12:55:10 +02:00
l_current_handler = opj_jp2_img_find_handler ( box . type ) ;
2011-09-19 15:36:07 +02:00
l_current_data_size = box . length - l_box_size ;
p_header_data + = l_box_size ;
if ( l_current_handler ! = 00 ) {
if ( ! l_current_handler - > handler ( jp2 , p_header_data , l_current_data_size , p_manager ) ) {
return OPJ_FALSE ;
}
}
else {
jp2 - > jp2_img_state | = JP2_IMG_STATE_UNKNOWN ;
}
2014-10-21 14:35:16 +02:00
if ( box . type = = JP2_IHDR ) {
l_has_ihdr = 1 ;
}
2011-09-19 15:36:07 +02:00
p_header_data + = l_current_data_size ;
p_header_size - = box . length ;
}
2014-10-21 14:35:16 +02:00
if ( l_has_ihdr = = 0 ) {
opj_event_msg ( p_manager , EVT_ERROR , " Stream error while reading JP2 Header box: no 'ihdr' box. \n " ) ;
return OPJ_FALSE ;
}
2011-09-19 15:36:07 +02:00
jp2 - > jp2_state | = JP2_STATE_HEADER ;
return OPJ_TRUE ;
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_read_boxhdr_char ( opj_jp2_box_t * box ,
2012-08-10 12:55:10 +02:00
OPJ_BYTE * p_data ,
OPJ_UINT32 * p_number_bytes_read ,
OPJ_UINT32 p_box_max_size ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager
2012-08-10 12:55:10 +02:00
)
2011-09-19 15:36:07 +02:00
{
OPJ_UINT32 l_value ;
2012-03-02 16:53:14 +01:00
/* preconditions */
2011-09-19 15:36:07 +02:00
assert ( p_data ! = 00 ) ;
assert ( box ! = 00 ) ;
assert ( p_number_bytes_read ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
if ( p_box_max_size < 8 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Cannot handle box of less than 8 bytes \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
/* process read data */
opj_read_bytes ( p_data , & l_value , 4 ) ;
p_data + = 4 ;
2014-03-07 15:14:31 +01:00
box - > length = ( OPJ_UINT32 ) ( l_value ) ;
2011-09-19 15:36:07 +02:00
opj_read_bytes ( p_data , & l_value , 4 ) ;
p_data + = 4 ;
2014-03-07 15:14:31 +01:00
box - > type = ( OPJ_UINT32 ) ( l_value ) ;
2011-09-19 15:36:07 +02:00
* p_number_bytes_read = 8 ;
2012-03-02 16:53:14 +01:00
/* do we have a "special very large box ?" */
/* read then the XLBox */
2011-09-19 15:36:07 +02:00
if ( box - > length = = 1 ) {
2012-10-24 14:49:28 +02:00
OPJ_UINT32 l_xl_part_size ;
2011-09-19 15:36:07 +02:00
if ( p_box_max_size < 16 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Cannot handle XL box of less than 16 bytes \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
opj_read_bytes ( p_data , & l_xl_part_size , 4 ) ;
p_data + = 4 ;
* p_number_bytes_read + = 4 ;
if ( l_xl_part_size ! = 0 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Cannot handle box sizes higher than 2^32 \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
opj_read_bytes ( p_data , & l_value , 4 ) ;
* p_number_bytes_read + = 4 ;
2014-03-07 15:14:31 +01:00
box - > length = ( OPJ_UINT32 ) ( l_value ) ;
2011-09-19 15:36:07 +02:00
if ( box - > length = = 0 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Cannot handle box of undefined sizes \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
}
else if ( box - > length = = 0 ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Cannot handle box of undefined sizes \n " ) ;
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
2014-10-06 23:05:27 +02:00
if ( box - > length < * p_number_bytes_read ) {
opj_event_msg ( p_manager , EVT_ERROR , " Box length is inconsistent. \n " ) ;
return OPJ_FALSE ;
}
2011-09-19 15:36:07 +02:00
return OPJ_TRUE ;
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_read_header ( opj_stream_private_t * p_stream ,
2012-10-25 16:16:19 +02:00
opj_jp2_t * jp2 ,
2012-08-13 11:24:15 +02:00
opj_image_t * * p_image ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager
2012-08-13 11:24:15 +02:00
)
2011-09-19 15:36:07 +02:00
{
2011-10-07 19:31:35 +02:00
/* preconditions */
2011-09-19 15:36:07 +02:00
assert ( jp2 ! = 00 ) ;
assert ( p_stream ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
/* customization of the validation */
2012-08-10 12:55:10 +02:00
opj_jp2_setup_decoding_validation ( jp2 ) ;
2011-09-19 15:36:07 +02:00
/* customization of the encoding */
2012-08-10 12:55:10 +02:00
opj_jp2_setup_header_reading ( jp2 ) ;
2011-09-19 15:36:07 +02:00
/* validation of the parameters codec */
2012-08-10 12:55:10 +02:00
if ( ! opj_jp2_exec ( jp2 , jp2 - > m_validation_list , p_stream , p_manager ) ) {
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
/* read header */
2012-08-10 12:55:10 +02:00
if ( ! opj_jp2_exec ( jp2 , jp2 - > m_procedure_list , p_stream , p_manager ) ) {
2011-09-19 15:36:07 +02:00
return OPJ_FALSE ;
}
2012-08-16 13:51:34 +02:00
return opj_j2k_read_header ( p_stream ,
2011-09-19 15:36:07 +02:00
jp2 - > j2k ,
2011-10-05 18:27:16 +02:00
p_image ,
2011-09-19 15:36:07 +02:00
p_manager ) ;
}
2012-10-25 16:16:19 +02:00
void opj_jp2_setup_encoding_validation ( opj_jp2_t * jp2 )
2012-03-15 11:23:20 +01:00
{
/* preconditions */
assert ( jp2 ! = 00 ) ;
2012-08-10 12:55:10 +02:00
opj_procedure_list_add_procedure ( jp2 - > m_validation_list , ( opj_procedure ) opj_jp2_default_validation ) ;
2012-03-15 11:23:20 +01:00
/* DEVELOPER CORNER, add your custom validation procedure */
}
2012-10-25 16:16:19 +02:00
void opj_jp2_setup_decoding_validation ( opj_jp2_t * jp2 )
2011-09-19 15:36:07 +02:00
{
2012-03-02 16:53:14 +01:00
/* preconditions */
2011-09-19 15:36:07 +02:00
assert ( jp2 ! = 00 ) ;
/* DEVELOPER CORNER, add your custom validation procedure */
}
2012-10-25 16:16:19 +02:00
void opj_jp2_setup_header_writing ( opj_jp2_t * jp2 )
2012-03-15 11:23:20 +01:00
{
/* preconditions */
assert ( jp2 ! = 00 ) ;
2012-08-13 12:03:57 +02:00
opj_procedure_list_add_procedure ( jp2 - > m_procedure_list , ( opj_procedure ) opj_jp2_write_jp ) ;
2012-08-13 11:39:51 +02:00
opj_procedure_list_add_procedure ( jp2 - > m_procedure_list , ( opj_procedure ) opj_jp2_write_ftyp ) ;
2012-08-13 11:24:15 +02:00
opj_procedure_list_add_procedure ( jp2 - > m_procedure_list , ( opj_procedure ) opj_jp2_write_jp2h ) ;
2012-10-29 11:12:03 +01:00
if ( jp2 - > jpip_on )
opj_procedure_list_add_procedure ( jp2 - > m_procedure_list , ( opj_procedure ) opj_jpip_skip_iptr ) ;
2012-08-13 11:44:40 +02:00
opj_procedure_list_add_procedure ( jp2 - > m_procedure_list , ( opj_procedure ) opj_jp2_skip_jp2c ) ;
2012-03-15 11:23:20 +01:00
/* DEVELOPER CORNER, insert your custom procedures */
}
2012-10-25 16:16:19 +02:00
void opj_jp2_setup_header_reading ( opj_jp2_t * jp2 )
2011-09-19 15:36:07 +02:00
{
2012-03-02 16:53:14 +01:00
/* preconditions */
2011-09-19 15:36:07 +02:00
assert ( jp2 ! = 00 ) ;
2012-08-10 12:55:10 +02:00
opj_procedure_list_add_procedure ( jp2 - > m_procedure_list , ( opj_procedure ) opj_jp2_read_header_procedure ) ;
2011-09-19 15:36:07 +02:00
/* DEVELOPER CORNER, add your custom procedures */
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_read_tile_header ( opj_jp2_t * p_jp2 ,
2012-08-13 11:24:15 +02:00
OPJ_UINT32 * p_tile_index ,
OPJ_UINT32 * p_data_size ,
OPJ_INT32 * p_tile_x0 ,
OPJ_INT32 * p_tile_y0 ,
OPJ_INT32 * p_tile_x1 ,
OPJ_INT32 * p_tile_y1 ,
OPJ_UINT32 * p_nb_comps ,
2012-11-15 14:13:36 +01:00
OPJ_BOOL * p_go_on ,
2012-08-13 11:24:15 +02:00
opj_stream_private_t * p_stream ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager
2012-08-13 11:24:15 +02:00
)
2011-09-19 15:36:07 +02:00
{
2012-08-16 13:51:34 +02:00
return opj_j2k_read_tile_header ( p_jp2 - > j2k ,
2011-09-19 15:36:07 +02:00
p_tile_index ,
p_data_size ,
2011-09-19 18:05:43 +02:00
p_tile_x0 , p_tile_y0 ,
p_tile_x1 , p_tile_y1 ,
2011-09-19 15:36:07 +02:00
p_nb_comps ,
p_go_on ,
p_stream ,
p_manager ) ;
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_write_tile ( opj_jp2_t * p_jp2 ,
2012-08-13 11:24:15 +02:00
OPJ_UINT32 p_tile_index ,
OPJ_BYTE * p_data ,
OPJ_UINT32 p_data_size ,
opj_stream_private_t * p_stream ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager
2012-08-13 11:24:15 +02:00
)
2012-08-30 18:56:31 +02:00
2012-03-15 11:23:20 +01:00
{
2012-08-16 13:51:34 +02:00
return opj_j2k_write_tile ( p_jp2 - > j2k , p_tile_index , p_data , p_data_size , p_stream , p_manager ) ;
2012-03-15 11:23:20 +01:00
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_decode_tile ( opj_jp2_t * p_jp2 ,
2012-08-13 11:24:15 +02:00
OPJ_UINT32 p_tile_index ,
OPJ_BYTE * p_data ,
OPJ_UINT32 p_data_size ,
opj_stream_private_t * p_stream ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager
2012-08-13 11:24:15 +02:00
)
2011-09-19 15:36:07 +02:00
{
2012-08-16 13:51:34 +02:00
return opj_j2k_decode_tile ( p_jp2 - > j2k , p_tile_index , p_data , p_data_size , p_stream , p_manager ) ;
2011-09-19 15:36:07 +02:00
}
2012-10-25 16:16:19 +02:00
void opj_jp2_destroy ( opj_jp2_t * jp2 )
2011-09-19 15:36:07 +02:00
{
if ( jp2 ) {
/* destroy the J2K codec */
2012-08-16 13:51:34 +02:00
opj_j2k_destroy ( jp2 - > j2k ) ;
2011-09-19 15:36:07 +02:00
jp2 - > j2k = 00 ;
if ( jp2 - > comps ) {
opj_free ( jp2 - > comps ) ;
jp2 - > comps = 00 ;
}
if ( jp2 - > cl ) {
opj_free ( jp2 - > cl ) ;
jp2 - > cl = 00 ;
}
if ( jp2 - > color . icc_profile_buf ) {
opj_free ( jp2 - > color . icc_profile_buf ) ;
jp2 - > color . icc_profile_buf = 00 ;
}
if ( jp2 - > color . jp2_cdef ) {
2011-10-20 15:18:52 +02:00
if ( jp2 - > color . jp2_cdef - > info ) {
opj_free ( jp2 - > color . jp2_cdef - > info ) ;
jp2 - > color . jp2_cdef - > info = NULL ;
}
2011-09-19 15:36:07 +02:00
opj_free ( jp2 - > color . jp2_cdef ) ;
jp2 - > color . jp2_cdef = 00 ;
}
if ( jp2 - > color . jp2_pclr ) {
2011-10-20 15:18:52 +02:00
if ( jp2 - > color . jp2_pclr - > cmap ) {
opj_free ( jp2 - > color . jp2_pclr - > cmap ) ;
jp2 - > color . jp2_pclr - > cmap = NULL ;
}
if ( jp2 - > color . jp2_pclr - > channel_sign ) {
opj_free ( jp2 - > color . jp2_pclr - > channel_sign ) ;
jp2 - > color . jp2_pclr - > channel_sign = NULL ;
}
if ( jp2 - > color . jp2_pclr - > channel_size ) {
opj_free ( jp2 - > color . jp2_pclr - > channel_size ) ;
jp2 - > color . jp2_pclr - > channel_size = NULL ;
}
if ( jp2 - > color . jp2_pclr - > entries ) {
opj_free ( jp2 - > color . jp2_pclr - > entries ) ;
jp2 - > color . jp2_pclr - > entries = NULL ;
}
2011-09-19 15:36:07 +02:00
opj_free ( jp2 - > color . jp2_pclr ) ;
jp2 - > color . jp2_pclr = 00 ;
}
if ( jp2 - > m_validation_list ) {
opj_procedure_list_destroy ( jp2 - > m_validation_list ) ;
jp2 - > m_validation_list = 00 ;
}
if ( jp2 - > m_procedure_list ) {
opj_procedure_list_destroy ( jp2 - > m_procedure_list ) ;
jp2 - > m_procedure_list = 00 ;
}
opj_free ( jp2 ) ;
}
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_set_decode_area ( opj_jp2_t * p_jp2 ,
2012-08-13 11:24:15 +02:00
opj_image_t * p_image ,
OPJ_INT32 p_start_x , OPJ_INT32 p_start_y ,
OPJ_INT32 p_end_x , OPJ_INT32 p_end_y ,
2012-08-30 18:56:31 +02:00
opj_event_mgr_t * p_manager
2012-08-13 11:24:15 +02:00
)
2011-09-19 15:36:07 +02:00
{
2012-08-16 13:51:34 +02:00
return opj_j2k_set_decode_area ( p_jp2 - > j2k , p_image , p_start_x , p_start_y , p_end_x , p_end_y , p_manager ) ;
2011-09-19 15:36:07 +02:00
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_get_tile ( opj_jp2_t * p_jp2 ,
2012-08-13 11:24:15 +02:00
opj_stream_private_t * p_stream ,
opj_image_t * p_image ,
opj_event_mgr_t * p_manager ,
2012-08-30 18:56:31 +02:00
OPJ_UINT32 tile_index
2012-08-13 11:24:15 +02:00
)
2011-11-08 14:21:17 +01:00
{
if ( ! p_image )
return OPJ_FALSE ;
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_WARNING , " JP2 box which are after the codestream will not be read by this function. \n " ) ;
2011-11-08 14:21:17 +01:00
2012-08-16 13:51:34 +02:00
if ( ! opj_j2k_get_tile ( p_jp2 - > j2k , p_stream , p_image , p_manager , tile_index ) ) {
2012-10-25 15:49:20 +02:00
opj_event_msg ( p_manager , EVT_ERROR , " Failed to decode the codestream in the JP2 file \n " ) ;
2011-11-08 14:21:17 +01:00
return OPJ_FALSE ;
}
2014-02-26 12:05:31 +01:00
if ( ! opj_jp2_check_color ( p_image , & ( p_jp2 - > color ) , p_manager ) ) {
return OPJ_FALSE ;
}
2011-11-08 14:21:17 +01:00
/* Set Image Color Space */
2012-08-13 11:24:15 +02:00
if ( p_jp2 - > enumcs = = 16 )
2012-11-15 13:58:32 +01:00
p_image - > color_space = OPJ_CLRSPC_SRGB ;
2012-08-13 11:24:15 +02:00
else if ( p_jp2 - > enumcs = = 17 )
2012-11-15 13:58:32 +01:00
p_image - > color_space = OPJ_CLRSPC_GRAY ;
2012-08-13 11:24:15 +02:00
else if ( p_jp2 - > enumcs = = 18 )
2012-11-15 13:58:32 +01:00
p_image - > color_space = OPJ_CLRSPC_SYCC ;
2011-11-08 14:21:17 +01:00
else
2012-11-15 13:58:32 +01:00
p_image - > color_space = OPJ_CLRSPC_UNKNOWN ;
2011-11-08 14:21:17 +01:00
2012-08-13 11:24:15 +02:00
if ( p_jp2 - > color . jp2_pclr ) {
2011-11-08 14:21:17 +01:00
/* Part 1, I.5.3.4: Either both or none : */
2012-08-13 11:24:15 +02:00
if ( ! p_jp2 - > color . jp2_pclr - > cmap )
2012-08-13 12:10:25 +02:00
opj_jp2_free_pclr ( & ( p_jp2 - > color ) ) ;
2011-11-08 14:21:17 +01:00
else
2012-08-13 12:10:25 +02:00
opj_jp2_apply_pclr ( p_image , & ( p_jp2 - > color ) ) ;
2011-11-08 14:21:17 +01:00
}
2014-11-17 22:46:43 +01:00
/* Apply the color space if needed */
if ( p_jp2 - > color . jp2_cdef ) {
opj_jp2_apply_cdef ( p_image , & ( p_jp2 - > color ) ) ;
}
2011-11-08 14:21:17 +01:00
2012-08-13 11:24:15 +02:00
if ( p_jp2 - > color . icc_profile_buf ) {
p_image - > icc_profile_buf = p_jp2 - > color . icc_profile_buf ;
p_image - > icc_profile_len = p_jp2 - > color . icc_profile_len ;
p_jp2 - > color . icc_profile_buf = NULL ;
2011-11-08 14:21:17 +01:00
}
return OPJ_TRUE ;
}
2011-09-19 15:36:07 +02:00
/* ----------------------------------------------------------------------- */
/* JP2 encoder interface */
/* ----------------------------------------------------------------------- */
2012-11-15 14:13:36 +01:00
opj_jp2_t * opj_jp2_create ( OPJ_BOOL p_is_decoder )
2011-09-19 15:36:07 +02:00
{
2014-09-16 17:48:04 +02:00
opj_jp2_t * jp2 = ( opj_jp2_t * ) opj_calloc ( 1 , sizeof ( opj_jp2_t ) ) ;
2011-09-19 15:36:07 +02:00
if ( jp2 ) {
/* create the J2K codec */
if ( ! p_is_decoder ) {
2012-08-16 15:46:43 +02:00
jp2 - > j2k = opj_j2k_create_compress ( ) ;
2011-09-19 15:36:07 +02:00
}
else {
2012-08-09 17:00:50 +02:00
jp2 - > j2k = opj_j2k_create_decompress ( ) ;
2011-09-19 15:36:07 +02:00
}
if ( jp2 - > j2k = = 00 ) {
2012-08-13 11:24:15 +02:00
opj_jp2_destroy ( jp2 ) ;
2011-09-19 15:36:07 +02:00
return 00 ;
}
2011-10-11 12:09:02 +02:00
/* Color structure */
jp2 - > color . icc_profile_buf = NULL ;
jp2 - > color . icc_profile_len = 0 ;
jp2 - > color . jp2_cdef = NULL ;
jp2 - > color . jp2_pclr = NULL ;
jp2 - > color . jp2_has_colr = 0 ;
2012-03-02 16:53:14 +01:00
/* validation list creation */
2011-09-19 15:36:07 +02:00
jp2 - > m_validation_list = opj_procedure_list_create ( ) ;
if ( ! jp2 - > m_validation_list ) {
2012-08-13 11:24:15 +02:00
opj_jp2_destroy ( jp2 ) ;
2011-09-19 15:36:07 +02:00
return 00 ;
}
2012-03-02 16:53:14 +01:00
/* execution list creation */
2011-09-19 15:36:07 +02:00
jp2 - > m_procedure_list = opj_procedure_list_create ( ) ;
if ( ! jp2 - > m_procedure_list ) {
2012-08-13 11:24:15 +02:00
opj_jp2_destroy ( jp2 ) ;
2011-09-19 15:36:07 +02:00
return 00 ;
}
}
return jp2 ;
}
2011-10-07 19:31:35 +02:00
2012-10-25 16:16:19 +02:00
void jp2_dump ( opj_jp2_t * p_jp2 , OPJ_INT32 flag , FILE * out_stream )
2011-10-07 19:31:35 +02:00
{
/* preconditions */
assert ( p_jp2 ! = 00 ) ;
j2k_dump ( p_jp2 - > j2k ,
flag ,
out_stream ) ;
}
2012-10-25 16:16:19 +02:00
opj_codestream_index_t * jp2_get_cstr_index ( opj_jp2_t * p_jp2 )
2011-10-07 19:31:35 +02:00
{
return j2k_get_cstr_index ( p_jp2 - > j2k ) ;
}
2012-10-25 16:16:19 +02:00
opj_codestream_info_v2_t * jp2_get_cstr_info ( opj_jp2_t * p_jp2 )
2011-10-07 19:31:35 +02:00
{
return j2k_get_cstr_info ( p_jp2 - > j2k ) ;
}
2012-11-15 14:13:36 +01:00
OPJ_BOOL opj_jp2_set_decoded_resolution_factor ( opj_jp2_t * p_jp2 ,
2012-08-30 18:56:31 +02:00
OPJ_UINT32 res_factor ,
2012-08-13 11:24:15 +02:00
opj_event_mgr_t * p_manager )
2011-11-17 15:21:11 +01:00
{
2012-08-16 13:51:34 +02:00
return opj_j2k_set_decoded_resolution_factor ( p_jp2 - > j2k , res_factor , p_manager ) ;
2011-11-17 15:21:11 +01:00
}
2012-10-29 11:12:03 +01:00
/* JPIP specific */
2012-10-29 14:27:39 +01:00
# ifdef USE_JPIP
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jpip_write_iptr ( opj_jp2_t * jp2 ,
2012-10-29 11:12:03 +01:00
opj_stream_private_t * cio ,
opj_event_mgr_t * p_manager )
{
OPJ_OFF_T j2k_codestream_exit ;
OPJ_BYTE l_data_header [ 24 ] ;
/* preconditions */
assert ( jp2 ! = 00 ) ;
assert ( cio ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
assert ( opj_stream_has_seek ( cio ) ) ;
j2k_codestream_exit = opj_stream_tell ( cio ) ;
opj_write_bytes ( l_data_header , 24 , 4 ) ; /* size of iptr */
opj_write_bytes ( l_data_header + 4 , JPIP_IPTR , 4 ) ; /* IPTR */
#if 0
opj_write_bytes ( l_data_header + 4 + 4 , 0 , 8 ) ; /* offset */
opj_write_bytes ( l_data_header + 8 + 8 , 0 , 8 ) ; /* length */
# else
opj_write_double ( l_data_header + 4 + 4 , 0 ) ; /* offset */
opj_write_double ( l_data_header + 8 + 8 , 0 ) ; /* length */
# endif
if ( ! opj_stream_seek ( cio , jp2 - > jpip_iptr_offset , p_manager ) ) {
opj_event_msg ( p_manager , EVT_ERROR , " Failed to seek in the stream. \n " ) ;
return OPJ_FALSE ;
}
if ( opj_stream_write_data ( cio , l_data_header , 24 , p_manager ) ! = 24 ) {
opj_event_msg ( p_manager , EVT_ERROR , " Failed to seek in the stream. \n " ) ;
return OPJ_FALSE ;
}
if ( ! opj_stream_seek ( cio , j2k_codestream_exit , p_manager ) ) {
opj_event_msg ( p_manager , EVT_ERROR , " Failed to seek in the stream. \n " ) ;
return OPJ_FALSE ;
}
return OPJ_TRUE ;
}
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jpip_write_fidx ( opj_jp2_t * jp2 ,
2012-10-29 11:12:03 +01:00
opj_stream_private_t * cio ,
opj_event_mgr_t * p_manager )
{
OPJ_OFF_T j2k_codestream_exit ;
OPJ_BYTE l_data_header [ 24 ] ;
/* preconditions */
assert ( jp2 ! = 00 ) ;
assert ( cio ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
assert ( opj_stream_has_seek ( cio ) ) ;
opj_write_bytes ( l_data_header , 24 , 4 ) ; /* size of iptr */
opj_write_bytes ( l_data_header + 4 , JPIP_FIDX , 4 ) ; /* IPTR */
opj_write_double ( l_data_header + 4 + 4 , 0 ) ; /* offset */
opj_write_double ( l_data_header + 8 + 8 , 0 ) ; /* length */
if ( opj_stream_write_data ( cio , l_data_header , 24 , p_manager ) ! = 24 ) {
opj_event_msg ( p_manager , EVT_ERROR , " Failed to seek in the stream. \n " ) ;
return OPJ_FALSE ;
}
j2k_codestream_exit = opj_stream_tell ( cio ) ;
if ( ! opj_stream_seek ( cio , j2k_codestream_exit , p_manager ) ) {
opj_event_msg ( p_manager , EVT_ERROR , " Failed to seek in the stream. \n " ) ;
return OPJ_FALSE ;
}
return OPJ_TRUE ;
}
2012-11-15 14:13:36 +01:00
static OPJ_BOOL opj_jpip_write_cidx ( opj_jp2_t * jp2 ,
2012-10-29 11:12:03 +01:00
opj_stream_private_t * cio ,
opj_event_mgr_t * p_manager )
{
OPJ_OFF_T j2k_codestream_exit ;
OPJ_BYTE l_data_header [ 24 ] ;
/* preconditions */
assert ( jp2 ! = 00 ) ;
assert ( cio ! = 00 ) ;
assert ( p_manager ! = 00 ) ;
assert ( opj_stream_has_seek ( cio ) ) ;
j2k_codestream_exit = opj_stream_tell ( cio ) ;
opj_write_bytes ( l_data_header , 24 , 4 ) ; /* size of iptr */
opj_write_bytes ( l_data_header + 4 , JPIP_CIDX , 4 ) ; /* IPTR */
#if 0
opj_write_bytes ( l_data_header + 4 + 4 , 0 , 8 ) ; /* offset */
opj_write_bytes ( l_data_header + 8 + 8 , 0 , 8 ) ; /* length */
# else
opj_write_double ( l_data_header + 4 + 4 , 0 ) ; /* offset */
opj_write_double ( l_data_header + 8 + 8 , 0 ) ; /* length */
# endif
if ( ! opj_stream_seek ( cio , j2k_codestream_exit , p_manager ) ) {
opj_event_msg ( p_manager , EVT_ERROR , " Failed to seek in the stream. \n " ) ;
return OPJ_FALSE ;
}
if ( opj_stream_write_data ( cio , l_data_header , 24 , p_manager ) ! = 24 ) {
opj_event_msg ( p_manager , EVT_ERROR , " Failed to seek in the stream. \n " ) ;
return OPJ_FALSE ;
}
j2k_codestream_exit = opj_stream_tell ( cio ) ;
if ( ! opj_stream_seek ( cio , j2k_codestream_exit , p_manager ) ) {
opj_event_msg ( p_manager , EVT_ERROR , " Failed to seek in the stream. \n " ) ;
return OPJ_FALSE ;
}
return OPJ_TRUE ;
}
2014-03-03 09:30:36 +01:00
#if 0
2012-10-29 14:27:39 +01:00
static void write_prxy ( int offset_jp2c , int length_jp2c , int offset_idx , int length_idx , opj_stream_private_t * cio ,
2012-10-29 11:12:03 +01:00
opj_event_mgr_t * p_manager )
{
OPJ_BYTE l_data_header [ 8 ] ;
2012-10-29 17:07:09 +01:00
OPJ_OFF_T len , lenp ;
2012-10-29 11:12:03 +01:00
lenp = opj_stream_tell ( cio ) ;
opj_stream_skip ( cio , 4 , p_manager ) ; /* L [at the end] */
opj_write_bytes ( l_data_header , JPIP_PRXY , 4 ) ; /* IPTR */
opj_stream_write_data ( cio , l_data_header , 4 , p_manager ) ;
opj_write_bytes ( l_data_header , offset_jp2c , 8 ) ; /* OOFF */
opj_stream_write_data ( cio , l_data_header , 8 , p_manager ) ;
opj_write_bytes ( l_data_header , length_jp2c , 4 ) ; /* OBH part 1 */
opj_write_bytes ( l_data_header + 4 , JP2_JP2C , 4 ) ; /* OBH part 2 */
opj_stream_write_data ( cio , l_data_header , 8 , p_manager ) ;
opj_write_bytes ( l_data_header , 1 , 1 ) ; /* NI */
opj_stream_write_data ( cio , l_data_header , 1 , p_manager ) ;
opj_write_bytes ( l_data_header , offset_idx , 8 ) ; /* IOFF */
opj_stream_write_data ( cio , l_data_header , 8 , p_manager ) ;
opj_write_bytes ( l_data_header , length_idx , 4 ) ; /* IBH part 1 */
opj_write_bytes ( l_data_header + 4 , JPIP_CIDX , 4 ) ; /* IBH part 2 */
opj_stream_write_data ( cio , l_data_header , 8 , p_manager ) ;
len = opj_stream_tell ( cio ) - lenp ;
opj_stream_skip ( cio , lenp , p_manager ) ;
opj_write_bytes ( l_data_header , len , 4 ) ; /* L */
opj_stream_write_data ( cio , l_data_header , 4 , p_manager ) ;
opj_stream_seek ( cio , lenp + len , p_manager ) ;
}
2014-03-03 09:30:36 +01:00
# endif
2012-10-29 11:12:03 +01:00
2014-03-03 09:30:36 +01:00
#if 0
2012-10-29 14:27:39 +01:00
static int write_fidx ( int offset_jp2c , int length_jp2c , int offset_idx , int length_idx , opj_stream_private_t * cio ,
2012-10-29 11:12:03 +01:00
opj_event_mgr_t * p_manager )
{
OPJ_BYTE l_data_header [ 4 ] ;
2012-10-29 17:07:09 +01:00
OPJ_OFF_T len , lenp ;
2012-10-29 11:12:03 +01:00
lenp = opj_stream_tell ( cio ) ;
opj_stream_skip ( cio , 4 , p_manager ) ;
opj_write_bytes ( l_data_header , JPIP_FIDX , 4 ) ; /* FIDX */
opj_stream_write_data ( cio , l_data_header , 4 , p_manager ) ;
2012-10-29 14:27:39 +01:00
write_prxy ( offset_jp2c , length_jp2c , offset_idx , length_idx , cio , p_manager ) ;
2012-10-29 11:12:03 +01:00
len = opj_stream_tell ( cio ) - lenp ;
opj_stream_skip ( cio , lenp , p_manager ) ;
opj_write_bytes ( l_data_header , len , 4 ) ; /* L */
opj_stream_write_data ( cio , l_data_header , 4 , p_manager ) ;
opj_stream_seek ( cio , lenp + len , p_manager ) ;
return len ;
}
2014-03-03 09:30:36 +01:00
# endif
2012-10-29 14:27:39 +01:00
# endif /* USE_JPIP */