Skip to content

Commit 439cfe5

Browse files
committed
Add support for 32-bit and sub-sampling
1 parent 3cc1729 commit 439cfe5

File tree

5 files changed

+278
-75
lines changed

5 files changed

+278
-75
lines changed

cmake/OpenEXRSetup.cmake

+1-1
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ include(FetchContent)
292292
FetchContent_Declare(
293293
openjph
294294
GIT_REPOSITORY https://github.com/aous72/OpenJPH
295-
GIT_TAG origin/master
295+
GIT_TAG 0.18.2
296296
)
297297

298298
FetchContent_MakeAvailable(openjph)

src/lib/OpenEXRCore/internal_ht.cpp

+241-51
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
** Copyright Contributors to the OpenEXR Project.
44
*/
55

6+
#include <fstream>
7+
68
#include "internal_compress.h"
79
#include "internal_decompress.h"
810

@@ -32,8 +34,8 @@ internal_exr_undo_ht (
3234
{
3335
exr_result_t rv = EXR_ERR_SUCCESS;
3436

35-
std::vector<int> cs_to_file_ch (decode->channel_count);
36-
bool isRGB = make_channel_map (
37+
std::vector<CodestreamChannelInfo> cs_to_file_ch (decode->channel_count);
38+
bool isRGB = make_channel_map (
3739
decode->channel_count, decode->channels, cs_to_file_ch);
3840

3941
ojph::mem_infile infile;
@@ -44,41 +46,131 @@ internal_exr_undo_ht (
4446
cs.read_headers (&infile);
4547

4648
ojph::param_siz siz = cs.access_siz ();
47-
ojph::ui32 width = siz.get_image_extent ().x - siz.get_image_offset ().x;
48-
ojph::ui32 height = siz.get_image_extent ().y - siz.get_image_offset ().y;
49+
ojph::param_nlt nlt = cs.access_nlt ();
4950

50-
assert (decode->chunk.width == width);
51-
assert (decode->chunk.height == height);
52-
assert (decode->channel_count == siz.get_num_components ());
51+
ojph::ui32 image_width =
52+
siz.get_image_extent ().x - siz.get_image_offset ().x;
53+
ojph::ui32 image_height =
54+
siz.get_image_extent ().y - siz.get_image_offset ().y;
5355

54-
assert (decode->channel_count * 2 * width * height == uncompressed_size);
56+
int bpl = 0;
57+
bool is_planar = false;
58+
for (ojph::ui32 c = 0; c < decode->channel_count; c++)
59+
{
60+
bpl +=
61+
decode->channels[c].bytes_per_element * decode->channels[c].width;
62+
if (decode->channels[c].x_samples > 1 ||
63+
decode->channels[c].y_samples > 1)
64+
{ is_planar = true; }
65+
}
66+
cs.set_planar (is_planar);
5567

56-
cs.set_planar (false);
68+
assert (decode->chunk.width == image_width);
69+
assert (decode->chunk.height == image_height);
70+
assert (decode->channel_count == siz.get_num_components ());
5771

5872
cs.create ();
5973

60-
assert (sizeof (int16_t) == 2);
61-
int16_t* line_pixels = static_cast<int16_t*> (uncompressed_data);
62-
63-
for (uint32_t i = 0; i < height; ++i)
74+
assert (sizeof (uint16_t) == 2);
75+
assert (sizeof (uint32_t) == 4);
76+
ojph::ui32 next_comp = 0;
77+
ojph::line_buf* cur_line;
78+
if (cs.is_planar ())
6479
{
65-
6680
for (uint32_t c = 0; c < decode->channel_count; c++)
6781
{
68-
ojph::ui32 next_comp = 0;
69-
ojph::line_buf* cur_line = cs.pull (next_comp);
82+
int file_c = cs_to_file_ch[c].file_index;
83+
assert (
84+
siz.get_recon_height (c) == decode->channels[file_c].height);
85+
assert (decode->channels[file_c].width == siz.get_recon_width (c));
7086

71-
assert (next_comp == c);
87+
if (decode->channels[file_c].height == 0) continue;
7288

73-
int16_t* channel_pixels = line_pixels + width * cs_to_file_ch[c];
89+
uint8_t* line_pixels = static_cast<uint8_t*> (uncompressed_data);
7490

75-
for (uint32_t p = 0; p < width; p++)
91+
for (int64_t y = decode->chunk.start_y;
92+
y < image_height + decode->chunk.start_y;
93+
y++)
7694
{
77-
*channel_pixels++ = (int16_t) (cur_line->i32[p]);
95+
for (ojph::ui32 line_c = 0; line_c < decode->channel_count;
96+
line_c++)
97+
{
98+
if (y % decode->channels[line_c].y_samples != 0) continue;
99+
100+
if (line_c == file_c)
101+
{
102+
cur_line = cs.pull (next_comp);
103+
assert (next_comp == c);
104+
105+
if (decode->channels[file_c].data_type ==
106+
EXR_PIXEL_HALF)
107+
{
108+
int16_t* channel_pixels = (int16_t*) line_pixels;
109+
for (uint32_t p = 0;
110+
p < decode->channels[file_c].width;
111+
p++)
112+
{
113+
*channel_pixels++ = cur_line->i32[p];
114+
// assert (*(channel_pixels - 1) == 0);
115+
}
116+
}
117+
else
118+
{
119+
int32_t* channel_pixels = (int32_t*) line_pixels;
120+
for (uint32_t p = 0;
121+
p < decode->channels[file_c].width;
122+
p++)
123+
{
124+
*channel_pixels++ = cur_line->i32[p];
125+
// assert (*(channel_pixels - 1) == 0);
126+
}
127+
}
128+
}
129+
130+
line_pixels += decode->channels[line_c].bytes_per_element *
131+
decode->channels[line_c].width;
132+
}
78133
}
79134
}
135+
}
136+
else
137+
{
138+
uint8_t* line_pixels = static_cast<uint8_t*> (uncompressed_data);
80139

81-
line_pixels += width * decode->channel_count;
140+
assert (bpl * image_height == uncompressed_size);
141+
142+
for (uint32_t y = 0; y < image_height; ++y)
143+
{
144+
for (uint32_t c = 0; c < decode->channel_count; c++)
145+
{
146+
int file_c = cs_to_file_ch[c].file_index;
147+
cur_line = cs.pull (next_comp);
148+
assert (next_comp == c);
149+
if (decode->channels[file_c].data_type == EXR_PIXEL_HALF)
150+
{
151+
int16_t* channel_pixels =
152+
(int16_t*) (line_pixels + cs_to_file_ch[c].raster_line_offset);
153+
for (uint32_t p = 0; p < decode->channels[file_c].width;
154+
p++)
155+
{
156+
*channel_pixels++ = cur_line->i32[p];
157+
// assert (*(channel_pixels - 1) == 0);
158+
}
159+
}
160+
else
161+
{
162+
int32_t* channel_pixels =
163+
(int32_t*) (line_pixels + cs_to_file_ch[c].raster_line_offset);
164+
for (uint32_t p = 0; p < decode->channels[file_c].width;
165+
p++)
166+
{
167+
*channel_pixels++ = cur_line->i32[p];
168+
// assert (*(channel_pixels - 1) == 0);
169+
}
170+
}
171+
}
172+
line_pixels += bpl;
173+
}
82174
}
83175

84176
infile.close ();
@@ -91,71 +183,162 @@ internal_exr_apply_ht (exr_encode_pipeline_t* encode)
91183
{
92184
exr_result_t rv = EXR_ERR_SUCCESS;
93185

94-
std::vector<int> cs_to_file_ch(encode->channel_count);
95-
bool isRGB = make_channel_map (
186+
std::vector<CodestreamChannelInfo> cs_to_file_ch (encode->channel_count);
187+
bool isRGB = make_channel_map (
96188
encode->channel_count, encode->channels, cs_to_file_ch);
97189

98-
int height = encode->channels[0].height;
99-
int width = encode->channels[0].width;
190+
int image_height = encode->chunk.height;
191+
int image_width = encode->chunk.width;
100192

101193
ojph::codestream cs;
102-
cs.set_planar (false);
103194

104195
ojph::param_siz siz = cs.access_siz ();
196+
ojph::param_nlt nlt = cs.access_nlt ();
105197

198+
bool isPlanar = false;
106199
siz.set_num_components (encode->channel_count);
200+
int bpl = 0;
107201
for (ojph::ui32 c = 0; c < encode->channel_count; c++)
108-
siz.set_component (c, ojph::point (1, 1), 16, true);
202+
{
203+
int file_c = cs_to_file_ch[c].file_index;
204+
nlt.set_type3_transformation (
205+
c, encode->channels[file_c].data_type != EXR_PIXEL_UINT);
206+
207+
siz.set_component (
208+
c,
209+
ojph::point (
210+
encode->channels[file_c].x_samples,
211+
encode->channels[file_c].y_samples),
212+
encode->channels[file_c].data_type == EXR_PIXEL_HALF ? 16 : 32,
213+
encode->channels[file_c].data_type != EXR_PIXEL_UINT);
214+
215+
if (encode->channels[file_c].x_samples > 1 ||
216+
encode->channels[file_c].y_samples > 1)
217+
{ isPlanar = true; }
218+
219+
// std::cout << " Component number, color, bitdepth: " << c << ", " << encode->channels[file_c].channel_name << ", " << siz.get_bit_depth(c) << std::endl;
220+
221+
bpl += encode->channels[file_c].bytes_per_element *
222+
encode->channels[file_c].width;
223+
}
224+
225+
cs.set_planar (isPlanar);
109226

110227
siz.set_image_offset (ojph::point (0, 0));
111-
siz.set_tile_offset (ojph::point (0, 0));
112-
siz.set_image_extent (ojph::point (width, height));
113-
siz.set_tile_size (ojph::size (width, height));
228+
siz.set_image_extent (ojph::point (image_width, image_height));
114229

115230
ojph::param_cod cod = cs.access_cod ();
116231

117-
cod.set_color_transform (isRGB);
232+
cod.set_color_transform (isRGB && !isPlanar);
118233
cod.set_reversible (true);
119234
cod.set_block_dims (128, 32);
120235
cod.set_num_decomposition (5);
121236

122-
ojph::param_nlt nlt = cs.access_nlt();
123-
nlt.set_type3_transformation(65535, true);
124-
125237
ojph::mem_outfile output;
126238

127239
output.open ();
128240

129241
cs.write_headers (&output);
130242

131-
assert (
132-
encode->packed_bytes == (encode->channel_count * 2 * height * width));
133-
134-
const int16_t* line_pixels =
135-
static_cast<const int16_t*> (encode->packed_buffer);
136243
ojph::ui32 next_comp = 0;
137244
ojph::line_buf* cur_line = cs.exchange (NULL, next_comp);
138245

139-
for (ojph::ui32 i = 0; i < height; ++i)
246+
if (cs.is_planar ())
140247
{
141-
const char* in_buf;
142-
143248
for (ojph::ui32 c = 0; c < encode->channel_count; c++)
144249
{
145-
assert (next_comp == c);
250+
if (encode->channels[c].height == 0) continue;
146251

147-
const int16_t* channel_pixels =
148-
line_pixels + width * cs_to_file_ch[c];
252+
const uint8_t* line_pixels =
253+
static_cast<const uint8_t*> (encode->packed_buffer);
254+
int file_c = cs_to_file_ch[c].file_index;
149255

150-
for (uint32_t p = 0; p < width; p++)
256+
for (int64_t y = encode->chunk.start_y;
257+
y < image_height + encode->chunk.start_y;
258+
y++)
151259
{
152-
cur_line->i32[p] = static_cast<const ojph::si32> (*channel_pixels++);
260+
for (ojph::ui32 line_c = 0; line_c < encode->channel_count;
261+
line_c++)
262+
{
263+
264+
if (y % encode->channels[line_c].y_samples != 0) continue;
265+
266+
if (line_c == file_c)
267+
{
268+
if (encode->channels[file_c].data_type ==
269+
EXR_PIXEL_HALF)
270+
{
271+
int16_t* channel_pixels = (int16_t*) (line_pixels);
272+
for (uint32_t p = 0;
273+
p < encode->channels[file_c].width;
274+
p++)
275+
{
276+
// assert (*channel_pixels == 0);
277+
cur_line->i32[p] = *channel_pixels++;
278+
}
279+
}
280+
else
281+
{
282+
int32_t* channel_pixels = (int32_t*) (line_pixels);
283+
for (uint32_t p = 0;
284+
p < encode->channels[file_c].width;
285+
p++)
286+
{
287+
// assert (*channel_pixels == 0);
288+
cur_line->i32[p] = *channel_pixels++;
289+
}
290+
}
291+
292+
assert (next_comp == c);
293+
cur_line = cs.exchange (cur_line, next_comp);
294+
}
295+
296+
line_pixels += encode->channels[line_c].bytes_per_element *
297+
encode->channels[line_c].width;
298+
}
153299
}
154-
155-
cur_line = cs.exchange (cur_line, next_comp);
156300
}
301+
}
302+
else
303+
{
304+
const uint8_t* line_pixels =
305+
static_cast<const uint8_t*> (encode->packed_buffer);
157306

158-
line_pixels += width * encode->channel_count;
307+
assert (bpl * image_height == encode->packed_bytes);
308+
309+
for (int y = 0; y < image_height; y++)
310+
{
311+
for (ojph::ui32 c = 0; c < encode->channel_count; c++)
312+
{
313+
int file_c = cs_to_file_ch[c].file_index;
314+
315+
if (encode->channels[file_c].data_type == EXR_PIXEL_HALF)
316+
{
317+
int16_t* channel_pixels =
318+
(int16_t*) (line_pixels + cs_to_file_ch[c].raster_line_offset);
319+
for (uint32_t p = 0; p < encode->channels[file_c].width;
320+
p++)
321+
{
322+
cur_line->i32[p] = *channel_pixels++;
323+
//assert (cur_line->i32[p] == 0);
324+
}
325+
}
326+
else
327+
{
328+
int32_t* channel_pixels =
329+
(int32_t*) (line_pixels + cs_to_file_ch[c].raster_line_offset);
330+
for (uint32_t p = 0; p < encode->channels[file_c].width;
331+
p++)
332+
{
333+
cur_line->i32[p] = *channel_pixels++;
334+
//assert (cur_line->i32[p] == 0);
335+
}
336+
}
337+
assert (next_comp == c);
338+
cur_line = cs.exchange (cur_line, next_comp);
339+
}
340+
line_pixels += bpl;
341+
}
159342
}
160343

161344
cs.flush ();
@@ -164,12 +347,19 @@ internal_exr_apply_ht (exr_encode_pipeline_t* encode)
164347

165348
int compressed_sz = static_cast<size_t> (output.tell ());
166349

350+
// std::ofstream outf ("out7.j2c", std::ios::binary);
351+
// outf.write ((char*) output.get_data (), compressed_sz);
352+
// outf.close ();
353+
167354
if (compressed_sz < encode->packed_bytes)
168355
{
169356
memcpy (encode->compressed_buffer, output.get_data (), compressed_sz);
170357
encode->compressed_bytes = compressed_sz;
171358
}
172-
else { encode->compressed_bytes = encode->packed_bytes; }
359+
else
360+
{
361+
encode->compressed_bytes = encode->packed_bytes;
362+
}
173363

174364
return rv;
175365
}

0 commit comments

Comments
 (0)