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_base.h"
47#include "ojph_arch.h"
48#include "ojph_message.h"
49
50namespace ojph {
51
53 class outfile_base;
54 class infile_base;
55
58 {
63 OJPH_PO_CPRL = 4
64 };
65
67 const char OJPH_PO_STRING_LRCP[] = "LRCP";
68 const char OJPH_PO_STRING_RLCP[] = "RLCP";
69 const char OJPH_PO_STRING_RPCL[] = "RPCL";
70 const char OJPH_PO_STRING_PCRL[] = "PCRL";
71 const char OJPH_PO_STRING_CPRL[] = "CPRL";
72
75 {
84 OJPH_PN_IMF = 8
85 };
86
88 const char OJPH_PN_STRING_PROFILE0[] = "PROFILE0";
89 const char OJPH_PN_STRING_PROFILE1[] = "PROFILE1";
90 const char OJPH_PN_STRING_CINEMA2K[] = "CINEMA2K";
91 const char OJPH_PN_STRING_CINEMA4K[] = "CINEMA4K";
92 const char OJPH_PN_STRING_CINEMAS2K[] = "CINEMAS2K";
93 const char OJPH_PN_STRING_CINEMAS4K[] = "CINEMAS4K";
94 const char OJPH_PN_STRING_BROADCAST[] = "BROADCAST";
95 const char OJPH_PN_STRING_IMF[] = "IMF";
96
99 OJPH_TILEPART_NODIVSIONS = 0x0, // no divisions to tile parts
102 OJPH_TILEPART_LAYERS = 0x4, // these are meaningless with HTJ2K
103 };
104
105 namespace local {
106
109 {
110 SOC = 0xFF4F, //start of codestream (required)
111 CAP = 0xFF50, //extended capability
112 SIZ = 0xFF51, //image and tile size (required)
113 COD = 0xFF52, //coding style default (required)
114 TLM = 0xFF55, //tile-part lengths
115 PRF = 0xFF56, //profile
116 PLM = 0xFF57, //packet length, main header
117 PLT = 0xFF58, //packet length, tile-part header
118 CPF = 0xFF59, //corresponding profile values
119 QCD = 0xFF5C, //qunatization default (required)
120 QCC = 0xFF5D, //quantization component
121 COM = 0xFF64, //comment
122 SOT = 0xFF90, //start of tile-part
123 SOP = 0xFF91, //start of packet
124 EPH = 0xFF92, //end of packet
125 SOD = 0xFF93, //start of data
126 EOC = 0xFFD9, //end of codestream (required)
127
128 COC = 0xFF53, //coding style component
129 RGN = 0xFF5E, //region of interest
130 POC = 0xFF5F, //progression order change
131 PPM = 0xFF60, //packed packet headers, main header
132 PPT = 0xFF61, //packed packet headers, tile-part header
133 CRG = 0xFF63, //component registration
134 };
135
137 //
138 //
139 //
140 //
141 //
144 {
148 };
149
152 {
153 friend ::ojph::param_siz;
154
155 public:
157 {
158 memset(this, 0, sizeof(param_siz));
159 cptr = store;
160 old_Csiz = 4;
161 Rsiz = 0x4000; //for jph, bit 14 of Rsiz is 1
162 }
163
165 {
166 if (cptr != store) delete[] cptr;
167 }
168
169 void set_num_components(ui32 num_comps)
170 {
171 Csiz = (ui16)num_comps;
172 if (Csiz > old_Csiz)
173 {
174 if (cptr != store)
175 delete[] cptr;
176 cptr = new siz_comp_info[num_comps];
177 old_Csiz = Csiz;
178 }
179 memset(cptr, 0, sizeof(local::siz_comp_info) * num_comps);
180 }
181
182 void set_comp_info(ui32 comp_num, const point& downsampling,
183 ui32 bit_depth, bool is_signed)
184 {
185 assert(comp_num < Csiz);
186 assert(downsampling.x != 0 && downsampling.y != 0);
187 cptr[comp_num].SSiz = (ui8)(bit_depth - 1 + (is_signed ? 0x80 : 0));
188 cptr[comp_num].XRsiz = (ui8)downsampling.x;
189 cptr[comp_num].YRsiz = (ui8)downsampling.y;
190 }
191
193 {
194 if (XTsiz == 0 && YTsiz == 0)
195 { XTsiz = Xsiz - XOsiz; YTsiz = Ysiz - YOsiz; }
196 if (Xsiz == 0 || Ysiz == 0 || XTsiz == 0 || YTsiz == 0)
197 OJPH_ERROR(0x00040001,
198 "You cannot set image extent nor tile size to zero");
199 if (XTOsiz > XOsiz || YTOsiz > YOsiz)
200 OJPH_ERROR(0x00040002,
201 "tile offset has to be smaller than image offset");
202 if (XTsiz + XTOsiz <= XOsiz || YTsiz + YTOsiz <= YOsiz)
203 OJPH_ERROR(0x00040003,
204 "the top left tile must intersect with the image");
205 }
206
207 ui16 get_num_components() const { return Csiz; }
208 ui32 get_bit_depth(ui32 comp_num) const
209 {
210 assert(comp_num < Csiz);
211 return (cptr[comp_num].SSiz & 0x7F) + 1u;
212 }
213 bool is_signed(ui32 comp_num) const
214 {
215 assert(comp_num < Csiz);
216 return (cptr[comp_num].SSiz & 0x80) != 0;
217 }
219 {
220 assert(comp_num < Csiz);
221 return point(cptr[comp_num].XRsiz, cptr[comp_num].YRsiz);
222 }
223
224 bool write(outfile_base *file);
225 void read(infile_base *file);
226
228 {
229 this->skipped_resolutions = skipped_resolutions;
230 }
231 ui32 get_width(ui32 comp_num) const
232 {
233 assert(comp_num < get_num_components());
234 ui32 ds = (ui32)cptr[comp_num].XRsiz;
235 ui32 t = ojph_div_ceil(Xsiz, ds) - ojph_div_ceil(XOsiz, ds);
236 return t;
237 }
238 ui32 get_height(ui32 comp_num) const
239 {
240 assert(comp_num < get_num_components());
241 ui32 ds = (ui32)cptr[comp_num].YRsiz;
242 ui32 t = ojph_div_ceil(Ysiz, ds) - ojph_div_ceil(YOsiz, ds);
243 return t;
244 }
245 ui32 get_recon_width(ui32 comp_num) const
246 {
247 assert(comp_num < get_num_components());
248 ui32 ds = (ui32)cptr[comp_num].XRsiz * (1u << skipped_resolutions);
249 ui32 t = ojph_div_ceil(Xsiz, ds) - ojph_div_ceil(XOsiz, ds);
250 return t;
251 }
252 ui32 get_recon_height(ui32 comp_num) const
253 {
254 assert(comp_num < get_num_components());
255 ui32 ds = (ui32)cptr[comp_num].YRsiz * (1u << skipped_resolutions);
256 ui32 t = ojph_div_ceil(Ysiz, ds) - ojph_div_ceil(YOsiz, ds);
257 return t;
258 }
259
260 private:
273
274 private:
278 param_siz(const param_siz&) = delete; //prevent copy constructor
279 param_siz& operator=(const param_siz&) = delete; //prevent copy
280 };
281
283 //
284 //
285 //
286 //
287 //
290 {
296 ui8 precinct_size[33]; //num_decomp is in [0,32]
297 };
298
301
304 {
308 };
309
312 {
313 friend ::ojph::param_cod;
316 HT_MODE = 0x40
317 };
318 public:
320 {
321 memset(this, 0, sizeof(param_cod));
323 SGCod.prog_order = 2;
324 SGCod.num_layers = 1;
325 SGCod.mc_trans = 0;
326 SPcod.num_decomp = 5;
327 SPcod.block_width = 4; //64
328 SPcod.block_height = 4; //64
329 set_reversible(false);
330 }
331
332 void set_reversible(bool reversible)
333 {
334 SPcod.wavelet_trans = reversible ? 1 : 0;
335 }
336
338 {
339 assert(val == 0 || val == 1);
340 SGCod.mc_trans = val;
341 }
342
343 void check_validity(const param_siz& siz)
344 {
345 //check that colour transform and match number of components and
346 // downsampling
347 int num_comps = siz.get_num_components();
348 if (SGCod.mc_trans == 1 && num_comps < 3)
349 OJPH_ERROR(0x00040011,
350 "color transform can only be employed when the image has 3 or "
351 "more color components");
352
353 if (SGCod.mc_trans == 1)
354 {
355 bool test = false;
356 point p = siz.get_downsampling(0);
357 for (ui32 i = 1; i < 3; ++i)
358 {
359 point p1 = siz.get_downsampling(i);
360 test = test || (p.x != p1.x || p.y != p1.y);
361 }
362 if (test)
363 OJPH_ERROR(0x00040012,
364 "when color transform is used, the first 3 colour "
365 "components must have the same downsampling.");
366 }
367
368 //check the progression order matches downsampling
369 if (SGCod.prog_order == 2 || SGCod.prog_order == 3)
370 {
371 ui32 num_comps = siz.get_num_components();
372 for (ui32 i = 0; i < num_comps; ++i)
373 {
374 point r = siz.get_downsampling(i);
375 if (r.x & (r.x - 1) || r.y & (r.y - 1))
376 OJPH_ERROR(0x00040013, "For RPCL and PCRL progression orders,"
377 "component downsampling factors have to be powers of 2");
378 }
379 }
380 }
381
383 { return SPcod.num_decomp; }
385 {
386 return size(1 << (SPcod.block_width + 2),
387 1 << (SPcod.block_height + 2));
388 }
389 bool is_reversible() const
390 { return (SPcod.wavelet_trans == 1); }
392 { return (SGCod.mc_trans == 1); }
394 { return size(SPcod.block_width + 2, SPcod.block_height + 2); }
396 {
397 size t = get_log_precinct_size(res_num);
398 t.w = 1 << t.w;
399 t.h = 1 << t.h;
400 return t;
401 }
403 {
404 assert(res_num <= SPcod.num_decomp);
405 size ps(15, 15);
406 if (Scod & 1)
407 {
408 ps.w = SPcod.precinct_size[res_num] & 0xF;
409 ps.h = SPcod.precinct_size[res_num] >> 4;
410 }
411 return ps;
412 }
414 { return (Scod & 2) == 2; }
415 bool packets_use_eph() const
416 { return (Scod & 4) == 4; }
417
418 bool write(outfile_base *file);
419 void read(infile_base *file);
420
421 private:
426 };
427
429 //
430 //
431 //
432 //
433 //
436 {
437 friend ::ojph::param_qcd;
438 public:
440 {
441 Lqcd = 0;
442 Sqcd = 0;
443 for (int i = 0; i < 97; ++i)
444 u16_SPqcd[i] = 0;
445 num_decomps = 0;
446 base_delta = -1.0f;
447 }
448
449 void set_delta(float delta) { base_delta = delta; }
450 void set_rev_quant(ui32 bit_depth, bool is_employing_color_transform);
451 void set_irrev_quant();
452
453 void check_validity(const param_siz& siz, const param_cod& cod)
454 {
456 if (cod.is_reversible())
457 {
458 ui32 bit_depth = 0;
459 for (ui32 i = 0; i < siz.get_num_components(); ++i)
460 bit_depth = ojph_max(bit_depth, siz.get_bit_depth(i));
462 }
463 else
464 {
465 if (base_delta == -1.0f) {
466 ui32 bit_depth = 0;
467 for (ui32 i = 0; i < siz.get_num_components(); ++i)
468 bit_depth =
469 ojph_max(bit_depth, siz.get_bit_depth(i) + siz.is_signed(i));
470 base_delta = 1.0f / (float)(1 << bit_depth);
471 }
473 }
474 }
475
476 ui32 get_num_guard_bits() const;
477 ui32 get_MAGBp() const;
480
481 bool write(outfile_base *file);
482 void read(infile_base *file);
483
484 protected:
487 union
488 {
491 };
494 };
495
497 //
498 //
499 //
500 //
501 //
503 struct param_qcc : public param_qcd
504 {
505 //friend ::ojph::param_qcc;
506 public:
508 { comp_idx = 0; }
509
511 void read(infile_base *file, ui32 num_comps);
512
513 protected:
515 };
516
518 //
519 //
520 //
521 //
522 //
525 {
526 public:
528 {
529 memset(this, 0, sizeof(param_cap));
530 Lcap = 8;
531 Pcap = 0x00020000; //for jph, Pcap^15 must be set, the 15th MSB
532 }
533
534 void check_validity(const param_cod& cod, const param_qcd& qcd)
535 {
536 if (cod.is_reversible())
537 Ccap[0] &= 0xFFDF;
538 else
539 Ccap[0] |= 0x0020;
540 Ccap[0] &= 0xFFE0;
541 ui32 Bp = 0;
542 ui32 B = qcd.get_MAGBp();
543 if (B <= 8)
544 Bp = 0;
545 else if (B < 28)
546 Bp = B - 8;
547 else if (B < 48)
548 Bp = 13 + (B >> 2);
549 else
550 Bp = 31;
551 Ccap[0] = (ui16)(Ccap[0] | (ui16)Bp);
552 }
553
554 bool write(outfile_base *file);
555 void read(infile_base *file);
556
557 private:
560 ui16 Ccap[32]; //a maximum of 32
561 };
562
563
565 //
566 //
567 //
568 //
569 //
572 {
573 public:
574 void init(ui32 payload_length = 0, ui16 tile_idx = 0,
575 ui8 tile_part_index = 0, ui8 num_tile_parts = 0)
576 {
577 Lsot = 10;
578 Psot = payload_length + 12; //total = payload + SOT marker
579 Isot = tile_idx;
580 TPsot = tile_part_index;
581 TNsot = num_tile_parts;
582 }
583
584 bool write(outfile_base *file, ui32 payload_len);
585 bool write(outfile_base *file, ui32 payload_len, ui8 TPsot, ui8 TNsot);
586 bool read(infile_base *file, bool resilient);
587
588 ui16 get_tile_index() const { return Isot; }
589 ui32 get_payload_length() const { return Psot > 0 ? Psot - 12 : 0; }
590 ui8 get_tile_part_index() const { return TPsot; }
591 ui8 get_num_tile_parts() const { return TNsot; }
592
593 private:
599 };
600
602 //
603 //
604 //
605 //
606 //
609 {
611 {
614 };
615
616 public:
617 param_tlm() { pairs = NULL; num_pairs = 0; next_pair_index = 0; };
618 void init(ui32 num_pairs, Ttlm_Ptlm_pair* store);
619
620 void set_next_pair(ui16 Ttlm, ui32 Ptlm);
621 bool write(outfile_base *file);
622
623 private:
630
631 };
632 }
633}
634
635#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[]
OJPH_TILEPART_DIVISONS
@ OJPH_TILEPART_RESOLUTIONS
@ OJPH_TILEPART_LAYERS
@ OJPH_TILEPART_COMPONENTS
@ OJPH_TILEPART_NODIVSIONS
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