Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for NLT marker segment of type 3 #154

Merged
merged 20 commits into from
Sep 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
0f21481
Added support for NLT marker only, but not tested.
aous72 Sep 17, 2024
5d888b5
This is for lossless compression. It removes the 1.1f factor.
aous72 Sep 17, 2024
5f29603
This should complete all code changed for the library. We need to te…
aous72 Sep 17, 2024
517e1be
Getting rid of some of the warnings
aous72 Sep 17, 2024
2626fe2
2nd attempt to get rid of warnings.
aous72 Sep 17, 2024
fcd652c
Small bug fix for wasm
aous72 Sep 17, 2024
086a5a5
A bug fix, and addressing the float to double type conversion.
aous72 Sep 17, 2024
5921b01
Added support for .pfm in ojph_compress and ojph_expand -- not happy…
aous72 Sep 18, 2024
2a36ea4
Bug fixes, pfm with different bit_depth/signedness are supported now.
aous72 Sep 20, 2024
27c9a2e
This fixes the one component case.
aous72 Sep 20, 2024
0c6dfd3
Removes compilation warnings.
aous72 Sep 20, 2024
9f8011c
This fixes a bug in the block decoder code. The bug can happen when …
aous72 Sep 20, 2024
7b0f5c8
Improvement for pfm_in, and a bug fix for handling signed pfm data.
aous72 Sep 20, 2024
b6ddad9
This should address "strict-aliasing". Cosmetic change to a wasm file…
aous72 Sep 20, 2024
1580ae7
This address one more warning.
aous72 Sep 20, 2024
9e97f99
Hopefully, this will remove warnings.
aous72 Sep 20, 2024
bcc4d3b
Added usage text for ojph_compress. Also , the end user must now spe…
aous72 Sep 20, 2024
11307b6
Change default signedness of .pfm to true.
aous72 Sep 22, 2024
57c7af3
This adds some codestream checking in ojph_expand.
aous72 Sep 22, 2024
796fb6b
Spelling mistake fix.
aous72 Sep 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 113 additions & 2 deletions src/apps/common/ojph_img_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ namespace ojph {

ui32 cur_line;
si64 start_of_data;
int planar;
bool planar;
ui32 bit_depth[3];
bool is_signed[3];
point subsampling[3];
Expand Down Expand Up @@ -446,6 +446,68 @@ namespace ojph {
size_t buffer_size;
};

////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////
class pfm_in : public image_in_base
{
public:
pfm_in(mem_fixed_allocator *p = NULL)
{
fh = 0;
fname = NULL;
alloc_p = p;
temp_buf = NULL;
temp_buf_byte_size = 0;
bit_depth[0] = bit_depth[1] = bit_depth[2] = 32;
scale = 0.0f;
little_endian = true;
width = height = num_comps = 0;

cur_line = 0;
start_of_data = 0;
}
virtual ~pfm_in()
{
close();
if (alloc_p == NULL && temp_buf)
free(temp_buf);
}

void open(const char* filename);
void finalize_alloc();
void configure(ui32* bit_depth) {
assert(num_comps != 0);
for (ui32 c = 0; c < num_comps; ++c)
this->bit_depth[c] = bit_depth[c];
}
virtual ui32 read(const line_buf* line, ui32 comp_num);
void close() { if(fh) { fclose(fh); fh = NULL; } fname = NULL; }

size get_size() { assert(fh); return size(width, height); }
ui32 get_width() { assert(fh); return width; }
ui32 get_height() { assert(fh); return height; }
ui32 get_num_components() { assert(fh); return num_comps; }

private:
FILE *fh;
const char *fname;
mem_fixed_allocator *alloc_p;
float *temp_buf;
size_t temp_buf_byte_size;
ui32 bit_depth[3]; // this truncates data to bit_depth in the LSB
float scale;
bool little_endian;
ui32 width, height, num_comps;
ui32 cur_line;
si64 start_of_data;
};


////////////////////////////////////////////////////////////////////////////
// Accelerators (defined in ojph_img_io_*)
typedef void (*conversion_fun)(const line_buf *ln0, const line_buf *ln1,
Expand Down Expand Up @@ -559,7 +621,7 @@ namespace ojph {
ui32 width, height, num_components;
ui32 bit_depth, bytes_per_sample;
ui8* buffer;
ui32 buffer_size;
size_t buffer_size;
ui32 cur_line, samples_per_line, bytes_per_line;
conversion_fun converter;
const line_buf *lptr[3];
Expand Down Expand Up @@ -703,6 +765,55 @@ namespace ojph {
ui8* buffer;
ui32 buffer_size;
};

////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////
class pfm_out : public image_out_base
{
public:
pfm_out()
{
fh = NULL;
fname = NULL;
buffer = NULL;
buffer_size = 0;
width = height = num_components = 0;
scale = -1.0f;
bit_depth[0] = bit_depth[1] = bit_depth[2] = 32;
cur_line = 0;
start_of_data = 0;
}
virtual ~pfm_out()
{
close();
if (buffer)
free(buffer);
}

void open(char* filename);
void configure(ui32 width, ui32 height, ui32 num_components,
float scale, ui32* bit_depth);
virtual ui32 write(const line_buf* line, ui32 comp_num);
virtual void close() { if(fh) { fclose(fh); fh = NULL; } fname = NULL; }

private:
FILE *fh;
const char *fname;
float* buffer;
size_t buffer_size;
ui32 width, height, num_components;
float scale;
ui32 bit_depth[3];
ui32 cur_line;
si64 start_of_data;
};


}

#endif // !OJPH_IMG_IO_H
135 changes: 132 additions & 3 deletions src/apps/ojph_compress/ojph_compress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -526,9 +526,9 @@ int main(int argc, char * argv[]) {
std::cout <<
"\nThe following arguments are necessary:\n"
#ifdef OJPH_ENABLE_TIFF_SUPPORT
" -i input file name (either pgm, ppm, tif(f), or raw(yuv))\n"
" -i input file name (either pgm, ppm, pfm, tif(f), or raw(yuv))\n"
#else
" -i input file name (either pgm, ppm, or raw(yuv))\n"
" -i input file name (either pgm, ppm, pfm, or raw(yuv))\n"
#endif // !OJPH_ENABLE_TIFF_SUPPORT
" -o output file name\n\n"

Expand Down Expand Up @@ -587,7 +587,28 @@ int main(int argc, char * argv[]) {
" component; for example: 12,10,10\n"
" -downsamp {x,y},{x,y},...,{x,y} a list of x,y points, one for each\n"
" component; for example {1,1},{2,2},{2,2}\n\n"
;
"\n"

".pfm files receive special treatment. Currently, lossy compression\n"
"with these files is not supported, only lossless. When these files are\n"
"used, the NLT segment marker is automatically inserted into the\n"
"codestream. For these files the following arguments can be useful\n"
" -signed a comma - separated list of true or false parameters, one\n"
" for each component; for example: true,false,false.\n"
" The sign only affects how values are treated; for negative\n"
" values the standard requires a special non-linear\n"
" transformation. When signed is false, no transformation\n"
" is employed, as we assume all values are 0 or positive.\n"
" When signed is true, the aforementioned transformation is\n"
" employed on negative values only.\n"
" -bit_depth a comma-separated list of bit depth values, one per \n"
" component; for example: 12,10,10.\n"
" Floating value numbers are treated as integers, and they\n"
" are shifted to the right, keeping only the specified\n"
" number of bits. Note that a bit depth of 28 upwards is not\n"
" supported.\n"

"\n";
return -1;
}
if (!get_arguments(argc, argv, input_filename, output_filename,
Expand All @@ -611,6 +632,7 @@ int main(int argc, char * argv[]) {
ojph::codestream codestream;

ojph::ppm_in ppm;
ojph::pfm_in pfm;
ojph::yuv_in yuv;
ojph::raw_in raw;
ojph::dpx_in dpx;
Expand Down Expand Up @@ -736,6 +758,113 @@ int main(int argc, char * argv[]) {

base = &ppm;
}
else if (is_matching(".pfm", v))
{
pfm.open(input_filename);
ojph::param_siz siz = codestream.access_siz();
siz.set_image_extent(ojph::point(image_offset.x + pfm.get_width(),
image_offset.y + pfm.get_height()));
ojph::ui32 num_comps = pfm.get_num_components();
assert(num_comps == 1 || num_comps == 3);
siz.set_num_components(num_comps);

if (bit_depth[0] == 0)
OJPH_ERROR(0x01000091,
"-bit_depth must be specified (this is temporary only).\n");

if (bit_depth[0] != 0) // one was set
if (num_bit_depths < num_comps) // but if not enough, repeat
for (ojph::ui32 c = num_bit_depths; c < num_comps; ++c)
bit_depth[c] = bit_depth[num_bit_depths - 1];
if (is_signed[0] != -1) // one was set
if (num_is_signed < num_comps) // but if not enough, repeat
for (ojph::ui32 c = num_is_signed; c < num_comps; ++c)
is_signed[c] = is_signed[num_is_signed - 1];

bool all_the_same = true;
if (num_comps == 3)
{
all_the_same = all_the_same
&& bit_depth[0] == bit_depth[1]
&& bit_depth[1] == bit_depth[2];
all_the_same = all_the_same
&& is_signed[0] == is_signed[1]
&& is_signed[1] == is_signed[2];
}

pfm.configure(bit_depth);
ojph::point ds(1, 1);
for (ojph::ui32 c = 0; c < num_comps; ++c) {
ojph::ui32 bd = 32;
if (bit_depth[c] != 0)
bd = bit_depth[c];
bool is = true;
if (is_signed[c] != -1)
is = is_signed[c] != 0;
siz.set_component(c, ds, bd, is);
}
siz.set_image_offset(image_offset);
siz.set_tile_size(tile_size);
siz.set_tile_offset(tile_offset);

ojph::param_cod cod = codestream.access_cod();
cod.set_num_decomposition(num_decompositions);
cod.set_block_dims(block_size.w, block_size.h);
if (num_precincts != -1)
cod.set_precinct_size(num_precincts, precinct_size);
cod.set_progression_order(prog_order);
if (num_comps == 1)
{
if (employ_color_transform != -1)
OJPH_WARN(0x01000092,
"-colour_trans option is not needed and was not used; "
"this is because the image has one component only\n");
}
else
{
if (employ_color_transform == -1)
cod.set_color_transform(true);
else
cod.set_color_transform(employ_color_transform == 1);
}
cod.set_reversible(reversible);
if (!reversible && quantization_step != -1.0f)
codestream.access_qcd().set_irrev_quant(quantization_step);

ojph::param_nlt nlt = codestream.access_nlt();
if (reversible) {
if (all_the_same)
nlt.set_type3_transformation(ojph::param_nlt::ALL_COMPS, true);
else
for (ojph::ui32 c = 0; c < num_comps; ++c)
nlt.set_type3_transformation(c, true);
}
else
OJPH_ERROR(0x01000093, "The support for pfm image is not "
"complete; I need to figure how to modify the interface "
"to better support the exchange of floating point data. "
"Feeding float point data is not supported yet, unless it "
"is for lossless compression.");

codestream.set_planar(false);
if (profile_string[0] != '\0')
codestream.set_profile(profile_string);
codestream.set_tilepart_divisions(tileparts_at_resolutions,
tileparts_at_components);
codestream.request_tlm_marker(tlm_marker);

if (dims.w != 0 || dims.h != 0)
OJPH_WARN(0x01000094,
"-dims option is not needed and was not used\n");
if (num_components != 0)
OJPH_WARN(0x01000095,
"-num_comps is not needed and was not used\n");
if (comp_downsampling[0].x != 0 || comp_downsampling[0].y != 0)
OJPH_WARN(0x01000096,
"-downsamp is not needed and was not used\n");

base = &pfm;
}
#ifdef OJPH_ENABLE_TIFF_SUPPORT
else if (is_matching(".tif", v) || is_matching(".tiff", v))
{
Expand Down
54 changes: 54 additions & 0 deletions src/apps/ojph_expand/ojph_expand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ int main(int argc, char *argv[]) {
ojph::codestream codestream;

ojph::ppm_out ppm;
ojph::pfm_out pfm;
#ifdef OJPH_ENABLE_TIFF_SUPPORT
ojph::tif_out tif;
#endif /* OJPH_ENABLE_TIFF_SUPPORT */
Expand Down Expand Up @@ -266,6 +267,59 @@ int main(int argc, char *argv[]) {
ppm.open(output_filename);
base = &ppm;
}
else if (is_matching(".pfm", v))
{
codestream.set_planar(false);
ojph::param_siz siz = codestream.access_siz();
ojph::param_cod cod = codestream.access_cod();
ojph::param_nlt nlt = codestream.access_nlt();

ojph::ui32 num_comps = siz.get_num_components();
if (num_comps != 3 && num_comps != 1)
OJPH_ERROR(0x0200000C,
"The file has %d color components; this cannot be saved to"
" a .pfm file\n", num_comps);
bool all_same = true;
ojph::point p = siz.get_downsampling(0);
for (ojph::ui32 i = 1; i < siz.get_num_components(); ++i)
{
ojph::point p1 = siz.get_downsampling(i);
all_same = all_same && (p1.x == p.x) && (p1.y == p.y);
}
if (!all_same)
OJPH_ERROR(0x0200000D,
"To save an image to ppm, all the components must have the "
"same downsampling ratio\n");
ojph::ui32 bit_depth[3];
for (ojph::ui32 c = 0; c < siz.get_num_components(); ++c) {
ojph::ui8 bd = 0;
bool is = true;
bool result = nlt.get_type3_transformation(c, bd, is);
if (result == false)
OJPH_ERROR(0x0200000E,
"This codestream is not supported; it does not have an "
"NLT segment marker for this component (or no default NLT "
"settings) .\n");
if (bd != siz.get_bit_depth(c) || is != siz.is_signed(c))
OJPH_ERROR(0x0200000F,
"There is discrepancy in component %d configuration between "
"SIZ marker segment, which specifies bit_depth = %d and "
"signedness = %s, and NLT marker segment, which specifies "
"bit_depth = %d and signedness = %s.\n", c,
siz.get_bit_depth(c), is != siz.is_signed(c) ? "True" : "False",
bd, is ? "True" : "False");
bit_depth[c] = bd;
}
if (!cod.is_reversible())
OJPH_ERROR(0x02000010,
"This codestream is lossy (not reversible), and we currently "
"only support reversible codestreams for .pfm target files. "
"This is only temporary and will be changed at some point.\n");
pfm.configure(siz.get_recon_width(0), siz.get_recon_height(0),
siz.get_num_components(), -1.0f, bit_depth);
pfm.open(output_filename);
base = &pfm;
}
#ifdef OJPH_ENABLE_TIFF_SUPPORT
else if (is_matching(".tif", v) || is_matching(".tiff", v))
{
Expand Down
Loading
Loading