1 //***************************************************************************/
2 // This software is released under the 2-Clause BSD license, included
3 // below.
4 //
5 // Copyright (c) 2019, Aous Naman
6 // Copyright (c) 2019, Kakadu Software Pty Ltd, Australia
7 // Copyright (c) 2019, The University of New South Wales, Australia
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are
11 // met:
12 //
13 // 1. Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
15 //
16 // 2. Redistributions in binary form must reproduce the above copyright
17 // notice, this list of conditions and the following disclaimer in the
18 // documentation and/or other materials provided with the distribution.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
26 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 //***************************************************************************/
32 // This file is part of the OpenJPH software implementation.
33 // File: ojph_codestream_local.h
34 // Author: Aous Naman
35 // Date: 28 August 2019
36 //***************************************************************************/
37 
38 
39 #ifndef OJPH_CODESTREAM_LOCAL_H
40 #define OJPH_CODESTREAM_LOCAL_H
41 
42 #include "ojph_defs.h"
43 #include "ojph_file.h"
44 #include "ojph_params_local.h"
45 
46 namespace ojph {
47 
48   ////////////////////////////////////////////////////////////////////////////
49   //defined elsewhere
50   struct line_buf;
51   class mem_fixed_allocator;
52   class mem_elastic_allocator;
53   class codestream;
54   struct coded_lists;
55 
56   namespace local {
57 
58     //////////////////////////////////////////////////////////////////////////
59     //defined here
60     class tile;
61     class tile_comp;
62     class resolution;
63     struct precinct;
64     class subband;
65     class codeblock;
66     struct coded_cb_header;
67 
68     //////////////////////////////////////////////////////////////////////////
69     class codestream
70     {
71       friend ::ojph::codestream;
72 
73     public:
74       codestream();
75       ~codestream();
76 
77       void pre_alloc();
78       void finalize_alloc();
79 
access_siz()80       ojph::param_siz access_siz()            //return externally wrapped siz
81       { return ojph::param_siz(&siz); }
get_siz()82       const param_siz* get_siz() //return internal siz
83       { return &siz; }
access_cod()84       ojph::param_cod access_cod()            //return externally wrapped cod
85       { return ojph::param_cod(&cod); }
get_cod()86       const param_cod* get_cod() //return internal code
87       { return &cod; }
access_qcd(int comp_num)88       param_qcd* access_qcd(int comp_num)
89       {
90         if (used_qcc_fields > 0)
91           for (int v = 0; v < used_qcc_fields; ++v)
92             if (qcc[v].get_comp_num() == comp_num)
93               return qcc + v;
94         return &qcd;
95       }
get_allocator()96       mem_fixed_allocator* get_allocator() { return allocator; }
get_elastic_alloc()97       mem_elastic_allocator* get_elastic_alloc() { return elastic_alloc; }
get_file()98       outfile_base* get_file() { return outfile; }
99 
100       line_buf* exchange(line_buf* line, int& next_component);
101       void write_headers(outfile_base *file);
102       void enable_resilience();
is_resilient()103       bool is_resilient() { return resilient; }
104       void read_headers(infile_base *file);
105       void restrict_input_resolution(int skipped_res_for_data,
106         int skipped_res_for_recon);
107       void read();
108       void set_planar(int planar);
109       void set_profile(const char *s);
110       line_buf* pull(int &comp_num);
111       void flush();
112       void close();
113 
is_planar()114       bool is_planar() const { return planar != 0; }
get_profile()115       si32 get_profile() const { return profile; };
116 
117       void check_imf_validity();
118       void check_broadcast_validity();
119 
get_precinct_scratch()120       ui8* get_precinct_scratch() { return precinct_scratch; }
get_skipped_res_for_recon()121       int get_skipped_res_for_recon()
122       { return skipped_res_for_recon; }
get_skipped_res_for_read()123       int get_skipped_res_for_read()
124       { return skipped_res_for_read; }
125 
126     private:
127       int precinct_scratch_needed_bytes;
128       ui8* precinct_scratch;
129 
130     private:
131       int cur_line;
132       int cur_comp;
133       int cur_tile_row;
134       bool resilient;
135       int skipped_res_for_read, skipped_res_for_recon;
136 
137     private:
138       size num_tiles;
139       tile *tiles;
140       line_buf* line;
141       int num_comps;
142       size *comp_size;       //stores full resolution no. of lines and width
143       size *recon_comp_size; //stores number of lines and width of each comp
144       bool employ_color_transform;
145       int planar;
146       int profile;
147 
148     private:
149       param_siz siz;
150       param_cod cod;
151       param_cap cap;
152       param_qcd qcd;
153       param_tlm tlm;
154 
155     private: // this is to handle qcc
156       int used_qcc_fields;
157       param_qcc qcc_store[4], *qcc; // we allocate 4,
158                                     // if not enough, we allocate more
159 
160     private:
161       mem_fixed_allocator *allocator;
162       mem_elastic_allocator *elastic_alloc;
163       outfile_base *outfile;
164       infile_base *infile;
165     };
166 
167     //////////////////////////////////////////////////////////////////////////
168     class tile
169     {
170     public:
171       static void pre_alloc(codestream *codestream, const rect& tile_rect,
172                             const rect& recon_tile_rect);
173       void finalize_alloc(codestream *codestream, const rect& tile_rect,
174                           const rect& recon_tile_rect,
175                           int tile_idx, int offset);
176 
177       bool push(line_buf *line, int comp_num);
178       void prepare_for_flush();
179       void fill_tlm(param_tlm* tlm);
180       void flush(outfile_base *file);
181       void parse_tile_header(const param_sot& sot, infile_base *file,
182                              const ui64& tile_start_location);
183       bool pull(line_buf *, int comp_num);
184 
185     private:
186       codestream *parent;
187       rect tile_rect, recon_tile_rect;
188       int num_comps;
189       tile_comp *comps;
190       int num_lines;
191       line_buf* lines;
192       bool reversible, employ_color_transform, resilient;
193       rect *comp_rects, *recon_comp_rects;
194       int *line_offsets;
195       int skipped_res_for_read;
196 
197       int *num_bits;
198       bool *is_signed;
199       int *cur_line;
200       int prog_order;
201 
202     private:
203       param_sot sot;
204       int next_tile_part;
205 
206     private:
207       int profile;
208       int *num_comp_bytes; //this for use with TLM
209     };
210 
211     //////////////////////////////////////////////////////////////////////////
212     class tile_comp
213     {
214     public:
215       static void pre_alloc(codestream *codestream, const rect& comp_rect,
216                             const rect& recon_comp_rect);
217       void finalize_alloc(codestream *codestream, tile *parent,
218                           int comp_num, const rect& comp_rect,
219                           const rect& recon_comp_rect);
220 
get_num_resolutions()221       int get_num_resolutions() { return num_decomps + 1; }
get_num_decompositions()222       int get_num_decompositions() { return num_decomps; }
223       line_buf* get_line();
224       void push_line();
225       line_buf* pull_line();
226 
227       ui32 prepare_precincts();
228       void write_precincts(int res_num, outfile_base *file);
229       bool get_top_left_precinct(int res_num, point &top_left);
230       void write_one_precinct(int res_num, outfile_base *file);
231       void parse_precincts(int res_num, ui32& data_left, infile_base *file);
232       void parse_one_precinct(int res_num, ui32& data_left, infile_base *file);
233 
234     private:
235       tile *parent_tile;
236       resolution *res;
237       rect comp_rect;
238       ojph::point comp_downsamp;
239       int num_decomps;
240       int comp_num;
241     };
242 
243     //////////////////////////////////////////////////////////////////////////
244     class resolution
245     {
246     public:
247 
248     public:
249       static void pre_alloc(codestream *codestream, const rect& res_rect,
250                             const rect& recon_res_rect, int res_num);
251       void finalize_alloc(codestream *codestream, const rect& res_rect,
252                           const rect& recon_res_rect, int comp_num,
253                           int res_num, point comp_downsamp,
254                           tile_comp *parent_tile,
255                           resolution *parent_res);
256 
get_line()257       line_buf* get_line() { return lines + 0; }
258       void push_line();
259       line_buf* pull_line();
get_rect()260       rect get_rect() { return res_rect; }
get_comp_num()261       int get_comp_num() { return comp_num; }
262 
263       ui32 prepare_precinct();
264       void write_precincts(outfile_base *file);
265       bool get_top_left_precinct(point &top_left);
266       void write_one_precinct(outfile_base *file);
next_resolution()267       resolution *next_resolution() { return child_res; }
268       void parse_all_precincts(ui32& data_left, infile_base *file);
269       void parse_one_precinct(ui32& data_left, infile_base *file);
270 
271     private:
272       bool reversible, skipped_res_for_read, skipped_res_for_recon;
273       int num_lines, num_bands, res_num;
274       int comp_num;
275       point comp_downsamp;
276       rect res_rect;
277       line_buf *lines;
278       subband *bands;
279       tile_comp *parent;
280       resolution *parent_res, *child_res;
281       //precincts stuff
282       precinct *precincts;
283       size num_precincts;
284       size log_PP;
285       int max_num_levels;
286       int tag_tree_size;
287       si32 level_index[20]; //more than enough
288       point cur_precinct_loc; //used for progressing spatial modes (2, 3, 4)
289       //wavelet machinery
290       int cur_line, available_lines;
291       bool vert_even, horz_even;
292       mem_elastic_allocator *elastic;
293     };
294 
295     //////////////////////////////////////////////////////////////////////////
296     struct precinct
297     {
298       ui32 prepare_precinct(int tag_tree_size, si32* lev_idx,
299                             mem_elastic_allocator *elastic);
300       void write(outfile_base *file);
301       void parse(int tag_tree_size, si32* lev_idx,
302                  mem_elastic_allocator *elastic,
303                  ui32& data_left, infile_base *file, bool skipped);
304 
305       ui8 *scratch;
306       point img_point;   //the precinct projected to full resolution
307       rect cb_idxs[4]; //indices of codeblocks
308       subband *bands;  //the subbands
309       coded_lists* coded;
310       int num_bands;
311       bool special_x, special_y;
312       bool may_use_sop, uses_eph;
313     };
314 
315     //////////////////////////////////////////////////////////////////////////
316     class subband
317     {
318       friend struct precinct;
319     public:
320       static void pre_alloc(codestream *codestream, const rect& band_rect,
321                             int res_num);
322       void finalize_alloc(codestream *codestream, const rect& band_rect,
323                           resolution* res, int res_num, int subband_num);
324 
325       void exchange_buf(line_buf* l);
get_line()326       line_buf* get_line() { return lines; }
327       void push_line();
328 
329       void get_cb_indices(const size& num_precincts, precinct *precincts);
330 
331       line_buf* pull_line();
332 
333     private:
334       int res_num, band_num;
335       bool reversible;
336       rect band_rect;
337       line_buf *lines;
338       resolution* parent;
339       codeblock* blocks;
340       size num_blocks;
341       size log_PP;
342       int xcb_prime, ycb_prime;
343       int cur_cb_row;
344       int cur_line;
345       int cur_cb_height;
346       float delta, delta_inv;
347       int K_max;
348       coded_cb_header *coded_cbs;
349       mem_elastic_allocator *elastic;
350     };
351 
352     //////////////////////////////////////////////////////////////////////////
353     class codeblock
354     {
355       friend struct precinct;
356     public:
357       static void pre_alloc(codestream *codestream, const size& nominal);
358       void finalize_alloc(codestream *codestream, subband* parent,
359                           const size& nominal, const size& cb_size,
360                           coded_cb_header* coded_cb,
361                           int K_max, int tbx0);
362       void push(line_buf *line);
363       void encode(mem_elastic_allocator *elastic);
364       void recreate(const size& cb_size, coded_cb_header* coded_cb);
365 
366       void decode();
367       void pull_line(line_buf *line);
368 
369     private:
370       si32* buf;
371       size nominal_size;
372       size cb_size;
373       subband* parent;
374       int line_offset;
375       int cur_line;
376       int K_max;
377       int max_val;
378       bool resilient;
379       coded_cb_header* coded_cb;
380     };
381 
382     //////////////////////////////////////////////////////////////////////////
383     struct coded_cb_header
384     {
385       int pass_length[2];
386       int num_passes;
387       int Kmax;
388       int missing_msbs;
389       coded_lists *next_coded;
390 
391       static const int prefix_buf_size = 8;
392       static const int suffix_buf_size = 8;
393     };
394 
395   }
396 }
397 
398 
399 #endif // !OJPH_CODESTREAM_LOCAL_H
400