Work In Progress: insert elements from V2 framework into the trunk

This commit is contained in:
Mickael Savinaud 2011-09-19 13:04:04 +00:00
parent 93f3e2b007
commit b551844cc2
30 changed files with 8815 additions and 231 deletions

View File

@ -5,6 +5,9 @@ What's New for OpenJPEG
! : changed ! : changed
+ : added + : added
September 19, 2011
+ [mickael] Work In Progress: insert elements from V2 framework into the trunk.
September 9, 2011 September 9, 2011
+ [antonin] added a new indexer functionality to the library. With the new '-jpip' option at encoding, the user can now generate a JP2 file including an XML box with the index used when browsing the image with JPIP. + [antonin] added a new indexer functionality to the library. With the new '-jpip' option at encoding, the user can now generate a JP2 file including an XML box with the index used when browsing the image with JPIP.

View File

@ -93,9 +93,9 @@ void decode_help_display(void) {
fprintf(stdout," Currently accepts J2K-files, JP2-files and JPT-files. The file type\n"); fprintf(stdout," Currently accepts J2K-files, JP2-files and JPT-files. The file type\n");
fprintf(stdout," is identified based on its suffix.\n"); fprintf(stdout," is identified based on its suffix.\n");
fprintf(stdout," -o <output file>\n"); fprintf(stdout," -o <output file>\n");
fprintf(stdout," OPTIONAL\n"); fprintf(stdout," OPTIONAL\n");
fprintf(stdout," Output file where file info will be dump.\n"); fprintf(stdout," Output file where file info will be dump.\n");
fprintf(stdout," By default it will be in the stdout.\n"); fprintf(stdout," By default it will be in the stdout.\n");
fprintf(stdout,"\n"); fprintf(stdout,"\n");
} }
@ -317,26 +317,30 @@ void info_callback(const char *msg, void *client_data) {
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int ret;
opj_dparameters_t parameters; /* decompression parameters */ opj_dparameters_t parameters; /* decompression parameters */
img_fol_t img_fol; img_fol_t img_fol;
opj_event_mgr_t event_mgr; /* event manager */ opj_event_mgr_t event_mgr; /* event manager */
opj_image_t *image = NULL; opj_image_t *image = NULL;
FILE *fsrc = NULL, *fout = NULL; FILE *fsrc = NULL, *fout = NULL;
unsigned char *src = NULL; opj_bool bResult;
int file_length;
int num_images; int num_images;
int i,imageno; int i,imageno;
dircnt_t *dirptr = NULL; dircnt_t *dirptr = NULL;
opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ opj_codec_t* dinfo = NULL; /* handle to a decompressor */
opj_cio_t *cio = NULL; opj_stream_t *cio = NULL;
opj_codestream_info_t cstr_info; /* Codestream information structure */ opj_codestream_info_t cstr_info; /* Codestream information structure */
char indexfilename[OPJ_PATH_LEN]; /* index file name */ char indexfilename[OPJ_PATH_LEN]; /* index file name */
OPJ_INT32 l_tile_x0,l_tile_y0;
OPJ_UINT32 l_tile_width,l_tile_height,l_nb_tiles_x,l_nb_tiles_y;
/* configure the event callbacks (not required) */
/* FIXME configure the event callbacks (not required) */
memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
event_mgr.error_handler = error_callback; event_mgr.error_handler = error_callback;
event_mgr.warning_handler = warning_callback; event_mgr.warning_handler = warning_callback;
event_mgr.info_handler = info_callback; event_mgr.info_handler = info_callback;
event_mgr.client_data = stderr;
/* set decoding parameters to default values */ /* set decoding parameters to default values */
opj_set_default_decoder_parameters(&parameters); opj_set_default_decoder_parameters(&parameters);
@ -347,7 +351,7 @@ int main(int argc, char *argv[])
/* parse input and get user encoding parameters */ /* parse input and get user encoding parameters */
if(parse_cmdline_decoder(argc, argv, &parameters,&img_fol, indexfilename) == 1) { if(parse_cmdline_decoder(argc, argv, &parameters,&img_fol, indexfilename) == 1) {
return 1; return EXIT_FAILURE;
} }
/* Initialize reading of directory */ /* Initialize reading of directory */
@ -360,39 +364,36 @@ int main(int argc, char *argv[])
dirptr->filename = (char**) malloc(num_images*sizeof(char*)); dirptr->filename = (char**) malloc(num_images*sizeof(char*));
if(!dirptr->filename_buf){ if(!dirptr->filename_buf){
return 1; return EXIT_FAILURE;
} }
for(i=0;i<num_images;i++){ for(i=0;i<num_images;i++){
dirptr->filename[i] = dirptr->filename_buf + i*OPJ_PATH_LEN; dirptr->filename[i] = dirptr->filename_buf + i*OPJ_PATH_LEN;
} }
} }
if(load_images(dirptr,img_fol.imgdirpath)==1){ if(load_images(dirptr,img_fol.imgdirpath)==1){
return 1; return EXIT_FAILURE;
} }
if (num_images==0){ if (num_images==0){
fprintf(stdout,"Folder is empty\n"); fprintf(stdout,"Folder is empty\n");
return 1; return EXIT_FAILURE;
} }
}else{ }else{
num_images=1; num_images=1;
} }
// //
if (parameters.outfile[0] != 0) if (parameters.outfile[0] != 0){
{ fout = fopen(parameters.outfile,"w");
fout = fopen(parameters.outfile,"w"); if (!fout){
if (!fout) fprintf(stderr, "ERROR -> failed to open %s for reading\n", parameters.outfile);
{ return EXIT_FAILURE;
fprintf(stderr, "ERROR -> failed to open %s for reading\n", parameters.outfile); }
return 1; }
}
}
else else
fout = stdout; fout = stdout;
/*Encoding image one by one*/ /*Encoding image one by one*/
for(imageno = 0; imageno < num_images ; imageno++) for(imageno = 0; imageno < num_images ; imageno++){
{
image = NULL; image = NULL;
fprintf(stderr,"\n"); fprintf(stderr,"\n");
@ -403,182 +404,118 @@ int main(int argc, char *argv[])
} }
} }
/*NEW V2 STYLE*/
/* read the input file and put it in memory */ /* read the input file and put it in memory */
/* ---------------------------------------- */ /* ---------------------------------------- */
fsrc = fopen(parameters.infile, "rb"); fsrc = fopen(parameters.infile, "rb");
if (!fsrc) { if (!fsrc) {
fprintf(stderr, "ERROR -> failed to open %s for reading\n", parameters.infile); fprintf(stderr, "ERROR -> failed to open %s for reading\n", parameters.infile);
return 1; return EXIT_FAILURE;
} }
fseek(fsrc, 0, SEEK_END);
file_length = ftell(fsrc);
fseek(fsrc, 0, SEEK_SET); cio = opj_stream_create_default_file_stream(fsrc,1);
src = (unsigned char *) malloc(file_length);
if (fread(src, 1, file_length, fsrc) != (size_t)file_length)
{
free(src);
fclose(fsrc);
fprintf(stderr, "\nERROR: fread return a number of element different from the expected.\n");
return 1;
}
fclose(fsrc);
/* decode the code-stream */ /* decode the code-stream */
/* ---------------------- */ /* ---------------------- */
switch(parameters.decod_format) { switch(parameters.decod_format) {
case J2K_CFMT: case J2K_CFMT:
{ { /* JPEG-2000 codestream */
/* JPEG-2000 codestream */
/* get a decoder handle */ /* get a decoder handle */
dinfo = opj_create_decompress(CODEC_J2K); dinfo = opj_create_decompress_v2(CODEC_J2K);
break;
}
case JP2_CFMT:
{ /* JPEG 2000 compressed image data */
/* catch events using our callbacks and give a local context */ /* get a decoder handle */
opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); dinfo = opj_create_decompress_v2(CODEC_JP2);
break;
}
case JPT_CFMT:
{ /* JPEG 2000, JPIP */
/* setup the decoder decoding parameters using user parameters */ /* get a decoder handle */
opj_setup_decoder(dinfo, &parameters); dinfo = opj_create_decompress_v2(CODEC_JPT);
break;
}
default:
fprintf(stderr, "skipping file..\n");
opj_stream_destroy(cio);
continue;
}
/* open a byte stream */ /* FIXME catch events using our callbacks and give a local context */
cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); //opj_set_event_mgr_v2(dinfo, &event_mgr, stderr);
/* decode the stream and fill the image structure */
if (*indexfilename) // If need to extract codestream information
/* setup the decoder decoding parameters using user parameters */
opj_setup_decoder_v2(dinfo, &parameters, &event_mgr);
/* decode the stream and fill the image structure */
/* if (*indexfilename) // If need to extract codestream information
image = opj_decode_with_info(dinfo, cio, &cstr_info); image = opj_decode_with_info(dinfo, cio, &cstr_info);
else else
image = opj_decode(dinfo, cio); */
if(!image) { bResult = opj_read_header( dinfo,
fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); &image,
opj_destroy_decompress(dinfo); &l_tile_x0,
opj_cio_close(cio); &l_tile_y0,
return 1; &l_tile_width,
} &l_tile_height,
&l_nb_tiles_x,
&l_nb_tiles_y,
cio);
if(!bResult){
fprintf(stderr, "ERROR -> j2k_to_image: failed to read header\n");
return EXIT_FAILURE;
}
if (parameters.decod_format == J2K_CFMT){
/* dump image */ /* dump image */
j2k_dump_image(fout, image); j2k_dump_image(fout, image);
/* dump cp */ /* dump cp */
j2k_dump_cp(fout, image, ((opj_j2k_t*)dinfo->j2k_handle)->cp); //j2k_dump_cp(stdout, image, dinfo->m_codec);
//j2k_dump_cp(fout, image, ((opj_j2k_t*)dinfo->j2k_handle)->cp);
/* close the byte stream */
opj_cio_close(cio);
/* Write the index to disk */
if (*indexfilename) {
opj_bool bSuccess;
bSuccess = write_index_file(&cstr_info, indexfilename);
if (bSuccess) {
fprintf(stderr, "Failed to output index file\n");
}
}
} }
break; else if (parameters.decod_format == JP2_CFMT){
case JP2_CFMT:
{
/* JPEG 2000 compressed image data */
/* get a decoder handle */
dinfo = opj_create_decompress(CODEC_JP2);
/* catch events using our callbacks and give a local context */
opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
/* setup the decoder decoding parameters using the current image and user parameters */
opj_setup_decoder(dinfo, &parameters);
/* open a byte stream */
cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
/* decode the stream and fill the image structure */
if (*indexfilename) // If need to extract codestream information
image = opj_decode_with_info(dinfo, cio, &cstr_info);
else
image = opj_decode(dinfo, cio);
if(!image) {
fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n");
opj_destroy_decompress(dinfo);
opj_cio_close(cio);
return 1;
}
/* dump image */ /* dump image */
if(image->icc_profile_buf) if(image->icc_profile_buf){
{ free(image->icc_profile_buf);
free(image->icc_profile_buf); image->icc_profile_buf = NULL; image->icc_profile_buf = NULL;
} }
j2k_dump_image(fout, image); j2k_dump_image(fout, image);
/* dump cp */ /* dump cp */
j2k_dump_cp(fout, image, ((opj_jp2_t*)dinfo->jp2_handle)->j2k->cp); //j2k_dump_cp(stdout, image, dinfo->m_codec);
//j2k_dump_cp(fout, image, ((opj_jp2_t*)dinfo->jp2_handle)->j2k->cp);
/* close the byte stream */
opj_cio_close(cio);
/* Write the index to disk */
if (*indexfilename) {
opj_bool bSuccess;
bSuccess = write_index_file(&cstr_info, indexfilename);
if (bSuccess) {
fprintf(stderr, "Failed to output index file\n");
}
}
} }
break;
case JPT_CFMT: /* close the byte stream */
{ opj_stream_destroy(cio);
/* JPEG 2000, JPIP */ fclose(fsrc);
/* get a decoder handle */ /* Write the index to disk */
dinfo = opj_create_decompress(CODEC_JPT); if (*indexfilename) {
char bSuccess;
/* catch events using our callbacks and give a local context */ bSuccess = write_index_file(&cstr_info, indexfilename);
opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); if (bSuccess) {
fprintf(stderr, "Failed to output index file\n");
/* setup the decoder decoding parameters using user parameters */ ret = EXIT_FAILURE;
opj_setup_decoder(dinfo, &parameters); }
/* open a byte stream */
cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
/* decode the stream and fill the image structure */
if (*indexfilename) // If need to extract codestream information
image = opj_decode_with_info(dinfo, cio, &cstr_info);
else else
image = opj_decode(dinfo, cio); ret = EXIT_SUCCESS;
if(!image) {
fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n");
opj_destroy_decompress(dinfo);
opj_cio_close(cio);
return 1;
}
/* close the byte stream */
opj_cio_close(cio);
/* Write the index to disk */
if (*indexfilename) {
opj_bool bSuccess;
bSuccess = write_index_file(&cstr_info, indexfilename);
if (bSuccess) {
fprintf(stderr, "Failed to output index file\n");
}
}
} }
break; else
ret = EXIT_SUCCESS;
default:
fprintf(stderr, "skipping file..\n");
continue;
}
/* free the memory containing the code-stream */
free(src);
src = NULL;
/* free remaining structures */ /* free remaining structures */
if(dinfo) { if (dinfo) {
opj_destroy_decompress(dinfo); opj_destroy_codec(dinfo);
} }
/* free codestream information structure */ /* free codestream information structure */
if (*indexfilename) if (*indexfilename)
@ -587,10 +524,11 @@ int main(int argc, char *argv[])
opj_image_destroy(image); opj_image_destroy(image);
} }
/*NEW V2 STYLE*/
fclose(fout); fclose(fout);
return EXIT_SUCCESS; return ret;
} }
@ -662,9 +600,9 @@ static void j2k_dump_cp(FILE *fd, opj_image_t * img, opj_cp_t * cp) {
fprintf(fd, "\n"); fprintf(fd, "\n");
} }
fprintf(fd, " }\n"); fprintf(fd, " }\n");
} } /*end of component*/
fprintf(fd, " }\n"); fprintf(fd, " }\n");
} } /*end of tile */
fprintf(fd, "}\n"); fprintf(fd, "}\n");
} }

View File

@ -24,6 +24,7 @@ SET(OPENJPEG_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/ppix_manager.c ${CMAKE_CURRENT_SOURCE_DIR}/ppix_manager.c
${CMAKE_CURRENT_SOURCE_DIR}/thix_manager.c ${CMAKE_CURRENT_SOURCE_DIR}/thix_manager.c
${CMAKE_CURRENT_SOURCE_DIR}/tpix_manager.c ${CMAKE_CURRENT_SOURCE_DIR}/tpix_manager.c
${CMAKE_CURRENT_SOURCE_DIR}/function_list.c
) )
# Build the library # Build the library

View File

@ -188,4 +188,790 @@ void cio_skip(opj_cio_t *cio, int n) {
} }
/* ----------------------------------------------------------------------- */
/**
* Write some bytes to the given data buffer, this function is used in Big Endian cpus.
* @param p_buffer pointer the data buffer to write data to.
* @param p_value the value to write
* @param p_nb_bytes the number of bytes to write
*/
void opj_write_bytes_BE (OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, OPJ_UINT32 p_nb_bytes)
{
const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + p_nb_bytes;
assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32));
memcpy(p_buffer,l_data_ptr,p_nb_bytes);
}
/**
* Write some bytes to the given data buffer, this function is used in Little Endian cpus.
* @param p_buffer pointer the data buffer to write data to.
* @param p_value the value to write
* @param p_nb_bytes the number of bytes to write
* @return the number of bytes written or -1 if an error occured
*/
void opj_write_bytes_LE (OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, OPJ_UINT32 p_nb_bytes)
{
const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + p_nb_bytes - 1;
OPJ_UINT32 i;
assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32));
for (i=0;i<p_nb_bytes;++i) {
*(p_buffer++) = *(l_data_ptr--);
}
}
/**
* Reads some bytes from the given data buffer, this function is used in Big Endian cpus.
* @param p_buffer pointer the data buffer to read data from.
* @param p_value pointer to the value that will store the data.
* @param p_nb_bytes the nb bytes to read.
* @return the number of bytes read or -1 if an error occured.
*/
void opj_read_bytes_BE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, OPJ_UINT32 p_nb_bytes)
{
OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value);
assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32));
*p_value = 0;
memcpy(l_data_ptr+4-p_nb_bytes,p_buffer,p_nb_bytes);
}
/**
* Reads some bytes from the given data buffer, this function is used in Little Endian cpus.
* @param p_buffer pointer the data buffer to read data from.
* @param p_value pointer to the value that will store the data.
* @param p_nb_bytes the nb bytes to read.
* @return the number of bytes read or -1 if an error occured.
*/
void opj_read_bytes_LE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, OPJ_UINT32 p_nb_bytes)
{
OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + p_nb_bytes-1;
OPJ_UINT32 i;
assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32));
*p_value = 0;
for (i=0;i<p_nb_bytes;++i) {
*(l_data_ptr--) = *(p_buffer++);
}
}
/**
* Write some bytes to the given data buffer, this function is used in Big Endian cpus.
* @param p_buffer pointer the data buffer to write data to.
* @param p_value the value to write
* @return the number of bytes written or -1 if an error occured
*/
void opj_write_double_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value)
{
const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value);
memcpy(p_buffer,l_data_ptr,sizeof(OPJ_FLOAT64));
}
/**
* Write some bytes to the given data buffer, this function is used in Little Endian cpus.
* @param p_buffer pointer the data buffer to write data to.
* @param p_value the value to write
*/
void opj_write_double_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value)
{
const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + sizeof(OPJ_FLOAT64) - 1;
OPJ_UINT32 i;
for (i=0;i<sizeof(OPJ_FLOAT64);++i) {
*(p_buffer++) = *(l_data_ptr--);
}
}
/**
* Reads some bytes from the given data buffer, this function is used in Big Endian cpus.
* @param p_buffer pointer the data buffer to read data from.
* @param p_value pointer to the value that will store the data.
*/
void opj_read_double_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value)
{
OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value);
memcpy(l_data_ptr,p_buffer,sizeof(OPJ_FLOAT64));
}
/**
* Reads some bytes from the given data buffer, this function is used in Little Endian cpus.
* @param p_buffer pointer the data buffer to read data from.
* @param p_value pointer to the value that will store the data.
*/
void opj_read_double_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value)
{
OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + sizeof(OPJ_FLOAT64)-1;
OPJ_UINT32 i;
for (i=0;i<sizeof(OPJ_FLOAT64);++i) {
*(l_data_ptr--) = *(p_buffer++);
}
}
/**
* Write some bytes to the given data buffer, this function is used in Big Endian cpus.
* @param p_buffer pointer the data buffer to write data to.
* @param p_value the value to write
* @return the number of bytes written or -1 if an error occured
*/
void opj_write_float_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value)
{
const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value);
memcpy(p_buffer,l_data_ptr,sizeof(OPJ_FLOAT32));
}
/**
* Write some bytes to the given data buffer, this function is used in Little Endian cpus.
* @param p_buffer pointer the data buffer to write data to.
* @param p_value the value to write
*/
void opj_write_float_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value)
{
const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + sizeof(OPJ_FLOAT32) - 1;
OPJ_UINT32 i;
for (i=0;i<sizeof(OPJ_FLOAT32);++i) {
*(p_buffer++) = *(l_data_ptr--);
}
}
/**
* Reads some bytes from the given data buffer, this function is used in Big Endian cpus.
* @param p_buffer pointer the data buffer to read data from.
* @param p_value pointer to the value that will store the data.
*/
void opj_read_float_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value)
{
OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value);
memcpy(l_data_ptr,p_buffer,sizeof(OPJ_FLOAT32));
}
/**
* Reads some bytes from the given data buffer, this function is used in Little Endian cpus.
* @param p_buffer pointer the data buffer to read data from.
* @param p_value pointer to the value that will store the data.
*/
void opj_read_float_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value)
{
OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + sizeof(OPJ_FLOAT32)-1;
OPJ_UINT32 i;
for (i=0;i<sizeof(OPJ_FLOAT32);++i) {
*(l_data_ptr--) = *(p_buffer++);
}
}
/**
* Creates an abstract stream. This function does nothing except allocating memory and initializing the abstract stream.
* @return a stream object.
*/
opj_stream_t* OPJ_CALLCONV opj_stream_create(OPJ_UINT32 p_size,opj_bool l_is_input)
{
opj_stream_private_t * l_stream = 00;
l_stream = (opj_stream_private_t*) opj_malloc(sizeof(opj_stream_private_t));
if (! l_stream) {
return 00;
}
memset(l_stream,0,sizeof(opj_stream_private_t));
l_stream->m_buffer_size = p_size;
l_stream->m_stored_data = (OPJ_BYTE *) opj_malloc(p_size);
if (! l_stream->m_stored_data) {
opj_free(l_stream);
return 00;
}
l_stream->m_current_data = l_stream->m_stored_data;
if (l_is_input) {
l_stream->m_status |= opj_stream_e_input;
l_stream->m_opj_skip = opj_stream_read_skip;
l_stream->m_opj_seek = opj_stream_read_seek;
}
else {
l_stream->m_status |= opj_stream_e_output;
l_stream->m_opj_skip = opj_stream_write_skip;
l_stream->m_opj_seek = opj_stream_write_seek;
}
l_stream->m_read_fn = opj_stream_default_read;
l_stream->m_write_fn = opj_stream_default_write;
l_stream->m_skip_fn = opj_stream_default_skip;
l_stream->m_seek_fn = opj_stream_default_seek;
return (opj_stream_t *) l_stream;
}
/**
* Creates an abstract stream. This function does nothing except allocating memory and initializing the abstract stream.
* @return a stream object.
*/
opj_stream_t* OPJ_CALLCONV opj_stream_default_create(opj_bool l_is_input)
{
return opj_stream_create(J2K_STREAM_CHUNK_SIZE,l_is_input);
}
/**
* Destroys a stream created by opj_create_stream. This function does NOT close the abstract stream. If needed the user must
* close its own implementation of the stream.
*/
OPJ_API void OPJ_CALLCONV opj_stream_destroy(opj_stream_t* p_stream)
{
opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
if (l_stream) {
opj_free(l_stream->m_stored_data);
l_stream->m_stored_data = 00;
opj_free(l_stream);
}
}
/**
* Sets the given function to be used as a read function.
* @param p_stream the stream to modify
* @param p_function the function to use a read function.
*/
OPJ_API void OPJ_CALLCONV opj_stream_set_read_function(opj_stream_t* p_stream, opj_stream_read_fn p_function)
{
opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
if
((!l_stream) || (! (l_stream->m_status & opj_stream_e_input)))
{
return;
}
l_stream->m_read_fn = p_function;
}
OPJ_API void OPJ_CALLCONV opj_stream_set_seek_function(opj_stream_t* p_stream, opj_stream_seek_fn p_function)
{
opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
if
(!l_stream)
{
return;
}
l_stream->m_seek_fn = p_function;
}
/**
* Sets the given function to be used as a write function.
* @param p_stream the stream to modify
* @param p_function the function to use a write function.
*/
OPJ_API void OPJ_CALLCONV opj_stream_set_write_function(opj_stream_t* p_stream, opj_stream_write_fn p_function)
{
opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
if
((!l_stream )|| (! (l_stream->m_status & opj_stream_e_output)))
{
return;
}
l_stream->m_write_fn = p_function;
}
/**
* Sets the given function to be used as a skip function.
* @param p_stream the stream to modify
* @param p_function the function to use a skip function.
*/
OPJ_API void OPJ_CALLCONV opj_stream_set_skip_function(opj_stream_t* p_stream, opj_stream_skip_fn p_function)
{
opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
if
(! l_stream)
{
return;
}
l_stream->m_skip_fn = p_function;
}
/**
* Sets the given data to be used as a user data for the stream.
* @param p_stream the stream to modify
* @param p_data the data to set.
*/
OPJ_API void OPJ_CALLCONV opj_stream_set_user_data(opj_stream_t* p_stream, void * p_data)
{
opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
l_stream->m_user_data = p_data;
}
/**
* Reads some bytes from the stream.
* @param p_stream the stream to read data from.
* @param p_buffer pointer to the data buffer that will receive the data.
* @param p_size number of bytes to read.
* @param p_event_mgr the user event manager to be notified of special events.
* @return the number of bytes read, or -1 if an error occured or if the stream is at the end.
*/
OPJ_UINT32 opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_buffer, OPJ_UINT32 p_size, opj_event_mgr_t * p_event_mgr)
{
OPJ_UINT32 l_read_nb_bytes = 0;
if
(p_stream->m_bytes_in_buffer >= p_size)
{
memcpy(p_buffer,p_stream->m_current_data,p_size);
p_stream->m_current_data += p_size;
p_stream->m_bytes_in_buffer -= p_size;
l_read_nb_bytes += p_size;
p_stream->m_byte_offset += p_size;
return l_read_nb_bytes;
}
// we are now in the case when the remaining data if not sufficient
if
(p_stream->m_status & opj_stream_e_end)
{
l_read_nb_bytes += p_stream->m_bytes_in_buffer;
memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer);
p_stream->m_current_data += p_stream->m_bytes_in_buffer;
p_stream->m_byte_offset += p_stream->m_bytes_in_buffer;
p_stream->m_bytes_in_buffer = 0;
return l_read_nb_bytes ? l_read_nb_bytes : -1;
}
// the flag is not set, we copy data and then do an actual read on the stream
if
(p_stream->m_bytes_in_buffer)
{
l_read_nb_bytes += p_stream->m_bytes_in_buffer;
memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer);
p_stream->m_current_data = p_stream->m_stored_data;
p_buffer += p_stream->m_bytes_in_buffer;
p_size -= p_stream->m_bytes_in_buffer;
p_stream->m_byte_offset += p_stream->m_bytes_in_buffer;
p_stream->m_bytes_in_buffer = 0;
}
else
{
/* case where we are already at the end of the buffer
so reset the m_current_data to point to the start of the
stored buffer to get ready to read from disk*/
p_stream->m_current_data = p_stream->m_stored_data;
}
while(1){
// we should read less than a chunk -> read a chunk
if
(p_size < p_stream->m_buffer_size)
{
// we should do an actual read on the media
p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_stream->m_stored_data,p_stream->m_buffer_size,p_stream->m_user_data);
if
(p_stream->m_bytes_in_buffer == -1)
{
// end of stream
#ifdef TODO_MSD
opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
#endif
p_stream->m_bytes_in_buffer = 0;
p_stream->m_status |= opj_stream_e_end;
// end of stream
return l_read_nb_bytes ? l_read_nb_bytes : -1;
}
else if
(p_stream->m_bytes_in_buffer < p_size)
{
// not enough data
l_read_nb_bytes += p_stream->m_bytes_in_buffer;
memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer);
p_stream->m_current_data = p_stream->m_stored_data;
p_buffer += p_stream->m_bytes_in_buffer;
p_size -= p_stream->m_bytes_in_buffer;
p_stream->m_byte_offset += p_stream->m_bytes_in_buffer;
p_stream->m_bytes_in_buffer = 0;
}
else
{
l_read_nb_bytes += p_size;
memcpy(p_buffer,p_stream->m_current_data,p_size);
p_stream->m_current_data += p_size;
p_stream->m_bytes_in_buffer -= p_size;
p_stream->m_byte_offset += p_size;
return l_read_nb_bytes;
}
}
else
{
// direct read on the dest buffer
p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_buffer,p_size,p_stream->m_user_data);
if
(p_stream->m_bytes_in_buffer == -1)
{
// end of stream
#ifdef TODO_MSD
opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
#endif
p_stream->m_bytes_in_buffer = 0;
p_stream->m_status |= opj_stream_e_end;
// end of stream
return l_read_nb_bytes ? l_read_nb_bytes : -1;
}
else if
(p_stream->m_bytes_in_buffer < p_size)
{
// not enough data
l_read_nb_bytes += p_stream->m_bytes_in_buffer;
p_stream->m_current_data = p_stream->m_stored_data;
p_buffer += p_stream->m_bytes_in_buffer;
p_size -= p_stream->m_bytes_in_buffer;
p_stream->m_byte_offset += p_stream->m_bytes_in_buffer;
p_stream->m_bytes_in_buffer = 0;
}
else
{
// we have read the exact size
l_read_nb_bytes += p_stream->m_bytes_in_buffer;
p_stream->m_byte_offset += p_stream->m_bytes_in_buffer;
p_stream->m_current_data = p_stream->m_stored_data;
p_stream->m_bytes_in_buffer = 0;
return l_read_nb_bytes;
}
}
}
}
/**
* Writes some bytes from the stream.
* @param p_stream the stream to write data to.
* @param p_buffer pointer to the data buffer holds the data to be writtent.
* @param p_size number of bytes to write.
* @param p_event_mgr the user event manager to be notified of special events.
* @return the number of bytes writtent, or -1 if an error occured.
*/
OPJ_UINT32 opj_stream_write_data (opj_stream_private_t * p_stream,const OPJ_BYTE * p_buffer,OPJ_UINT32 p_size, opj_event_mgr_t * p_event_mgr)
{
OPJ_UINT32 l_remaining_bytes = 0;
OPJ_UINT32 l_write_nb_bytes = 0;
if
(p_stream->m_status & opj_stream_e_error)
{
return -1;
}
while(1)
{
l_remaining_bytes = p_stream->m_buffer_size - p_stream->m_bytes_in_buffer;
// we have more memory than required
if
(l_remaining_bytes >= p_size)
{
memcpy(p_stream->m_current_data,p_buffer,p_size);
p_stream->m_current_data += p_size;
p_stream->m_bytes_in_buffer += p_size;
l_write_nb_bytes += p_size;
p_stream->m_byte_offset += p_size;
return l_write_nb_bytes;
}
// we copy data and then do an actual read on the stream
if
(l_remaining_bytes)
{
l_write_nb_bytes += l_remaining_bytes;
memcpy(p_stream->m_current_data,p_buffer,l_remaining_bytes);
p_stream->m_current_data = p_stream->m_stored_data;
p_buffer += l_remaining_bytes;
p_size -= l_remaining_bytes;
p_stream->m_bytes_in_buffer += l_remaining_bytes;
p_stream->m_byte_offset += l_remaining_bytes;
}
if
(! opj_stream_flush(p_stream, p_event_mgr))
{
return -1;
}
}
}
/**
* Writes the content of the stream buffer to the stream.
* @param p_stream the stream to write data to.
* @param p_event_mgr the user event manager to be notified of special events.
* @return the number of bytes written, or -1 if an error occured.
*/
opj_bool opj_stream_flush (opj_stream_private_t * p_stream, opj_event_mgr_t * p_event_mgr)
{
// the number of bytes written on the media.
OPJ_UINT32 l_current_write_nb_bytes = 0;
p_stream->m_current_data = p_stream->m_stored_data;
while
(p_stream->m_bytes_in_buffer)
{
// we should do an actual write on the media
l_current_write_nb_bytes = p_stream->m_write_fn(p_stream->m_current_data,p_stream->m_bytes_in_buffer,p_stream->m_user_data);
if
(l_current_write_nb_bytes == -1)
{
p_stream->m_status |= opj_stream_e_error;
#ifdef TODO_MSD
opj_event_msg(p_event_mgr, EVT_INFO, "Error on writting stream!\n");
#endif
return EXIT_FAILURE;
}
p_stream->m_current_data += l_current_write_nb_bytes;
p_stream->m_bytes_in_buffer -= l_current_write_nb_bytes;
}
p_stream->m_current_data = p_stream->m_stored_data;
return EXIT_SUCCESS;
}
/**
* Skips a number of bytes from the stream.
* @param p_stream the stream to skip data from.
* @param p_size the number of bytes to skip.
* @param p_event_mgr the user event manager to be notified of special events.
* @return the number of bytes skipped, or -1 if an error occured.
*/
OPJ_SIZE_T opj_stream_read_skip (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr)
{
OPJ_SIZE_T l_skip_nb_bytes = 0;
OPJ_SIZE_T l_current_skip_nb_bytes = 0;
if
(p_stream->m_bytes_in_buffer >= p_size)
{
p_stream->m_current_data += p_size;
p_stream->m_bytes_in_buffer -= p_size;
l_skip_nb_bytes += p_size;
p_stream->m_byte_offset += l_skip_nb_bytes;
return l_skip_nb_bytes;
}
// we are now in the case when the remaining data if not sufficient
if
(p_stream->m_status & opj_stream_e_end)
{
l_skip_nb_bytes += p_stream->m_bytes_in_buffer;
p_stream->m_current_data += p_stream->m_bytes_in_buffer;
p_stream->m_bytes_in_buffer = 0;
p_stream->m_byte_offset += l_skip_nb_bytes;
return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_SIZE_T) -1;
}
// the flag is not set, we copy data and then do an actual skip on the stream
if
(p_stream->m_bytes_in_buffer)
{
l_skip_nb_bytes += p_stream->m_bytes_in_buffer;
p_stream->m_current_data = p_stream->m_stored_data;
p_size -= p_stream->m_bytes_in_buffer;
p_stream->m_bytes_in_buffer = 0;
}
while
(p_size > 0)
{
// we should do an actual skip on the media
l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data);
if
(l_current_skip_nb_bytes == (OPJ_SIZE_T) -1)
{
#ifdef TODO_MSD
opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
# endif
p_stream->m_status |= opj_stream_e_end;
p_stream->m_byte_offset += l_skip_nb_bytes;
// end if stream
return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_SIZE_T) -1;
}
p_size -= l_current_skip_nb_bytes;
l_skip_nb_bytes += l_current_skip_nb_bytes;
}
p_stream->m_byte_offset += l_skip_nb_bytes;
return l_skip_nb_bytes;
}
/**
* Skips a number of bytes from the stream.
* @param p_stream the stream to skip data from.
* @param p_size the number of bytes to skip.
* @param p_event_mgr the user event manager to be notified of special events.
* @return the number of bytes skipped, or -1 if an error occured.
*/
OPJ_SIZE_T opj_stream_write_skip (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr)
{
opj_bool l_is_written = 0;
OPJ_SIZE_T l_current_skip_nb_bytes = 0;
OPJ_SIZE_T l_skip_nb_bytes = 0;
if
(p_stream->m_status & opj_stream_e_error)
{
return (OPJ_SIZE_T) -1;
}
// we should flush data
l_is_written = opj_stream_flush (p_stream, p_event_mgr);
if
(! l_is_written)
{
p_stream->m_status |= opj_stream_e_error;
p_stream->m_bytes_in_buffer = 0;
p_stream->m_current_data = p_stream->m_current_data;
return (OPJ_SIZE_T) -1;
}
// then skip
while
(p_size > 0)
{
// we should do an actual skip on the media
l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data);
if
(l_current_skip_nb_bytes == (OPJ_SIZE_T)-1)
{
#ifdef TODO_MSD
opj_event_msg(p_event_mgr, EVT_INFO, "Stream error!\n");
#endif
p_stream->m_status |= opj_stream_e_error;
p_stream->m_byte_offset += l_skip_nb_bytes;
// end if stream
return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_SIZE_T)-1;
}
p_size -= l_current_skip_nb_bytes;
l_skip_nb_bytes += l_current_skip_nb_bytes;
}
p_stream->m_byte_offset += l_skip_nb_bytes;
return l_skip_nb_bytes;
}
/**
* Tells the byte offset on the stream (similar to ftell).
*
* @param p_stream the stream to get the information from.
*
* @return the current position of the stream.
*/
OPJ_SIZE_T opj_stream_tell (const opj_stream_private_t * p_stream)
{
return p_stream->m_byte_offset;
}
/**
* Skips a number of bytes from the stream.
* @param p_stream the stream to skip data from.
* @param p_size the number of bytes to skip.
* @param p_event_mgr the user event manager to be notified of special events.
* @return the number of bytes skipped, or -1 if an error occured.
*/
OPJ_SIZE_T opj_stream_skip (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr)
{
return p_stream->m_opj_skip(p_stream,p_size,p_event_mgr);
}
/**
* Skips a number of bytes from the stream.
* @param p_stream the stream to skip data from.
* @param p_size the number of bytes to skip.
* @param p_event_mgr the user event manager to be notified of special events.
* @return the number of bytes skipped, or -1 if an error occured.
*/
opj_bool opj_stream_read_seek (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr)
{
p_stream->m_current_data = p_stream->m_stored_data;
p_stream->m_bytes_in_buffer = 0;
if
(! p_stream->m_seek_fn(p_size,p_stream->m_user_data))
{
p_stream->m_status |= opj_stream_e_end;
return EXIT_FAILURE;
}
else
{
// reset stream status
p_stream->m_status &= (~opj_stream_e_end);
p_stream->m_byte_offset = p_size;
}
return EXIT_SUCCESS;
}
/**
* Skips a number of bytes from the stream.
* @param p_stream the stream to skip data from.
* @param p_size the number of bytes to skip.
* @param p_event_mgr the user event manager to be notified of special events.
* @return the number of bytes skipped, or -1 if an error occured.
*/
opj_bool opj_stream_write_seek (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr)
{
if
(! opj_stream_flush(p_stream,p_event_mgr))
{
p_stream->m_status |= opj_stream_e_error;
return EXIT_FAILURE;
}
p_stream->m_current_data = p_stream->m_stored_data;
p_stream->m_bytes_in_buffer = 0;
if
(! p_stream->m_seek_fn(p_size,p_stream->m_user_data))
{
p_stream->m_status |= opj_stream_e_error;
return EXIT_FAILURE;
}
else
{
p_stream->m_byte_offset = p_size;
}
return EXIT_SUCCESS;
}
/**
* Seeks a number of bytes from the stream.
* @param p_stream the stream to skip data from.
* @param p_size the number of bytes to skip.
* @param p_event_mgr the user event manager to be notified of special events.
* @return true if the stream is seekable.
*/
opj_bool opj_stream_seek (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr)
{
return p_stream->m_opj_seek(p_stream,p_size,p_event_mgr);
}
/**
* Tells if the given stream is seekable.
*/
opj_bool opj_stream_has_seek (const opj_stream_private_t * p_stream)
{
return p_stream->m_seek_fn != opj_stream_default_seek;
}
OPJ_UINT32 opj_stream_default_read (void * p_buffer, OPJ_UINT32 p_nb_bytes, void * p_user_data)
{
return (OPJ_UINT32) -1;
}
OPJ_UINT32 opj_stream_default_write (void * p_buffer, OPJ_UINT32 p_nb_bytes, void * p_user_data)
{
return (OPJ_UINT32) -1;
}
OPJ_SIZE_T opj_stream_default_skip (OPJ_SIZE_T p_nb_bytes, void * p_user_data)
{
return (OPJ_SIZE_T) -1;
}
opj_bool opj_stream_default_seek (OPJ_SIZE_T p_nb_bytes, void * p_user_data)
{
return EXIT_FAILURE;
}

View File

@ -41,6 +41,8 @@ The functions in CIO.C have for goal to realize a byte input / output process.
/** @defgroup CIO CIO - byte input-output stream */ /** @defgroup CIO CIO - byte input-output stream */
/*@{*/ /*@{*/
#include "opj_config.h"
/** @name Exported functions (see also openjpeg.h) */ /** @name Exported functions (see also openjpeg.h) */
/*@{*/ /*@{*/
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
@ -82,5 +84,312 @@ void cio_skip(opj_cio_t *cio, int n);
/*@}*/ /*@}*/
/* ----------------------------------------------------------------------- */
#if defined(OPJ_BIG_ENDIAN)
#if !defined(OPJ_LITTLE_ENDIAN)
#define opj_write_bytes opj_write_bytes_BE
#define opj_read_bytes opj_read_bytes_BE
#define opj_write_double opj_write_double_BE
#define opj_read_double opj_read_double_BE
#define opj_write_float opj_write_float_BE
#define opj_read_float opj_read_float_BE
#else
#error "Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but not both."
#endif
#else
#if defined(OPJ_LITTLE_ENDIAN)
#define opj_write_bytes opj_write_bytes_LE
#define opj_read_bytes opj_read_bytes_LE
#define opj_write_double opj_write_double_LE
#define opj_read_double opj_read_double_LE
#define opj_write_float opj_write_float_LE
#define opj_read_float opj_read_float_LE
#else
#error "Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but not none."
#endif
#endif
typedef enum
{
opj_stream_e_output = 0x1,
opj_stream_e_input = 0x2,
opj_stream_e_end = 0x4,
opj_stream_e_error = 0x8
}
opj_stream_flag ;
/**
Byte input-output stream.
*/
typedef struct opj_stream_private
{
/**
* User data, be it files, ... The actual data depends on the type of the stream.
*/
void * m_user_data;
/**
* Pointer to actual read function (NULL at the initialization of the cio.
*/
opj_stream_read_fn m_read_fn;
/**
* Pointer to actual write function (NULL at the initialization of the cio.
*/
opj_stream_write_fn m_write_fn;
/**
* Pointer to actual skip function (NULL at the initialization of the cio.
* There is no seek function to prevent from back and forth slow procedures.
*/
opj_stream_skip_fn m_skip_fn;
/**
* Pointer to actual seek function (if available).
*/
opj_stream_seek_fn m_seek_fn;
/**
* Actual data stored into the stream if readed from. Data is read by chunk of fixed size.
* you should never access this data directly.
*/
OPJ_BYTE * m_stored_data;
/**
* Pointer to the current read data.
*/
OPJ_BYTE * m_current_data;
OPJ_SIZE_T (* m_opj_skip)(struct opj_stream_private * ,OPJ_SIZE_T , struct opj_event_mgr *);
opj_bool (* m_opj_seek) (struct opj_stream_private * , OPJ_SIZE_T , struct opj_event_mgr *);
/**
* number of bytes containing in the buffer.
*/
OPJ_UINT32 m_bytes_in_buffer;
/**
* The number of bytes read/written.
*/
OPJ_SIZE_T m_byte_offset;
/**
* The size of the buffer.
*/
OPJ_UINT32 m_buffer_size;
/**
* Flags to tell the status of the stream.
*/
OPJ_UINT32 m_status;
}
opj_stream_private_t;
/**
* Write some bytes to the given data buffer, this function is used in Big Endian cpus.
* @param p_buffer pointer the data buffer to write data to.
* @param p_value the value to write
* @param p_nb_bytes the number of bytes to write
*/
void opj_write_bytes_BE (OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, OPJ_UINT32 p_nb_bytes);
/**
* Reads some bytes from the given data buffer, this function is used in Big Endian cpus.
* @param p_buffer pointer the data buffer to read data from.
* @param p_value pointer to the value that will store the data.
* @param p_nb_bytes the nb bytes to read.
* @return the number of bytes read or -1 if an error occured.
*/
void opj_read_bytes_BE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, OPJ_UINT32 p_nb_bytes);
/**
* Write some bytes to the given data buffer, this function is used in Little Endian cpus.
* @param p_buffer pointer the data buffer to write data to.
* @param p_value the value to write
* @param p_nb_bytes the number of bytes to write
* @return the number of bytes written or -1 if an error occured
*/
void opj_write_bytes_LE (OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, OPJ_UINT32 p_nb_bytes);
/**
* Reads some bytes from the given data buffer, this function is used in Little Endian cpus.
* @param p_buffer pointer the data buffer to read data from.
* @param p_value pointer to the value that will store the data.
* @param p_nb_bytes the nb bytes to read.
* @return the number of bytes read or -1 if an error occured.
*/
void opj_read_bytes_LE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, OPJ_UINT32 p_nb_bytes);
/**
* Write some bytes to the given data buffer, this function is used in Little Endian cpus.
* @param p_buffer pointer the data buffer to write data to.
* @param p_value the value to write
*/
void opj_write_double_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value);
/***
* Write some bytes to the given data buffer, this function is used in Big Endian cpus.
* @param p_buffer pointer the data buffer to write data to.
* @param p_value the value to write
*/
void opj_write_double_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value);
/**
* Reads some bytes from the given data buffer, this function is used in Little Endian cpus.
* @param p_buffer pointer the data buffer to read data from.
* @param p_value pointer to the value that will store the data.
*/
void opj_read_double_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value);
/**
* Reads some bytes from the given data buffer, this function is used in Big Endian cpus.
* @param p_buffer pointer the data buffer to read data from.
* @param p_value pointer to the value that will store the data.
*/
void opj_read_double_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value);
/**
* Reads some bytes from the given data buffer, this function is used in Little Endian cpus.
* @param p_buffer pointer the data buffer to read data from.
* @param p_value pointer to the value that will store the data.
*/
void opj_read_float_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value);
/**
* Reads some bytes from the given data buffer, this function is used in Big Endian cpus.
* @param p_buffer pointer the data buffer to read data from.
* @param p_value pointer to the value that will store the data.
*/
void opj_read_float_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value);
/**
* Write some bytes to the given data buffer, this function is used in Little Endian cpus.
* @param p_buffer pointer the data buffer to write data to.
* @param p_value the value to write
*/
void opj_write_float_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value);
/***
* Write some bytes to the given data buffer, this function is used in Big Endian cpus.
* @param p_buffer pointer the data buffer to write data to.
* @param p_value the value to write
*/
void opj_write_float_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value);
/**
* Reads some bytes from the stream.
* @param p_stream the stream to read data from.
* @param p_buffer pointer to the data buffer that will receive the data.
* @param p_size number of bytes to read.
* @param p_event_mgr the user event manager to be notified of special events.
* @return the number of bytes read, or -1 if an error occured or if the stream is at the end.
*/
OPJ_UINT32 opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_buffer, OPJ_UINT32 p_size, struct opj_event_mgr * p_event_mgr);
/**
* Writes some bytes to the stream.
* @param p_stream the stream to write data to.
* @param p_buffer pointer to the data buffer holds the data to be writtent.
* @param p_size number of bytes to write.
* @param p_event_mgr the user event manager to be notified of special events.
* @return the number of bytes writtent, or -1 if an error occured.
*/
OPJ_UINT32 opj_stream_write_data (opj_stream_private_t * p_stream,const OPJ_BYTE * p_buffer, OPJ_UINT32 p_size, struct opj_event_mgr * p_event_mgr);
/**
* Writes the content of the stream buffer to the stream.
* @param p_stream the stream to write data to.
* @param p_event_mgr the user event manager to be notified of special events.
* @return true if the data could be flushed, false else.
*/
opj_bool opj_stream_flush (opj_stream_private_t * p_stream, struct opj_event_mgr * p_event_mgr);
/**
* Skips a number of bytes from the stream.
* @param p_stream the stream to skip data from.
* @param p_size the number of bytes to skip.
* @param p_event_mgr the user event manager to be notified of special events.
* @return the number of bytes skipped, or -1 if an error occured.
*/
OPJ_SIZE_T opj_stream_skip (opj_stream_private_t * p_stream,OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr);
/**
* Tells the byte offset on the stream (similar to ftell).
*
* @param p_stream the stream to get the information from.
*
* @return the current position o fthe stream.
*/
OPJ_SIZE_T opj_stream_tell (const opj_stream_private_t * p_stream);
/**
* Skips a number of bytes from the stream.
* @param p_stream the stream to skip data from.
* @param p_size the number of bytes to skip.
* @param p_event_mgr the user event manager to be notified of special events.
* @return the number of bytes skipped, or -1 if an error occured.
*/
OPJ_SIZE_T opj_stream_write_skip (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr);
/**
* Skips a number of bytes from the stream.
* @param p_stream the stream to skip data from.
* @param p_size the number of bytes to skip.
* @param p_event_mgr the user event manager to be notified of special events.
* @return the number of bytes skipped, or -1 if an error occured.
*/
OPJ_SIZE_T opj_stream_read_skip (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr);
/**
* Skips a number of bytes from the stream.
* @param p_stream the stream to skip data from.
* @param p_size the number of bytes to skip.
* @param p_event_mgr the user event manager to be notified of special events.
* @return the number of bytes skipped, or -1 if an error occured.
*/
opj_bool opj_stream_read_seek (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr);
/**
* Skips a number of bytes from the stream.
* @param p_stream the stream to skip data from.
* @param p_size the number of bytes to skip.
* @param p_event_mgr the user event manager to be notified of special events.
* @return the number of bytes skipped, or -1 if an error occured.
*/
opj_bool opj_stream_write_seek (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr);
/**
* Seeks a number of bytes from the stream.
* @param p_stream the stream to skip data from.
* @param p_size the number of bytes to skip.
* @param p_event_mgr the user event manager to be notified of special events.
* @return true if the stream is seekable.
*/
opj_bool opj_stream_seek (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr);
/**
* Tells if the given stream is seekable.
*/
opj_bool opj_stream_has_seek (const opj_stream_private_t * p_stream);
OPJ_UINT32 opj_stream_default_read (void * p_buffer, OPJ_UINT32 p_nb_bytes, void * p_user_data);
OPJ_UINT32 opj_stream_default_write (void * p_buffer, OPJ_UINT32 p_nb_bytes, void * p_user_data);
OPJ_SIZE_T opj_stream_default_skip (OPJ_SIZE_T p_nb_bytes, void * p_user_data);
opj_bool opj_stream_default_seek (OPJ_SIZE_T p_nb_bytes, void * p_user_data);
#endif /* __CIO_H */ #endif /* __CIO_H */

View File

@ -118,7 +118,11 @@ static void dwt_encode_stepsize(int stepsize, int numbps, opj_stepsize_t *bandno
/** /**
Inverse wavelet transform in 2-D. Inverse wavelet transform in 2-D.
*/ */
#ifdef OPJ_V1
static void dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int i, DWT1DFN fn); static void dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int i, DWT1DFN fn);
#endif
static opj_bool dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 i, DWT1DFN fn);
/*@}*/ /*@}*/
@ -375,13 +379,21 @@ void dwt_encode(opj_tcd_tilecomp_t * tilec) {
} }
} }
#ifdef OPJ_V1
/* <summary> */ /* <summary> */
/* Inverse 5-3 wavelet transform in 2-D. */ /* Inverse 5-3 wavelet transform in 2-D. */
/* </summary> */ /* </summary> */
void dwt_decode(opj_tcd_tilecomp_t* tilec, int numres) { void dwt_decode(opj_tcd_tilecomp_t* tilec, int numres) {
dwt_decode_tile(tilec, numres, &dwt_decode_1); dwt_decode_tile(tilec, numres, &dwt_decode_1);
} }
#endif
/* <summary> */
/* Inverse 5-3 wavelet transform in 2-D. */
/* </summary> */
opj_bool dwt_decode(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres) {
return dwt_decode_tile(tilec, numres, &dwt_decode_1);
}
/* <summary> */ /* <summary> */
@ -495,7 +507,7 @@ void dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, int prec) {
} }
} }
#ifdef OPJ_V1
/* <summary> */ /* <summary> */
/* Determine maximum computed resolution level for inverse wavelet transform */ /* Determine maximum computed resolution level for inverse wavelet transform */
/* </summary> */ /* </summary> */
@ -511,8 +523,24 @@ static int dwt_decode_max_resolution(opj_tcd_resolution_t* restrict r, int i) {
} }
return mr ; return mr ;
} }
#endif
/* <summary> */
/* Determine maximum computed resolution level for inverse wavelet transform */
/* </summary> */
static OPJ_UINT32 dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_UINT32 i) {
OPJ_UINT32 mr = 0;
OPJ_UINT32 w;
while( --i ) {
++r;
if( mr < ( w = r->x1 - r->x0 ) )
mr = w ;
if( mr < ( w = r->y1 - r->y0 ) )
mr = w ;
}
return mr ;
}
#ifdef OPJ_V1
/* <summary> */ /* <summary> */
/* Inverse wavelet transform in 2-D. */ /* Inverse wavelet transform in 2-D. */
/* </summary> */ /* </summary> */
@ -527,7 +555,7 @@ static void dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int numres, DWT1DFN dwt_1
int w = tilec->x1 - tilec->x0; int w = tilec->x1 - tilec->x0;
h.mem = (int*)opj_aligned_malloc(dwt_decode_max_resolution(tr, numres) * sizeof(int)); h.mem = (int*)opj_aligned_malloc(dwt_max_resolution(tr, numres) * sizeof(int));
v.mem = h.mem; v.mem = h.mem;
while( --numres) { while( --numres) {
@ -564,6 +592,67 @@ static void dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int numres, DWT1DFN dwt_1
} }
opj_aligned_free(h.mem); opj_aligned_free(h.mem);
} }
#endif
/* <summary> */
/* Inverse wavelet transform in 2-D. */
/* </summary> */
static opj_bool dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres, DWT1DFN dwt_1D) {
dwt_t h;
dwt_t v;
opj_tcd_resolution_t* tr = tilec->resolutions;
OPJ_UINT32 rw = tr->x1 - tr->x0; /* width of the resolution level computed */
OPJ_UINT32 rh = tr->y1 - tr->y0; /* height of the resolution level computed */
OPJ_UINT32 w = tilec->x1 - tilec->x0;
h.mem = (OPJ_INT32*)
opj_aligned_malloc(dwt_max_resolution(tr, numres) * sizeof(OPJ_INT32));
if
(! h.mem)
{
return OPJ_FALSE;
}
v.mem = h.mem;
while( --numres) {
OPJ_INT32 * restrict tiledp = tilec->data;
OPJ_UINT32 j;
++tr;
h.sn = rw;
v.sn = rh;
rw = tr->x1 - tr->x0;
rh = tr->y1 - tr->y0;
h.dn = rw - h.sn;
h.cas = tr->x0 % 2;
for(j = 0; j < rh; ++j) {
dwt_interleave_h(&h, &tiledp[j*w]);
(dwt_1D)(&h);
memcpy(&tiledp[j*w], h.mem, rw * sizeof(OPJ_INT32));
}
v.dn = rh - v.sn;
v.cas = tr->y0 % 2;
for(j = 0; j < rw; ++j){
OPJ_UINT32 k;
dwt_interleave_v(&v, &tiledp[j], w);
(dwt_1D)(&v);
for(k = 0; k < rh; ++k) {
tiledp[k * w + j] = v.mem[k];
}
}
}
opj_aligned_free(h.mem);
return OPJ_TRUE;
}
static void v4dwt_interleave_h(v4dwt_t* restrict w, float* restrict a, int x, int size){ static void v4dwt_interleave_h(v4dwt_t* restrict w, float* restrict a, int x, int size){
float* restrict bi = (float*) (w->wavelet + w->cas); float* restrict bi = (float*) (w->wavelet + w->cas);
@ -769,10 +858,13 @@ static void v4dwt_decode(v4dwt_t* restrict dwt){
#endif #endif
} }
// KEEP TRUNK VERSION + return type of v2 because rev557
/* <summary> */ /* <summary> */
/* Inverse 9-7 wavelet transform in 2-D. */ /* Inverse 9-7 wavelet transform in 2-D. */
/* </summary> */ /* </summary> */
void dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, int numres){ // V1 void dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, int numres){
opj_bool dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, int numres){
v4dwt_t h; v4dwt_t h;
v4dwt_t v; v4dwt_t v;
@ -783,7 +875,7 @@ void dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, int numres){
int w = tilec->x1 - tilec->x0; int w = tilec->x1 - tilec->x0;
h.wavelet = (v4*) opj_aligned_malloc((dwt_decode_max_resolution(res, numres)+5) * sizeof(v4)); h.wavelet = (v4*) opj_aligned_malloc((dwt_max_resolution(res, numres)+5) * sizeof(v4));
v.wavelet = h.wavelet; v.wavelet = h.wavelet;
while( --numres) { while( --numres) {
@ -854,5 +946,6 @@ void dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, int numres){
} }
opj_aligned_free(h.wavelet); opj_aligned_free(h.wavelet);
return OPJ_TRUE;
} }

View File

@ -59,7 +59,12 @@ Apply a reversible inverse DWT transform to a component of an image.
@param tilec Tile component information (current tile) @param tilec Tile component information (current tile)
@param numres Number of resolution levels to decode @param numres Number of resolution levels to decode
*/ */
#ifdef OPJ_V1
void dwt_decode(opj_tcd_tilecomp_t* tilec, int numres); void dwt_decode(opj_tcd_tilecomp_t* tilec, int numres);
#endif
opj_bool dwt_decode(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres);
/** /**
Get the gain of a subband for the reversible 5-3 DWT. Get the gain of a subband for the reversible 5-3 DWT.
@param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH) @param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH)
@ -80,12 +85,14 @@ Apply an irreversible DWT transform to a component of an image.
*/ */
void dwt_encode_real(opj_tcd_tilecomp_t * tilec); void dwt_encode_real(opj_tcd_tilecomp_t * tilec);
/** /**
KEEP TRUNK VERSION + return type of v2 because rev557
Inverse 9-7 wavelet transform in 2-D. Inverse 9-7 wavelet transform in 2-D.
Apply an irreversible inverse DWT transform to a component of an image. Apply an irreversible inverse DWT transform to a component of an image.
@param tilec Tile component information (current tile) @param tilec Tile component information (current tile)
@param numres Number of resolution levels to decode @param numres Number of resolution levels to decode
*/ */
void dwt_decode_real(opj_tcd_tilecomp_t* tilec, int numres); // V1 void dwt_decode_real(opj_tcd_tilecomp_t* tilec, int numres);
opj_bool dwt_decode_real(opj_tcd_tilecomp_t* tilec, int numres);
/** /**
Get the gain of a subband for the irreversible 9-7 DWT. Get the gain of a subband for the irreversible 9-7 DWT.
@param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH) @param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH)

View File

@ -120,3 +120,48 @@ opj_bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ..
return OPJ_TRUE; return OPJ_TRUE;
} }
opj_bool opj_event_msg_v2(opj_event_mgr_t* event_mgr, int event_type, const char *fmt, ...) {
#define MSG_SIZE 512 /* 512 bytes should be more than enough for a short message */
opj_msg_callback msg_handler = NULL;
if(event_mgr != NULL) {
switch(event_type) {
case EVT_ERROR:
msg_handler = event_mgr->error_handler;
break;
case EVT_WARNING:
msg_handler = event_mgr->warning_handler;
break;
case EVT_INFO:
msg_handler = event_mgr->info_handler;
break;
default:
break;
}
if(msg_handler == NULL) {
return OPJ_FALSE;
}
} else {
return OPJ_FALSE;
}
if ((fmt != NULL) && (event_mgr != NULL)) {
va_list arg;
int str_length/*, i, j*/; /* UniPG */
char message[MSG_SIZE];
memset(message, 0, MSG_SIZE);
/* initialize the optional parameter list */
va_start(arg, fmt);
/* check the length of the format string */
str_length = (strlen(fmt) > MSG_SIZE) ? MSG_SIZE : strlen(fmt);
/* parse the format string and put the result in 'message' */
vsprintf(message, fmt, arg); /* UniPG */
/* deinitialize the optional parameter list */
va_end(arg);
/* output the message to the user program */
msg_handler(message, event_mgr->client_data);
}
return OPJ_TRUE;
}

View File

@ -46,10 +46,13 @@ The functions in EVENT.C have for goal to send output messages (errors, warnings
Write formatted data to a string and send the string to a user callback. Write formatted data to a string and send the string to a user callback.
@param cinfo Codec context info @param cinfo Codec context info
@param event_type Event type or callback to use to send the message @param event_type Event type or callback to use to send the message
@param fmt Format-control string (plus optionnal arguments) @param fmt Format-control string (plus optional arguments)
@return Returns true if successful, returns false otherwise @return Returns true if successful, returns false otherwise
*/ */
opj_bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...); opj_bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...);
opj_bool opj_event_msg_v2(opj_event_mgr_t* event_mgr, int event_type, const char *fmt, ...);
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/*@}*/ /*@}*/

View File

@ -87,3 +87,37 @@ void OPJ_CALLCONV opj_image_destroy(opj_image_t *image) {
} }
} }
/**
* Updates the components of the image from the coding parameters.
*
* @param p_image the image to update.
* @param p_cp the coding parameters from which to update the image.
*/
void opj_image_comp_update(opj_image_t * p_image,const opj_cp_v2_t * p_cp)
{
OPJ_UINT32 i, l_width, l_height;
OPJ_INT32 l_x0,l_y0,l_x1,l_y1;
OPJ_INT32 l_comp_x0,l_comp_y0,l_comp_x1,l_comp_y1;
opj_image_comp_t * l_img_comp = 00;
l_x0 = int_max(p_cp->tx0 , p_image->x0);
l_y0 = int_max(p_cp->ty0 , p_image->y0);
l_x1 = int_min(p_cp->tx0 + p_cp->tw * p_cp->tdx, p_image->x1);
l_y1 = int_min(p_cp->ty0 + p_cp->th * p_cp->tdy, p_image->y1);
l_img_comp = p_image->comps;
for (i = 0; i < p_image->numcomps; ++i) {
l_comp_x0 = int_ceildiv(l_x0, l_img_comp->dx);
l_comp_y0 = int_ceildiv(l_y0, l_img_comp->dy);
l_comp_x1 = int_ceildiv(l_x1, l_img_comp->dx);
l_comp_y1 = int_ceildiv(l_y1, l_img_comp->dy);
l_width = int_ceildivpow2(l_comp_x1 - l_comp_x0, l_img_comp->factor);
l_height = int_ceildivpow2(l_comp_y1 - l_comp_y0, l_img_comp->factor);
l_img_comp->w = l_width;
l_img_comp->h = l_height;
l_img_comp->x0 = l_x0;
l_img_comp->y0 = l_y0;
++l_img_comp;
}
}

View File

@ -32,6 +32,9 @@
The functions in IMAGE.C have for goal to realize operations on images. The functions in IMAGE.C have for goal to realize operations on images.
*/ */
struct opj_image;
struct opj_cp_v2;
/** @defgroup IMAGE IMAGE - Implementation of operations on images */ /** @defgroup IMAGE IMAGE - Implementation of operations on images */
/*@{*/ /*@{*/
@ -42,6 +45,14 @@ Create an empty image
*/ */
opj_image_t* opj_image_create0(void); opj_image_t* opj_image_create0(void);
/**
* Updates the components of the image from the coding parameters.
*
* @param p_image the image to update.
* @param p_cp the coding parameters from which to update the image.
*/
void opj_image_comp_update(struct opj_image * p_image,const struct opj_cp_v2 * p_cp);
/*@}*/ /*@}*/
#endif /* __IMAGE_H */ #endif /* __IMAGE_H */

View File

@ -50,6 +50,15 @@ Get the minimum of two integers
static INLINE int int_min(int a, int b) { static INLINE int int_min(int a, int b) {
return a < b ? a : b; return a < b ? a : b;
} }
/**
Get the minimum of two integers
@return Returns a if a < b else b
*/
static INLINE OPJ_UINT32 uint_min(OPJ_UINT32 a, OPJ_UINT32 b) {
return a < b ? a : b;
}
/** /**
Get the maximum of two integers Get the maximum of two integers
@return Returns a if a > b else b @return Returns a if a > b else b
@ -57,6 +66,15 @@ Get the maximum of two integers
static INLINE int int_max(int a, int b) { static INLINE int int_max(int a, int b) {
return (a > b) ? a : b; return (a > b) ? a : b;
} }
/**
Get the maximum of two integers
@return Returns a if a > b else b
*/
static INLINE OPJ_UINT32 uint_max(OPJ_UINT32 a, OPJ_UINT32 b) {
return (a > b) ? a : b;
}
/** /**
Clamp an integer inside an interval Clamp an integer inside an interval
@return @return
@ -111,6 +129,19 @@ static INLINE int int_floorlog2(int a) {
} }
return l; return l;
} }
/**
Get logarithm of an integer and round downwards
@return Returns log2(a)
*/
static INLINE OPJ_UINT32 uint_floorlog2(OPJ_UINT32 a) {
OPJ_UINT32 l;
for (l = 0; a > 1; ++l)
{
a >>= 1;
}
return l;
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/*@}*/ /*@}*/

File diff suppressed because it is too large Load Diff

View File

@ -77,6 +77,14 @@ The functions in J2K.C have for goal to read/write the several parts of the code
#define J2K_MS_EPH 0xff92 /**< EPH marker value */ #define J2K_MS_EPH 0xff92 /**< EPH marker value */
#define J2K_MS_CRG 0xff63 /**< CRG marker value */ #define J2K_MS_CRG 0xff63 /**< CRG marker value */
#define J2K_MS_COM 0xff64 /**< COM marker value */ #define J2K_MS_COM 0xff64 /**< COM marker value */
#ifdef TODO_MS
#define J2K_MS_CBD 0xff78 /**< CBD marker value */
#define J2K_MS_MCC 0xff75 /**< MCC marker value */
#define J2K_MS_MCT 0xff74 /**< MCT marker value */
#define J2K_MS_MCO 0xff77 /**< MCO marker value */
#endif
/* UniPG>> */ /* UniPG>> */
#ifdef USE_JPWL #ifdef USE_JPWL
#define J2K_MS_EPC 0xff68 /**< EPC marker value (Part 11: JPEG 2000 for Wireless) */ #define J2K_MS_EPC 0xff68 /**< EPC marker value (Part 11: JPEG 2000 for Wireless) */
@ -91,6 +99,8 @@ The functions in J2K.C have for goal to read/write the several parts of the code
/* <<UniPG */ /* <<UniPG */
struct opj_stream_private;
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/** /**
@ -128,35 +138,70 @@ typedef struct opj_stepsize {
int mant; int mant;
} opj_stepsize_t; } opj_stepsize_t;
//OPJ_V1/**
//Tile-component coding parameters
//*/
//typedef struct opj_tccp {
// /** coding style */
// int csty;
// /** number of resolutions */
// int numresolutions;
// /** code-blocks width */
// int cblkw;
// /** code-blocks height */
// int cblkh;
// /** code-block coding style */
// int cblksty;
// /** discrete wavelet transform identifier */
// int qmfbid;
// /** quantisation style */
// int qntsty;
// /** stepsizes used for quantization */
// opj_stepsize_t stepsizes[J2K_MAXBANDS];
// /** number of guard bits */
// int numgbits;
// /** Region Of Interest shift */
// int roishift;
// /** precinct width */
// int prcw[J2K_MAXRLVLS];
// /** precinct height */
// int prch[J2K_MAXRLVLS];
//} opj_tccp_t;
/** /**
Tile-component coding parameters Tile-component coding parameters
*/ */
typedef struct opj_tccp { typedef struct opj_tccp
{
/** coding style */ /** coding style */
int csty; OPJ_UINT32 csty;
/** number of resolutions */ /** number of resolutions */
int numresolutions; OPJ_UINT32 numresolutions;
/** code-blocks width */ /** code-blocks width */
int cblkw; OPJ_UINT32 cblkw;
/** code-blocks height */ /** code-blocks height */
int cblkh; OPJ_UINT32 cblkh;
/** code-block coding style */ /** code-block coding style */
int cblksty; OPJ_UINT32 cblksty;
/** discrete wavelet transform identifier */ /** discrete wavelet transform identifier */
int qmfbid; OPJ_UINT32 qmfbid;
/** quantisation style */ /** quantisation style */
int qntsty; OPJ_UINT32 qntsty;
/** stepsizes used for quantization */ /** stepsizes used for quantization */
opj_stepsize_t stepsizes[J2K_MAXBANDS]; opj_stepsize_t stepsizes[J2K_MAXBANDS];
/** number of guard bits */ /** number of guard bits */
int numgbits; OPJ_UINT32 numgbits;
/** Region Of Interest shift */ /** Region Of Interest shift */
int roishift; OPJ_INT32 roishift;
/** precinct width */ /** precinct width */
int prcw[J2K_MAXRLVLS]; OPJ_UINT32 prcw[J2K_MAXRLVLS];
/** precinct height */ /** precinct height */
int prch[J2K_MAXRLVLS]; OPJ_UINT32 prch[J2K_MAXRLVLS];
} opj_tccp_t; /** the dc_level_shift **/
OPJ_INT32 m_dc_level_shift;
}
opj_tccp_t;
/** /**
Tile coding parameters : Tile coding parameters :
@ -198,6 +243,120 @@ typedef struct opj_tcp {
opj_tccp_t *tccps; opj_tccp_t *tccps;
} opj_tcp_t; } opj_tcp_t;
/**
* Type of data for storing the MCT data
*/
typedef enum MCT_ELEMENT_TYPE
{
MCT_TYPE_INT16 = 0, /** MCT data is stored as signed shorts*/
MCT_TYPE_INT32 = 1, /** MCT data is stored as signed integers*/
MCT_TYPE_FLOAT = 2, /** MCT data is stored as floats*/
MCT_TYPE_DOUBLE = 3 /** MCT data is stored as doubles*/
} J2K_MCT_ELEMENT_TYPE;
/**
* Type of data for storing the MCT data
*/
typedef enum MCT_ARRAY_TYPE
{
MCT_TYPE_DEPENDENCY = 0,
MCT_TYPE_DECORRELATION = 1,
MCT_TYPE_OFFSET = 2
} J2K_MCT_ARRAY_TYPE;
typedef struct opj_mct_data
{
J2K_MCT_ELEMENT_TYPE m_element_type;
J2K_MCT_ARRAY_TYPE m_array_type;
OPJ_UINT32 m_index;
OPJ_BYTE * m_data;
OPJ_UINT32 m_data_size;
}
opj_mct_data_t;
typedef struct opj_simple_mcc_decorrelation_data
{
OPJ_UINT32 m_index;
OPJ_UINT32 m_nb_comps;
opj_mct_data_t * m_decorrelation_array;
opj_mct_data_t * m_offset_array;
OPJ_UINT32 m_is_irreversible : 1;
}
opj_simple_mcc_decorrelation_data_t;
/**
Tile coding parameters :
this structure is used to store coding/decoding parameters common to all
tiles (information like COD, COC in main header)
*/
typedef struct opj_tcp_v2
{
/** coding style */
OPJ_UINT32 csty;
/** progression order */
OPJ_PROG_ORDER prg;
/** number of layers */
OPJ_UINT32 numlayers;
OPJ_UINT32 num_layers_to_decode;
/** multi-component transform identifier */
OPJ_UINT32 mct;
/** rates of layers */
OPJ_FLOAT32 rates[100];
/** number of progression order changes */
OPJ_UINT32 numpocs;
/** progression order changes */
opj_poc_t pocs[32];
/** packet header store there for futur use in t2_decode_packet */
OPJ_BYTE *ppt_data;
/** used to keep a track of the allocated memory */
OPJ_BYTE *ppt_buffer;
/** Number of bytes stored inside ppt_data*/
OPJ_UINT32 ppt_data_size;
/** size of ppt_data*/
OPJ_UINT32 ppt_len;
/** add fixed_quality */
OPJ_FLOAT32 distoratio[100];
/** tile-component coding parameters */
opj_tccp_t *tccps;
/** number of tile parts for the tile. */
OPJ_UINT32 m_nb_tile_parts;
/** data for the tile */
OPJ_BYTE * m_data;
/** size of data */
OPJ_UINT32 m_data_size;
/** encoding norms */
OPJ_FLOAT64 * mct_norms;
/** the mct decoding matrix */
OPJ_FLOAT32 * m_mct_decoding_matrix;
/** the mct coding matrix */
OPJ_FLOAT32 * m_mct_coding_matrix;
/** mct records */
opj_mct_data_t * m_mct_records;
/** the number of mct records. */
OPJ_UINT32 m_nb_mct_records;
/** the max number of mct records. */
OPJ_UINT32 m_nb_max_mct_records;
/** mcc records */
opj_simple_mcc_decorrelation_data_t * m_mcc_records;
/** the number of mct records. */
OPJ_UINT32 m_nb_mcc_records;
/** the max number of mct records. */
OPJ_UINT32 m_nb_max_mcc_records;
/***** FLAGS *******/
/** If ppt == 1 --> there was a PPT marker for the present tile */
OPJ_UINT32 ppt : 1;
/** indicates if a POC marker has been used O:NO, 1:YES */
OPJ_UINT32 POC : 1;
} opj_tcp_v2_t;
/** /**
Coding parameters Coding parameters
*/ */
@ -308,6 +467,198 @@ typedef struct opj_cp {
/* <<UniPG */ /* <<UniPG */
} opj_cp_t; } opj_cp_t;
typedef struct opj_encoding_param
{
/** Digital cinema profile*/
OPJ_CINEMA_MODE m_cinema;
/** Maximum rate for each component. If == 0, component size limitation is not considered */
OPJ_UINT32 m_max_comp_size;
/** Position of tile part flag in progression order*/
OPJ_INT32 m_tp_pos;
/** fixed layer */
OPJ_INT32 *m_matrice;
/** Flag determining tile part generation*/
OPJ_BYTE m_tp_flag;
/** allocation by rate/distortion */
OPJ_UINT32 m_disto_alloc : 1;
/** allocation by fixed layer */
OPJ_UINT32 m_fixed_alloc : 1;
/** add fixed_quality */
OPJ_UINT32 m_fixed_quality : 1;
/** Enabling Tile part generation*/
OPJ_UINT32 m_tp_on : 1;
}
opj_encoding_param_t;
typedef struct opj_decoding_param
{
/** if != 0, then original dimension divided by 2^(reduce); if == 0 or not used, image is decoded to the full resolution */
OPJ_UINT32 m_reduce;
/** if != 0, then only the first "layer" layers are decoded; if == 0 or not used, all the quality layers are decoded */
OPJ_UINT32 m_layer;
}
opj_decoding_param_t;
/**
Coding parameters
*/
typedef struct opj_cp_v2
{
/** Size of the image in bits*/
/*int img_size;*/
/** Rsiz*/
OPJ_RSIZ_CAPABILITIES rsiz;
/** XTOsiz */
OPJ_UINT32 tx0; // MSD see norm
/** YTOsiz */
OPJ_UINT32 ty0; // MSD see norm
/** XTsiz */
OPJ_UINT32 tdx;
/** YTsiz */
OPJ_UINT32 tdy;
/** comment */
OPJ_CHAR *comment;
/** number of tiles in width */
OPJ_UINT32 tw;
/** number of tiles in heigth */
OPJ_UINT32 th;
/** packet header storage original buffer */
OPJ_BYTE *ppm_buffer;
/** packet header store there for futur use in t2_decode_packet */
OPJ_BYTE *ppm_data;
/** size of the ppm_data*/
OPJ_UINT32 ppm_len;
/** Number of bytes actually stored inside the ppm_data */
OPJ_UINT32 ppm_data_size;
/** tile coding parameters */
opj_tcp_v2_t *tcps;
union
{
opj_decoding_param_t m_dec;
opj_encoding_param_t m_enc;
}
m_specific_param;
/* UniPG>> */
#ifdef USE_JPWL
/** enables writing of EPC in MH, thus activating JPWL */
bool epc_on;
/** enables writing of EPB, in case of activated JPWL */
bool epb_on;
/** enables writing of ESD, in case of activated JPWL */
bool esd_on;
/** enables writing of informative techniques of ESD, in case of activated JPWL */
bool info_on;
/** enables writing of RED, in case of activated JPWL */
bool red_on;
/** error protection method for MH (0,1,16,32,37-128) */
int hprot_MH;
/** tile number of header protection specification (>=0) */
int hprot_TPH_tileno[JPWL_MAX_NO_TILESPECS];
/** error protection methods for TPHs (0,1,16,32,37-128) */
int hprot_TPH[JPWL_MAX_NO_TILESPECS];
/** tile number of packet protection specification (>=0) */
int pprot_tileno[JPWL_MAX_NO_PACKSPECS];
/** packet number of packet protection specification (>=0) */
int pprot_packno[JPWL_MAX_NO_PACKSPECS];
/** error protection methods for packets (0,1,16,32,37-128) */
int pprot[JPWL_MAX_NO_PACKSPECS];
/** enables writing of ESD, (0/2/4 bytes) */
int sens_size;
/** sensitivity addressing size (0=auto/2/4 bytes) */
int sens_addr;
/** sensitivity range (0-3) */
int sens_range;
/** sensitivity method for MH (-1,0-7) */
int sens_MH;
/** tile number of sensitivity specification (>=0) */
int sens_TPH_tileno[JPWL_MAX_NO_TILESPECS];
/** sensitivity methods for TPHs (-1,0-7) */
int sens_TPH[JPWL_MAX_NO_TILESPECS];
/** enables JPWL correction at the decoder */
bool correct;
/** expected number of components at the decoder */
int exp_comps;
/** maximum number of tiles at the decoder */
int max_tiles;
#endif /* USE_JPWL */
/******** FLAGS *********/
/** if ppm == 1 --> there was a PPM marker*/
OPJ_UINT32 ppm : 1;
/** tells if the parameter is a coding or decoding one */
OPJ_UINT32 m_is_decoder : 1;
/* <<UniPG */
} opj_cp_v2_t;
typedef struct opj_j2k_dec
{
/** locate in which part of the codestream the decoder is (main header, tile header, end) */
OPJ_UINT32 m_state;
/**
* store decoding parameters common to all tiles (information like COD, COC in main header)
*/
opj_tcp_v2_t *m_default_tcp;
OPJ_BYTE *m_header_data;
OPJ_UINT32 m_header_data_size;
/** to tell the tile part length */
OPJ_UINT32 m_sot_length;
/** Only tiles index in the correct range will be decoded.*/
OPJ_UINT32 m_start_tile_x;
OPJ_UINT32 m_start_tile_y;
OPJ_UINT32 m_end_tile_x;
OPJ_UINT32 m_end_tile_y;
/** to tell that a tile can be decoded. */
OPJ_UINT32 m_can_decode : 1;
OPJ_UINT32 m_discard_tiles : 1;
OPJ_UINT32 m_skip_data : 1;
} opj_j2k_dec_t;
typedef struct opj_j2k_enc
{
/** Tile part number, regardless of poc, for each new poc, tp is reset to 1*/
OPJ_UINT32 m_current_poc_tile_part_number; // tp_num
/** Tile part number currently coding, taking into account POC. m_current_tile_part_number holds the total number of tile parts while encoding the last tile part.*/
OPJ_UINT32 m_current_tile_part_number; //cur_tp_num
/**
locate the start position of the TLM marker
after encoding the tilepart, a jump (in j2k_write_sod) is done to the TLM marker to store the value of its length.
*/
OPJ_SIZE_T m_tlm_start;
/**
* Stores the sizes of the tlm.
*/
OPJ_BYTE * m_tlm_sot_offsets_buffer;
/**
* The current offset of the tlm buffer.
*/
OPJ_BYTE * m_tlm_sot_offsets_current;
/** Total num of tile parts in whole image = num tiles* num tileparts in each tile*/
/** used in TLMmarker*/
OPJ_UINT32 m_total_tile_parts; // totnum_tp
/* encoded data for a tile */
OPJ_BYTE * m_encoded_tile_data;
/* size of the encoded_data */
OPJ_UINT32 m_encoded_tile_size;
/* encoded data for a tile */
OPJ_BYTE * m_header_tile_data;
/* size of the encoded_data */
OPJ_UINT32 m_header_tile_data_size;
} opj_j2k_enc_t;
/** /**
JPEG-2000 codestream reader/writer JPEG-2000 codestream reader/writer
*/ */
@ -368,6 +719,49 @@ typedef struct opj_j2k {
opj_cio_t *cio; opj_cio_t *cio;
} opj_j2k_t; } opj_j2k_t;
struct opj_tcd_v2;
/**
JPEG-2000 codestream reader/writer
*/
typedef struct opj_j2k_v2
{
union
{
opj_j2k_dec_t m_decoder;
opj_j2k_enc_t m_encoder;
}
m_specific_param;
/** number of the tile curently concern by coding/decoding */
OPJ_UINT32 m_current_tile_number;
/** pointer to the encoded / decoded image */
opj_image_t *m_image;
/** Coding parameters */
opj_cp_v2_t m_cp;
/** the list of procedures to exec **/
struct opj_procedure_list * m_procedure_list;
/** the list of validation procedures to follow to make sure the code is valid **/
struct opj_procedure_list * m_validation_list;
/** helper used to write the index file */
opj_codestream_info_t *cstr_info;
/** the current tile coder/decoder **/
struct opj_tcd_v2 * m_tcd;
//opj_tcd_v2_t * m_tcd;
OPJ_UINT32 m_is_decoder : 1;
}
opj_j2k_v2_t;
/** @name Exported functions */ /** @name Exported functions */
/*@{*/ /*@{*/
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
@ -443,4 +837,104 @@ opj_bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_code
/*@}*/ /*@}*/
/**
* Ends the decompression procedures and possibiliy add data to be read after the
* codestream.
*/
opj_bool j2k_end_decompress(opj_j2k_t *j2k, struct opj_stream_private *cio, struct opj_event_mgr * p_manager);
/**
* Reads a jpeg2000 codestream header structure.
*
* @param cio the stream to read data from.
* @param p_j2k the jpeg2000 codec.
* @param p_manager the user event manager.
*
* @return true if the box is valid.
*/
opj_bool j2k_read_header(
opj_j2k_v2_t *p_j2k,
struct opj_image ** p_image,
OPJ_INT32 * p_tile_x0,
OPJ_INT32 * p_tile_y0,
OPJ_UINT32 * p_tile_width,
OPJ_UINT32 * p_tile_height,
OPJ_UINT32 * p_nb_tiles_x,
OPJ_UINT32 * p_nb_tiles_y,
struct opj_stream_private *cio,
struct opj_event_mgr * p_manager
);
/**
* Destroys a jpeg2000 codec.
*
* @param p_j2k the jpeg20000 structure to destroy.
*/
void j2k_destroy (opj_j2k_v2_t *p_j2k);
/**
* Decode tile data.
* @param p_j2k the jpeg2000 codec.
* @param p_stream the stream to write data to.
* @param p_manager the user event manager.
*/
opj_bool j2k_decode_tile (
opj_j2k_v2_t * p_j2k,
OPJ_UINT32 p_tile_index,
OPJ_BYTE * p_data,
OPJ_UINT32 p_data_size,
struct opj_stream_private *p_stream,
struct opj_event_mgr * p_manager
);
/**
* Reads a tile header.
* @param p_j2k the jpeg2000 codec.
* @param p_stream the stream to write data to.
* @param p_manager the user event manager.
*/
opj_bool j2k_read_tile_header (
opj_j2k_v2_t * p_j2k,
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,
opj_bool * p_go_on,
struct opj_stream_private *p_stream,
struct opj_event_mgr * p_manager
);
/**
* Sets the given area to be decoded. This function should be called right after opj_read_header and before any tile header reading.
*
* @param p_j2k the jpeg2000 codec.
* @param p_start_x the left position of the rectangle to decode (in image coordinates).
* @param p_end_x the right position of the rectangle to decode (in image coordinates).
* @param p_start_y the up position of the rectangle to decode (in image coordinates).
* @param p_end_y the bottom position of the rectangle to decode (in image coordinates).
* @param p_manager the user event manager
*
* @return true if the area could be set.
*/
opj_bool j2k_set_decode_area(
opj_j2k_v2_t *p_j2k,
OPJ_INT32 p_start_x,
OPJ_INT32 p_start_y,
OPJ_INT32 p_end_x,
OPJ_INT32 p_end_y,
struct opj_event_mgr * p_manager
);
/**
* Creates a J2K decompression structure.
*
* @return a handle to a J2K decompressor if successful, NULL otherwise.
*/
opj_j2k_v2_t* j2k_create_decompress_v2();
#endif /* __J2K_H */ #endif /* __J2K_H */

View File

@ -188,3 +188,58 @@ void mct_decode_real(
double mct_getnorm_real(int compno) { double mct_getnorm_real(int compno) {
return mct_norms_real[compno]; return mct_norms_real[compno];
} }
opj_bool mct_decode_custom(
// MCT data
OPJ_BYTE * pDecodingData,
// size of components
OPJ_UINT32 n,
// components
OPJ_BYTE ** pData,
// nb of components (i.e. size of pData)
OPJ_UINT32 pNbComp,
// tells if the data is signed
OPJ_UINT32 isSigned)
{
OPJ_FLOAT32 * lMct;
OPJ_UINT32 i;
OPJ_UINT32 j;
OPJ_UINT32 k;
OPJ_FLOAT32 * lCurrentData = 00;
OPJ_FLOAT32 * lCurrentResult = 00;
OPJ_FLOAT32 ** lData = (OPJ_FLOAT32 **) pData;
lCurrentData = (OPJ_FLOAT32 *) opj_malloc (2 * pNbComp * sizeof(OPJ_FLOAT32));
if
(! lCurrentData)
{
return OPJ_FALSE;
}
lCurrentResult = lCurrentData + pNbComp;
for
(i = 0; i < n; ++i)
{
lMct = (OPJ_FLOAT32 *) pDecodingData;
for
(j=0;j<pNbComp;++j)
{
lCurrentData[j] = (OPJ_FLOAT32) (*(lData[j]));
}
for
(j=0;j<pNbComp;++j)
{
lCurrentResult[j] = 0;
for
(k=0;k<pNbComp;++k)
{
lCurrentResult[j] += *(lMct++) * lCurrentData[k];
}
*(lData[j]++) = (OPJ_FLOAT32) (lCurrentResult[j]);
}
}
opj_free(lCurrentData);
return OPJ_TRUE;
}

View File

@ -90,6 +90,18 @@ Get norm of the basis function used for the irreversible multi-component transfo
@return @return
*/ */
double mct_getnorm_real(int compno); double mct_getnorm_real(int compno);
opj_bool mct_decode_custom(
// MCT data
OPJ_BYTE * pDecodingData,
// size of components
OPJ_UINT32 n,
// components
OPJ_BYTE ** pData,
// nb of components (i.e. size of pData)
OPJ_UINT32 pNbComp,
// tells if the data is signed
OPJ_UINT32 isSigned);
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/*@}*/ /*@}*/

View File

@ -31,6 +31,116 @@
#include "opj_config.h" #include "opj_config.h"
#include "opj_includes.h" #include "opj_includes.h"
typedef struct opj_decompression
{
opj_bool (* opj_read_header) (
void *p_codec,
opj_image_t **,
OPJ_INT32 * p_tile_x0,
OPJ_INT32 * p_tile_y0,
OPJ_UINT32 * p_tile_width,
OPJ_UINT32 * p_tile_height,
OPJ_UINT32 * p_nb_tiles_x,
OPJ_UINT32 * p_nb_tiles_y,
struct opj_stream_private *cio,
struct opj_event_mgr * p_manager);
opj_image_t* (* opj_decode) (void * p_codec, struct opj_stream_private *p_cio, struct opj_event_mgr * p_manager);
opj_bool (*opj_read_tile_header)(
void * p_codec,
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,
opj_bool * p_should_go_on,
struct opj_stream_private *p_cio,
struct opj_event_mgr * p_manager);
opj_bool (*opj_decode_tile_data)(void * p_codec,OPJ_UINT32 p_tile_index,OPJ_BYTE * p_data,OPJ_UINT32 p_data_size,struct opj_stream_private *p_cio,struct opj_event_mgr * p_manager);
opj_bool (* opj_end_decompress) (void *p_codec,struct opj_stream_private *cio,struct opj_event_mgr * p_manager);
void (* opj_destroy) (void * p_codec);
void (*opj_setup_decoder) (void * p_codec,opj_dparameters_t * p_param);
opj_bool (*opj_set_decode_area) (void * p_codec,OPJ_INT32 p_start_x,OPJ_INT32 p_end_x,OPJ_INT32 p_start_y,OPJ_INT32 p_end_y,struct opj_event_mgr * p_manager);
}opj_decompression_t;
typedef struct opj_compression
{
opj_bool (* opj_start_compress) (void *p_codec,struct opj_stream_private *cio,struct opj_image * p_image, struct opj_event_mgr * p_manager);
opj_bool (* opj_encode) (void * p_codec, struct opj_stream_private *p_cio, struct opj_event_mgr * p_manager);
opj_bool (* opj_write_tile) (void * p_codec,OPJ_UINT32 p_tile_index,OPJ_BYTE * p_data,OPJ_UINT32 p_data_size,struct opj_stream_private * p_cio,struct opj_event_mgr * p_manager);
opj_bool (* opj_end_compress) (void * p_codec, struct opj_stream_private *p_cio, struct opj_event_mgr * p_manager);
void (* opj_destroy) (void * p_codec);
void (*opj_setup_encoder) (void * p_codec,opj_cparameters_t * p_param,struct opj_image * p_image, struct opj_event_mgr * p_manager);
}opj_compression_t;
typedef struct opj_codec_private
{
union
{ /* code-blocks informations */
opj_decompression_t m_decompression;
opj_compression_t m_compression;
} m_codec_data;
void * m_codec;
opj_event_mgr_t* m_event_mgr;
unsigned is_decompressor : 1;
}
opj_codec_private_t;
/**
* Default callback function.
* Do nothing.
*/
void opj_default_callback (const char *msg, void *client_data)
{
//FIXME V2 -> V1 cf below
}
void set_default_event_handler(opj_event_mgr_t * p_manager)
{
//FIXME V2 -> V1
//p_manager->m_error_data = 00;
//p_manager->m_warning_data = 00;
//p_manager->m_info_data = 00;
p_manager->error_handler = opj_default_callback;
p_manager->info_handler = opj_default_callback;
p_manager->warning_handler = opj_default_callback;
}
OPJ_UINT32 opj_read_from_file (void * p_buffer, OPJ_UINT32 p_nb_bytes, FILE * p_file)
{
OPJ_UINT32 l_nb_read = fread(p_buffer,1,p_nb_bytes,p_file);
return l_nb_read ? l_nb_read : -1;
}
OPJ_UINT32 opj_write_from_file (void * p_buffer, OPJ_UINT32 p_nb_bytes, FILE * p_file)
{
return fwrite(p_buffer,1,p_nb_bytes,p_file);
}
OPJ_SIZE_T opj_skip_from_file (OPJ_SIZE_T p_nb_bytes, FILE * p_user_data)
{
if
(fseek(p_user_data,p_nb_bytes,SEEK_CUR))
{
return -1;
}
return p_nb_bytes;
}
opj_bool opj_seek_from_file (OPJ_SIZE_T p_nb_bytes, FILE * p_user_data)
{
if
(fseek(p_user_data,p_nb_bytes,SEEK_SET))
{
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
#ifdef _WIN32 #ifdef _WIN32
#ifndef OPJ_STATIC #ifndef OPJ_STATIC
@ -95,6 +205,120 @@ opj_dinfo_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT format) {
return dinfo; return dinfo;
} }
opj_codec_t* OPJ_CALLCONV opj_create_decompress_v2(OPJ_CODEC_FORMAT p_format)
{
opj_codec_private_t *l_info = 00;
l_info = (opj_codec_private_t*) opj_calloc(1, sizeof(opj_codec_private_t));
if (!l_info){
return 00;
}
memset(l_info, 0, sizeof(opj_codec_private_t));
l_info->is_decompressor = 1;
switch
(p_format)
{
case CODEC_J2K:
l_info->m_codec_data.m_decompression.opj_decode = (opj_image_t* (*) (void *, struct opj_stream_private *, struct opj_event_mgr * ))j2k_decode;
l_info->m_codec_data.m_decompression.opj_end_decompress = (opj_bool (*) (void *,struct opj_stream_private *,struct opj_event_mgr *))j2k_end_decompress;
l_info->m_codec_data.m_decompression.opj_read_header = (opj_bool (*) (
void *,
opj_image_t **,
OPJ_INT32 * ,
OPJ_INT32 * ,
OPJ_UINT32 * ,
OPJ_UINT32 * ,
OPJ_UINT32 * ,
OPJ_UINT32 * ,
struct opj_stream_private *,
struct opj_event_mgr * )) j2k_read_header;
l_info->m_codec_data.m_decompression.opj_destroy = (void (*) (void *))j2k_destroy;
l_info->m_codec_data.m_decompression.opj_setup_decoder = (void (*) (void * ,opj_dparameters_t * )) j2k_setup_decoder;
l_info->m_codec_data.m_decompression.opj_read_tile_header = (opj_bool (*) (
void *,
OPJ_UINT32*,
OPJ_UINT32*,
OPJ_INT32 * ,
OPJ_INT32 * ,
OPJ_INT32 * ,
OPJ_INT32 * ,
OPJ_UINT32 * ,
opj_bool *,
struct opj_stream_private *,
struct opj_event_mgr * )) j2k_read_tile_header;
l_info->m_codec_data.m_decompression.opj_decode_tile_data = (opj_bool (*) (void *,OPJ_UINT32,OPJ_BYTE*,OPJ_UINT32,struct opj_stream_private *, struct opj_event_mgr * )) j2k_decode_tile;
l_info->m_codec_data.m_decompression.opj_set_decode_area = (opj_bool (*) (void *,OPJ_INT32,OPJ_INT32,OPJ_INT32,OPJ_INT32, struct opj_event_mgr * )) j2k_set_decode_area;
l_info->m_codec = j2k_create_decompress_v2();
if
(! l_info->m_codec)
{
opj_free(l_info);
return 00;
}
break;
case CODEC_JP2:
/* get a JP2 decoder handle */
#ifdef TODO_MSD
l_info->m_codec_data.m_decompression.opj_decode = (opj_image_t* (*) (void *, struct opj_stream_private *, struct opj_event_mgr * ))opj_jp2_decode;
l_info->m_codec_data.m_decompression.opj_end_decompress = (opj_bool (*) (void *,struct opj_stream_private *,struct opj_event_mgr *)) jp2_end_decompress;
l_info->m_codec_data.m_decompression.opj_read_header = (opj_bool (*) (
void *,
opj_image_t **,
OPJ_INT32 * ,
OPJ_INT32 * ,
OPJ_UINT32 * ,
OPJ_UINT32 * ,
OPJ_UINT32 * ,
OPJ_UINT32 * ,
struct opj_stream_private *,
struct opj_event_mgr * )) jp2_read_header;
l_info->m_codec_data.m_decompression.opj_read_tile_header = (
opj_bool (*) (
void *,
OPJ_UINT32*,
OPJ_UINT32*,
OPJ_INT32*,
OPJ_INT32*,
OPJ_INT32 * ,
OPJ_INT32 * ,
OPJ_UINT32 * ,
opj_bool *,
struct opj_stream_private *,
struct opj_event_mgr * )) jp2_read_tile_header;
l_info->m_codec_data.m_decompression.opj_decode_tile_data = (opj_bool (*) (void *,OPJ_UINT32,OPJ_BYTE*,OPJ_UINT32,struct opj_stream_private *, struct opj_event_mgr * )) opj_jp2_decode_tile;
l_info->m_codec_data.m_decompression.opj_destroy = (void (*) (void *))jp2_destroy;
l_info->m_codec_data.m_decompression.opj_setup_decoder = (void (*) (void * ,opj_dparameters_t * )) jp2_setup_decoder;
l_info->m_codec_data.m_decompression.opj_set_decode_area = (opj_bool (*) (void *,OPJ_INT32,OPJ_INT32,OPJ_INT32,OPJ_INT32, struct opj_event_mgr * )) jp2_set_decode_area;
l_info->m_codec = jp2_create(OPJ_TRUE);
if
(! l_info->m_codec)
{
opj_free(l_info);
return 00;
}
#endif
break;
case CODEC_UNKNOWN:
case CODEC_JPT:
default:
opj_free(l_info);
return 00;
}
// FIXME set_default_event_handler(&(l_info->m_event_mgr));
return (opj_codec_t*) l_info;
}
void OPJ_CALLCONV opj_destroy_decompress(opj_dinfo_t *dinfo) { void OPJ_CALLCONV opj_destroy_decompress(opj_dinfo_t *dinfo) {
if(dinfo) { if(dinfo) {
/* destroy the codec */ /* destroy the codec */
@ -152,6 +376,22 @@ void OPJ_CALLCONV opj_setup_decoder(opj_dinfo_t *dinfo, opj_dparameters_t *param
} }
} }
opj_bool OPJ_CALLCONV opj_setup_decoder_v2(opj_codec_t *p_info, opj_dparameters_t *parameters, opj_event_mgr_t* event_mgr)
{
if (p_info && parameters) {
opj_codec_private_t * l_info = (opj_codec_private_t *) p_info;
if (! l_info->is_decompressor) {
return OPJ_FALSE;
}
l_info->m_codec_data.m_decompression.opj_setup_decoder(l_info->m_codec,parameters);
l_info->m_event_mgr = event_mgr;
return OPJ_TRUE;
}
return OPJ_FALSE;
}
opj_image_t* OPJ_CALLCONV opj_decode(opj_dinfo_t *dinfo, opj_cio_t *cio) { opj_image_t* OPJ_CALLCONV opj_decode(opj_dinfo_t *dinfo, opj_cio_t *cio) {
return opj_decode_with_info(dinfo, cio, NULL); return opj_decode_with_info(dinfo, cio, NULL);
} }
@ -284,6 +524,39 @@ void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t *paramete
} }
} }
/**
* Helper function.
* Sets the stream to be a file stream. The FILE must have been open previously.
* @param p_stream the stream to modify
* @param p_file handler to an already open file.
*/
opj_stream_t* OPJ_CALLCONV opj_stream_create_default_file_stream (FILE * p_file, opj_bool p_is_read_stream)
{
return opj_stream_create_file_stream(p_file,J2K_STREAM_CHUNK_SIZE,p_is_read_stream);
}
opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream (FILE * p_file, OPJ_UINT32 p_size, opj_bool p_is_read_stream)
{
opj_stream_t* l_stream = 00;
if
(! p_file)
{
return 00;
}
l_stream = opj_stream_create(p_size,p_is_read_stream);
if
(! l_stream)
{
return 00;
}
opj_stream_set_user_data(l_stream,p_file);
opj_stream_set_read_function(l_stream,(opj_stream_read_fn) opj_read_from_file);
opj_stream_set_write_function(l_stream, (opj_stream_write_fn) opj_write_from_file);
opj_stream_set_skip_function(l_stream, (opj_stream_skip_fn) opj_skip_from_file);
opj_stream_set_seek_function(l_stream, (opj_stream_seek_fn) opj_seek_from_file);
return l_stream;
}
void OPJ_CALLCONV opj_setup_encoder(opj_cinfo_t *cinfo, opj_cparameters_t *parameters, opj_image_t *image) { void OPJ_CALLCONV opj_setup_encoder(opj_cinfo_t *cinfo, opj_cparameters_t *parameters, opj_image_t *image) {
if(cinfo && parameters && image) { if(cinfo && parameters && image) {
switch(cinfo->codec_format) { switch(cinfo->codec_format) {
@ -340,3 +613,61 @@ void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_t *cstr_info) {
opj_free(cstr_info->numdecompos); opj_free(cstr_info->numdecompos);
} }
} }
opj_bool OPJ_CALLCONV opj_read_header (
opj_codec_t *p_codec,
opj_image_t ** p_image,
OPJ_INT32 * p_tile_x0,
OPJ_INT32 * p_tile_y0,
OPJ_UINT32 * p_tile_width,
OPJ_UINT32 * p_tile_height,
OPJ_UINT32 * p_nb_tiles_x,
OPJ_UINT32 * p_nb_tiles_y,
opj_stream_t *p_cio)
{
if
(p_codec && p_cio)
{
opj_codec_private_t * l_info = (opj_codec_private_t *) p_codec;
opj_stream_private_t * l_cio = (opj_stream_private_t *) p_cio;
if
(! l_info->is_decompressor)
{
return OPJ_FALSE;
}
return l_info->m_codec_data.m_decompression.opj_read_header(
l_info->m_codec,
p_image,
p_tile_x0,
p_tile_y0,
p_tile_width,
p_tile_height,
p_nb_tiles_x,
p_nb_tiles_y,
l_cio,
//&(l_info->m_event_mgr));
l_info->m_event_mgr);
}
return OPJ_FALSE;
}
void OPJ_CALLCONV opj_destroy_codec(opj_codec_t *p_info)
{
if
(p_info)
{
opj_codec_private_t * l_info = (opj_codec_private_t *) p_info;
if
(l_info->is_decompressor)
{
l_info->m_codec_data.m_decompression.opj_destroy(l_info->m_codec);
}
else
{
l_info->m_codec_data.m_compression.opj_destroy(l_info->m_codec);
}
l_info->m_codec = 00;
opj_free(l_info);
}
}

View File

@ -64,8 +64,19 @@ typedef int opj_bool;
#define OPJ_TRUE 1 #define OPJ_TRUE 1
#define OPJ_FALSE 0 #define OPJ_FALSE 0
typedef unsigned int OPJ_UINT32;
typedef int OPJ_INT32;
typedef unsigned short OPJ_UINT16;
typedef short OPJ_INT16;
typedef char OPJ_CHAR;
typedef unsigned char OPJ_BYTE;
typedef unsigned int OPJ_SIZE_T;
typedef double OPJ_FLOAT64;
typedef float OPJ_FLOAT32;
// Avoid compile-time warning because parameter is not used // Avoid compile-time warning because parameter is not used
#define OPJ_ARG_NOT_USED(x) (void)(x) #define OPJ_ARG_NOT_USED(x) (void)(x)
/* /*
========================================================== ==========================================================
Useful constant definitions Useful constant definitions
@ -77,6 +88,12 @@ typedef int opj_bool;
#define J2K_MAXRLVLS 33 /**< Number of maximum resolution level authorized */ #define J2K_MAXRLVLS 33 /**< Number of maximum resolution level authorized */
#define J2K_MAXBANDS (3*J2K_MAXRLVLS-2) /**< Number of maximum sub-band linked to number of resolution level */ #define J2K_MAXBANDS (3*J2K_MAXRLVLS-2) /**< Number of maximum sub-band linked to number of resolution level */
#define J2K_DEFAULT_NB_SEGS 10
#define J2K_STREAM_CHUNK_SIZE 0x100000 /** 1 mega by default */
#define J2K_DEFAULT_HEADER_SIZE 1000
#define J2K_MCC_DEFAULT_NB_RECORDS 10
#define J2K_MCT_DEFAULT_NB_RECORDS 10
/* UniPG>> */ /* UniPG>> */
#define JPWL_MAX_NO_TILESPECS 16 /**< Maximum number of tile parts expected by JPWL: increase at your will */ #define JPWL_MAX_NO_TILESPECS 16 /**< Maximum number of tile parts expected by JPWL: increase at your will */
#define JPWL_MAX_NO_PACKSPECS 16 /**< Maximum number of packet parts expected by JPWL: increase at your will */ #define JPWL_MAX_NO_PACKSPECS 16 /**< Maximum number of packet parts expected by JPWL: increase at your will */
@ -177,6 +194,7 @@ used for
</ul> </ul>
*/ */
typedef struct opj_event_mgr { typedef struct opj_event_mgr {
void* client_data;
/** Error message callback if available, NULL otherwise */ /** Error message callback if available, NULL otherwise */
opj_msg_callback error_handler; opj_msg_callback error_handler;
/** Warning message callback if available, NULL otherwise */ /** Warning message callback if available, NULL otherwise */
@ -448,6 +466,11 @@ typedef struct opj_dinfo {
/* other specific fields go here */ /* other specific fields go here */
} opj_dinfo_t; } opj_dinfo_t;
/**
* J2k codec.
*/
typedef void * opj_codec_t;
/* /*
========================================================== ==========================================================
I/O stream typedef definitions I/O stream typedef definitions
@ -484,6 +507,14 @@ typedef struct opj_cio {
unsigned char *bp; unsigned char *bp;
} opj_cio_t; } opj_cio_t;
typedef OPJ_UINT32 (* opj_stream_read_fn) (void * p_buffer, OPJ_UINT32 p_nb_bytes, void * p_user_data) ;
typedef OPJ_UINT32 (* opj_stream_write_fn) (void * p_buffer, OPJ_UINT32 p_nb_bytes, void * p_user_data) ;
typedef OPJ_SIZE_T (* opj_stream_skip_fn) (OPJ_SIZE_T p_nb_bytes, void * p_user_data) ;
typedef opj_bool (* opj_stream_seek_fn) (OPJ_SIZE_T p_nb_bytes, void * p_user_data) ;
typedef void * opj_stream_t;
/* /*
========================================================== ==========================================================
image typedef definitions image typedef definitions
@ -525,15 +556,15 @@ Defines image data and characteristics
*/ */
typedef struct opj_image { typedef struct opj_image {
/** XOsiz: horizontal offset from the origin of the reference grid to the left side of the image area */ /** XOsiz: horizontal offset from the origin of the reference grid to the left side of the image area */
int x0; OPJ_UINT32 x0;
/** YOsiz: vertical offset from the origin of the reference grid to the top side of the image area */ /** YOsiz: vertical offset from the origin of the reference grid to the top side of the image area */
int y0; OPJ_UINT32 y0;
/** Xsiz: width of the reference grid */ /** Xsiz: width of the reference grid */
int x1; OPJ_UINT32 x1;
/** Ysiz: height of the reference grid */ /** Ysiz: height of the reference grid */
int y1; OPJ_UINT32 y1;
/** number of components in the image */ /** number of components in the image */
int numcomps; OPJ_UINT16 numcomps;
/** color space: sRGB, Greyscale or YUV */ /** color space: sRGB, Greyscale or YUV */
OPJ_COLOR_SPACE color_space; OPJ_COLOR_SPACE color_space;
/** image components */ /** image components */
@ -544,6 +575,7 @@ typedef struct opj_image {
int icc_profile_len; int icc_profile_len;
} opj_image_t; } opj_image_t;
/** /**
Component parameters structure used by the opj_image_create function Component parameters structure used by the opj_image_create function
*/ */
@ -783,6 +815,73 @@ Set position in byte stream
*/ */
OPJ_API void OPJ_CALLCONV cio_seek(opj_cio_t *cio, int pos); OPJ_API void OPJ_CALLCONV cio_seek(opj_cio_t *cio, int pos);
/**
* Creates an abstract stream. This function does nothing except allocating memory and initializing the abstract stream.
*
* @param l_is_reader if set to true then the stream will be an input stream, an output stream else.
*
* @return a stream object.
*/
OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_default_create(opj_bool p_is_input);
OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create(OPJ_UINT32 p_size, opj_bool p_is_input);
/**
* Destroys a stream created by opj_create_stream. This function does NOT close the abstract stream. If needed the user must
* close its own implementation of the stream.
*
* @param p_stream the stream to destroy.
*/
OPJ_API void OPJ_CALLCONV opj_stream_destroy(opj_stream_t* p_stream);
/**
* Sets the given function to be used as a read function.
* @param p_stream the stream to modify
* @param p_function the function to use a read function.
*/
OPJ_API void OPJ_CALLCONV opj_stream_set_read_function(opj_stream_t* p_stream, opj_stream_read_fn p_function);
/**
* Sets the given function to be used as a write function.
* @param p_stream the stream to modify
* @param p_function the function to use a write function.
*/
OPJ_API void OPJ_CALLCONV opj_stream_set_write_function(opj_stream_t* p_stream, opj_stream_write_fn p_function);
/**
* Sets the given function to be used as a skip function.
* @param p_stream the stream to modify
* @param p_function the function to use a skip function.
*/
OPJ_API void OPJ_CALLCONV opj_stream_set_skip_function(opj_stream_t* p_stream, opj_stream_skip_fn p_function);
/**
* Sets the given function to be used as a seek function, the stream is then seekable.
* @param p_stream the stream to modify
* @param p_function the function to use a skip function.
*/
OPJ_API void OPJ_CALLCONV opj_stream_set_seek_function(opj_stream_t* p_stream, opj_stream_seek_fn p_function);
/**
* Sets the given data to be used as a user data for the stream.
* @param p_stream the stream to modify
* @param p_data the data to set.
*/
OPJ_API void OPJ_CALLCONV opj_stream_set_user_data (opj_stream_t* p_stream, void * p_data);
/**
* Helper function.
* Sets the stream to be a file stream. The FILE must have been open previously.
* @param p_stream the stream to modify
* @param p_file handler to an already open file.
*/
OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_default_file_stream (FILE * p_file, opj_bool p_is_read_stream);
OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream (FILE * p_file, OPJ_UINT32 p_buffer_size, opj_bool p_is_read_stream);
/* /*
========================================================== ==========================================================
event manager functions definitions event manager functions definitions
@ -796,6 +895,14 @@ OPJ_API opj_event_mgr_t* OPJ_CALLCONV opj_set_event_mgr(opj_common_ptr cinfo, op
codec functions definitions codec functions definitions
========================================================== ==========================================================
*/ */
/**
Creates a J2K/JPT/JP2 decompression structure
@param format Decoder to select
@return Returns a handle to a decompressor if successful, returns NULL otherwise
*/
OPJ_API opj_codec_t* OPJ_CALLCONV opj_create_decompress_v2(OPJ_CODEC_FORMAT format);
/** /**
Creates a J2K/JPT/JP2 decompression structure Creates a J2K/JPT/JP2 decompression structure
@param format Decoder to select @param format Decoder to select
@ -819,6 +926,11 @@ Decoding parameters are returned in j2k->cp.
@param parameters decompression parameters @param parameters decompression parameters
*/ */
OPJ_API void OPJ_CALLCONV opj_setup_decoder(opj_dinfo_t *dinfo, opj_dparameters_t *parameters); OPJ_API void OPJ_CALLCONV opj_setup_decoder(opj_dinfo_t *dinfo, opj_dparameters_t *parameters);
OPJ_API opj_bool OPJ_CALLCONV opj_setup_decoder_v2( opj_codec_t *p_info,
opj_dparameters_t *parameters,
opj_event_mgr_t* event_mgr);
/** /**
Decode an image from a JPEG-2000 codestream Decode an image from a JPEG-2000 codestream
@param dinfo decompressor handle @param dinfo decompressor handle
@ -900,6 +1012,35 @@ Destroy Codestream information after compression or decompression
OPJ_API void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_t *cstr_info); OPJ_API void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_t *cstr_info);
/**
* Decodes an image header.
*
* @param p_codec codec to use to decode the image.
* @param p_image pointer to a previously created image.
* @param p_tile_x0 pointer to a value that will hold the reference point x0 of the tiling grid.
* @param p_tile_y0 pointer to a value that will hold the reference point y0 of the tiling grid.
* @param p_tile_width pointer to a value that will hold the size in x of a tile in the grid.
* @param p_tile_height pointer to a value that will hold the size in y of a tile in the grid.
* @param p_nb_tiles_x pointer to a value that will hold the number of tiles in the x direction.
* @param p_nb_tiles_y pointer to a value that will hold the number of tiles in the y direction.
*/
OPJ_API opj_bool OPJ_CALLCONV opj_read_header (
opj_codec_t *p_codec,
opj_image_t ** p_image,
OPJ_INT32 * p_tile_x0,
OPJ_INT32 * p_tile_y0,
OPJ_UINT32 * p_tile_width,
OPJ_UINT32 * p_tile_height,
OPJ_UINT32 * p_nb_tiles_x,
OPJ_UINT32 * p_nb_tiles_y,
opj_stream_t *p_cio);
/**
Destroy a decompressor handle
@param dinfo decompressor handle to destroy
*/
OPJ_API void OPJ_CALLCONV opj_destroy_codec(opj_codec_t * p_codec);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -40,6 +40,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <ctype.h> #include <ctype.h>
#include <assert.h>
/* /*
========================================================== ==========================================================
@ -136,4 +137,7 @@ static INLINE long lrintf(float f){
#endif /* USE_JPWL */ #endif /* USE_JPWL */
/* <<JPWL */ /* <<JPWL */
// V2
#include "function_list.h"
#endif /* OPJ_INCLUDES_H */ #endif /* OPJ_INCLUDES_H */

View File

@ -69,6 +69,62 @@ Get next packet in component-precinct-resolution-layer order.
*/ */
static opj_bool pi_next_cprl(opj_pi_iterator_t * pi); static opj_bool pi_next_cprl(opj_pi_iterator_t * pi);
/**
* Gets the encoding parameters needed to update the coding parameters and all the pocs.
* The precinct widths, heights, dx and dy for each component at each resolution will be stored as well.
* the last parameter of the function should be an array of pointers of size nb components, each pointer leading
* to an area of size 4 * max_res. The data is stored inside this area with the following pattern :
* dx_compi_res0 , dy_compi_res0 , w_compi_res0, h_compi_res0 , dx_compi_res1 , dy_compi_res1 , w_compi_res1, h_compi_res1 , ...
*
* @param p_image the image being encoded.
* @param p_cp the coding parameters.
* @param tileno the tile index of the tile being encoded.
* @param p_tx0 pointer that will hold the X0 parameter for the tile
* @param p_tx1 pointer that will hold the X1 parameter for the tile
* @param p_ty0 pointer that will hold the Y0 parameter for the tile
* @param p_ty1 pointer that will hold the Y1 parameter for the tile
* @param p_max_prec pointer that will hold the the maximum precision for all the bands of the tile
* @param p_max_res pointer that will hold the the maximum number of resolutions for all the poc inside the tile.
* @param dx_min pointer that will hold the the minimum dx of all the components of all the resolutions for the tile.
* @param dy_min pointer that will hold the the minimum dy of all the components of all the resolutions for the tile.
* @param p_resolutions pointer to an area corresponding to the one described above.
*/
void get_all_encoding_parameters(
const opj_image_t *p_image,
const opj_cp_v2_t *p_cp,
OPJ_UINT32 tileno,
OPJ_INT32 * p_tx0,
OPJ_INT32 * p_tx1,
OPJ_INT32 * p_ty0,
OPJ_INT32 * p_ty1,
OPJ_UINT32 * p_dx_min,
OPJ_UINT32 * p_dy_min,
OPJ_UINT32 * p_max_prec,
OPJ_UINT32 * p_max_res,
OPJ_UINT32 ** p_resolutions
);
/**
* Allocates memory for a packet iterator. Data and data sizes are set by this operation.
* No other data is set. The include section of the packet iterator is not allocated.
*
* @param p_image the image used to initialize the packet iterator (in fact only the number of components is relevant.
* @param p_cp the coding parameters.
* @param p_tile_no the index of the tile from which creating the packet iterator.
*/
opj_pi_iterator_t * pi_create(
const opj_image_t *image,
const opj_cp_v2_t *cp,
OPJ_UINT32 tileno
);
void pi_update_decode_not_poc (opj_pi_iterator_t * p_pi,opj_tcp_v2_t * p_tcp,OPJ_UINT32 p_max_precision,OPJ_UINT32 p_max_res);
void pi_update_decode_poc (opj_pi_iterator_t * p_pi,opj_tcp_v2_t * p_tcp,OPJ_UINT32 p_max_precision,OPJ_UINT32 p_max_res);
/*@}*/ /*@}*/
/*@}*/ /*@}*/
@ -540,6 +596,210 @@ opj_pi_iterator_t *pi_create_decode(opj_image_t *image, opj_cp_t *cp, int tileno
} }
opj_pi_iterator_t *pi_create_decode_v2(
opj_image_t *p_image,
opj_cp_v2_t *p_cp,
OPJ_UINT32 p_tile_no
)
{
// loop
OPJ_UINT32 pino;
OPJ_UINT32 compno, resno;
// to store w, h, dx and dy fro all components and resolutions
OPJ_UINT32 * l_tmp_data;
OPJ_UINT32 ** l_tmp_ptr;
// encoding prameters to set
OPJ_UINT32 l_max_res;
OPJ_UINT32 l_max_prec;
OPJ_INT32 l_tx0,l_tx1,l_ty0,l_ty1;
OPJ_UINT32 l_dx_min,l_dy_min;
OPJ_UINT32 l_bound;
OPJ_UINT32 l_step_p , l_step_c , l_step_r , l_step_l ;
OPJ_UINT32 l_data_stride;
// pointers
opj_pi_iterator_t *l_pi = 00;
opj_tcp_v2_t *l_tcp = 00;
const opj_tccp_t *l_tccp = 00;
opj_pi_comp_t *l_current_comp = 00;
opj_image_comp_t * l_img_comp = 00;
opj_pi_iterator_t * l_current_pi = 00;
OPJ_UINT32 * l_encoding_value_ptr = 00;
// preconditions in debug
assert(p_cp != 00);
assert(p_image != 00);
assert(p_tile_no < p_cp->tw * p_cp->th);
// initializations
l_tcp = &p_cp->tcps[p_tile_no];
l_bound = l_tcp->numpocs+1;
l_data_stride = 4 * J2K_MAXRLVLS;
l_tmp_data = (OPJ_UINT32*)opj_malloc(
l_data_stride * p_image->numcomps * sizeof(OPJ_UINT32));
if
(! l_tmp_data)
{
return 00;
}
l_tmp_ptr = (OPJ_UINT32**)opj_malloc(
p_image->numcomps * sizeof(OPJ_UINT32 *));
if
(! l_tmp_ptr)
{
opj_free(l_tmp_data);
return 00;
}
// memory allocation for pi
l_pi = pi_create(p_image,p_cp,p_tile_no);
if
(!l_pi)
{
opj_free(l_tmp_data);
opj_free(l_tmp_ptr);
return 00;
}
l_encoding_value_ptr = l_tmp_data;
// update pointer array
for
(compno = 0; compno < p_image->numcomps; ++compno)
{
l_tmp_ptr[compno] = l_encoding_value_ptr;
l_encoding_value_ptr += l_data_stride;
}
// get encoding parameters
get_all_encoding_parameters(p_image,p_cp,p_tile_no,&l_tx0,&l_tx1,&l_ty0,&l_ty1,&l_dx_min,&l_dy_min,&l_max_prec,&l_max_res,l_tmp_ptr);
// step calculations
l_step_p = 1;
l_step_c = l_max_prec * l_step_p;
l_step_r = p_image->numcomps * l_step_c;
l_step_l = l_max_res * l_step_r;
// set values for first packet iterator
l_current_pi = l_pi;
// memory allocation for include
l_current_pi->include = (OPJ_INT16*) opj_calloc(l_tcp->numlayers * l_step_l, sizeof(OPJ_INT16));
if
(!l_current_pi->include)
{
opj_free(l_tmp_data);
opj_free(l_tmp_ptr);
pi_destroy_v2(l_pi, l_bound);
return 00;
}
memset(l_current_pi->include,0,l_tcp->numlayers * l_step_l* sizeof(OPJ_INT16));
// special treatment for the first packet iterator
l_current_comp = l_current_pi->comps;
l_img_comp = p_image->comps;
l_tccp = l_tcp->tccps;
l_current_pi->tx0 = l_tx0;
l_current_pi->ty0 = l_ty0;
l_current_pi->tx1 = l_tx1;
l_current_pi->ty1 = l_ty1;
//l_current_pi->dx = l_img_comp->dx;
//l_current_pi->dy = l_img_comp->dy;
l_current_pi->step_p = l_step_p;
l_current_pi->step_c = l_step_c;
l_current_pi->step_r = l_step_r;
l_current_pi->step_l = l_step_l;
/* allocation for components and number of components has already been calculated by pi_create */
for
(compno = 0; compno < l_current_pi->numcomps; ++compno)
{
opj_pi_resolution_t *l_res = l_current_comp->resolutions;
l_encoding_value_ptr = l_tmp_ptr[compno];
l_current_comp->dx = l_img_comp->dx;
l_current_comp->dy = l_img_comp->dy;
/* resolutions have already been initialized */
for
(resno = 0; resno < l_current_comp->numresolutions; resno++)
{
l_res->pdx = *(l_encoding_value_ptr++);
l_res->pdy = *(l_encoding_value_ptr++);
l_res->pw = *(l_encoding_value_ptr++);
l_res->ph = *(l_encoding_value_ptr++);
++l_res;
}
++l_current_comp;
++l_img_comp;
++l_tccp;
}
++l_current_pi;
for
(pino = 1 ; pino<l_bound ; ++pino )
{
opj_pi_comp_t *l_current_comp = l_current_pi->comps;
opj_image_comp_t * l_img_comp = p_image->comps;
l_tccp = l_tcp->tccps;
l_current_pi->tx0 = l_tx0;
l_current_pi->ty0 = l_ty0;
l_current_pi->tx1 = l_tx1;
l_current_pi->ty1 = l_ty1;
//l_current_pi->dx = l_dx_min;
//l_current_pi->dy = l_dy_min;
l_current_pi->step_p = l_step_p;
l_current_pi->step_c = l_step_c;
l_current_pi->step_r = l_step_r;
l_current_pi->step_l = l_step_l;
/* allocation for components and number of components has already been calculated by pi_create */
for
(compno = 0; compno < l_current_pi->numcomps; ++compno)
{
opj_pi_resolution_t *l_res = l_current_comp->resolutions;
l_encoding_value_ptr = l_tmp_ptr[compno];
l_current_comp->dx = l_img_comp->dx;
l_current_comp->dy = l_img_comp->dy;
/* resolutions have already been initialized */
for
(resno = 0; resno < l_current_comp->numresolutions; resno++)
{
l_res->pdx = *(l_encoding_value_ptr++);
l_res->pdy = *(l_encoding_value_ptr++);
l_res->pw = *(l_encoding_value_ptr++);
l_res->ph = *(l_encoding_value_ptr++);
++l_res;
}
++l_current_comp;
++l_img_comp;
++l_tccp;
}
// special treatment
l_current_pi->include = (l_current_pi-1)->include;
++l_current_pi;
}
opj_free(l_tmp_data);
l_tmp_data = 00;
opj_free(l_tmp_ptr);
l_tmp_ptr = 00;
if
(l_tcp->POC)
{
pi_update_decode_poc (l_pi,l_tcp,l_max_prec,l_max_res);
}
else
{
pi_update_decode_not_poc(l_pi,l_tcp,l_max_prec,l_max_res);
}
return l_pi;
}
opj_pi_iterator_t *pi_initialise_encode(opj_image_t *image, opj_cp_t *cp, int tileno, J2K_T2_MODE t2_mode){ opj_pi_iterator_t *pi_initialise_encode(opj_image_t *image, opj_cp_t *cp, int tileno, J2K_T2_MODE t2_mode){
int p, q, pino; int p, q, pino;
int compno, resno; int compno, resno;
@ -961,3 +1221,355 @@ opj_bool pi_create_encode( opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int p
return OPJ_FALSE; return OPJ_FALSE;
} }
/**
* Gets the encoding parameters needed to update the coding parameters and all the pocs.
* The precinct widths, heights, dx and dy for each component at each resolution will be stored as well.
* the last parameter of the function should be an array of pointers of size nb components, each pointer leading
* to an area of size 4 * max_res. The data is stored inside this area with the following pattern :
* dx_compi_res0 , dy_compi_res0 , w_compi_res0, h_compi_res0 , dx_compi_res1 , dy_compi_res1 , w_compi_res1, h_compi_res1 , ...
*
* @param p_image the image being encoded.
* @param p_cp the coding parameters.
* @param tileno the tile index of the tile being encoded.
* @param p_tx0 pointer that will hold the X0 parameter for the tile
* @param p_tx1 pointer that will hold the X1 parameter for the tile
* @param p_ty0 pointer that will hold the Y0 parameter for the tile
* @param p_ty1 pointer that will hold the Y1 parameter for the tile
* @param p_max_prec pointer that will hold the the maximum precision for all the bands of the tile
* @param p_max_res pointer that will hold the the maximum number of resolutions for all the poc inside the tile.
* @param dx_min pointer that will hold the the minimum dx of all the components of all the resolutions for the tile.
* @param dy_min pointer that will hold the the minimum dy of all the components of all the resolutions for the tile.
* @param p_resolutions pointer to an area corresponding to the one described above.
*/
void get_all_encoding_parameters(
const opj_image_t *p_image,
const opj_cp_v2_t *p_cp,
OPJ_UINT32 tileno,
OPJ_INT32 * p_tx0,
OPJ_INT32 * p_tx1,
OPJ_INT32 * p_ty0,
OPJ_INT32 * p_ty1,
OPJ_UINT32 * p_dx_min,
OPJ_UINT32 * p_dy_min,
OPJ_UINT32 * p_max_prec,
OPJ_UINT32 * p_max_res,
OPJ_UINT32 ** p_resolutions
)
{
// loop
OPJ_UINT32 compno, resno;
// pointers
const opj_tcp_v2_t *tcp = 00;
const opj_tccp_t * l_tccp = 00;
const opj_image_comp_t * l_img_comp = 00;
// to store l_dx, l_dy, w and h for each resolution and component.
OPJ_UINT32 * lResolutionPtr;
// position in x and y of tile
OPJ_UINT32 p, q;
// preconditions in debug
assert(p_cp != 00);
assert(p_image != 00);
assert(tileno < p_cp->tw * p_cp->th);
// initializations
tcp = &p_cp->tcps [tileno];
l_tccp = tcp->tccps;
l_img_comp = p_image->comps;
// position in x and y of tile
p = tileno % p_cp->tw;
q = tileno / p_cp->tw;
/* here calculation of tx0, tx1, ty0, ty1, maxprec, l_dx and l_dy */
*p_tx0 = int_max(p_cp->tx0 + p * p_cp->tdx, p_image->x0);
*p_tx1 = int_min(p_cp->tx0 + (p + 1) * p_cp->tdx, p_image->x1);
*p_ty0 = int_max(p_cp->ty0 + q * p_cp->tdy, p_image->y0);
*p_ty1 = int_min(p_cp->ty0 + (q + 1) * p_cp->tdy, p_image->y1);
// max precision and resolution is 0 (can only grow)
*p_max_prec = 0;
*p_max_res = 0;
// take the largest value for dx_min and dy_min
*p_dx_min = 0x7fffffff;
*p_dy_min = 0x7fffffff;
for
(compno = 0; compno < p_image->numcomps; ++compno)
{
// aritmetic variables to calculate
OPJ_UINT32 l_level_no;
OPJ_INT32 l_rx0, l_ry0, l_rx1, l_ry1;
OPJ_INT32 l_px0, l_py0, l_px1, py1;
OPJ_UINT32 l_product;
OPJ_INT32 l_tcx0, l_tcy0, l_tcx1, l_tcy1;
OPJ_UINT32 l_pdx, l_pdy , l_pw , l_ph;
lResolutionPtr = p_resolutions[compno];
l_tcx0 = int_ceildiv(*p_tx0, l_img_comp->dx);
l_tcy0 = int_ceildiv(*p_ty0, l_img_comp->dy);
l_tcx1 = int_ceildiv(*p_tx1, l_img_comp->dx);
l_tcy1 = int_ceildiv(*p_ty1, l_img_comp->dy);
if
(l_tccp->numresolutions > *p_max_res)
{
*p_max_res = l_tccp->numresolutions;
}
// use custom size for precincts
l_level_no = l_tccp->numresolutions - 1;
for
(resno = 0; resno < l_tccp->numresolutions; ++resno)
{
OPJ_UINT32 l_dx, l_dy;
// precinct width and height
l_pdx = l_tccp->prcw[resno];
l_pdy = l_tccp->prch[resno];
*lResolutionPtr++ = l_pdx;
*lResolutionPtr++ = l_pdy;
l_dx = l_img_comp->dx * (1 << (l_pdx + l_level_no));
l_dy = l_img_comp->dy * (1 << (l_pdy + l_level_no));
// take the minimum size for l_dx for each comp and resolution
*p_dx_min = int_min(*p_dx_min, l_dx);
*p_dy_min = int_min(*p_dy_min, l_dy);
// various calculations of extents
l_rx0 = int_ceildivpow2(l_tcx0, l_level_no);
l_ry0 = int_ceildivpow2(l_tcy0, l_level_no);
l_rx1 = int_ceildivpow2(l_tcx1, l_level_no);
l_ry1 = int_ceildivpow2(l_tcy1, l_level_no);
l_px0 = int_floordivpow2(l_rx0, l_pdx) << l_pdx;
l_py0 = int_floordivpow2(l_ry0, l_pdy) << l_pdy;
l_px1 = int_ceildivpow2(l_rx1, l_pdx) << l_pdx;
py1 = int_ceildivpow2(l_ry1, l_pdy) << l_pdy;
l_pw = (l_rx0==l_rx1)?0:((l_px1 - l_px0) >> l_pdx);
l_ph = (l_ry0==l_ry1)?0:((py1 - l_py0) >> l_pdy);
*lResolutionPtr++ = l_pw;
*lResolutionPtr++ = l_ph;
l_product = l_pw * l_ph;
// update precision
if
(l_product > *p_max_prec)
{
*p_max_prec = l_product;
}
--l_level_no;
}
++l_tccp;
++l_img_comp;
}
}
/**
* Allocates memory for a packet iterator. Data and data sizes are set by this operation.
* No other data is set. The include section of the packet iterator is not allocated.
*
* @param p_image the image used to initialize the packet iterator (in fact only the number of components is relevant.
* @param p_cp the coding parameters.
* @param p_tile_no the index of the tile from which creating the packet iterator.
*/
opj_pi_iterator_t * pi_create(
const opj_image_t *image,
const opj_cp_v2_t *cp,
OPJ_UINT32 tileno
)
{
// loop
OPJ_UINT32 pino, compno;
// number of poc in the p_pi
OPJ_UINT32 l_poc_bound;
// pointers to tile coding parameters and components.
opj_pi_iterator_t *l_pi = 00;
opj_tcp_v2_t *tcp = 00;
const opj_tccp_t *tccp = 00;
// current packet iterator being allocated
opj_pi_iterator_t *l_current_pi = 00;
// preconditions in debug
assert(cp != 00);
assert(image != 00);
assert(tileno < cp->tw * cp->th);
// initializations
tcp = &cp->tcps[tileno];
l_poc_bound = tcp->numpocs+1;
// memory allocations
l_pi = (opj_pi_iterator_t*) opj_calloc((l_poc_bound), sizeof(opj_pi_iterator_t));
if
(!l_pi)
{
return 00;
}
memset(l_pi,0,l_poc_bound * sizeof(opj_pi_iterator_t));
l_current_pi = l_pi;
for
(pino = 0; pino < l_poc_bound ; ++pino)
{
l_current_pi->comps = (opj_pi_comp_t*) opj_calloc(image->numcomps, sizeof(opj_pi_comp_t));
if
(! l_current_pi->comps)
{
pi_destroy_v2(l_pi, l_poc_bound);
return 00;
}
l_current_pi->numcomps = image->numcomps;
memset(l_current_pi->comps,0,image->numcomps * sizeof(opj_pi_comp_t));
for
(compno = 0; compno < image->numcomps; ++compno)
{
opj_pi_comp_t *comp = &l_current_pi->comps[compno];
tccp = &tcp->tccps[compno];
comp->resolutions = (opj_pi_resolution_t*) opj_malloc(tccp->numresolutions * sizeof(opj_pi_resolution_t));
if
(!comp->resolutions)
{
pi_destroy_v2(l_pi, l_poc_bound);
return 00;
}
comp->numresolutions = tccp->numresolutions;
memset(comp->resolutions,0,tccp->numresolutions * sizeof(opj_pi_resolution_t));
}
++l_current_pi;
}
return l_pi;
}
/**
* Destroys a packet iterator array.
*
* @param p_pi the packet iterator array to destroy.
* @param p_nb_elements the number of elements in the array.
*/
void pi_destroy_v2(
opj_pi_iterator_t *p_pi,
OPJ_UINT32 p_nb_elements)
{
OPJ_UINT32 compno, pino;
opj_pi_iterator_t *l_current_pi = p_pi;
if
(p_pi)
{
if
(p_pi->include)
{
opj_free(p_pi->include);
p_pi->include = 00;
}
// TODO
for
(pino = 0; pino < p_nb_elements; ++pino)
{
if
(l_current_pi->comps)
{
opj_pi_comp_t *l_current_component = l_current_pi->comps;
for
(compno = 0; compno < l_current_pi->numcomps; compno++)
{
if
(l_current_component->resolutions)
{
opj_free(l_current_component->resolutions);
l_current_component->resolutions = 00;
}
++l_current_component;
}
opj_free(l_current_pi->comps);
l_current_pi->comps = 0;
}
++l_current_pi;
}
opj_free(p_pi);
}
}
void pi_update_decode_poc (opj_pi_iterator_t * p_pi,opj_tcp_v2_t * p_tcp,OPJ_UINT32 p_max_precision,OPJ_UINT32 p_max_res)
{
// loop
OPJ_UINT32 pino;
// encoding prameters to set
OPJ_UINT32 l_bound;
opj_pi_iterator_t * l_current_pi = 00;
opj_poc_t* l_current_poc = 0;
// preconditions in debug
assert(p_pi != 00);
assert(p_tcp != 00);
// initializations
l_bound = p_tcp->numpocs+1;
l_current_pi = p_pi;
l_current_poc = p_tcp->pocs;
for
(pino = 0;pino<l_bound;++pino)
{
l_current_pi->poc.prg = l_current_poc->prg;
l_current_pi->first = 1;
l_current_pi->poc.resno0 = l_current_poc->resno0;
l_current_pi->poc.compno0 = l_current_poc->compno0;
l_current_pi->poc.layno0 = 0;
l_current_pi->poc.precno0 = 0;
l_current_pi->poc.resno1 = l_current_poc->resno1;
l_current_pi->poc.compno1 = l_current_poc->compno1;
l_current_pi->poc.layno1 = l_current_poc->layno1;
l_current_pi->poc.precno1 = p_max_precision;
++l_current_pi;
++l_current_poc;
}
}
void pi_update_decode_not_poc (opj_pi_iterator_t * p_pi,opj_tcp_v2_t * p_tcp,OPJ_UINT32 p_max_precision,OPJ_UINT32 p_max_res)
{
// loop
OPJ_UINT32 pino;
// encoding prameters to set
OPJ_UINT32 l_bound;
opj_pi_iterator_t * l_current_pi = 00;
// preconditions in debug
assert(p_tcp != 00);
assert(p_pi != 00);
// initializations
l_bound = p_tcp->numpocs+1;
l_current_pi = p_pi;
for
(pino = 0;pino<l_bound;++pino)
{
l_current_pi->poc.prg = p_tcp->prg;
l_current_pi->first = 1;
l_current_pi->poc.resno0 = 0;
l_current_pi->poc.compno0 = 0;
l_current_pi->poc.layno0 = 0;
l_current_pi->poc.precno0 = 0;
l_current_pi->poc.resno1 = p_max_res;
l_current_pi->poc.compno1 = l_current_pi->numcomps;
l_current_pi->poc.layno1 = p_tcp->numlayers;
l_current_pi->poc.precno1 = p_max_precision;
++l_current_pi;
}
}

View File

@ -133,6 +133,18 @@ Create a packet iterator for Decoder
*/ */
opj_pi_iterator_t *pi_create_decode(opj_image_t * image, opj_cp_t * cp, int tileno); opj_pi_iterator_t *pi_create_decode(opj_image_t * image, opj_cp_t * cp, int tileno);
/**
Create a packet iterator for Decoder
@param image Raw image for which the packets will be listed
@param cp Coding parameters
@param tileno Number that identifies the tile for which to list the packets
@return Returns a packet iterator that points to the first packet of the tile
@see pi_destroy
*/
opj_pi_iterator_t *pi_create_decode_v2(struct opj_image * image, struct opj_cp_v2 * cp, OPJ_UINT32 tileno);
/** /**
Destroy a packet iterator Destroy a packet iterator
@param pi Previously created packet iterator @param pi Previously created packet iterator
@ -142,6 +154,17 @@ Destroy a packet iterator
*/ */
void pi_destroy(opj_pi_iterator_t *pi, opj_cp_t *cp, int tileno); void pi_destroy(opj_pi_iterator_t *pi, opj_cp_t *cp, int tileno);
/**
* Destroys a packet iterator array.
*
* @param p_pi the packet iterator array to destroy.
* @param p_nb_elements the number of elements in the array.
*/
void pi_destroy_v2(
opj_pi_iterator_t *p_pi,
OPJ_UINT32 p_nb_elements);
/** /**
Modify the packet iterator to point to the next packet Modify the packet iterator to point to the next packet
@param pi Packet iterator to modify @param pi Packet iterator to modify

View File

@ -1582,3 +1582,74 @@ void t1_decode_cblks(
} /* resno */ } /* resno */
} }
/* ----------------------------------------------------------------------- */
/**
* Creates a new Tier 1 handle
* and initializes the look-up tables of the Tier-1 coder/decoder
* @return a new T1 handle if successful, returns NULL otherwise
*/
opj_t1_t* t1_create_v2()
{
opj_t1_t *l_t1 = 00;
l_t1 = (opj_t1_t*) opj_malloc(sizeof(opj_t1_t));
if
(!l_t1)
{
return 00;
}
memset(l_t1,0,sizeof(opj_t1_t));
/* create MQC and RAW handles */
l_t1->mqc = mqc_create();
if
(! l_t1->mqc)
{
t1_destroy(l_t1);
return 00;
}
l_t1->raw = raw_create();
if
(! l_t1->raw)
{
t1_destroy(l_t1);
return 00;
}
return l_t1;
}
/**
* Destroys a previously created T1 handle
*
* @param p_t1 Tier 1 handle to destroy
*/
void t1_destroy_v2(opj_t1_t *p_t1)
{
if
(! p_t1)
{
return;
}
/* destroy MQC and RAW handles */
mqc_destroy(p_t1->mqc);
p_t1->mqc = 00;
raw_destroy(p_t1->raw);
p_t1->raw = 00;
if
(p_t1->data)
{
opj_aligned_free(p_t1->data);
p_t1->data = 00;
}
if
(p_t1->flags)
{
opj_aligned_free(p_t1->flags);
p_t1->flags = 00;
}
opj_free(p_t1);
}

View File

@ -139,6 +139,22 @@ Decode the code-blocks of a tile
@param tccp Tile coding parameters @param tccp Tile coding parameters
*/ */
void t1_decode_cblks(opj_t1_t* t1, opj_tcd_tilecomp_t* tilec, opj_tccp_t* tccp); void t1_decode_cblks(opj_t1_t* t1, opj_tcd_tilecomp_t* tilec, opj_tccp_t* tccp);
/**
* Creates a new Tier 1 handle
* and initializes the look-up tables of the Tier-1 coder/decoder
* @return a new T1 handle if successful, returns NULL otherwise
*/
opj_t1_t* t1_create_v2();
/**
* Destroys a previously created T1 handle
*
* @param p_t1 Tier 1 handle to destroy
*/
void t1_destroy_v2(opj_t1_t *p_t1);
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/*@}*/ /*@}*/

View File

@ -79,6 +79,72 @@ Decode a packet of a tile from a source buffer
static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile, static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile,
opj_tcp_t *tcp, opj_pi_iterator_t *pi, opj_packet_info_t *pack_info); opj_tcp_t *tcp, opj_pi_iterator_t *pi, opj_packet_info_t *pack_info);
/**
Decode a packet of a tile from a source buffer
@param t2 T2 handle
@param src Source buffer
@param len Length of the source buffer
@param tile Tile for which to write the packets
@param tcp Tile coding parameters
@param pi Packet identity
@return
*/
static opj_bool t2_decode_packet_v2(
opj_t2_v2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_tcp_v2_t *p_tcp,
opj_pi_iterator_t *p_pi,
OPJ_BYTE *p_src,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *p_pack_info);
static opj_bool t2_skip_packet(
opj_t2_v2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_tcp_v2_t *p_tcp,
opj_pi_iterator_t *p_pi,
OPJ_BYTE *p_src,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *p_pack_info);
static opj_bool t2_read_packet_header(
opj_t2_v2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_tcp_v2_t *p_tcp,
opj_pi_iterator_t *p_pi,
opj_bool * p_is_data_present,
OPJ_BYTE *p_src_data,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *p_pack_info);
static opj_bool t2_read_packet_data(
opj_t2_v2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_pi_iterator_t *p_pi,
OPJ_BYTE *p_src_data,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *pack_info);
static opj_bool t2_skip_packet_data(
opj_t2_v2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_pi_iterator_t *p_pi,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *pack_info);
/**
@param seg
@param cblksty
@param first
*/
static opj_bool t2_init_seg_v2(opj_tcd_cblk_dec_t* cblk, OPJ_UINT32 index, OPJ_UINT32 cblksty, OPJ_UINT32 first);
/*@}*/ /*@}*/
/*@}*/ /*@}*/
@ -768,6 +834,116 @@ int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj
return (c - src); return (c - src);
} }
opj_bool t2_decode_packets_v2(
opj_t2_v2_t *p_t2,
OPJ_UINT32 p_tile_no,
struct opj_tcd_tile *p_tile,
OPJ_BYTE *p_src,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_len,
struct opj_codestream_info *p_cstr_info)
{
OPJ_BYTE *l_current_data = p_src;
opj_pi_iterator_t *l_pi = 00;
OPJ_UINT32 pino;
opj_image_t *l_image = p_t2->image;
opj_cp_v2_t *l_cp = p_t2->cp;
opj_cp_v2_t *cp = p_t2->cp;
opj_tcp_v2_t *l_tcp = &(p_t2->cp->tcps[p_tile_no]);
OPJ_UINT32 l_nb_bytes_read;
OPJ_UINT32 l_nb_pocs = l_tcp->numpocs + 1;
opj_pi_iterator_t *l_current_pi = 00;
OPJ_UINT32 curtp = 0;
OPJ_UINT32 tp_start_packno;
opj_packet_info_t *l_pack_info = 00;
opj_image_comp_t* l_img_comp = 00;
if
(p_cstr_info)
{
l_pack_info = p_cstr_info->tile[p_tile_no].packet;
}
/* create a packet iterator */
l_pi = pi_create_decode_v2(l_image, l_cp, p_tile_no);
if
(!l_pi)
{
return OPJ_FALSE;
}
tp_start_packno = 0;
l_current_pi = l_pi;
for
(pino = 0; pino <= l_tcp->numpocs; ++pino)
{
while
(pi_next(l_current_pi))
{
if
(l_tcp->num_layers_to_decode > l_current_pi->layno && l_current_pi->resno < p_tile->comps[l_current_pi->compno].minimum_num_resolutions)
{
l_nb_bytes_read = 0;
if
(! t2_decode_packet_v2(p_t2,p_tile,l_tcp,l_current_pi,l_current_data,&l_nb_bytes_read,p_max_len,l_pack_info))
{
pi_destroy_v2(l_pi,l_nb_pocs);
return OPJ_FALSE;
}
l_img_comp = &(l_image->comps[l_current_pi->compno]);
l_img_comp->resno_decoded = uint_max(l_current_pi->resno, l_img_comp->resno_decoded);
}
else
{
l_nb_bytes_read = 0;
if
(! t2_skip_packet(p_t2,p_tile,l_tcp,l_current_pi,l_current_data,&l_nb_bytes_read,p_max_len,l_pack_info))
{
pi_destroy_v2(l_pi,l_nb_pocs);
return OPJ_FALSE;
}
}
l_current_data += l_nb_bytes_read;
p_max_len -= l_nb_bytes_read;
/* INDEX >> */
if(p_cstr_info) {
opj_tile_info_t *info_TL = &p_cstr_info->tile[p_tile_no];
opj_packet_info_t *info_PK = &info_TL->packet[p_cstr_info->packno];
if (!p_cstr_info->packno) {
info_PK->start_pos = info_TL->end_header + 1;
} else if (info_TL->packet[p_cstr_info->packno-1].end_pos >= (OPJ_INT32)p_cstr_info->tile[p_tile_no].tp[curtp].tp_end_pos){ // New tile part
info_TL->tp[curtp].tp_numpacks = p_cstr_info->packno - tp_start_packno; // Number of packets in previous tile-part
tp_start_packno = p_cstr_info->packno;
curtp++;
info_PK->start_pos = p_cstr_info->tile[p_tile_no].tp[curtp].tp_end_header+1;
} else {
info_PK->start_pos = (cp->m_specific_param.m_enc.m_tp_on && info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[p_cstr_info->packno - 1].end_pos + 1;
}
info_PK->end_pos = info_PK->start_pos + l_nb_bytes_read - 1;
info_PK->end_ph_pos += info_PK->start_pos - 1; // End of packet header which now only represents the distance
++p_cstr_info->packno;
}
/* << INDEX */
}
++l_current_pi;
}
/* INDEX >> */
if
(p_cstr_info) {
p_cstr_info->tile[p_tile_no].tp[curtp].tp_numpacks = p_cstr_info->packno - tp_start_packno; // Number of packets in last tile-part
}
/* << INDEX */
/* don't forget to release pi */
pi_destroy_v2(l_pi,l_nb_pocs);
*p_data_read = l_current_data - p_src;
return OPJ_TRUE;
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
opj_t2_t* t2_create(opj_common_ptr cinfo, opj_image_t *image, opj_cp_t *cp) { opj_t2_t* t2_create(opj_common_ptr cinfo, opj_image_t *image, opj_cp_t *cp) {
@ -781,13 +957,660 @@ opj_t2_t* t2_create(opj_common_ptr cinfo, opj_image_t *image, opj_cp_t *cp) {
return t2; return t2;
} }
/**
* Creates a Tier 2 handle
*
* @param p_image Source or destination image
* @param p_cp Image coding parameters.
* @return a new T2 handle if successful, NULL otherwise.
*/
opj_t2_v2_t* t2_create_v2(
opj_image_t *p_image,
opj_cp_v2_t *p_cp)
{
/* create the tcd structure */
opj_t2_v2_t *l_t2 = (opj_t2_v2_t*)opj_malloc(sizeof(opj_t2_v2_t));
if
(!l_t2)
{
return 00;
}
memset(l_t2,0,sizeof(opj_t2_t));
l_t2->image = p_image;
l_t2->cp = p_cp;
return l_t2;
}
void t2_destroy(opj_t2_t *t2) { void t2_destroy(opj_t2_t *t2) {
if(t2) { if(t2) {
opj_free(t2); opj_free(t2);
} }
} }
void t2_destroy_v2(opj_t2_v2_t *t2) {
if(t2) {
opj_free(t2);
}
}
static opj_bool t2_decode_packet_v2(
opj_t2_v2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_tcp_v2_t *p_tcp,
opj_pi_iterator_t *p_pi,
OPJ_BYTE *p_src,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *p_pack_info)
{
opj_bool l_read_data;
OPJ_UINT32 l_nb_bytes_read = 0;
OPJ_UINT32 l_nb_total_bytes_read = 0;
*p_data_read = 0;
if
(! t2_read_packet_header(p_t2,p_tile,p_tcp,p_pi,&l_read_data,p_src,&l_nb_bytes_read,p_max_length,p_pack_info))
{
return OPJ_FALSE;
}
p_src += l_nb_bytes_read;
l_nb_total_bytes_read += l_nb_bytes_read;
p_max_length -= l_nb_bytes_read;
/* we should read data for the packet */
if
(l_read_data)
{
l_nb_bytes_read = 0;
if
(! t2_read_packet_data(p_t2,p_tile,p_pi,p_src,&l_nb_bytes_read,p_max_length,p_pack_info))
{
return OPJ_FALSE;
}
l_nb_total_bytes_read += l_nb_bytes_read;
}
*p_data_read = l_nb_total_bytes_read;
return OPJ_FALSE;
}
static opj_bool t2_skip_packet(
opj_t2_v2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_tcp_v2_t *p_tcp,
opj_pi_iterator_t *p_pi,
OPJ_BYTE *p_src,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *p_pack_info)
{
opj_bool l_read_data;
OPJ_UINT32 l_nb_bytes_read = 0;
OPJ_UINT32 l_nb_total_bytes_read = 0;
*p_data_read = 0;
if
(! t2_read_packet_header(p_t2,p_tile,p_tcp,p_pi,&l_read_data,p_src,&l_nb_bytes_read,p_max_length,p_pack_info))
{
return OPJ_FALSE;
}
p_src += l_nb_bytes_read;
l_nb_total_bytes_read += l_nb_bytes_read;
p_max_length -= l_nb_bytes_read;
/* we should read data for the packet */
if
(l_read_data)
{
l_nb_bytes_read = 0;
if
(! t2_skip_packet_data(p_t2,p_tile,p_pi,&l_nb_bytes_read,p_max_length,p_pack_info))
{
return OPJ_FALSE;
}
l_nb_total_bytes_read += l_nb_bytes_read;
}
*p_data_read = l_nb_total_bytes_read;
return OPJ_TRUE;
}
static opj_bool t2_read_packet_header(
opj_t2_v2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_tcp_v2_t *p_tcp,
opj_pi_iterator_t *p_pi,
opj_bool * p_is_data_present,
OPJ_BYTE *p_src_data,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *p_pack_info)
{
/* loop */
OPJ_UINT32 bandno, cblkno;
OPJ_UINT32 l_nb_code_blocks;
OPJ_UINT32 l_remaining_length;
OPJ_UINT32 l_header_length;
OPJ_UINT32 * l_modified_length_ptr = 00;
OPJ_BYTE *l_current_data = p_src_data;
opj_cp_v2_t *l_cp = p_t2->cp;
opj_bio_t *l_bio = 00; /* BIO component */
opj_tcd_band_t *l_band = 00;
opj_tcd_cblk_dec_t* l_cblk = 00;
opj_tcd_resolution_t* l_res = &p_tile->comps[p_pi->compno].resolutions[p_pi->resno];
OPJ_BYTE *l_header_data = 00;
OPJ_BYTE **l_header_data_start = 00;
OPJ_UINT32 l_present;
if
(p_pi->layno == 0)
{
l_band = l_res->bands;
/* reset tagtrees */
for
(bandno = 0; bandno < l_res->numbands; ++bandno)
{
opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno];
if (
! ((l_band->x1-l_band->x0 == 0)||(l_band->y1-l_band->y0 == 0)))
{
tgt_reset(l_prc->incltree);
tgt_reset(l_prc->imsbtree);
l_cblk = l_prc->cblks.dec;
l_nb_code_blocks = l_prc->cw * l_prc->ch;
for
(cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno)
{
l_cblk->numsegs = 0;
l_cblk->real_num_segs = 0;
++l_cblk;
}
}
++l_band;
}
}
/* SOP markers */
if (p_tcp->csty & J2K_CP_CSTY_SOP) {
if ((*l_current_data) != 0xff || (*(l_current_data + 1) != 0x91)) {
// TODO opj_event_msg(t2->cinfo->event_mgr, EVT_WARNING, "Expected SOP marker\n");
} else {
l_current_data += 6;
}
/** TODO : check the Nsop value */
}
/*
When the marker PPT/PPM is used the packet header are store in PPT/PPM marker
This part deal with this caracteristic
step 1: Read packet header in the saved structure
step 2: Return to codestream for decoding
*/
l_bio = bio_create();
if
(! l_bio)
{
return OPJ_FALSE;
}
if
(l_cp->ppm == 1)
{ /* PPM */
l_header_data_start = &l_cp->ppm_data;
l_header_data = *l_header_data_start;
l_modified_length_ptr = &(l_cp->ppm_len);
}
else if
(p_tcp->ppt == 1)
{ /* PPT */
l_header_data_start = &(p_tcp->ppt_data);
l_header_data = *l_header_data_start;
l_modified_length_ptr = &(p_tcp->ppt_len);
}
else
{ /* Normal Case */
l_header_data_start = &(l_current_data);
l_header_data = *l_header_data_start;
l_remaining_length = p_src_data+p_max_length-l_header_data;
l_modified_length_ptr = &(l_remaining_length);
}
bio_init_dec(l_bio, l_header_data,*l_modified_length_ptr);
l_present = bio_read(l_bio, 1);
if
(!l_present)
{
bio_inalign(l_bio);
l_header_data += bio_numbytes(l_bio);
bio_destroy(l_bio);
/* EPH markers */
if (p_tcp->csty & J2K_CP_CSTY_EPH) {
if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) {
printf("Error : expected EPH marker\n");
} else {
l_header_data += 2;
}
}
l_header_length = (l_header_data - *l_header_data_start);
*l_modified_length_ptr -= l_header_length;
*l_header_data_start += l_header_length;
/* << INDEX */
// End of packet header position. Currently only represents the distance to start of packet
// Will be updated later by incrementing with packet start value
if
(p_pack_info)
{
p_pack_info->end_ph_pos = (OPJ_INT32)(l_current_data - p_src_data);
}
/* INDEX >> */
* p_is_data_present = OPJ_FALSE;
*p_data_read = l_current_data - p_src_data;
return OPJ_TRUE;
}
l_band = l_res->bands;
for
(bandno = 0; bandno < l_res->numbands; ++bandno)
{
opj_tcd_precinct_t *l_prc = &(l_band->precincts[p_pi->precno]);
if ((l_band->x1-l_band->x0 == 0)||(l_band->y1-l_band->y0 == 0))
{
++l_band;
continue;
}
l_nb_code_blocks = l_prc->cw * l_prc->ch;
l_cblk = l_prc->cblks.dec;
for
(cblkno = 0; cblkno < l_nb_code_blocks; cblkno++)
{
OPJ_UINT32 l_included,l_increment, l_segno;
OPJ_INT32 n;
/* if cblk not yet included before --> inclusion tagtree */
if
(!l_cblk->numsegs)
{
l_included = tgt_decode(l_bio, l_prc->incltree, cblkno, p_pi->layno + 1);
/* else one bit */
}
else
{
l_included = bio_read(l_bio, 1);
}
/* if cblk not included */
if
(!l_included)
{
l_cblk->numnewpasses = 0;
++l_cblk;
continue;
}
/* if cblk not yet included --> zero-bitplane tagtree */
if
(!l_cblk->numsegs)
{
OPJ_UINT32 i = 0;
while
(!tgt_decode(l_bio, l_prc->imsbtree, cblkno, i))
{
++i;
}
l_cblk->numbps = l_band->numbps + 1 - i;
l_cblk->numlenbits = 3;
}
/* number of coding passes */
l_cblk->numnewpasses = t2_getnumpasses(l_bio);
l_increment = t2_getcommacode(l_bio);
/* length indicator increment */
l_cblk->numlenbits += l_increment;
l_segno = 0;
if
(!l_cblk->numsegs)
{
if
(! t2_init_seg_v2(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 1))
{
bio_destroy(l_bio);
return OPJ_FALSE;
}
}
else
{
l_segno = l_cblk->numsegs - 1;
if
(l_cblk->segs[l_segno].numpasses == l_cblk->segs[l_segno].maxpasses)
{
++l_segno;
if
(! t2_init_seg_v2(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0))
{
bio_destroy(l_bio);
return OPJ_FALSE;
}
}
}
n = l_cblk->numnewpasses;
do {
l_cblk->segs[l_segno].numnewpasses = int_min(l_cblk->segs[l_segno].maxpasses - l_cblk->segs[l_segno].numpasses, n);
l_cblk->segs[l_segno].newlen = bio_read(l_bio, l_cblk->numlenbits + uint_floorlog2(l_cblk->segs[l_segno].numnewpasses));
n -= l_cblk->segs[l_segno].numnewpasses;
if
(n > 0)
{
++l_segno;
if
(! t2_init_seg_v2(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0))
{
bio_destroy(l_bio);
return OPJ_FALSE;
}
}
}
while (n > 0);
++l_cblk;
}
++l_band;
}
if
(bio_inalign(l_bio))
{
bio_destroy(l_bio);
return OPJ_FALSE;
}
l_header_data += bio_numbytes(l_bio);
bio_destroy(l_bio);
/* EPH markers */
if (p_tcp->csty & J2K_CP_CSTY_EPH) {
if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) {
// TODO opj_event_msg(t2->cinfo->event_mgr, EVT_ERROR, "Expected EPH marker\n");
} else {
l_header_data += 2;
}
}
l_header_length = (l_header_data - *l_header_data_start);
*l_modified_length_ptr -= l_header_length;
*l_header_data_start += l_header_length;
/* << INDEX */
// End of packet header position. Currently only represents the distance to start of packet
// Will be updated later by incrementing with packet start value
if
(p_pack_info)
{
p_pack_info->end_ph_pos = (OPJ_INT32)(l_current_data - p_src_data);
}
/* INDEX >> */
* p_is_data_present = OPJ_TRUE;
*p_data_read = l_current_data - p_src_data;
return OPJ_TRUE;
}
static opj_bool t2_read_packet_data(
opj_t2_v2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_pi_iterator_t *p_pi,
OPJ_BYTE *p_src_data,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *pack_info)
{
OPJ_UINT32 bandno, cblkno;
OPJ_UINT32 l_nb_code_blocks;
OPJ_BYTE *l_current_data = p_src_data;
opj_tcd_band_t *l_band = 00;
opj_tcd_cblk_dec_t* l_cblk = 00;
opj_tcd_resolution_t* l_res = &p_tile->comps[p_pi->compno].resolutions[p_pi->resno];
l_band = l_res->bands;
for
(bandno = 0; bandno < l_res->numbands; ++bandno)
{
opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno];
if
((l_band->x1-l_band->x0 == 0)||(l_band->y1-l_band->y0 == 0))
{
++l_band;
continue;
}
l_nb_code_blocks = l_prc->cw * l_prc->ch;
l_cblk = l_prc->cblks.dec;
for
(cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno)
{
opj_tcd_seg_t *l_seg = 00;
if
(!l_cblk->numnewpasses)
{
/* nothing to do */
++l_cblk;
continue;
}
if
(!l_cblk->numsegs)
{
l_seg = l_cblk->segs;
++l_cblk->numsegs;
l_cblk->len = 0;
}
else
{
l_seg = &l_cblk->segs[l_cblk->numsegs - 1];
if
(l_seg->numpasses == l_seg->maxpasses)
{
++l_seg;
++l_cblk->numsegs;
}
}
do
{
if
(l_current_data + l_seg->newlen > p_src_data + p_max_length)
{
return OPJ_FALSE;
}
#ifdef USE_JPWL
/* we need here a j2k handle to verify if making a check to
the validity of cblocks parameters is selected from user (-W) */
/* let's check that we are not exceeding */
if ((cblk->len + seg->newlen) > 8192) {
opj_event_msg(t2->cinfo, EVT_WARNING,
"JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
seg->newlen, cblkno, precno, bandno, resno, compno);
if (!JPWL_ASSUME) {
opj_event_msg(t2->cinfo, EVT_ERROR, "JPWL: giving up\n");
return -999;
}
seg->newlen = 8192 - cblk->len;
opj_event_msg(t2->cinfo, EVT_WARNING, " - truncating segment to %d\n", seg->newlen);
break;
};
#endif /* USE_JPWL */
memcpy(l_cblk->data + l_cblk->len, l_current_data, l_seg->newlen);
if
(l_seg->numpasses == 0)
{
l_seg->data = &l_cblk->data;
l_seg->dataindex = l_cblk->len;
}
l_current_data += l_seg->newlen;
l_seg->numpasses += l_seg->numnewpasses;
l_cblk->numnewpasses -= l_seg->numnewpasses;
l_seg->real_num_passes = l_seg->numpasses;
l_cblk->len += l_seg->newlen;
l_seg->len += l_seg->newlen;
if
(l_cblk->numnewpasses > 0)
{
++l_seg;
++l_cblk->numsegs;
}
}
while (l_cblk->numnewpasses > 0);
l_cblk->real_num_segs = l_cblk->numsegs;
++l_cblk;
}
++l_band;
}
*(p_data_read) = l_current_data - p_src_data;
return OPJ_TRUE;
}
static opj_bool t2_skip_packet_data(
opj_t2_v2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_pi_iterator_t *p_pi,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *pack_info)
{
OPJ_UINT32 bandno, cblkno;
OPJ_UINT32 l_nb_code_blocks;
opj_tcd_band_t *l_band = 00;
opj_tcd_cblk_dec_t* l_cblk = 00;
opj_tcd_resolution_t* l_res = &p_tile->comps[p_pi->compno].resolutions[p_pi->resno];
*p_data_read = 0;
l_band = l_res->bands;
for
(bandno = 0; bandno < l_res->numbands; ++bandno)
{
opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno];
if
((l_band->x1-l_band->x0 == 0)||(l_band->y1-l_band->y0 == 0))
{
++l_band;
continue;
}
l_nb_code_blocks = l_prc->cw * l_prc->ch;
l_cblk = l_prc->cblks.dec;
for
(cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno)
{
opj_tcd_seg_t *l_seg = 00;
if
(!l_cblk->numnewpasses)
{
/* nothing to do */
++l_cblk;
continue;
}
if
(!l_cblk->numsegs)
{
l_seg = l_cblk->segs;
++l_cblk->numsegs;
l_cblk->len = 0;
}
else
{
l_seg = &l_cblk->segs[l_cblk->numsegs - 1];
if
(l_seg->numpasses == l_seg->maxpasses)
{
++l_seg;
++l_cblk->numsegs;
}
}
do
{
if
(* p_data_read + l_seg->newlen > p_max_length)
{
return OPJ_FALSE;
}
#ifdef USE_JPWL
/* we need here a j2k handle to verify if making a check to
the validity of cblocks parameters is selected from user (-W) */
/* let's check that we are not exceeding */
if ((cblk->len + seg->newlen) > 8192) {
opj_event_msg(t2->cinfo, EVT_WARNING,
"JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
seg->newlen, cblkno, precno, bandno, resno, compno);
if (!JPWL_ASSUME) {
opj_event_msg(t2->cinfo, EVT_ERROR, "JPWL: giving up\n");
return -999;
}
seg->newlen = 8192 - cblk->len;
opj_event_msg(t2->cinfo, EVT_WARNING, " - truncating segment to %d\n", seg->newlen);
break;
};
#endif /* USE_JPWL */
*(p_data_read) += l_seg->newlen;
l_seg->numpasses += l_seg->numnewpasses;
l_cblk->numnewpasses -= l_seg->numnewpasses;
if
(l_cblk->numnewpasses > 0)
{
++l_seg;
++l_cblk->numsegs;
}
}
while (l_cblk->numnewpasses > 0);
++l_cblk;
}
++l_band;
}
return OPJ_TRUE;
}
static opj_bool t2_init_seg_v2(opj_tcd_cblk_dec_t* cblk, OPJ_UINT32 index, OPJ_UINT32 cblksty, OPJ_UINT32 first)
{
opj_tcd_seg_t* seg = 00;
OPJ_UINT32 l_nb_segs = index + 1;
if
(l_nb_segs > cblk->m_current_max_segs)
{
cblk->m_current_max_segs += J2K_DEFAULT_NB_SEGS;
cblk->segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, cblk->m_current_max_segs * sizeof(opj_tcd_seg_t));
if
(! cblk->segs)
{
return OPJ_FALSE;
}
}
seg = &cblk->segs[index];
memset(seg,0,sizeof(opj_tcd_seg_t));
if (cblksty & J2K_CCP_CBLKSTY_TERMALL) {
seg->maxpasses = 1;
}
else if (cblksty & J2K_CCP_CBLKSTY_LAZY) {
if (first) {
seg->maxpasses = 10;
} else {
seg->maxpasses = (((seg - 1)->maxpasses == 1) || ((seg - 1)->maxpasses == 10)) ? 2 : 1;
}
} else {
seg->maxpasses = 109;
}
return OPJ_TRUE;
}

View File

@ -52,6 +52,19 @@ typedef struct opj_t2 {
opj_cp_t *cp; opj_cp_t *cp;
} opj_t2_t; } opj_t2_t;
/**
Tier-2 coding
*/
typedef struct opj_t2_v2 {
/** codec context */
opj_common_ptr cinfo;
/** Encoding: pointer to the src image. Decoding: pointer to the dst image. */
opj_image_t *image;
/** pointer to the image coding parameters */
opj_cp_v2_t *cp;
} opj_t2_v2_t;
/** @name Exported functions */ /** @name Exported functions */
/*@{*/ /*@{*/
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
@ -83,6 +96,25 @@ Decode the packets of a tile from a source buffer
*/ */
int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj_tcd_tile_t *tile, opj_codestream_info_t *cstr_info); int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj_tcd_tile_t *tile, opj_codestream_info_t *cstr_info);
/**
Decode the packets of a tile from a source buffer
@param t2 T2 handle
@param src the source buffer
@param len length of the source buffer
@param tileno number that identifies the tile for which to decode the packets
@param tile tile for which to decode the packets
*/
opj_bool t2_decode_packets_v2(opj_t2_v2_t *t2, OPJ_UINT32 tileno,struct opj_tcd_tile *tile, OPJ_BYTE *src, OPJ_UINT32 * p_data_read, OPJ_UINT32 len, struct opj_codestream_info *cstr_info);
/**
* Creates a Tier 2 handle
*
* @param p_image Source or destination image
* @param p_cp Image coding parameters.
* @return a new T2 handle if successful, NULL otherwise.
*/
opj_t2_v2_t* t2_create_v2(struct opj_image *p_image, opj_cp_v2_t *p_cp);
/** /**
Create a T2 handle Create a T2 handle
@param cinfo Codec context info @param cinfo Codec context info
@ -97,6 +129,12 @@ Destroy a T2 handle
*/ */
void t2_destroy(opj_t2_t *t2); void t2_destroy(opj_t2_t *t2);
/**
Destroy a T2 handle
@param t2 T2 handle to destroy
*/
void t2_destroy_v2(opj_t2_v2_t *t2);
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/*@}*/ /*@}*/

File diff suppressed because it is too large Load Diff

View File

@ -41,17 +41,31 @@ each other. The functions in TCD.C are used by some function in J2K.C.
/** @defgroup TCD TCD - Implementation of a tile coder/decoder */ /** @defgroup TCD TCD - Implementation of a tile coder/decoder */
/*@{*/ /*@{*/
/**
FIXME: documentation
*/
//typedef struct opj_tcd_seg {
// unsigned char** data;
// int dataindex;
// int numpasses;
// int len;
// int maxpasses;
// int numnewpasses;
// int newlen;
//} opj_tcd_seg_t;
/** /**
FIXME: documentation FIXME: documentation
*/ */
typedef struct opj_tcd_seg { typedef struct opj_tcd_seg {
unsigned char** data; OPJ_BYTE ** data;
int dataindex; OPJ_UINT32 dataindex;
int numpasses; OPJ_UINT32 numpasses;
int len; OPJ_UINT32 real_num_passes;
int maxpasses; OPJ_UINT32 len;
int numnewpasses; OPJ_UINT32 maxpasses;
int newlen; OPJ_UINT32 numnewpasses;
OPJ_UINT32 newlen;
} opj_tcd_seg_t; } opj_tcd_seg_t;
/** /**
@ -88,40 +102,75 @@ typedef struct opj_tcd_cblk_enc {
int totalpasses; /* total number of passes */ int totalpasses; /* total number of passes */
} opj_tcd_cblk_enc_t; } opj_tcd_cblk_enc_t;
//typedef struct opj_tcd_cblk_dec {
// unsigned char* data; /* Data */
// opj_tcd_seg_t* segs; /* segments informations */
// int x0, y0, x1, y1; /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */
// int numbps;
// int numlenbits;
// int len; /* length */
// int numnewpasses; /* number of pass added to the code-blocks */
// int numsegs; /* number of segments */
//} opj_tcd_cblk_dec_t;
typedef struct opj_tcd_cblk_dec { typedef struct opj_tcd_cblk_dec {
unsigned char* data; /* Data */ OPJ_BYTE * data; /* Data */
opj_tcd_seg_t* segs; /* segments informations */ opj_tcd_seg_t* segs; /* segments informations */
int x0, y0, x1, y1; /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */ OPJ_INT32 x0, y0, x1, y1; /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */
int numbps; OPJ_UINT32 numbps;
int numlenbits; OPJ_UINT32 numlenbits;
int len; /* length */ OPJ_UINT32 len; /* length */
int numnewpasses; /* number of pass added to the code-blocks */ OPJ_UINT32 numnewpasses; /* number of pass added to the code-blocks */
int numsegs; /* number of segments */ OPJ_UINT32 numsegs; /* number of segments */
OPJ_UINT32 real_num_segs;
OPJ_UINT32 m_current_max_segs;
} opj_tcd_cblk_dec_t; } opj_tcd_cblk_dec_t;
/** /**
FIXME: documentation FIXME: documentation
*/ */
//typedef struct opj_tcd_precinct {
// int x0, y0, x1, y1; /* dimension of the precinct : left upper corner (x0, y0) right low corner (x1,y1) */
// int cw, ch; /* number of precinct in width and heigth */
// union{ /* code-blocks informations */
// opj_tcd_cblk_enc_t* enc;
// opj_tcd_cblk_dec_t* dec;
// } cblks;
// opj_tgt_tree_t *incltree; /* inclusion tree */
// opj_tgt_tree_t *imsbtree; /* IMSB tree */
//} opj_tcd_precinct_t;
typedef struct opj_tcd_precinct { typedef struct opj_tcd_precinct {
int x0, y0, x1, y1; /* dimension of the precinct : left upper corner (x0, y0) right low corner (x1,y1) */ OPJ_INT32 x0, y0, x1, y1; /* dimension of the precinct : left upper corner (x0, y0) right low corner (x1,y1) */
int cw, ch; /* number of precinct in width and heigth */ OPJ_UINT32 cw, ch; /* number of precinct in width and heigth */
union{ /* code-blocks informations */ union{ /* code-blocks informations */
opj_tcd_cblk_enc_t* enc; opj_tcd_cblk_enc_t* enc;
opj_tcd_cblk_dec_t* dec; opj_tcd_cblk_dec_t* dec;
} cblks; } cblks;
opj_tgt_tree_t *incltree; /* inclusion tree */ OPJ_UINT32 block_size; /* size taken by cblks (in bytes) */
opj_tgt_tree_t *imsbtree; /* IMSB tree */ struct opj_tgt_tree *incltree; /* inclusion tree */
struct opj_tgt_tree *imsbtree; /* IMSB tree */
} opj_tcd_precinct_t; } opj_tcd_precinct_t;
/** /**
FIXME: documentation FIXME: documentation
*/ */
//typedef struct opj_tcd_band {
// int x0, y0, x1, y1; /* dimension of the subband : left upper corner (x0, y0) right low corner (x1,y1) */
// int bandno;
// opj_tcd_precinct_t *precincts; /* precinct information */
// int numbps;
// float stepsize;
//} opj_tcd_band_t;
typedef struct opj_tcd_band { typedef struct opj_tcd_band {
int x0, y0, x1, y1; /* dimension of the subband : left upper corner (x0, y0) right low corner (x1,y1) */ OPJ_INT32 x0, y0, x1, y1; /* dimension of the subband : left upper corner (x0, y0) right low corner (x1,y1) */
int bandno; OPJ_UINT32 bandno;
opj_tcd_precinct_t *precincts; /* precinct information */ opj_tcd_precinct_t *precincts; /* precinct information */
int numbps; OPJ_UINT32 precincts_data_size; /* size of data taken by precincts */
float stepsize; OPJ_INT32 numbps;
OPJ_FLOAT32 stepsize;
} opj_tcd_band_t; } opj_tcd_band_t;
/** /**
@ -137,14 +186,27 @@ typedef struct opj_tcd_resolution {
/** /**
FIXME: documentation FIXME: documentation
*/ */
typedef struct opj_tcd_tilecomp { //typedef struct opj_tcd_tilecomp {
int x0, y0, x1, y1; /* dimension of component : left upper corner (x0, y0) right low corner (x1,y1) */ // int x0, y0, x1, y1; /* dimension of component : left upper corner (x0, y0) right low corner (x1,y1) */
int numresolutions; /* number of resolutions level */ // int numresolutions; /* number of resolutions level */
// opj_tcd_resolution_t *resolutions; /* resolutions information */
// int *data; /* data of the component */
// int numpix; /* add fixed_quality */
//} opj_tcd_tilecomp_t;
typedef struct opj_tcd_tilecomp
{
OPJ_INT32 x0, y0, x1, y1; /* dimension of component : left upper corner (x0, y0) right low corner (x1,y1) */
OPJ_UINT32 numresolutions; /* number of resolutions level */
OPJ_UINT32 minimum_num_resolutions; /* number of resolutions level to decode (at max)*/
opj_tcd_resolution_t *resolutions; /* resolutions information */ opj_tcd_resolution_t *resolutions; /* resolutions information */
int *data; /* data of the component */ OPJ_UINT32 resolutions_size; /* size of data for resolutions (in bytes) */
int numpix; /* add fixed_quality */ OPJ_INT32 *data; /* data of the component */
OPJ_UINT32 data_size; /* size of the data of the component */
OPJ_INT32 numpix; /* add fixed_quality */
} opj_tcd_tilecomp_t; } opj_tcd_tilecomp_t;
/** /**
FIXME: documentation FIXME: documentation
*/ */
@ -200,6 +262,39 @@ typedef struct opj_tcd {
double encoding_time; double encoding_time;
} opj_tcd_t; } opj_tcd_t;
struct opj_image;
struct opj_cp_v2;
struct opj_tcp_v2;
/**
Tile coder/decoder
*/
typedef struct opj_tcd_v2
{
/** Position of the tilepart flag in Progression order*/
OPJ_INT32 tp_pos;
/** Tile part number*/
OPJ_UINT32 tp_num;
/** Current tile part number*/
OPJ_UINT32 cur_tp_num;
/** Total number of tileparts of the current tile*/
OPJ_UINT32 cur_totnum_tp;
/** Current Packet iterator number */
OPJ_UINT32 cur_pino;
/** info on each image tile */
opj_tcd_image_t *tcd_image;
/** image */
struct opj_image *image;
/** coding parameters */
struct opj_cp_v2 *cp;
/** coding/decoding parameters common to all tiles */
struct opj_tcp_v2 *tcp;
/** current encoded/decoded tile */
OPJ_UINT32 tcd_tileno;
/** tell if the tcd is a decoder. */
OPJ_UINT32 m_is_decoder : 1;
} opj_tcd_v2_t;
/** @name Exported functions */ /** @name Exported functions */
/*@{*/ /*@{*/
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
@ -214,6 +309,54 @@ Create a new TCD handle
@return Returns a new TCD handle if successful returns NULL otherwise @return Returns a new TCD handle if successful returns NULL otherwise
*/ */
opj_tcd_t* tcd_create(opj_common_ptr cinfo); opj_tcd_t* tcd_create(opj_common_ptr cinfo);
/**
Create a new TCD handle
@param FIXME
@return Returns a new TCD handle if successful returns NULL otherwise
*/
opj_tcd_v2_t* tcd_create_v2(opj_bool p_is_decoder);
/**
Destroy a previously created TCD handle
@param tcd TCD handle to destroy
*/
void tcd_destroy_v2(opj_tcd_v2_t *tcd);
/**
* Initialize the tile coder and may reuse some meory.
* @param p_tcd TCD handle.
* @param p_image raw image.
* @param p_cp coding parameters.
* @param p_tile_no current tile index to encode.
*
* @return true if the encoding values could be set (false otherwise).
*/
opj_bool tcd_init_v2(
opj_tcd_v2_t *p_tcd,
//struct opj_image * p_image,
opj_image_t * p_image,
//struct opj_cp * p_cp
opj_cp_v2_t * p_cp
);
/**
* Allocates memory for decoding a specific tile.
*
* @param p_tcd the tile decoder.
* @param p_image the image to decode.
* @param p_cp the decoding parameters.
* @param p_tile_no the index of the tile received in sequence. This not necesseraly lead to the
* tile at index p_tile_no.
* @param p_cstr_info codestream info (if any).
*
* @return true if the remaining data is sufficient.s
*/
opj_bool tcd_init_decode_tile(
opj_tcd_v2_t *p_tcd,
OPJ_UINT32 p_tile_no
);
/** /**
Destroy a previously created TCD handle Destroy a previously created TCD handle
@param tcd TCD handle to destroy @param tcd TCD handle to destroy
@ -278,6 +421,33 @@ Free the memory allocated for decoding
void tcd_free_decode(opj_tcd_t *tcd); void tcd_free_decode(opj_tcd_t *tcd);
void tcd_free_decode_tile(opj_tcd_t *tcd, int tileno); void tcd_free_decode_tile(opj_tcd_t *tcd, int tileno);
/**
* Gets the maximum tile size that will be taken by the tile once decoded.
*/
OPJ_UINT32 tcd_get_decoded_tile_size (
opj_tcd_v2_t *p_tcd
);
/**
Decode a tile from a buffer into a raw image
@param tcd TCD handle
@param src Source buffer
@param len Length of source buffer
@param tileno Number that identifies one of the tiles to be decoded
*/
opj_bool tcd_decode_tile_v2(opj_tcd_v2_t *tcd, OPJ_BYTE *src, OPJ_UINT32 len, OPJ_UINT32 tileno, struct opj_codestream_info *cstr_info);
/**
* Copies tile data from the system onto the given memory block.
*/
opj_bool tcd_update_tile_data (
opj_tcd_v2_t *p_tcd,
OPJ_BYTE * p_dest,
OPJ_UINT32 p_dest_length
);
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/*@}*/ /*@}*/

View File

@ -108,6 +108,114 @@ opj_tgt_tree_t *tgt_create(int numleafsh, int numleafsv) {
return tree; return tree;
} }
/**
* Reinitialises a tag-tree from an exixting one.
*
* @param p_tree the tree to reinitialize.
* @param p_num_leafs_h the width of the array of leafs of the tree
* @param p_num_leafs_v the height of the array of leafs of the tree
* @return a new tag-tree if successful, NULL otherwise
*/
opj_tgt_tree_t *tgt_init(opj_tgt_tree_t * p_tree,OPJ_UINT32 p_num_leafs_h, OPJ_UINT32 p_num_leafs_v)
{
OPJ_INT32 l_nplh[32];
OPJ_INT32 l_nplv[32];
opj_tgt_node_t *l_node = 00;
opj_tgt_node_t *l_parent_node = 00;
opj_tgt_node_t *l_parent_node0 = 00;
OPJ_UINT32 i;
OPJ_INT32 j,k;
OPJ_UINT32 l_num_levels;
OPJ_UINT32 n;
OPJ_UINT32 l_node_size;
if
(! p_tree)
{
return 00;
}
if
((p_tree->numleafsh != p_num_leafs_h) || (p_tree->numleafsv != p_num_leafs_v))
{
p_tree->numleafsh = p_num_leafs_h;
p_tree->numleafsv = p_num_leafs_v;
l_num_levels = 0;
l_nplh[0] = p_num_leafs_h;
l_nplv[0] = p_num_leafs_v;
p_tree->numnodes = 0;
do
{
n = l_nplh[l_num_levels] * l_nplv[l_num_levels];
l_nplh[l_num_levels + 1] = (l_nplh[l_num_levels] + 1) / 2;
l_nplv[l_num_levels + 1] = (l_nplv[l_num_levels] + 1) / 2;
p_tree->numnodes += n;
++l_num_levels;
}
while (n > 1);
/* ADD */
if
(p_tree->numnodes == 0)
{
tgt_destroy(p_tree);
return 00;
}
l_node_size = p_tree->numnodes * sizeof(opj_tgt_node_t);
if
(l_node_size > p_tree->nodes_size)
{
p_tree->nodes = (opj_tgt_node_t*) opj_realloc(p_tree->nodes, l_node_size);
if
(! p_tree->nodes)
{
tgt_destroy(p_tree);
return 00;
}
memset(((char *) p_tree->nodes) + p_tree->nodes_size, 0 , l_node_size - p_tree->nodes_size);
p_tree->nodes_size = l_node_size;
}
l_node = p_tree->nodes;
l_parent_node = &p_tree->nodes[p_tree->numleafsh * p_tree->numleafsv];
l_parent_node0 = l_parent_node;
for
(i = 0; i < l_num_levels - 1; ++i)
{
for
(j = 0; j < l_nplv[i]; ++j)
{
k = l_nplh[i];
while
(--k >= 0)
{
l_node->parent = l_parent_node;
++l_node;
if (--k >= 0)
{
l_node->parent = l_parent_node;
++l_node;
}
++l_parent_node;
}
if ((j & 1) || j == l_nplv[i] - 1)
{
l_parent_node0 = l_parent_node;
}
else
{
l_parent_node = l_parent_node0;
l_parent_node0 += l_nplh[i];
}
}
}
l_node->parent = 0;
}
tgt_reset(p_tree);
return p_tree;
}
void tgt_destroy(opj_tgt_tree_t *tree) { void tgt_destroy(opj_tgt_tree_t *tree) {
opj_free(tree->nodes); opj_free(tree->nodes);
opj_free(tree); opj_free(tree);

View File

@ -52,16 +52,29 @@ typedef struct opj_tgt_node {
int known; int known;
} opj_tgt_node_t; } opj_tgt_node_t;
///** OPJ_V1
//Tag tree
//*/
//typedef struct opj_tgt_tree {
// int numleafsh;
// int numleafsv;
// int numnodes;
// opj_tgt_node_t *nodes;
//} opj_tgt_tree_t;
/** /**
Tag tree Tag tree
*/ */
typedef struct opj_tgt_tree { typedef struct opj_tgt_tree
int numleafsh; {
int numleafsv; OPJ_UINT32 numleafsh;
int numnodes; OPJ_UINT32 numleafsv;
opj_tgt_node_t *nodes; OPJ_UINT32 numnodes;
opj_tgt_node_t *nodes;
OPJ_UINT32 nodes_size; /* maximum size taken by nodes */
} opj_tgt_tree_t; } opj_tgt_tree_t;
/** @name Exported functions */ /** @name Exported functions */
/*@{*/ /*@{*/
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
@ -72,6 +85,18 @@ Create a tag-tree
@return Returns a new tag-tree if successful, returns NULL otherwise @return Returns a new tag-tree if successful, returns NULL otherwise
*/ */
opj_tgt_tree_t *tgt_create(int numleafsh, int numleafsv); opj_tgt_tree_t *tgt_create(int numleafsh, int numleafsv);
/**
* Reinitialises a tag-tree from an exixting one.
*
* @param p_tree the tree to reinitialize.
* @param p_num_leafs_h the width of the array of leafs of the tree
* @param p_num_leafs_v the height of the array of leafs of the tree
* @return a new tag-tree if successful, NULL otherwise
*/
opj_tgt_tree_t *tgt_init(opj_tgt_tree_t * p_tree,OPJ_UINT32 p_num_leafs_h, OPJ_UINT32 p_num_leafs_v);
/** /**
Destroy a tag-tree, liberating memory Destroy a tag-tree, liberating memory
@param tree Tag-tree to destroy @param tree Tag-tree to destroy

View File

@ -20,3 +20,9 @@
#cmakedefine HAVE_LCMS1_H @HAVE_LCMS1_H@ #cmakedefine HAVE_LCMS1_H @HAVE_LCMS1_H@
#cmakedefine HAVE_LCMS2_H @HAVE_LCMS2_H@ #cmakedefine HAVE_LCMS2_H @HAVE_LCMS2_H@
#cmakedefine CMAKE_WORDS_BIGENDIAN
#ifdef CMAKE_WORDS_BIGENDIAN
#define OPJ_BIG_ENDIAN
#else
#define OPJ_LITTLE_ENDIAN
#endif