Skip to content

Commit 00ed30c

Browse files
committed
Group common HTJ2K functions
Signed-off-by: Pierre-Anthony Lemieux <pal@palemieux.com>
1 parent c7ab776 commit 00ed30c

File tree

3 files changed

+154
-140
lines changed

3 files changed

+154
-140
lines changed

src/lib/OpenEXRCore/internal_ht.cpp

Lines changed: 2 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -18,139 +18,6 @@
1818
#include "openexr_encode.h"
1919
#include "internal_ht_common.h"
2020

21-
/***********************************
22-
23-
Structure of the HTJ2K chunk
24-
- MAGIC = 0x4854: magic number
25-
- PLEN: length of header payload (big endian uint32_t)
26-
- header payload
27-
- NCH: number of channels in channel map (big endian uint16_t)
28-
- for(i = 0; i < NCH; i++)
29-
- CS_TO_F[i]: OpenEXR channel index corresponding to J2K component index i (big endian uint16_t)
30-
- any number of opaque bytes
31-
- CS: JPEG 2000 Codestream
32-
33-
***********************************/
34-
35-
class MemoryReader
36-
{
37-
public:
38-
MemoryReader (uint8_t* buffer, size_t max_sz)
39-
: buffer (buffer), cur (buffer), end (buffer + max_sz){};
40-
41-
uint32_t pull_uint32 ()
42-
{
43-
if (this->end - this->cur < 4)
44-
throw std::out_of_range ("Insufficient data to pull uint32_t");
45-
46-
uint32_t v = *this->cur++;
47-
v = (v << 8) + *this->cur++;
48-
v = (v << 8) + *this->cur++;
49-
return (v << 8) + *cur++;
50-
}
51-
52-
uint16_t pull_uint16 ()
53-
{
54-
if (this->end - this->cur < 2)
55-
throw std::out_of_range ("Insufficient data to pull uint16_t");
56-
57-
uint32_t v = *cur++;
58-
return (v << 8) + *cur++;
59-
}
60-
61-
protected:
62-
uint8_t* buffer;
63-
uint8_t* cur;
64-
uint8_t* end;
65-
};
66-
67-
class MemoryWriter
68-
{
69-
public:
70-
MemoryWriter (uint8_t* buffer, size_t max_sz)
71-
: buffer (buffer), cur (buffer), end (buffer + max_sz){};
72-
73-
void push_uint32 (uint32_t value)
74-
{
75-
if (this->end - this->cur < 4)
76-
throw std::range_error ("Insufficient data to push uint32_t");
77-
78-
*this->cur++ = (value >> 24) & 0xFF;
79-
*this->cur++ = (value >> 16) & 0xFF;
80-
*this->cur++ = (value >> 8) & 0xFF;
81-
*this->cur++ = value & 0xFF;
82-
}
83-
84-
void push_uint16 (uint16_t value)
85-
{
86-
if (this->end - this->cur < 2)
87-
throw std::range_error ("Insufficient data to push uint32_t");
88-
89-
*this->cur++ = (value >> 8) & 0xFF;
90-
*this->cur++ = value & 0xFF;
91-
}
92-
93-
size_t get_size () { return this->cur - this->buffer; }
94-
95-
uint8_t* get_buffer () { return this->buffer; }
96-
97-
uint8_t* get_cur () { return this->cur; }
98-
99-
protected:
100-
uint8_t* buffer;
101-
uint8_t* cur;
102-
uint8_t* end;
103-
};
104-
105-
constexpr uint16_t HEADER_MARKER = 'H' * 256 + 'T';
106-
constexpr uint16_t HEADER_SZ = 6;
107-
108-
size_t
109-
write_header (
110-
uint8_t* buffer,
111-
size_t max_sz,
112-
const std::vector<CodestreamChannelInfo>& map)
113-
{
114-
MemoryWriter payload (buffer + HEADER_SZ, max_sz - HEADER_SZ);
115-
payload.push_uint16 (map.size ());
116-
for (size_t i = 0; i < map.size (); i++)
117-
{
118-
payload.push_uint16 (map.at (i).file_index);
119-
}
120-
121-
MemoryWriter header (buffer, max_sz);
122-
header.push_uint16 (HEADER_MARKER);
123-
header.push_uint32 (payload.get_size ());
124-
125-
return header.get_size () + payload.get_size ();
126-
}
127-
128-
void
129-
read_header (
130-
void* buffer,
131-
size_t max_sz,
132-
size_t& length,
133-
std::vector<CodestreamChannelInfo>& map)
134-
{
135-
MemoryReader header ((uint8_t*) buffer, max_sz);
136-
if (header.pull_uint16 () != HEADER_MARKER)
137-
throw std::runtime_error (
138-
"HTJ2K chunk header missing does not start with magic number.");
139-
140-
length = header.pull_uint32 ();
141-
142-
if (length < 2)
143-
throw std::runtime_error ("Error while reading the channel map");
144-
145-
length += HEADER_SZ;
146-
147-
map.resize (header.pull_uint16 ());
148-
for (size_t i = 0; i < map.size (); i++)
149-
{
150-
map.at (i).file_index = header.pull_uint16 ();
151-
}
152-
}
153-
15421
/**
15522
* OpenJPH output file that is backed by a fixed-size memory buffer
15623
*/
@@ -305,8 +172,8 @@ internal_exr_undo_ht (
305172
/* read the channel map */
306173

307174
size_t header_sz;
308-
read_header (
309-
(uint8_t*) compressed_data, comp_buf_size, header_sz, cs_to_file_ch);
175+
header_sz = read_header (
176+
(uint8_t*) compressed_data, comp_buf_size, cs_to_file_ch);
310177
if (decode->channel_count != cs_to_file_ch.size ())
311178
throw std::runtime_error ("Unexpected number of channels");
312179

src/lib/OpenEXRCore/internal_ht_common.cpp

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <cassert>
1111
#include <algorithm>
1212
#include <cctype>
13+
#include <stdexcept>
1314

1415
const std::string RED_CH_FULLNAME = "red";
1516
const std::string GREEN_CH_FULLNAME = "green";
@@ -177,3 +178,137 @@ make_channel_map (
177178

178179
return isRGB;
179180
}
181+
182+
/***********************************
183+
184+
Structure of the HTJ2K chunk
185+
- MAGIC = 0x4854: magic number
186+
- PLEN: length of header payload (big endian uint32_t)
187+
- header payload
188+
- NCH: number of channels in channel map (big endian uint16_t)
189+
- for(i = 0; i < NCH; i++)
190+
- CS_TO_F[i]: OpenEXR channel index corresponding to J2K component index i (big endian uint16_t)
191+
- any number of opaque bytes
192+
- CS: JPEG 2000 Codestream
193+
194+
***********************************/
195+
196+
class MemoryReader
197+
{
198+
public:
199+
MemoryReader (uint8_t* buffer, size_t max_sz)
200+
: buffer (buffer), cur (buffer), end (buffer + max_sz){};
201+
202+
uint32_t pull_uint32 ()
203+
{
204+
if (this->end - this->cur < 4)
205+
throw std::out_of_range ("Insufficient data to pull uint32_t");
206+
207+
uint32_t v = *this->cur++;
208+
v = (v << 8) + *this->cur++;
209+
v = (v << 8) + *this->cur++;
210+
return (v << 8) + *cur++;
211+
}
212+
213+
uint16_t pull_uint16 ()
214+
{
215+
if (this->end - this->cur < 2)
216+
throw std::out_of_range ("Insufficient data to pull uint16_t");
217+
218+
uint32_t v = *cur++;
219+
return (v << 8) + *cur++;
220+
}
221+
222+
protected:
223+
uint8_t* buffer;
224+
uint8_t* cur;
225+
uint8_t* end;
226+
};
227+
228+
class MemoryWriter
229+
{
230+
public:
231+
MemoryWriter (uint8_t* buffer, size_t max_sz)
232+
: buffer (buffer), cur (buffer), end (buffer + max_sz){};
233+
234+
void push_uint32 (uint32_t value)
235+
{
236+
if (this->end - this->cur < 4)
237+
throw std::range_error ("Insufficient data to push uint32_t");
238+
239+
*this->cur++ = (value >> 24) & 0xFF;
240+
*this->cur++ = (value >> 16) & 0xFF;
241+
*this->cur++ = (value >> 8) & 0xFF;
242+
*this->cur++ = value & 0xFF;
243+
}
244+
245+
void push_uint16 (uint16_t value)
246+
{
247+
if (this->end - this->cur < 2)
248+
throw std::range_error ("Insufficient data to push uint32_t");
249+
250+
*this->cur++ = (value >> 8) & 0xFF;
251+
*this->cur++ = value & 0xFF;
252+
}
253+
254+
size_t get_size () { return this->cur - this->buffer; }
255+
256+
uint8_t* get_buffer () { return this->buffer; }
257+
258+
uint8_t* get_cur () { return this->cur; }
259+
260+
protected:
261+
uint8_t* buffer;
262+
uint8_t* cur;
263+
uint8_t* end;
264+
};
265+
266+
constexpr uint16_t HEADER_MARKER = 'H' * 256 + 'T';
267+
constexpr uint16_t HEADER_SZ = 6;
268+
269+
size_t
270+
write_header (
271+
uint8_t* buffer,
272+
size_t max_sz,
273+
const std::vector<CodestreamChannelInfo>& map)
274+
{
275+
MemoryWriter payload (buffer + HEADER_SZ, max_sz - HEADER_SZ);
276+
payload.push_uint16 (map.size ());
277+
for (size_t i = 0; i < map.size (); i++)
278+
{
279+
payload.push_uint16 (map.at (i).file_index);
280+
}
281+
282+
MemoryWriter header (buffer, max_sz);
283+
header.push_uint16 (HEADER_MARKER);
284+
header.push_uint32 (payload.get_size ());
285+
286+
return header.get_size () + payload.get_size ();
287+
}
288+
289+
size_t
290+
read_header (
291+
void* buffer,
292+
size_t max_sz,
293+
std::vector<CodestreamChannelInfo>& map)
294+
{
295+
MemoryReader header ((uint8_t*) buffer, max_sz);
296+
if (header.pull_uint16 () != HEADER_MARKER)
297+
throw std::runtime_error (
298+
"HTJ2K chunk header missing does not start with magic number.");
299+
300+
size_t length = header.pull_uint32 ();
301+
302+
if (length < 2)
303+
throw std::runtime_error ("Error while reading the channel map");
304+
305+
length += HEADER_SZ;
306+
307+
map.resize (header.pull_uint16 ());
308+
for (size_t i = 0; i < map.size (); i++)
309+
{
310+
map.at (i).file_index = header.pull_uint16 ();
311+
}
312+
313+
return length;
314+
}

src/lib/OpenEXRCore/internal_ht_common.h

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,25 @@
1010
#include <stdlib.h>
1111
#include "openexr_coding.h"
1212

13-
struct CodestreamChannelInfo {
14-
int file_index;
13+
struct CodestreamChannelInfo
14+
{
15+
int file_index;
1516
size_t raster_line_offset;
1617
};
1718

18-
bool
19-
make_channel_map (
20-
int channel_count, exr_coding_channel_info_t* channels, std::vector<CodestreamChannelInfo>& cs_to_file_ch);
19+
bool make_channel_map (
20+
int channel_count,
21+
exr_coding_channel_info_t* channels,
22+
std::vector<CodestreamChannelInfo>& cs_to_file_ch);
23+
24+
size_t write_header (
25+
uint8_t* buffer,
26+
size_t max_sz,
27+
const std::vector<CodestreamChannelInfo>& map);
28+
29+
size_t read_header (
30+
void* buffer,
31+
size_t max_sz,
32+
std::vector<CodestreamChannelInfo>& map);
2133

2234
#endif /* OPENEXR_PRIVATE_HT_COMMON_H */

0 commit comments

Comments
 (0)