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
49namespace 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
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 }
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:
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 //
281 {
287 ui8 precinct_size[33]; //num_decomp is in [0,32]
288 };
289
292
295 {
299 };
300
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); }
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 }
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 //
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 }
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 };
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
502 void read(infile_base *file, ui32 num_comps);
503
504 protected:
506 };
507
509 //
510 //
511 //
512 //
513 //
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 //
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 //
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
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)
param_siz & operator=(const param_siz &)=delete
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