Skip to content

Commit 7086c36

Browse files
committed
Generic NLT code is added. Testing is needed.
1 parent aed95f6 commit 7086c36

File tree

6 files changed

+239
-38
lines changed

6 files changed

+239
-38
lines changed

src/core/codestream/ojph_tile.cpp

Lines changed: 64 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -273,13 +273,18 @@ namespace ojph {
273273
}
274274
else
275275
{
276-
float mul = 1.0f / (float)(1<<num_bits[comp_num]);
277-
const si32 *sp = line->i32 + line_offsets[comp_num];
278-
float *dp = tc->f32;
279-
if (is_signed[comp_num])
280-
cnvrt_si32_to_float(sp, dp, mul, comp_width);
281-
else
282-
cnvrt_si32_to_float_shftd(sp, dp, mul, comp_width);
276+
if (nlt_type3[comp_num] == type3)
277+
irv_convert_to_float_nlt_type3(line, line_offsets[comp_num],
278+
tc, num_bits[comp_num], is_signed[comp_num], comp_width);
279+
else {
280+
float mul = 1.0f / (float)(1<<num_bits[comp_num]);
281+
const si32 *sp = line->i32 + line_offsets[comp_num];
282+
float *dp = tc->f32;
283+
if (is_signed[comp_num])
284+
cnvrt_si32_to_float(sp, dp, mul, comp_width);
285+
else
286+
cnvrt_si32_to_float_shftd(sp, dp, mul, comp_width);
287+
}
283288
}
284289
comps[comp_num].push_line();
285290
}
@@ -311,13 +316,19 @@ namespace ojph {
311316
}
312317
else
313318
{
314-
float mul = 1.0f / (float)(1<<num_bits[comp_num]);
315-
const si32 *sp = line->i32 + line_offsets[comp_num];
316-
float *dp = lines[comp_num].f32;
317-
if (is_signed[comp_num])
318-
cnvrt_si32_to_float(sp, dp, mul, comp_width);
319-
else
320-
cnvrt_si32_to_float_shftd(sp, dp, mul, comp_width);
319+
if (nlt_type3[comp_num] == type3)
320+
irv_convert_to_float_nlt_type3(line, line_offsets[comp_num],
321+
lines + comp_num, num_bits[comp_num], is_signed[comp_num],
322+
comp_width);
323+
else {
324+
float mul = 1.0f / (float)(1<<num_bits[comp_num]);
325+
const si32 *sp = line->i32 + line_offsets[comp_num];
326+
float *dp = lines[comp_num].f32;
327+
if (is_signed[comp_num])
328+
cnvrt_si32_to_float(sp, dp, mul, comp_width);
329+
else
330+
cnvrt_si32_to_float_shftd(sp, dp, mul, comp_width);
331+
}
321332
if (comp_num == 2)
322333
{ // irreversible color transform
323334
ict_forward(lines[0].f32, lines[1].f32, lines[2].f32,
@@ -364,13 +375,21 @@ namespace ojph {
364375
}
365376
else
366377
{
367-
float mul = (float)(1 << num_bits[comp_num]);
368-
const float *sp = src_line->f32;
369-
si32 *dp = tgt_line->i32 + line_offsets[comp_num];
370-
if (is_signed[comp_num])
371-
cnvrt_float_to_si32(sp, dp, mul, comp_width);
372-
else
373-
cnvrt_float_to_si32_shftd(sp, dp, mul, comp_width);
378+
if (nlt_type3[comp_num] == type3)
379+
{
380+
irv_convert_to_integer_nlt_type3(src_line, tgt_line,
381+
line_offsets[comp_num], num_bits[comp_num],
382+
is_signed[comp_num], comp_width);
383+
}
384+
else {
385+
float mul = (float)(1 << num_bits[comp_num]);
386+
const float *sp = src_line->f32;
387+
si32 *dp = tgt_line->i32 + line_offsets[comp_num];
388+
if (is_signed[comp_num])
389+
cnvrt_float_to_si32(sp, dp, mul, comp_width);
390+
else
391+
cnvrt_float_to_si32_shftd(sp, dp, mul, comp_width);
392+
}
374393
}
375394
}
376395
else
@@ -407,17 +426,30 @@ namespace ojph {
407426
}
408427
else
409428
{
410-
float mul = (float)(1 << num_bits[comp_num]);
411-
const float *sp;
412-
if (comp_num < 3)
413-
sp = lines[comp_num].f32;
414-
else
415-
sp = comps[comp_num].pull_line()->f32;
416-
si32 *dp = tgt_line->i32 + line_offsets[comp_num];
417-
if (is_signed[comp_num])
418-
cnvrt_float_to_si32(sp, dp, mul, comp_width);
419-
else
420-
cnvrt_float_to_si32_shftd(sp, dp, mul, comp_width);
429+
if (nlt_type3[comp_num] == type3)
430+
{
431+
line_buf* lbp;
432+
if (comp_num < 3)
433+
lbp = lines + comp_num;
434+
else
435+
lbp = comps[comp_num].pull_line();
436+
irv_convert_to_integer_nlt_type3(lbp, tgt_line,
437+
line_offsets[comp_num], num_bits[comp_num],
438+
is_signed[comp_num], comp_width);
439+
}
440+
else {
441+
float mul = (float)(1 << num_bits[comp_num]);
442+
const float *sp;
443+
if (comp_num < 3)
444+
sp = lines[comp_num].f32;
445+
else
446+
sp = comps[comp_num].pull_line()->f32;
447+
si32 *dp = tgt_line->i32 + line_offsets[comp_num];
448+
if (is_signed[comp_num])
449+
cnvrt_float_to_si32(sp, dp, mul, comp_width);
450+
else
451+
cnvrt_float_to_si32_shftd(sp, dp, mul, comp_width);
452+
}
421453
}
422454
}
423455

src/core/common/ojph_arch.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,18 @@ namespace ojph {
271271
#endif
272272
}
273273

274+
////////////////////////////////////////////////////////////////////////////
275+
static inline si64 ojph_round64(float val)
276+
{
277+
#ifdef OJPH_COMPILER_MSVC
278+
return (si64)(val + (val >= 0.0f ? 0.5f : -0.5f));
279+
#elif (defined OJPH_COMPILER_GNUC)
280+
return (si64)(val + (val >= 0.0f ? 0.5f : -0.5f));
281+
#else
282+
return (si64)round(val);
283+
#endif
284+
}
285+
274286
////////////////////////////////////////////////////////////////////////////
275287
static inline si32 ojph_trunc(float val)
276288
{

src/core/common/ojph_mem.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,8 @@ namespace ojph {
138138
enum : ui32 {
139139
LFT_UNDEFINED = 0x00, // Type is undefined/uninitialized
140140
// These flags reflects data size in bytes
141-
LFT_BYTE = 0x01, // Set when data is 1 byte
142-
LFT_16BIT = 0x02, // Set when data is 2 bytes
141+
LFT_BYTE = 0x01, // Set when data is 1 byte (not used)
142+
LFT_16BIT = 0x02, // Set when data is 2 bytes (not used)
143143
LFT_32BIT = 0x04, // Set when data is 4 bytes
144144
LFT_64BIT = 0x08, // Set when data is 8 bytes
145145
LFT_REVERSIBLE = 0x10, // Set when data is used for reversible coding

src/core/transform/ojph_colour.cpp

Lines changed: 141 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,16 @@ namespace ojph {
7878
void (*cnvrt_float_to_si32)
7979
(const float *sp, si32 *dp, float mul, ui32 width) = NULL;
8080

81+
//////////////////////////////////////////////////////////////////////////
82+
void (*irv_convert_to_float_nlt_type3) (
83+
const line_buf *src_line, ui32 src_line_offset,
84+
line_buf *dst_line, ui32 bit_depth, bool is_signed, ui32 width) = NULL;
85+
86+
//////////////////////////////////////////////////////////////////////////
87+
void (*irv_convert_to_integer_nlt_type3) (
88+
const line_buf *src_line, line_buf *dst_line, ui32 dst_line_offset,
89+
ui32 bit_depth, bool is_signed, ui32 width) = NULL;
90+
8191
//////////////////////////////////////////////////////////////////////////
8292
void (*rct_forward)
8393
(const line_buf* r, const line_buf* g, const line_buf* b,
@@ -115,6 +125,8 @@ namespace ojph {
115125
cnvrt_si32_to_float = gen_cnvrt_si32_to_float;
116126
cnvrt_float_to_si32_shftd = gen_cnvrt_float_to_si32_shftd;
117127
cnvrt_float_to_si32 = gen_cnvrt_float_to_si32;
128+
irv_convert_to_float_nlt_type3 = gen_irv_convert_to_float_nlt_type3;
129+
irv_convert_to_integer_nlt_type3 = gen_irv_convert_to_integer_nlt_type3;
118130
rct_forward = gen_rct_forward;
119131
rct_backward = gen_rct_backward;
120132
ict_forward = gen_ict_forward;
@@ -237,8 +249,8 @@ namespace ojph {
237249
}
238250
else
239251
{
240-
assert(src_line->flags | line_buf::LFT_64BIT);
241-
assert(dst_line->flags | line_buf::LFT_32BIT);
252+
assert(src_line->flags & line_buf::LFT_64BIT);
253+
assert(dst_line->flags & line_buf::LFT_32BIT);
242254
const si64 *sp = src_line->i64 + src_line_offset;
243255
si32 *dp = dst_line->i32 + dst_line_offset;
244256
for (ui32 i = width; i > 0; --i)
@@ -276,8 +288,8 @@ namespace ojph {
276288
}
277289
else
278290
{
279-
assert(src_line->flags | line_buf::LFT_64BIT);
280-
assert(dst_line->flags | line_buf::LFT_32BIT);
291+
assert(src_line->flags & line_buf::LFT_64BIT);
292+
assert(dst_line->flags & line_buf::LFT_32BIT);
281293
const si64 *sp = src_line->i64 + src_line_offset;
282294
si32 *dp = dst_line->i32 + dst_line_offset;
283295
for (ui32 i = width; i > 0; --i) {
@@ -319,6 +331,131 @@ namespace ojph {
319331
*dp++ = ojph_round(*sp++ * mul);
320332
}
321333

334+
//////////////////////////////////////////////////////////////////////////
335+
void gen_irv_convert_to_float_nlt_type3(const line_buf *src_line,
336+
ui32 src_line_offset, line_buf *dst_line,
337+
ui32 bit_depth, bool is_signed, ui32 width)
338+
{
339+
assert((src_line->flags & line_buf::LFT_32BIT) &&
340+
(src_line->flags & line_buf::LFT_REVERSIBLE) == 0 &&
341+
(dst_line->flags & line_buf::LFT_32BIT) &&
342+
(dst_line->flags & line_buf::LFT_REVERSIBLE) == 0);
343+
344+
float mul;
345+
if (bit_depth < 32)
346+
mul = 1.0f / (float)(1 << bit_depth);
347+
else
348+
mul = (float)(1.0 / 65536.0 / 65536.0);
349+
350+
const si32* sp = src_line->i32 + src_line_offset;
351+
float* dp = dst_line->f32;
352+
if (is_signed)
353+
{
354+
si32 shift = (1 << (bit_depth - 1)) + 1;
355+
for (ui32 i = width; i > 0; --i) {
356+
si32 v = *sp++;
357+
v = (v >= 0) ? v : (- v - shift);
358+
*dp++ = (float)v * mul;
359+
}
360+
}
361+
else
362+
{
363+
for (ui32 i = width; i > 0; --i)
364+
*dp++ = (float)*sp++ * mul - 0.5f;
365+
}
366+
}
367+
368+
//////////////////////////////////////////////////////////////////////////
369+
void gen_irv_convert_to_integer_nlt_type3(const line_buf *src_line,
370+
line_buf *dst_line, ui32 dst_line_offset,
371+
ui32 bit_depth, bool is_signed, ui32 width)
372+
{
373+
assert((src_line->flags & line_buf::LFT_32BIT) &&
374+
(src_line->flags & line_buf::LFT_REVERSIBLE) == 0 &&
375+
(dst_line->flags & line_buf::LFT_32BIT) &&
376+
(dst_line->flags & line_buf::LFT_REVERSIBLE) == 0);
377+
378+
float mul;
379+
if (bit_depth < 32)
380+
mul = 1.0f / (float)(1 << bit_depth);
381+
else
382+
mul = (float)(1.0 / 65536.0 / 65536.0);
383+
384+
const float* sp = src_line->f32;
385+
si32* dp = dst_line->i32 + dst_line_offset;
386+
if (bit_depth <= 30)
387+
{
388+
// We are leaving two bit overhead -- here, we are assuming that after
389+
// multiplications, the resulting number can still be represented
390+
// using 32 bit integer
391+
const si32 half = (1 << (bit_depth - 1));
392+
const si32 shift = half + 1;
393+
const si32 upper_limit = 0x7FFFFFFF >> (32 - bit_depth);
394+
const si32 lower_limit = 0x80000000 >> (32 - bit_depth);
395+
396+
if (is_signed)
397+
{
398+
for (ui32 i = width; i > 0; --i) {
399+
si32 v = ojph_round(*sp++ * mul);
400+
v = ojph_max(v, lower_limit);
401+
v = ojph_min(v, upper_limit);
402+
v = (v >= 0) ? v : (- v - shift);
403+
*dp++ = v;
404+
}
405+
}
406+
else
407+
{
408+
for (ui32 i = width; i > 0; --i) {
409+
si32 v = ojph_round(*sp++ * mul);
410+
v = ojph_max(v, lower_limit);
411+
v = ojph_min(v, upper_limit);
412+
v = (v >= 0) ? v : (- v - shift);
413+
*dp++ = v + half;
414+
}
415+
}
416+
}
417+
else
418+
{
419+
// There is the possibility that converting to integer will
420+
// exceed the dynamic range of 32bit integer; therefore, we need
421+
// to use 64 bit. One may think, why not limit the floats to the
422+
// range of [-0.5f, 0.5f)?
423+
// Notice the half closed range -- we need a value just below 0.5f.
424+
// While getting this number is possible, after multiplication, the
425+
// resulting number will not be exactly the maximum that the integer
426+
// can achieve. All this is academic, because here are talking
427+
// about a number which has all the exponent bits set, meaning
428+
// it is either infinity, -infinity, qNan or sNan.
429+
const si32 half = (1 << (bit_depth - 1));
430+
const si32 shift = half + 1;
431+
const si64 upper_limit = 0x7FFFFFFFFFFFFFFFLL >> (64 - bit_depth);
432+
const si64 lower_limit = 0x8000000000000000LL >> (64 - bit_depth);
433+
434+
if (is_signed)
435+
{
436+
for (ui32 i = width; i > 0; --i) {
437+
si64 t = ojph_round64(*sp++ * mul);
438+
t = ojph_max(t, lower_limit);
439+
t = ojph_min(t, upper_limit);
440+
si32 v = (si32)t;
441+
v = (v >= 0) ? v : (- v - shift);
442+
*dp++ = v;
443+
}
444+
}
445+
else
446+
{
447+
for (ui32 i = width; i > 0; --i) {
448+
si64 t = ojph_round64(*sp++ * mul);
449+
t = ojph_max(t, lower_limit);
450+
t = ojph_min(t, upper_limit);
451+
si32 v = (si32)t;
452+
v = (v >= 0) ? v : (- v - shift);
453+
*dp++ = v + half;
454+
}
455+
}
456+
}
457+
}
458+
322459
//////////////////////////////////////////////////////////////////////////
323460
void gen_rct_forward(
324461
const line_buf *r, const line_buf *g, const line_buf *b,

src/core/transform/ojph_colour.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ namespace ojph {
7777
extern void (*cnvrt_float_to_si32)
7878
(const float *sp, si32 *dp, float mul, ui32 width);
7979

80+
////////////////////////////////////////////////////////////////////////////
81+
extern void (*irv_convert_to_float_nlt_type3) (
82+
const line_buf *src_line, ui32 src_line_offset,
83+
line_buf *dst_line, ui32 bit_depth, bool is_signed, ui32 width);
84+
85+
////////////////////////////////////////////////////////////////////////////
86+
extern void (*irv_convert_to_integer_nlt_type3) (
87+
const line_buf *src_line, line_buf *dst_line, ui32 dst_line_offset,
88+
ui32 bit_depth, bool is_signed, ui32 width);
89+
8090
////////////////////////////////////////////////////////////////////////////
8191
extern void (*rct_forward)
8292
(const line_buf *r, const line_buf *g, const line_buf *b,

src/core/transform/ojph_colour_local.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,16 @@ namespace ojph {
9292
void gen_cnvrt_float_to_si32(const float *sp, si32 *dp, float mul,
9393
ui32 width);
9494

95+
//////////////////////////////////////////////////////////////////////////
96+
void gen_irv_convert_to_float_nlt_type3(
97+
const line_buf *src_line, ui32 src_line_offset,
98+
line_buf *dst_line, ui32 bit_depth, bool is_signed, ui32 width);
99+
100+
//////////////////////////////////////////////////////////////////////////
101+
void gen_irv_convert_to_integer_nlt_type3(
102+
const line_buf *src_line, line_buf *dst_line, ui32 dst_line_offset,
103+
ui32 bit_depth, bool is_signed, ui32 width);
104+
95105
//////////////////////////////////////////////////////////////////////////
96106
void gen_rct_forward(
97107
const line_buf *r, const line_buf *g, const line_buf *b,

0 commit comments

Comments
 (0)