Skip to content
Snippets Groups Projects
Commit 5c86d193 authored by Merov Linden's avatar Merov Linden
Browse files

SH-3050 : Parse an input codestream without decompressing it to find discard...

SH-3050 : Parse an input codestream without decompressing it to find discard levels boundaries (test only).
parent 1ebcb803
No related branches found
No related tags found
No related merge requests found
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "llmath.h" #include "llmath.h"
#include "llkdumem.h" #include "llkdumem.h"
#include "kdu_block_coding.h"
class kdc_flow_control { class kdc_flow_control {
...@@ -244,7 +245,7 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECod ...@@ -244,7 +245,7 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECod
mCodeStreamp->create(mInputp); mCodeStreamp->create(mInputp);
// Set the maximum number of bytes to use from the codestream // Set the maximum number of bytes to use from the codestream
mCodeStreamp->set_max_bytes(max_bytes); mCodeStreamp->set_max_bytes(max_bytes,true);
// If you want to flip or rotate the image for some reason, change // If you want to flip or rotate the image for some reason, change
// the resolution, or identify a restricted region of interest, this is // the resolution, or identify a restricted region of interest, this is
...@@ -369,6 +370,9 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco ...@@ -369,6 +370,9 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
// To regain control, we throw an exception, and catch it here. // To regain control, we throw an exception, and catch it here.
try try
{ {
// Merov : Test!! DO NOT COMMIT!!
//findDiscardLevelsBoundaries(base);
base.updateRawDiscardLevel(); base.updateRawDiscardLevel();
setupCodeStream(base, TRUE, mode); setupCodeStream(base, TRUE, mode);
...@@ -752,6 +756,202 @@ BOOL LLImageJ2CKDU::getMetadata(LLImageJ2C &base) ...@@ -752,6 +756,202 @@ BOOL LLImageJ2CKDU::getMetadata(LLImageJ2C &base)
} }
} }
/*****************************************************************************/
/* STATIC copy_block */
/*****************************************************************************/
static void copy_block(kdu_block *in, kdu_block *out)
{
if (in->K_max_prime != out->K_max_prime)
{
std::cout << "Cannot copy blocks belonging to subbands with different quantization parameters." << std::endl;
return;
}
if ((in->size.x != out->size.x) || (in->size.y != out->size.y))
{
std::cout << "Cannot copy code-blocks with different dimensions." << std::endl;
return;
}
out->missing_msbs = in->missing_msbs;
if (out->max_passes < (in->num_passes+2)) // Gives us enough to round up
out->set_max_passes(in->num_passes+2,false); // to the next whole bit-plane
out->num_passes = in->num_passes;
int num_bytes = 0;
for (int z=0; z < in->num_passes; z++)
{
num_bytes += (out->pass_lengths[z] = in->pass_lengths[z]);
out->pass_slopes[z] = in->pass_slopes[z];
}
// Just copy compressed code-bytes. Block transcoding not supported.
if (out->max_bytes < num_bytes)
out->set_max_bytes(num_bytes,false);
memcpy(out->byte_buffer,in->byte_buffer,(size_t) num_bytes);
}
/*****************************************************************************/
/* STATIC copy_tile */
/*****************************************************************************/
static void
copy_tile(kdu_tile tile_in, kdu_tile tile_out, int tnum_in, int tnum_out,
kdu_params *siz_in, kdu_params *siz_out, int skip_components,
int &num_blocks)
{
int num_components = tile_out.get_num_components();
int new_tpart=0, next_tpart = 1;
for (int c=0; c < num_components; c++)
{
kdu_tile_comp comp_in, comp_out;
comp_in = tile_in.access_component(c);
comp_out = tile_out.access_component(c);
int num_resolutions = comp_out.get_num_resolutions();
for (int r=0; r < num_resolutions; r++)
{
kdu_resolution res_in; res_in = comp_in.access_resolution(r);
kdu_resolution res_out; res_out = comp_out.access_resolution(r);
int b, min_band;
int num_bands = res_in.get_valid_band_indices(min_band);
for (b=min_band; num_bands > 0; num_bands--, b++)
{
kdu_subband band_in; band_in = res_in.access_subband(b);
kdu_subband band_out; band_out = res_out.access_subband(b);
kdu_dims blocks_in; band_in.get_valid_blocks(blocks_in);
kdu_dims blocks_out; band_out.get_valid_blocks(blocks_out);
if ((blocks_in.size.x != blocks_out.size.x) ||
(blocks_in.size.y != blocks_out.size.y))
{
std::cout << "Transcoding operation cannot proceed: Code-block partitions for the input and output code-streams do not agree." << std::endl;
return;
}
kdu_coords idx;
for (idx.y=0; idx.y < blocks_out.size.y; idx.y++)
{
for (idx.x=0; idx.x < blocks_out.size.x; idx.x++)
{
kdu_block *in =
band_in.open_block(idx+blocks_in.pos,&new_tpart);
for (; next_tpart <= new_tpart; next_tpart++)
siz_out->copy_from(siz_in,tnum_in,tnum_out,next_tpart,
skip_components);
kdu_block *out = band_out.open_block(idx+blocks_out.pos);
copy_block(in,out);
band_in.close_block(in);
band_out.close_block(out);
num_blocks++;
}
}
}
}
}
}
// Find the block boundary for each discard level in the input image.
// We parse the input blocks and copy them in a temporary output stream.
// For the moment, we do nothing more that parsing the raw list of blocks and outputing result.
void LLImageJ2CKDU::findDiscardLevelsBoundaries(LLImageJ2C &base)
{
// We need the number of levels in that image before starting.
getMetadata(base);
for (int discard_level = 0; discard_level < mLevels; discard_level++)
{
// Create the input codestream object.
setupCodeStream(base, TRUE, MODE_FAST);
mCodeStreamp->apply_input_restrictions(0, 4, discard_level, 0, NULL);
//mCodeStreamp->set_max_bytes(max,true);
siz_params *siz_in = mCodeStreamp->access_siz();
// Create the output codestream object.
siz_params siz;
siz.copy_from(siz_in,-1,-1,-1,0,discard_level,false,false,false);
siz.set(Scomponents,0,0,mCodeStreamp->get_num_components());
U32 max_output_size = base.getWidth()*base.getHeight()*base.getComponents();
max_output_size = (max_output_size < 1000 ? 1000 : max_output_size);
U8 *output_buffer = new U8[max_output_size];
U32 output_size = 0; // Address updated by LLKDUMemTarget to give the final compressed buffer size
LLKDUMemTarget output(output_buffer, output_size, max_output_size);
kdu_codestream codestream_out;
codestream_out.create(&siz,&output);
//codestream_out.share_buffering(*mCodeStreamp);
siz_params *siz_out = codestream_out.access_siz();
siz_out->copy_from(siz_in,-1,-1,-1,0,discard_level,false,false,false);
codestream_out.access_siz()->finalize_all(-1);
// Set up rate control variables
kdu_long max_bytes = KDU_LONG_MAX;
kdu_params *cod = siz_out->access_cluster(COD_params);
int total_layers; cod->get(Clayers,0,0,total_layers);
kdu_long *layer_bytes = new kdu_long[total_layers];
int nel, non_empty_layers = 0;
// Now ready to perform the transfer of compressed data between streams
int flush_counter = INT_MAX;
kdu_dims tile_indices_in;
mCodeStreamp->get_valid_tiles(tile_indices_in);
kdu_dims tile_indices_out;
codestream_out.get_valid_tiles(tile_indices_out);
assert((tile_indices_in.size.x == tile_indices_out.size.x) &&
(tile_indices_in.size.y == tile_indices_out.size.y));
int num_blocks=0;
kdu_coords idx;
for (idx.y=0; idx.y < tile_indices_out.size.y; idx.y++)
{
for (idx.x=0; idx.x < tile_indices_out.size.x; idx.x++)
{
kdu_tile tile_in = mCodeStreamp->open_tile(idx+tile_indices_in.pos);
int tnum_in = tile_in.get_tnum();
int tnum_out = idx.x + idx.y*tile_indices_out.size.x;
siz_out->copy_from(siz_in,tnum_in,tnum_out,0,0,discard_level,false,false,false);
siz_out->finalize_all(tnum_out);
// Note: do not open the output tile without first copying any tile-specific code-stream parameters
kdu_tile tile_out = codestream_out.open_tile(idx+tile_indices_out.pos);
assert(tnum_out == tile_out.get_tnum());
copy_tile(tile_in,tile_out,tnum_in,tnum_out,siz_in,siz_out,0,num_blocks);
tile_in.close();
tile_out.close();
flush_counter--;
if ((flush_counter <= 0) && codestream_out.ready_for_flush())
{
flush_counter = INT_MAX;
nel = codestream_out.trans_out(max_bytes,layer_bytes,total_layers);
non_empty_layers = (nel > non_empty_layers)?nel:non_empty_layers;
}
}
}
// Generate the output code-stream
if (codestream_out.ready_for_flush())
{
nel = codestream_out.trans_out(max_bytes,layer_bytes,total_layers);
non_empty_layers = (nel > non_empty_layers)?nel:non_empty_layers;
}
if (non_empty_layers > total_layers)
non_empty_layers = total_layers; // Can happen if a tile has more layers
// Print out stats
std::cout << "Code stream parsing for discard level = " << discard_level << std::endl;
std::cout << " Total compressed memory in = " << mCodeStreamp->get_compressed_data_memory() << " bytes" << std::endl;
std::cout << " Total compressed memory out = " << codestream_out.get_compressed_data_memory() << " bytes" << std::endl;
//std::cout << " Output contains " << total_layers << " quality layers" << std::endl;
std::cout << " Transferred " << num_blocks << " code-blocks from in to out" << std::endl;
//std::cout << " Read " << mCodeStreamp->get_num_tparts() << " tile-part(s) from a total of " << (int) tile_indices_in.area() << " tile(s)" << std::endl;
std::cout << " Total bytes read = " << mCodeStreamp->get_total_bytes() << std::endl;
//std::cout << " Wrote " << codestream_out.get_num_tparts() << " tile-part(s) in a total of " << (int) tile_indices_out.area() << " tile(s)" << std::endl;
std::cout << " Total bytes written = " << codestream_out.get_total_bytes() << std::endl;
std::cout << "-------------" << std::endl;
// Clean-up
cleanupCodeStream();
codestream_out.destroy();
delete[] output_buffer;
}
return;
}
void set_default_colour_weights(kdu_params *siz) void set_default_colour_weights(kdu_params *siz)
{ {
kdu_params *cod = siz->access_cluster(COD_params); kdu_params *cod = siz->access_cluster(COD_params);
......
...@@ -60,6 +60,7 @@ class LLImageJ2CKDU : public LLImageJ2CImpl ...@@ -60,6 +60,7 @@ class LLImageJ2CKDU : public LLImageJ2CImpl
BOOL reversible=FALSE); BOOL reversible=FALSE);
/*virtual*/ BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL); /*virtual*/ BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL);
/*virtual*/ BOOL initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1, int levels = 0); /*virtual*/ BOOL initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1, int levels = 0);
void findDiscardLevelsBoundaries(LLImageJ2C &base);
private: private:
BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level = -1, int* region = NULL); BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level = -1, int* region = NULL);
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
// Class to test // Class to test
#include "llimagej2ckdu.h" #include "llimagej2ckdu.h"
#include "llkdumem.h" #include "llkdumem.h"
#include "kdu_block_coding.h"
// Tut header // Tut header
#include "lltut.h" #include "lltut.h"
...@@ -107,16 +108,25 @@ bool LLKDUMemIn::get(int, kdu_line_buf&, int) { return false; } ...@@ -107,16 +108,25 @@ bool LLKDUMemIn::get(int, kdu_line_buf&, int) { return false; }
// Stub Kakadu Library calls // Stub Kakadu Library calls
kdu_tile_comp kdu_tile::access_component(int ) { kdu_tile_comp a; return a; } kdu_tile_comp kdu_tile::access_component(int ) { kdu_tile_comp a; return a; }
kdu_block_encoder::kdu_block_encoder() { }
kdu_block_decoder::kdu_block_decoder() { }
void kdu_block::set_max_passes(int , bool ) { }
void kdu_block::set_max_bytes(int , bool ) { }
void kdu_block::set_max_samples(int ) { }
void kdu_tile::close(kdu_thread_env* ) { } void kdu_tile::close(kdu_thread_env* ) { }
int kdu_tile::get_num_components() { return 0; } int kdu_tile::get_num_components() { return 0; }
bool kdu_tile::get_ycc() { return false; } bool kdu_tile::get_ycc() { return false; }
void kdu_tile::set_components_of_interest(int , const int* ) { } void kdu_tile::set_components_of_interest(int , const int* ) { }
int kdu_tile::get_tnum() { return 0; }
kdu_resolution kdu_tile_comp::access_resolution() { kdu_resolution a; return a; } kdu_resolution kdu_tile_comp::access_resolution() { kdu_resolution a; return a; }
kdu_resolution kdu_tile_comp::access_resolution(int ) { kdu_resolution a; return a; }
int kdu_tile_comp::get_bit_depth(bool ) { return 8; } int kdu_tile_comp::get_bit_depth(bool ) { return 8; }
bool kdu_tile_comp::get_reversible() { return false; } bool kdu_tile_comp::get_reversible() { return false; }
int kdu_tile_comp::get_num_resolutions() { return 1; }
kdu_subband kdu_resolution::access_subband(int ) { kdu_subband a; return a; } kdu_subband kdu_resolution::access_subband(int ) { kdu_subband a; return a; }
void kdu_resolution::get_dims(kdu_dims& ) { } void kdu_resolution::get_dims(kdu_dims& ) { }
int kdu_resolution::which() { return 0; } int kdu_resolution::which() { return 0; }
int kdu_resolution::get_valid_band_indices(int &) { return 1; }
kdu_decoder::kdu_decoder(kdu_subband , kdu_sample_allocator*, bool , float, int, kdu_thread_env*, kdu_thread_queue*) { } kdu_decoder::kdu_decoder(kdu_subband , kdu_sample_allocator*, bool , float, int, kdu_thread_env*, kdu_thread_queue*) { }
kdu_synthesis::kdu_synthesis(kdu_resolution, kdu_sample_allocator*, bool, float, kdu_thread_env*, kdu_thread_queue*) { } kdu_synthesis::kdu_synthesis(kdu_resolution, kdu_sample_allocator*, bool, float, kdu_thread_env*, kdu_thread_queue*) { }
kdu_params::kdu_params(const char*, bool, bool, bool, bool, bool) { } kdu_params::kdu_params(const char*, bool, bool, bool, bool, bool) { }
...@@ -124,6 +134,7 @@ kdu_params::~kdu_params() { } ...@@ -124,6 +134,7 @@ kdu_params::~kdu_params() { }
void kdu_params::set(const char* , int , int , bool ) { } void kdu_params::set(const char* , int , int , bool ) { }
void kdu_params::set(const char* , int , int , int ) { } void kdu_params::set(const char* , int , int , int ) { }
void kdu_params::finalize_all(bool ) { } void kdu_params::finalize_all(bool ) { }
void kdu_params::finalize_all(int, bool ) { }
void kdu_params::copy_from(kdu_params*, int, int, int, int, int, bool, bool, bool) { } void kdu_params::copy_from(kdu_params*, int, int, int, int, int, bool, bool, bool) { }
bool kdu_params::parse_string(const char*) { return false; } bool kdu_params::parse_string(const char*) { return false; }
bool kdu_params::get(const char*, int, int, bool&, bool, bool, bool) { return false; } bool kdu_params::get(const char*, int, int, bool&, bool, bool, bool) { return false; }
...@@ -148,9 +159,18 @@ void kdu_codestream::get_subsampling(int , kdu_coords&, bool ) { } ...@@ -148,9 +159,18 @@ void kdu_codestream::get_subsampling(int , kdu_coords&, bool ) { }
void kdu_codestream::flush(kdu_long *, int , kdu_uint16 *, bool, bool, double, kdu_thread_env*) { } void kdu_codestream::flush(kdu_long *, int , kdu_uint16 *, bool, bool, double, kdu_thread_env*) { }
void kdu_codestream::set_resilient(bool ) { } void kdu_codestream::set_resilient(bool ) { }
int kdu_codestream::get_num_components(bool ) { return 0; } int kdu_codestream::get_num_components(bool ) { return 0; }
kdu_long kdu_codestream::get_total_bytes(bool ) { return 0; }
kdu_long kdu_codestream::get_compressed_data_memory(bool ) {return 0; }
void kdu_codestream::share_buffering(kdu_codestream ) { }
int kdu_codestream::get_num_tparts() { return 0; }
int kdu_codestream::trans_out(kdu_long, kdu_long*, int, bool, kdu_thread_env* ) { return 0; }
bool kdu_codestream::ready_for_flush(kdu_thread_env*) { return false; }
siz_params* kdu_codestream::access_siz() { return NULL; } siz_params* kdu_codestream::access_siz() { return NULL; }
kdu_tile kdu_codestream::open_tile(kdu_coords , kdu_thread_env* ) { kdu_tile a; return a; } kdu_tile kdu_codestream::open_tile(kdu_coords , kdu_thread_env* ) { kdu_tile a; return a; }
kdu_codestream_comment kdu_codestream::add_comment() { kdu_codestream_comment a; return a; } kdu_codestream_comment kdu_codestream::add_comment() { kdu_codestream_comment a; return a; }
void kdu_subband::close_block(kdu_block*, kdu_thread_env*) { }
void kdu_subband::get_valid_blocks(kdu_dims &indices) { }
kdu_block* kdu_subband::open_block(kdu_coords, int*, kdu_thread_env*) { return NULL; }
bool kdu_codestream_comment::put_text(const char*) { return false; } bool kdu_codestream_comment::put_text(const char*) { return false; }
void kdu_customize_warnings(kdu_message*) { } void kdu_customize_warnings(kdu_message*) { }
void kdu_customize_errors(kdu_message*) { } void kdu_customize_errors(kdu_message*) { }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment