OpenJPH
Open-source implementation of JPEG2000 Part-15
ojph_params_local.h
Go to the documentation of this file.
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_params_local.h
34 // Author: Aous Naman
35 // Date: 28 August 2019
36 //***************************************************************************/
37 
38 
39 #ifndef OJPH_PARAMS_LOCAL_H
40 #define OJPH_PARAMS_LOCAL_H
41 
42 #include <cstring>
43 #include <cassert>
44 
45 #include "ojph_defs.h"
46 #include "ojph_arch.h"
47 #include "ojph_message.h"
48 
49 namespace ojph {
50 
52  class outfile_base;
53  class infile_base;
54 
57  {
62  OJPH_PO_CPRL = 4
63  };
64 
66  const char OJPH_PO_STRING_LRCP[] = "LRCP";
67  const char OJPH_PO_STRING_RLCP[] = "RLCP";
68  const char OJPH_PO_STRING_RPCL[] = "RPCL";
69  const char OJPH_PO_STRING_PCRL[] = "PCRL";
70  const char OJPH_PO_STRING_CPRL[] = "CPRL";
71 
74  {
83  OJPH_PN_IMF = 8
84  };
85 
87  const char OJPH_PN_STRING_PROFILE0[] = "PROFILE0";
88  const char OJPH_PN_STRING_PROFILE1[] = "PROFILE1";
89  const char OJPH_PN_STRING_CINEMA2K[] = "CINEMA2K";
90  const char OJPH_PN_STRING_CINEMA4K[] = "CINEMA4K";
91  const char OJPH_PN_STRING_CINEMAS2K[] = "CINEMAS2K";
92  const char OJPH_PN_STRING_CINEMAS4K[] = "CINEMAS4K";
93  const char OJPH_PN_STRING_BROADCAST[] = "BROADCAST";
94  const char OJPH_PN_STRING_IMF[] = "IMF";
95 
96  namespace local {
97 
100  {
101  SOC = 0xFF4F, //start of codestream (required)
102  CAP = 0xFF50, //extended capability
103  SIZ = 0xFF51, //image and tile size (required)
104  COD = 0xFF52, //coding style default (required)
105  TLM = 0xFF55, //tile-part lengths
106  PRF = 0xFF56, //profile
107  PLM = 0xFF57, //packet length, main header
108  PLT = 0xFF58, //packet length, tile-part header
109  CPF = 0xFF59, //corresponding profile values
110  QCD = 0xFF5C, //qunatization default (required)
111  QCC = 0xFF5D, //quantization component
112  COM = 0xFF64, //comment
113  SOT = 0xFF90, //start of tile-part
114  SOP = 0xFF91, //start of packet
115  EPH = 0xFF92, //end of packet
116  SOD = 0xFF93, //start of data
117  EOC = 0xFFD9, //end of codestream (required)
118 
119  COC = 0xFF53, //coding style component
120  RGN = 0xFF5E, //region of interest
121  POC = 0xFF5F, //progression order change
122  PPM = 0xFF60, //packed packet headers, main header
123  PPT = 0xFF61, //packed packet headers, tile-part header
124  CRG = 0xFF63, //component registration
125  };
126 
128  //
129  //
130  //
131  //
132  //
135  {
139  };
140 
142  struct param_siz
143  {
144  friend ::ojph::param_siz;
145 
146  public:
148  {
149  memset(this, 0, sizeof(param_siz));
150  cptr = store;
151  old_Csiz = 4;
152  Rsiz = 0x4000; //for jph, bit 14 of Rsiz is 1
153  }
154 
156  {
157  if (cptr != store) delete[] cptr;
158  }
159 
160  void set_num_components(ui32 num_comps)
161  {
162  Csiz = (ui16)num_comps;
163  if (Csiz > old_Csiz)
164  {
165  if (cptr != store)
166  delete[] cptr;
167  cptr = new siz_comp_info[num_comps];
168  old_Csiz = Csiz;
169  }
170  memset(cptr, 0, sizeof(local::siz_comp_info) * num_comps);
171  }
172 
173  void set_comp_info(ui32 comp_num, const point& downsampling,
174  ui32 bit_depth, bool is_signed)
175  {
176  assert(comp_num < Csiz);
177  assert(downsampling.x != 0 && downsampling.y != 0);
178  cptr[comp_num].SSiz = (ui8)(bit_depth - 1 + (is_signed ? 0x80 : 0));
179  cptr[comp_num].XRsiz = (ui8)downsampling.x;
180  cptr[comp_num].YRsiz = (ui8)downsampling.y;
181  }
182 
184  {
185  if (XTsiz == 0 && YTsiz == 0)
186  { XTsiz = Xsiz - XOsiz; YTsiz = Ysiz - YOsiz; }
187  if (Xsiz == 0 || Ysiz == 0 || XTsiz == 0 || YTsiz == 0)
188  OJPH_ERROR(0x00040001,
189  "You cannot set image extent nor tile size to zero");
190  if (XTOsiz > XOsiz || YTOsiz > YOsiz)
191  OJPH_ERROR(0x00040002,
192  "tile offset has to be smaller than image offset");
193  if (XTsiz + XTOsiz <= XOsiz || YTsiz + YTOsiz <= YOsiz)
194  OJPH_ERROR(0x00040003,
195  "the top left tile must intersect with the image");
196  }
197 
198  ui16 get_num_components() const { return Csiz; }
199  ui32 get_bit_depth(ui32 comp_num) const
200  {
201  assert(comp_num < Csiz);
202  return (cptr[comp_num].SSiz & 0x7F) + 1u;
203  }
204  bool is_signed(ui32 comp_num) const
205  {
206  assert(comp_num < Csiz);
207  return (cptr[comp_num].SSiz & 0x80) != 0;
208  }
209  point get_downsampling(ui32 comp_num) const
210  {
211  assert(comp_num < Csiz);
212  return point(cptr[comp_num].XRsiz, cptr[comp_num].YRsiz);
213  }
214 
215  bool write(outfile_base *file);
216  void read(infile_base *file);
217 
219  {
220  this->skipped_resolutions = skipped_resolutions;
221  }
222  ui32 get_width(ui32 comp_num) const
223  {
224  assert(comp_num < get_num_components());
225  ui32 ds = (ui32)cptr[comp_num].XRsiz;
226  ui32 t = ojph_div_ceil(Xsiz, ds) - ojph_div_ceil(XOsiz, ds);
227  return t;
228  }
229  ui32 get_height(ui32 comp_num) const
230  {
231  assert(comp_num < get_num_components());
232  ui32 ds = (ui32)cptr[comp_num].YRsiz;
233  ui32 t = ojph_div_ceil(Ysiz, ds) - ojph_div_ceil(YOsiz, ds);
234  return t;
235  }
236  ui32 get_recon_width(ui32 comp_num) const
237  {
238  assert(comp_num < get_num_components());
239  ui32 ds = (ui32)cptr[comp_num].XRsiz * (1u << skipped_resolutions);
240  ui32 t = ojph_div_ceil(Xsiz, ds) - ojph_div_ceil(XOsiz, ds);
241  return t;
242  }
243  ui32 get_recon_height(ui32 comp_num) const
244  {
245  assert(comp_num < get_num_components());
246  ui32 ds = (ui32)cptr[comp_num].YRsiz * (1u << skipped_resolutions);
247  ui32 t = ojph_div_ceil(Ysiz, ds) - ojph_div_ceil(YOsiz, ds);
248  return t;
249  }
250 
251  private:
264 
265  private:
267  int old_Csiz;
269  param_siz(const param_siz&) = delete; //prevent copy constructor
270  param_siz& operator=(const param_siz&) = delete; //prevent copy
271  };
272 
274  //
275  //
276  //
277  //
278  //
280  struct cod_SPcod
281  {
287  ui8 precinct_size[33]; //num_decomp is in [0,32]
288  };
289 
292 
294  struct cod_SGcod
295  {
299  };
300 
302  struct param_cod
303  {
304  friend ::ojph::param_cod;
307  HT_MODE = 0x40
308  };
309  public:
311  {
312  memset(this, 0, sizeof(param_cod));
314  SGCod.prog_order = 2;
315  SGCod.num_layers = 1;
316  SGCod.mc_trans = 0;
317  SPcod.num_decomp = 5;
318  SPcod.block_width = 4; //64
319  SPcod.block_height = 4; //64
320  set_reversible(false);
321  }
322 
323  void set_reversible(bool reversible)
324  {
325  SPcod.wavelet_trans = reversible ? 1 : 0;
326  }
327 
329  {
330  assert(val == 0 || val == 1);
331  SGCod.mc_trans = val;
332  }
333 
334  void check_validity(const param_siz& siz)
335  {
336  //check that colour transform and match number of components and
337  // downsampling
338  int num_comps = siz.get_num_components();
339  if (SGCod.mc_trans == 1 && num_comps < 3)
340  OJPH_ERROR(0x00040011,
341  "color transform can only be employed when the image has 3 or "
342  "more color components");
343 
344  if (SGCod.mc_trans == 1)
345  {
346  bool test = false;
347  point p = siz.get_downsampling(0);
348  for (ui32 i = 1; i < 3; ++i)
349  {
350  point p1 = siz.get_downsampling(i);
351  test = test || (p.x != p1.x || p.y != p1.y);
352  }
353  if (test)
354  OJPH_ERROR(0x00040012,
355  "when color transform is used, the first 3 colour "
356  "components must have the same downsampling.");
357  }
358 
359  //check the progression order matches downsampling
360  if (SGCod.prog_order == 2 || SGCod.prog_order == 3)
361  {
362  ui32 num_comps = siz.get_num_components();
363  for (ui32 i = 0; i < num_comps; ++i)
364  {
365  point r = siz.get_downsampling(i);
366  if (r.x & (r.x - 1) || r.y & (r.y - 1))
367  OJPH_ERROR(0x00040013, "For RPCL and PCRL progression orders,"
368  "component downsampling factors have to be powers of 2");
369  }
370  }
371  }
372 
374  { return SPcod.num_decomp; }
376  {
377  return size(1 << (SPcod.block_width + 2),
378  1 << (SPcod.block_height + 2));
379  }
380  bool is_reversible() const
381  { return (SPcod.wavelet_trans == 1); }
383  { return (SGCod.mc_trans == 1); }
385  { return size(SPcod.block_width + 2, SPcod.block_height + 2); }
386  size get_precinct_size(ui32 res_num) const
387  {
388  size t = get_log_precinct_size(res_num);
389  t.w = 1 << t.w;
390  t.h = 1 << t.h;
391  return t;
392  }
394  {
395  assert(res_num <= SPcod.num_decomp);
396  size ps(15, 15);
397  if (Scod & 1)
398  {
399  ps.w = SPcod.precinct_size[res_num] & 0xF;
400  ps.h = SPcod.precinct_size[res_num] >> 4;
401  }
402  return ps;
403  }
404  bool packets_may_use_sop() const
405  { return (Scod & 2) == 2; }
406  bool packets_use_eph() const
407  { return (Scod & 4) == 4; }
408 
409  bool write(outfile_base *file);
410  void read(infile_base *file);
411 
412  private:
417  };
418 
420  //
421  //
422  //
423  //
424  //
426  struct param_qcd
427  {
428  friend ::ojph::param_qcd;
429  public:
431  {
432  Lqcd = 0;
433  Sqcd = 0;
434  for (int i = 0; i < 97; ++i)
435  u16_SPqcd[i] = 0;
436  num_decomps = 0;
437  base_delta = -1.0f;
438  }
439 
440  void set_delta(float delta) { base_delta = delta; }
441  void set_rev_quant(ui32 bit_depth, bool is_employing_color_transform);
442  void set_irrev_quant();
443 
444  void check_validity(const param_siz& siz, const param_cod& cod)
445  {
447  if (cod.is_reversible())
448  {
449  ui32 bit_depth = 0;
450  for (ui32 i = 0; i < siz.get_num_components(); ++i)
451  bit_depth = ojph_max(bit_depth, siz.get_bit_depth(i));
453  }
454  else
455  {
456  if (base_delta == -1.0f) {
457  ui32 bit_depth = 0;
458  for (ui32 i = 0; i < siz.get_num_components(); ++i)
459  bit_depth =
460  ojph_max(bit_depth, siz.get_bit_depth(i) + siz.is_signed(i));
461  base_delta = 1.0f / (float)(1 << bit_depth);
462  }
463  set_irrev_quant();
464  }
465  }
466 
467  ui32 get_num_guard_bits() const;
468  ui32 get_MAGBp() const;
471 
472  bool write(outfile_base *file);
473  void read(infile_base *file);
474 
475  protected:
478  union
479  {
482  };
484  float base_delta;
485  };
486 
488  //
489  //
490  //
491  //
492  //
494  struct param_qcc : public param_qcd
495  {
496  //friend ::ojph::param_qcc;
497  public:
499  { comp_idx = 0; }
500 
501  ui16 get_comp_num() { return comp_idx; }
502  void read(infile_base *file, ui32 num_comps);
503 
504  protected:
506  };
507 
509  //
510  //
511  //
512  //
513  //
515  struct param_cap
516  {
517  public:
519  {
520  memset(this, 0, sizeof(param_cap));
521  Lcap = 8;
522  Pcap = 0x00020000; //for jph, Pcap^15 must be set, the 15th MSB
523  }
524 
525  void check_validity(const param_cod& cod, const param_qcd& qcd)
526  {
527  if (cod.is_reversible())
528  Ccap[0] &= 0xFFDF;
529  else
530  Ccap[0] |= 0x0020;
531  Ccap[0] &= 0xFFE0;
532  ui32 Bp = 0;
533  ui32 B = qcd.get_MAGBp();
534  if (B <= 8)
535  Bp = 0;
536  else if (B < 28)
537  Bp = B - 8;
538  else if (B < 48)
539  Bp = 13 + (B >> 2);
540  else
541  Bp = 31;
542  Ccap[0] = (ui16)(Ccap[0] | (ui16)Bp);
543  }
544 
545  bool write(outfile_base *file);
546  void read(infile_base *file);
547 
548  private:
551  ui16 Ccap[32]; //a maximum of 32
552  };
553 
554 
556  //
557  //
558  //
559  //
560  //
562  struct param_sot
563  {
564  public:
565  void init(ui32 payload_length = 0, ui16 tile_idx = 0,
566  ui8 tile_part_index = 0, ui8 num_tile_parts = 0)
567  {
568  Lsot = 10;
569  Psot = payload_length + 12; //total = payload + SOT marker
570  Isot = tile_idx;
571  TPsot = tile_part_index;
572  TNsot = num_tile_parts;
573  }
574 
575  bool write(outfile_base *file, ui32 payload_len);
576  bool write(outfile_base *file, ui32 payload_len, ui8 TPsot, ui8 TNsot);
577  bool read(infile_base *file, bool resilient);
578 
579  ui16 get_tile_index() const { return Isot; }
580  ui32 get_payload_length() const { return Psot > 0 ? Psot - 12 : 0; }
581  ui8 get_tile_part_index() const { return TPsot; }
582  ui8 get_num_tile_parts() const { return TNsot; }
583 
584  private:
590  };
591 
593  //
594  //
595  //
596  //
597  //
599  struct param_tlm
600  {
602  {
605  };
606 
607  public:
608  param_tlm() { pairs = NULL; num_pairs = 0; next_pair_index = 0; };
609  void init(ui32 num_pairs, Ttlm_Ptlm_pair* store);
610 
611  void set_next_pair(ui16 Ttlm, ui32 Ptlm);
612  bool write(outfile_base *file);
613 
614  private:
621 
622  };
623  }
624 }
625 
626 #endif // !OJPH_PARAMS_LOCAL_H
cod_SPcod cod_SPcoc
const char OJPH_PN_STRING_BROADCAST[]
const char OJPH_PN_STRING_CINEMAS4K[]
const char OJPH_PO_STRING_PCRL[]
const char OJPH_PN_STRING_IMF[]
const char OJPH_PN_STRING_CINEMA4K[]
uint16_t ui16
Definition: ojph_defs.h:52
const char OJPH_PO_STRING_RLCP[]
const char OJPH_PN_STRING_CINEMA2K[]
const char OJPH_PO_STRING_RPCL[]
const char OJPH_PO_STRING_CPRL[]
@ OJPH_PN_PROFILE1
@ OJPH_PN_BROADCAST
@ OJPH_PN_CINEMA4K
@ OJPH_PN_CINEMA2K
@ OJPH_PN_CINEMAS4K
@ OJPH_PN_UNDEFINED
@ OJPH_PN_CINEMAS2K
@ OJPH_PN_PROFILE0
int32_t si32
Definition: ojph_defs.h:55
const char OJPH_PN_STRING_PROFILE0[]
const char OJPH_PN_STRING_CINEMAS2K[]
uint32_t ui32
Definition: ojph_defs.h:54
uint8_t ui8
Definition: ojph_defs.h:50
const char OJPH_PO_STRING_LRCP[]
const char OJPH_PN_STRING_PROFILE1[]
#define ojph_max(a, b)
Definition: ojph_defs.h:73
#define ojph_div_ceil(a, b)
Definition: ojph_defs.h:70
#define OJPH_ERROR(t,...)
Definition: ojph_message.h:131
void check_validity(const param_cod &cod, const param_qcd &qcd)
void read(infile_base *file)
bool write(outfile_base *file)
void check_validity(const param_siz &siz)
bool write(outfile_base *file)
void set_reversible(bool reversible)
bool is_employing_color_transform() const
void employ_color_transform(ui8 val)
void read(infile_base *file)
size get_log_precinct_size(ui32 res_num) const
ui8 get_num_decompositions() const
bool packets_may_use_sop() const
size get_precinct_size(ui32 res_num) const
void read(infile_base *file, ui32 num_comps)
ui32 get_Kmax(ui32 resolution, ui32 subband) const
ui32 get_num_guard_bits() const
void set_delta(float delta)
void check_validity(const param_siz &siz, const param_cod &cod)
bool write(outfile_base *file)
void read(infile_base *file)
void set_rev_quant(ui32 bit_depth, bool is_employing_color_transform)
float irrev_get_delta(ui32 resolution, ui32 subband) const
void set_skipped_resolutions(ui32 skipped_resolutions)
ui32 get_bit_depth(ui32 comp_num) const
ui32 get_recon_height(ui32 comp_num) const
bool is_signed(ui32 comp_num) const
bool write(outfile_base *file)
param_siz(const param_siz &)=delete
param_siz & operator=(const param_siz &)=delete
ui32 get_height(ui32 comp_num) const
void set_comp_info(ui32 comp_num, const point &downsampling, ui32 bit_depth, bool is_signed)
point get_downsampling(ui32 comp_num) const
void read(infile_base *file)
void set_num_components(ui32 num_comps)
ui32 get_width(ui32 comp_num) const
ui32 get_recon_width(ui32 comp_num) const
void init(ui32 payload_length=0, ui16 tile_idx=0, ui8 tile_part_index=0, ui8 num_tile_parts=0)
bool read(infile_base *file, bool resilient)
bool write(outfile_base *file, ui32 payload_len)
void set_next_pair(ui16 Ttlm, ui32 Ptlm)
bool write(outfile_base *file)
void init(ui32 num_pairs, Ttlm_Ptlm_pair *store)
ui32 w
Definition: ojph_base.h:50
ui32 h
Definition: ojph_base.h:51