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

SH-3075 : Fix encoding for reversible images and small textures

parent df09fd8e
No related branches found
No related tags found
No related merge requests found
......@@ -48,6 +48,8 @@ const S32 MAX_PRECINCT_SIZE = 2048; // No reason to be bigger than MAX_IMAGE_S
const S32 MIN_PRECINCT_SIZE = 4; // Can't be smaller than MIN_BLOCK_SIZE
const S32 MAX_BLOCK_SIZE = 64; // Max total block size is 4096, hence 64x64 when using square blocks
const S32 MIN_BLOCK_SIZE = 4; // Min block dim is 4 according to jpeg2000 spec
const S32 MIN_LAYER_SIZE = 2000; // Size of the first quality layer (after header). Must be > to FIRST_PACKET_SIZE!!
const S32 MAX_NB_LAYERS = 64; // Max number of layers we'll entertain in SL (practical limit)
const S32 MIN_IMAGE_SIZE = (1<<MIN_IMAGE_MIP); // 4, only used for expand/contract power of 2
const S32 MAX_IMAGE_SIZE = (1<<MAX_IMAGE_MIP); // 2048
......
......@@ -599,12 +599,6 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co
comment.put_text(comment_text);
}
// Set codestream options
int num_layer_specs = 0;
kdu_long layer_bytes[64];
U32 max_bytes = 0;
if (num_components >= 3)
{
// Note that we always use YCC and not YUV
......@@ -612,67 +606,70 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co
set_default_colour_weights(codestream.access_siz());
}
// Set codestream options
int num_layer_specs = 0;
kdu_long layer_bytes[MAX_NB_LAYERS];
U32 max_bytes = (U32)(base.getWidth() * base.getHeight() * base.getComponents());
// Rate is the argument passed into the LLImageJ2C which
// specifies the target compression rate. The default is 8:1.
// *TODO: mRate is actually always 8:1 in the viewer. Test different values. Also force to reversible for small (< 500 bytes) textures.
if (base.mRate != 0.f)
{
max_bytes = (U32)((F32)(max_bytes) * base.mRate);
}
else
{
max_bytes = (U32)((F32)(max_bytes) / 8.0f);
}
// If the image is very small, code it in a lossless way.
// Note: it'll also have only 1 layer which is fine as there's no point reordering blocks in that case.
if (max_bytes < FIRST_PACKET_SIZE)
{
reversible = true;
}
// This code is where we specify the target number of bytes for each quality layer.
// We're using a logarithmic spacing rule that fits with our way of fetching texture data.
// Note: For more info on this layers business, read kdu_codestream::flush() doc in kdu_compressed.h
U32 i = FIRST_PACKET_SIZE;
while ((i < max_bytes) && (num_layer_specs < (MAX_NB_LAYERS-1)))
{
if (i == FIRST_PACKET_SIZE * 4)
{
// That really just means that the first layer is FIRST_PACKET_SIZE and the second is MIN_LAYER_SIZE
i = MIN_LAYER_SIZE;
}
layer_bytes[num_layer_specs] = i;
num_layer_specs++;
i *= 4;
}
if (reversible)
{
codestream.access_siz()->parse_string("Creversible=yes");
// *TODO: we should use yuv in reversible mode and one level since those images are small.
// *TODO: we should use yuv in reversible mode and one res level since those images are small.
// Don't turn this on now though as both create problems on decoding for the moment
//codestream.access_siz()->parse_string("Clevels=1");
//codestream.access_siz()->parse_string("Cycc=no");
// If we're doing reversible (i.e. lossless compression), assumes we're not using quality layers.
// *TODO: this is incorrect and unecessary. Try using the regular layer setting.
codestream.access_siz()->parse_string("Clayers=1");
num_layer_specs = 1;
layer_bytes[0] = 0;
// In the reversible case, set the last entry of that table to 0 so that all generated bits will
// indeed be output by the time the last quality layer is encountered.
layer_bytes[num_layer_specs] = 0;
}
else
{
// Rate is the argument passed into the LLImageJ2C which
// specifies the target compression rate. The default is 8:1.
// Possibly if max_bytes < 500, we should just use the default setting?
// *TODO: mRate is actually always 8:1 in the viewer. Test different values. Also force to reversible for small (< 500 bytes) textures.
if (base.mRate != 0.f)
{
max_bytes = (U32)(base.mRate*base.getWidth()*base.getHeight()*base.getComponents());
}
else
{
max_bytes = (U32)(base.getWidth()*base.getHeight()*base.getComponents()*0.125);
}
const U32 min_bytes = FIRST_PACKET_SIZE;
if (max_bytes > min_bytes)
{
U32 i;
// This code is where we specify the target number of bytes for
// each layer. Not sure if we should do this for small images
// or not. The goal is to have this roughly align with
// different quality levels that we decode at.
for (i = min_bytes; i < max_bytes; i*=4)
{
if (i == min_bytes * 4)
{
i = 2000;
}
layer_bytes[num_layer_specs] = i;
num_layer_specs++;
}
layer_bytes[num_layer_specs] = max_bytes;
num_layer_specs++;
std::string layer_string = llformat("Clayers=%d",num_layer_specs);
codestream.access_siz()->parse_string(layer_string.c_str());
}
else
{
layer_bytes[0] = min_bytes;
num_layer_specs = 1;
std::string layer_string = llformat("Clayers=%d",num_layer_specs);
codestream.access_siz()->parse_string(layer_string.c_str());
}
// Truncate the last quality layer if necessary so to fit the set compression ratio
layer_bytes[num_layer_specs] = max_bytes;
}
num_layer_specs++;
std::string layer_string = llformat("Clayers=%d",num_layer_specs);
codestream.access_siz()->parse_string(layer_string.c_str());
// Set up data ordering, markers, etc... if precincts or blocks specified
// Note: This code is *not* used in the encoding made by the viewer. It is currently used only
// by llimage_libtest to create various j2c and test alternative compression schemes.
if ((mBlocksSize != -1) || (mPrecinctsSize != -1))
{
if (mPrecinctsSize != -1)
......@@ -692,16 +689,19 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co
std::string Parts_string = llformat("ORGtparts=R");
codestream.access_siz()->parse_string(Parts_string.c_str());
}
// Set the number of wavelets subresolutions (aka levels)
if (mLevels != 0)
{
std::string levels_string = llformat("Clevels=%d",mLevels);
codestream.access_siz()->parse_string(levels_string.c_str());
}
// Complete the encode settings
codestream.access_siz()->finalize_all();
codestream.change_appearance(transpose,vflip,hflip);
// Now we are ready for sample data processing.
// Now we are ready for sample data processing
kdc_flow_control *tile = new kdc_flow_control(&mem_in,codestream);
bool done = false;
while (!done)
......
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