Newer
Older
Merov Linden
committed
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
"{0.3346},{0.4691},{0.4691},"
"{0.5444},{0.6523},{0.6523},"
"{0.7078},{0.7797},{0.7797},{1}");
cod->parse_string("Cband_weights:C2="
"{0.0773},{0.1835},{0.1835},"
"{0.2598},{0.4130},{0.4130},"
"{0.5040},{0.6464},{0.6464},"
"{0.7220},{0.8254},{0.8254},"
"{0.8769},{0.9424},{0.9424},{1}");
}
/******************************************************************************/
/* transfer_bytes */
/******************************************************************************/
void transfer_bytes(kdu_byte *dest, kdu_line_buf &src, int gap, int precision)
/* Transfers source samples from the supplied line buffer into the output
byte buffer, spacing successive output samples apart by `gap' bytes
(to allow for interleaving of colour components). The function performs
all necessary level shifting, type conversion, rounding and truncation. */
{
int width = src.get_width();
if (src.get_buf32() != NULL)
{ // Decompressed samples have a 32-bit representation (integer or float)
assert(precision >= 8); // Else would have used 16 bit representation
kdu_sample32 *sp = src.get_buf32();
if (!src.is_absolute())
{ // Transferring normalized floating point data.
float scale16 = (float)(1<<16);
kdu_int32 val;
for (; width > 0; width--, sp++, dest+=gap)
{
val = (kdu_int32)(sp->fval*scale16);
val = (val+128)>>8; // May be faster than true rounding
val += 128;
Merov Linden
committed
{
Merov Linden
committed
val = (val < 0 ? 0 : 255);
Merov Linden
committed
}
*dest = (kdu_byte) val;
}
}
else
{ // Transferring 32-bit absolute integers.
kdu_int32 val;
kdu_int32 downshift = precision-8;
kdu_int32 offset = (1<<downshift)>>1;
for (; width > 0; width--, sp++, dest+=gap)
{
val = sp->ival;
val = (val+offset)>>downshift;
val += 128;
Merov Linden
committed
{
Merov Linden
committed
val = (val < 0 ? 0 : 255);
Merov Linden
committed
}
*dest = (kdu_byte) val;
}
}
}
else
{ // Source data is 16 bits.
kdu_sample16 *sp = src.get_buf16();
if (!src.is_absolute())
{ // Transferring 16-bit fixed point quantities
kdu_int16 val;
if (precision >= 8)
{ // Can essentially ignore the bit-depth.
for (; width > 0; width--, sp++, dest+=gap)
{
val = sp->ival;
val += (1<<(KDU_FIX_POINT-8))>>1;
val >>= (KDU_FIX_POINT-8);
val += 128;
Merov Linden
committed
{
Merov Linden
committed
val = (val < 0 ? 0 : 255);
Merov Linden
committed
}
*dest = (kdu_byte) val;
}
}
else
{ // Need to force zeros into one or more least significant bits.
kdu_int16 downshift = KDU_FIX_POINT-precision;
kdu_int16 upshift = 8-precision;
kdu_int16 offset = 1<<(downshift-1);
for (; width > 0; width--, sp++, dest+=gap)
{
val = sp->ival;
val = (val+offset)>>downshift;
val <<= upshift;
val += 128;
Merov Linden
committed
{
Merov Linden
committed
val = (val < 0 ? 0 : 256 - (1<<upshift));
Merov Linden
committed
}
*dest = (kdu_byte) val;
}
}
}
else
{ // Transferring 16-bit absolute integers.
kdu_int16 val;
if (precision >= 8)
{
kdu_int16 downshift = precision-8;
kdu_int16 offset = (1<<downshift)>>1;
for (; width > 0; width--, sp++, dest+=gap)
{
val = sp->ival;
val = (val+offset)>>downshift;
val += 128;
Merov Linden
committed
{
Merov Linden
committed
val = (val < 0 ? 0 : 255);
Merov Linden
committed
}
*dest = (kdu_byte) val;
}
}
else
{
kdu_int16 upshift = 8-precision;
for (; width > 0; width--, sp++, dest+=gap)
{
val = sp->ival;
val <<= upshift;
val += 128;
Merov Linden
committed
{
Merov Linden
committed
val = (val < 0 ? 0 : 256 - (1<<upshift));
Merov Linden
committed
}
*dest = (kdu_byte) val;
}
}
}
}
}
LLKDUDecodeState::LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap)
{
S32 c;
mTile = tile;
mBuf = buf;
mRowGap = row_gap;
mNumComponents = tile.get_num_components();
Merov Linden
committed
llassert(mNumComponents <= 4);
Merov Linden
committed
mUseYCC = tile.get_ycc();
Merov Linden
committed
for (c = 0; c < 4; ++c)
Merov Linden
committed
{
mReversible[c] = false;
mBitDepths[c] = 0;
}
// Open tile-components and create processing engines and resources
Merov Linden
committed
for (c = 0; c < mNumComponents; c++)
Merov Linden
committed
{
mComps[c] = mTile.access_component(c);
mReversible[c] = mComps[c].get_reversible();
mBitDepths[c] = mComps[c].get_bit_depth();
kdu_resolution res = mComps[c].access_resolution(); // Get top resolution
kdu_dims comp_dims; res.get_dims(comp_dims);
if (c == 0)
{
mDims = comp_dims;
}
else
{
llassert(mDims == comp_dims); // Safety check; the caller has ensured this
}
bool use_shorts = (mComps[c].get_bit_depth(true) <= 16);
mLines[c].pre_create(&mAllocator,mDims.size.x,mReversible[c],use_shorts,0,0);
Merov Linden
committed
if (res.which() == 0) // No DWT levels used
{
mEngines[c] = kdu_decoder(res.access_subband(LL_BAND),&mAllocator,use_shorts);
}
else
{
mEngines[c] = kdu_synthesis(res,&mAllocator,use_shorts);
}
}
mAllocator.finalize(); // Actually creates buffering resources
Merov Linden
committed
for (c = 0; c < mNumComponents; c++)
Merov Linden
committed
{
mLines[c].create(); // Grabs resources from the allocator.
}
}
LLKDUDecodeState::~LLKDUDecodeState()
{
// Cleanup
Merov Linden
committed
for (S32 c = 0; c < mNumComponents; c++)
Merov Linden
committed
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
{
mEngines[c].destroy(); // engines are interfaces; no default destructors
}
mTile.close();
}
BOOL LLKDUDecodeState::processTileDecode(F32 decode_time, BOOL limit_time)
/* Decompresses a tile, writing the data into the supplied byte buffer.
The buffer contains interleaved image components, if there are any.
Although you may think of the buffer as belonging entirely to this tile,
the `buf' pointer may actually point into a larger buffer representing
multiple tiles. For this reason, `row_gap' is needed to identify the
separation between consecutive rows in the real buffer. */
{
S32 c;
// Now walk through the lines of the buffer, recovering them from the
// relevant tile-component processing engines.
LLTimer decode_timer;
while (mDims.size.y--)
{
Merov Linden
committed
for (c = 0; c < mNumComponents; c++)
Merov Linden
committed
{
mEngines[c].pull(mLines[c]);
Merov Linden
committed
}
if ((mNumComponents >= 3) && mUseYCC)
{
kdu_convert_ycc_to_rgb(mLines[0],mLines[1],mLines[2]);
}
Merov Linden
committed
for (c = 0; c < mNumComponents; c++)
Merov Linden
committed
{
transfer_bytes(mBuf+c,mLines[c],mNumComponents,mBitDepths[c]);
}
mBuf += mRowGap;
if (mDims.size.y % 10)
{
if (limit_time && decode_timer.getElapsedTimeF32() > decode_time)
{
return FALSE;
}
}
}
return TRUE;
}
// kdc_flow_control
kdc_flow_control::kdc_flow_control (kdu_image_in_base *img_in, kdu_codestream codestream)
{
Merov Linden
committed
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
int n;
this->codestream = codestream;
codestream.get_valid_tiles(valid_tile_indices);
tile_idx = valid_tile_indices.pos;
tile = codestream.open_tile(tile_idx,NULL);
// Set up the individual components
num_components = codestream.get_num_components(true);
components = new kdc_component_flow_control[num_components];
count_delta = 0;
kdc_component_flow_control *comp = components;
for (n = 0; n < num_components; n++, comp++)
{
comp->line = NULL;
comp->reader = img_in;
kdu_coords subsampling;
codestream.get_subsampling(n,subsampling,true);
kdu_dims dims;
codestream.get_tile_dims(tile_idx,n,dims,true);
comp->vert_subsampling = subsampling.y;
if ((n == 0) || (comp->vert_subsampling < count_delta))
{
count_delta = comp->vert_subsampling;
}
comp->ratio_counter = 0;
comp->remaining_lines = comp->initial_lines = dims.size.y;
}
assert(num_components >= 0);
tile.set_components_of_interest(num_components);
max_buffer_memory = engine.create(codestream,tile,false,NULL,false,1,NULL,NULL,false);
}
kdc_flow_control::~kdc_flow_control()
{
Merov Linden
committed
if (components != NULL)
{
delete[] components;
}
if (engine.exists())
{
engine.destroy();
}
}
bool kdc_flow_control::advance_components()
{
Merov Linden
committed
bool found_line = false;
while (!found_line)
{
bool all_done = true;
kdc_component_flow_control *comp = components;
for (int n = 0; n < num_components; n++, comp++)
{
assert(comp->ratio_counter >= 0);
if (comp->remaining_lines > 0)
{
all_done = false;
comp->ratio_counter -= count_delta;
if (comp->ratio_counter < 0)
{
found_line = true;
comp->line = engine.exchange_line(n,NULL,NULL);
assert(comp->line != NULL);
if (comp->line->get_width())
{
comp->reader->get(n,*(comp->line),0);
}
Merov Linden
committed
}
}
}
if (all_done)
{
return false;
}
}
return true;
}
void kdc_flow_control::process_components()
{
Merov Linden
committed
kdc_component_flow_control *comp = components;
for (int n = 0; n < num_components; n++, comp++)
{
if (comp->ratio_counter < 0)
{
comp->ratio_counter += comp->vert_subsampling;
assert(comp->ratio_counter >= 0);
assert(comp->remaining_lines > 0);
comp->remaining_lines--;
assert(comp->line != NULL);
engine.exchange_line(n,comp->line,NULL);
comp->line = NULL;
}
}