OpenJPH: /build/openjph/src/OpenJPH/src/core/codestream/ojph_codestream_local.cpp Source File

OpenJPH Open-source implementation of JPEG2000 Part-15

Loading...
Searching...
No Matches
ojph_codestream_local.cpp
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_codestream_local.cpp
34// Author: Aous Naman
35// Date: 28 August 2019
36//***************************************************************************/
37
38
39#include <climits>
40#include <cmath>
41
42#include "ojph_mem.h"
43#include "ojph_params.h"
44#include "ojph_codestream_local.h"
45#include "ojph_tile.h"
46
47#include "../transform/ojph_colour.h"
48#include "../transform/ojph_transform.h"
49
50namespace ojph {
51
52 namespace local
53 {
54
56 codestream::codestream()
57 : precinct_scratch(NULL), allocator(NULL), elastic_alloc(NULL)
58 {
59 allocator = new mem_fixed_allocator;
60 elastic_alloc = new mem_elastic_allocator(1048576); // 1 megabyte
61
62 init_colour_transform_functions();
63 init_wavelet_transform_functions();
64
65 restart();
66 }
67
69 codestream::~codestream()
70 {
71 if (allocator)
72 delete allocator;
73 if (elastic_alloc)
74 delete elastic_alloc;
75 }
76
78 void codestream::restart()
79 {
80 tiles = NULL;
81 lines = NULL;
82 comp_size = NULL;
83 recon_comp_size = NULL;
84 outfile = NULL;
85 infile = NULL;
86
87 num_comps = 0;
88 employ_color_transform = false;
89 planar = -1;
90 profile = OJPH_PN_UNDEFINED;
91 tilepart_div = OJPH_TILEPART_NO_DIVISIONS;
92 need_tlm = false;
93
94 cur_comp = 0;
95 cur_line = 0;
96 cur_tile_row = 0;
97 resilient = false;
98 skipped_res_for_read = skipped_res_for_recon = 0;
99
100 precinct_scratch_needed_bytes = 0;
101
102 cod.restart();
103 qcd.restart();
104 nlt.restart();
105 dfs.restart();
106 atk.restart();
107
108 allocator->restart();
109 elastic_alloc->restart();
110 }
111
113 void codestream::pre_alloc()
114 {
115 ojph::param_siz sz = access_siz();
116 num_tiles.w = sz.get_image_extent().x - sz.get_tile_offset().x;
117 num_tiles.w = ojph_div_ceil(num_tiles.w, sz.get_tile_size().w);
118 num_tiles.h = sz.get_image_extent().y - sz.get_tile_offset().y;
119 num_tiles.h = ojph_div_ceil(num_tiles.h, sz.get_tile_size().h);
120 if (num_tiles.area() > 65535)
121 OJPH_ERROR(0x00030011, "the number of tiles cannot exceed 65535");
122 if (num_tiles.area() == 0)
123 OJPH_ERROR(0x00030012, "the number of tiles cannot be 0");
124
125 //allocate tiles
126 allocator->pre_alloc_obj<tile>((size_t)num_tiles.area());
127
128 ui32 num_tileparts = 0;
129 point index;
130 rect tile_rect, recon_tile_rect;
131 ui32 ds = 1 << skipped_res_for_recon;
132 for (index.y = 0; index.y < num_tiles.h; ++index.y)
133 {
134 ui32 y0 = sz.get_tile_offset().y
135 + index.y * sz.get_tile_size().h;
136 ui32 y1 = y0 + sz.get_tile_size().h; //end of tile
137
138 tile_rect.org.y = ojph_max(y0, sz.get_image_offset().y);
139 tile_rect.siz.h =
140 ojph_min(y1, sz.get_image_extent().y) - tile_rect.org.y;
141
142 recon_tile_rect.org.y = ojph_max(ojph_div_ceil(y0, ds),
143 ojph_div_ceil(sz.get_image_offset().y, ds));
144 recon_tile_rect.siz.h = ojph_min(ojph_div_ceil(y1, ds),
145 ojph_div_ceil(sz.get_image_extent().y, ds))
146 - recon_tile_rect.org.y;
147
148 for (index.x = 0; index.x < num_tiles.w; ++index.x)
149 {
150 ui32 x0 = sz.get_tile_offset().x
151 + index.x * sz.get_tile_size().w;
152 ui32 x1 = x0 + sz.get_tile_size().w;
153
154 tile_rect.org.x = ojph_max(x0, sz.get_image_offset().x);
155 tile_rect.siz.w =
156 ojph_min(x1, sz.get_image_extent().x) - tile_rect.org.x;
157
158 recon_tile_rect.org.x = ojph_max(ojph_div_ceil(x0, ds),
159 ojph_div_ceil(sz.get_image_offset().x, ds));
160 recon_tile_rect.siz.w = ojph_min(ojph_div_ceil(x1, ds),
161 ojph_div_ceil(sz.get_image_extent().x, ds))
162 - recon_tile_rect.org.x;
163
164 ui32 tps = 0; // number of tileparts for this tile
165 tile::pre_alloc(this, tile_rect, recon_tile_rect, tps);
166 num_tileparts += tps;
167 }
168 }
169
170 //allocate lines
171 //These lines are used by codestream to exchange data with external
172 // world
173 ui32 num_comps = sz.get_num_components();
174 allocator->pre_alloc_obj<line_buf>(num_comps);
175 allocator->pre_alloc_obj<size>(num_comps); //for *comp_size
176 allocator->pre_alloc_obj<size>(num_comps); //for *recon_comp_size
177 for (ui32 i = 0; i < num_comps; ++i)
178 allocator->pre_alloc_data<si32>(siz.get_recon_width(i), 0);
179
180 //allocate tlm
181 if (outfile != NULL && need_tlm)
182 allocator->pre_alloc_obj<param_tlm::Ttlm_Ptlm_pair>(num_tileparts);
183
184 //precinct scratch buffer
185 // The precinct scratch is shared by all components, but each component
186 // may override the codeblock/precinct geometry via a COC marker. The
187 // per-component tag-tree storage (resolution.cpp) is derived from that
188 // component's effective params, so size the shared buffer from the
189 // largest ratio across every component (the main COD and all COC
190 // overrides). Sizing from the COD alone under-reserves the buffer for
191 // any component whose COC declares a smaller codeblock than the COD.
192 size ratio;
193 for (ui32 c = 0; c < num_comps; ++c)
194 {
195 const param_cod* cdp = cod.get_coc(c);
196 ui32 num_decomps = cdp->get_num_decompositions();
197 size log_cb = cdp->get_log_block_dims();
198 for (ui32 r = 0; r <= num_decomps; ++r)
199 {
200 size log_PP = cdp->get_log_precinct_size(r);
201 ratio.w = ojph_max(ratio.w, log_PP.w - ojph_min(log_cb.w, log_PP.w));
202 ratio.h = ojph_max(ratio.h, log_PP.h - ojph_min(log_cb.h, log_PP.h));
203 }
204 }
205 ui32 max_ratio = ojph_max(ratio.w, ratio.h);
206 max_ratio = 1 << max_ratio;
207 // assuming that we have a hierarchy of n levels.
208 // This needs 4/3 times the area, rounded up
209 // (rounding up leaves one extra entry).
210 // This exta entry is necessary
211 // We need 4 such tables. These tables store
212 // 1. missing msbs and 2. their flags,
213 // 3. number of layers and 4. their flags
214 precinct_scratch_needed_bytes =
215 4 * ((max_ratio * max_ratio * 4 + 2) / 3);
216
217 allocator->pre_alloc_obj<ui8>(precinct_scratch_needed_bytes);
218 }
219
221 void codestream::finalize_alloc()
222 {
223 allocator->alloc();
224
225 //precinct scratch buffer
226 precinct_scratch =
227 allocator->post_alloc_obj<ui8>(precinct_scratch_needed_bytes);
228
229 //get tiles
230 tiles = this->allocator->post_alloc_obj<tile>((size_t)num_tiles.area());
231
232 ui32 num_tileparts = 0;
233 point index;
234 rect tile_rect;
235 ojph::param_siz sz = access_siz();
236 for (index.y = 0; index.y < num_tiles.h; ++index.y)
237 {
238 ui32 y0 = sz.get_tile_offset().y
239 + index.y * sz.get_tile_size().h;
240 ui32 y1 = y0 + sz.get_tile_size().h; //end of tile
241
242 tile_rect.org.y = ojph_max(y0, sz.get_image_offset().y);
243 tile_rect.siz.h =
244 ojph_min(y1, sz.get_image_extent().y) - tile_rect.org.y;
245
246 ui32 offset = 0;
247 for (index.x = 0; index.x < num_tiles.w; ++index.x)
248 {
249 ui32 x0 = sz.get_tile_offset().x
250 + index.x * sz.get_tile_size().w;
251 ui32 x1 = x0 + sz.get_tile_size().w;
252
253 tile_rect.org.x = ojph_max(x0, sz.get_image_offset().x);
254 tile_rect.siz.w =
255 ojph_min(x1, sz.get_image_extent().x) - tile_rect.org.x;
256
257 ui32 tps = 0; // number of tileparts for this tile
258 ui32 idx = index.y * num_tiles.w + index.x;
259 tiles[idx].finalize_alloc(this, tile_rect, idx, offset, tps);
260 num_tileparts += tps;
261 }
262 }
263
264 //allocate lines
265 //These lines are used by codestream to exchange data with external
266 // world
267 this->num_comps = sz.get_num_components();
268 lines = allocator->post_alloc_obj<line_buf>(this->num_comps);
269 comp_size = allocator->post_alloc_obj<size>(this->num_comps);
270 recon_comp_size = allocator->post_alloc_obj<size>(this->num_comps);
271 employ_color_transform = cod.is_employing_color_transform();
272 for (ui32 i = 0; i < this->num_comps; ++i)
273 {
274 comp_size[i].w = siz.get_width(i);
275 comp_size[i].h = siz.get_height(i);
276 ui32 cw = siz.get_recon_width(i);
277 recon_comp_size[i].w = cw;
278 recon_comp_size[i].h = siz.get_recon_height(i);
279 lines[i].wrap(allocator->post_alloc_data<si32>(cw, 0), cw, 0);
280 }
281
282 cur_comp = 0;
283 cur_line = 0;
284
285 //allocate tlm
286 if (outfile != NULL && need_tlm)
287 tlm.init(num_tileparts,
288 allocator->post_alloc_obj<param_tlm::Ttlm_Ptlm_pair>(num_tileparts));
289 }
290
291
293 void codestream::check_imf_validity()
294 {
295 //two possibilities lossy single tile or lossless
296 //For the following code, we use the least strict profile
297 ojph::param_siz sz(&siz);
298 ojph::param_cod cd(&cod);
299 bool reversible = cd.is_reversible();
300 bool imf2k = !reversible, imf4k = !reversible, imf8k = !reversible;
301 bool imf2kls = reversible, imf4kls = reversible, imf8kls = reversible;
302
303 if (reversible)
304 {
305 point ext = sz.get_image_extent();
306 if (ext.x <= 2048 && ext.y <= 1556)
307 imf2kls &= true;
308 if (ext.x <= 4096 && ext.y <= 3112)
309 imf4kls &= true;
310 if (ext.x <= 8192 && ext.y <= 6224)
311 imf8kls &= true;
312
313 if (!imf2kls && !imf4kls && !imf8kls)
314 OJPH_ERROR(0x000300C1,
315 "Image dimensions do not meet any of the lossless IMF profiles");
316 }
317 else
318 {
319 point ext = sz.get_image_extent();
320 if (ext.x <= 2048 && ext.y <= 1556)
321 imf2k &= true;
322 if (ext.x <= 4096 && ext.y <= 3112)
323 imf4k &= true;
324 if (ext.x <= 8192 && ext.y <= 6224)
325 imf8k &= true;
326
327 if (!imf2k && !imf4k && !imf8k)
328 OJPH_ERROR(0x000300C2,
329 "Image dimensions do not meet any of the lossy IMF profiles");
330 }
331
332
333 if (sz.get_image_offset().x != 0 || sz.get_image_offset().y != 0)
334 OJPH_ERROR(0x000300C3,
335 "For IMF profile, image offset (XOsiz, YOsiz) has to be 0.");
336 if (sz.get_tile_offset().x != 0 || sz.get_tile_offset().y != 0)
337 OJPH_ERROR(0x000300C4,
338 "For IMF profile, tile offset (XTOsiz, YTOsiz) has to be 0.");
339 if (sz.get_num_components() > 3)
340 OJPH_ERROR(0x000300C5,
341 "For IMF profile, the number of components has to be less "
342 " or equal to 3");
343 bool test_ds1 = true, test_ds2 = true;
344 for (ojph::ui32 i = 0; i < sz.get_num_components(); ++i)
345 {
346 point downsamping = sz.get_downsampling(i);
347 test_ds1 &= downsamping.y == 1;
348 test_ds2 &= downsamping.y == 1;
349
350 test_ds1 &= downsamping.x == 1;
351 if (i == 1 || i == 2)
352 test_ds2 &= downsamping.x == 2;
353 else
354 test_ds2 &= downsamping.x == 1;
355 }
356 if (!test_ds1 && !test_ds2)
357 OJPH_ERROR(0x000300C6,
358 "For IMF profile, either no component downsampling is used,"
359 " or the x-dimension of the 2nd and 3rd components is downsampled"
360 " by 2.");
361
362 bool test_bd = true;
363 for (ojph::ui32 i = 0; i < sz.get_num_components(); ++i)
364 {
365 ui32 bit_depth = sz.get_bit_depth(i);
366 bool is_signed = sz.is_signed(i);
367 test_bd &= bit_depth >= 8 && bit_depth <= 16 && is_signed == false;
368 }
369 if (!test_bd)
370 OJPH_ERROR(0x000300C7,
371 "For IMF profile, compnent bit_depth has to be between"
372 " 8 and 16 bits inclusively, and the samples must be unsigned");
373
374 if (cd.get_log_block_dims().w != 5 || cd.get_log_block_dims().h != 5)
375 OJPH_ERROR(0x000300C8,
376 "For IMF profile, codeblock dimensions are restricted."
377 " Use \"-block_size {32,32}\" at the commandline");
378
379 ui32 num_decomps = cd.get_num_decompositions();
380 bool test_pz = cd.get_log_precinct_size(0).w == 7
381 && cd.get_log_precinct_size(0).h == 7;
382 for (ui32 i = 1; i <= num_decomps; ++i)
383 test_pz = cd.get_log_precinct_size(i).w == 8
384 && cd.get_log_precinct_size(i).h == 8;
385 if (!test_pz)
386 OJPH_ERROR(0x000300C9,
387 "For IMF profile, precinct sizes are restricted."
388 " Use \"-precincts {128,128},{256,256}\" at the commandline");
389
390 if (cd.get_progression_order() != OJPH_PO_CPRL)
391 OJPH_ERROR(0x000300CA,
392 "For IMF profile, the CPRL progression order must be used."
393 " Use \"-prog_order CPRL\".");
394
395 imf2k &= num_decomps <= 5;
396 imf2kls &= num_decomps <= 5;
397 imf4k &= num_decomps <= 6;
398 imf4kls &= num_decomps <= 6;
399 imf8k &= num_decomps <= 7;
400 imf8kls &= num_decomps <= 7;
401
402 if (num_decomps == 0 ||
403 (!imf2k && !imf4k && !imf8k && !imf2kls && !imf4kls && !imf8kls))
404 OJPH_ERROR(0x000300CB,
405 "Number of decompositions does not match the IMF profile"
406 " dictated by wavelet reversibility and image dimensions.");
407
408 ui32 tiles_w = sz.get_image_extent().x;
409 tiles_w = ojph_div_ceil(tiles_w, sz.get_tile_size().w);
410 ui32 tiles_h = sz.get_image_extent().y;
411 tiles_h = ojph_div_ceil(tiles_h, sz.get_tile_size().h);
412 ui32 total_tiles = tiles_w * tiles_h;
413
414 if (total_tiles > 1)
415 {
416 if (!reversible)
417 OJPH_ERROR(0x000300CC,
418 "Lossy IMF profile must have one tile.");
419
420 size tt = sz.get_tile_size();
421 imf2kls &= (tt.w == 1024 && tt.h == 1024);
422 imf2kls &= (tt.w >= 1024 && num_decomps <= 4)
423 || (tt.w >= 2048 && num_decomps <= 5);
424 imf4kls &= (tt.w == 1024 && tt.h == 1024)
425 || (tt.w == 2048 && tt.h == 2048);
426 imf4kls &= (tt.w >= 1024 && num_decomps <= 4)
427 || (tt.w >= 2048 && num_decomps <= 5)
428 || (tt.w >= 4096 && num_decomps <= 6);
429 imf8kls &= (tt.w == 1024 && tt.h == 1024)
430 || (tt.w == 2048 && tt.h == 2048)
431 || (tt.w == 4096 && tt.h == 4096);
432 imf8kls &= (tt.w >= 1024 && num_decomps <= 4)
433 || (tt.w >= 2048 && num_decomps <= 5)
434 || (tt.w >= 4096 && num_decomps <= 6)
435 || (tt.w >= 8192 && num_decomps <= 7);
436 if (!imf2kls && !imf4kls && !imf8kls)
437 OJPH_ERROR(0x000300CD,
438 "Number of decompositions does not match the IMF profile"
439 " dictated by wavelet reversibility and image dimensions and"
440 " tiles.");
441 }
442
443 need_tlm = true;
444 tilepart_div |= OJPH_TILEPART_COMPONENTS;
445 if (tilepart_div != OJPH_TILEPART_COMPONENTS)
446 {
447 tilepart_div = OJPH_TILEPART_COMPONENTS;
448 OJPH_WARN(0x000300C1,
449 "In IMF profile, tile part divisions at the component level must be "
450 "employed, while at the resolution level is not allowed. "
451 "This has been corrected.");
452 }
453 }
454
456 void codestream::check_broadcast_validity()
457 {
458 ojph::param_siz sz(&siz);
459 ojph::param_cod cd(&cod);
460
461 if (sz.get_image_offset().x != 0 || sz.get_image_offset().y != 0)
462 OJPH_ERROR(0x000300B1,
463 "For broadcast profile, image offset (XOsiz, YOsiz) has to be 0.");
464 if (sz.get_tile_offset().x != 0 || sz.get_tile_offset().y != 0)
465 OJPH_ERROR(0x000300B2,
466 "For broadcast profile, tile offset (XTOsiz, YTOsiz) has to be 0.");
467 if (sz.get_num_components() > 4)
468 OJPH_ERROR(0x000300B3,
469 "For broadcast profile, the number of components has to be less "
470 " or equal to 4");
471 bool test_ds1 = true, test_ds2 = true;
472 for (ojph::ui32 i = 0; i < sz.get_num_components(); ++i)
473 {
474 point downsamping = sz.get_downsampling(i);
475 test_ds1 &= downsamping.y == 1;
476 test_ds2 &= downsamping.y == 1;
477
478 test_ds1 &= downsamping.x == 1;
479 if (i == 1 || i == 2)
480 test_ds2 &= downsamping.x == 2;
481 else
482 test_ds2 &= downsamping.x == 1;
483 }
484 if (!test_ds1 && !test_ds2)
485 OJPH_ERROR(0x000300B4,
486 "For broadcast profile, either no component downsampling is used,"
487 " or the x-dimension of the 2nd and 3rd components is downsampled"
488 " by 2.");
489
490 bool test_bd = true;
491 for (ojph::ui32 i = 0; i < sz.get_num_components(); ++i)
492 {
493 ui32 bit_depth = sz.get_bit_depth(i);
494 bool is_signed = sz.is_signed(i);
495 test_bd &= bit_depth >= 8 && bit_depth <= 12 && is_signed == false;
496 }
497 if (!test_bd)
498 OJPH_ERROR(0x000300B5,
499 "For broadcast profile, compnent bit_depth has to be between"
500 " 8 and 12 bits inclusively, and the samples must be unsigned");
501
502 ui32 num_decomps = cd.get_num_decompositions();
503 if (num_decomps == 0 || num_decomps > 5)
504 OJPH_ERROR(0x000300B6,
505 "For broadcast profile, number of decompositions has to be between"
506 "1 and 5 inclusively.");
507
508 if (cd.get_log_block_dims().w < 5 || cd.get_log_block_dims().w > 7)
509 OJPH_ERROR(0x000300B7,
510 "For broadcast profile, codeblock dimensions are restricted such"
511 " that codeblock width has to be either 32, 64, or 128.");
512
513 if (cd.get_log_block_dims().h < 5 || cd.get_log_block_dims().h > 7)
514 OJPH_ERROR(0x000300B8,
515 "For broadcast profile, codeblock dimensions are restricted such"
516 " that codeblock height has to be either 32, 64, or 128.");
517
518 bool test_pz = cd.get_log_precinct_size(0).w == 7
519 && cd.get_log_precinct_size(0).h == 7;
520 for (ui32 i = 1; i <= num_decomps; ++i)
521 test_pz = cd.get_log_precinct_size(i).w == 8
522 && cd.get_log_precinct_size(i).h == 8;
523 if (!test_pz)
524 OJPH_ERROR(0x000300B9,
525 "For broadcast profile, precinct sizes are restricted."
526 " Use \"-precincts {128,128},{256,256}\" at the commandline");
527
528 if (cd.get_progression_order() != OJPH_PO_CPRL)
529 OJPH_ERROR(0x000300BA,
530 "For broadcast profile, the CPRL progression order must be used."
531 " Use \"-prog_order CPRL\".");
532
533 ui32 tiles_w = sz.get_image_extent().x;
534 tiles_w = ojph_div_ceil(tiles_w, sz.get_tile_size().w);
535 ui32 tiles_h = sz.get_image_extent().y;
536 tiles_h = ojph_div_ceil(tiles_h, sz.get_tile_size().h);
537 ui32 total_tiles = tiles_w * tiles_h;
538
539 if (total_tiles != 1 && total_tiles != 4)
540 OJPH_ERROR(0x000300BB,
541 "The broadcast profile can only have 1 or 4 tiles");
542
543 need_tlm = true;
544 tilepart_div |= OJPH_TILEPART_COMPONENTS;
545 if (tilepart_div != OJPH_TILEPART_COMPONENTS)
546 {
547 tilepart_div = OJPH_TILEPART_COMPONENTS;
548 OJPH_WARN(0x000300B1,
549 "In BROADCAST profile, tile part divisions at the component level "
550 "must be employed, while at the resolution level is not allowed. "
551 "This has been corrected.");
552 }
553 }
554
556 void codestream::write_headers(outfile_base *file,
557 const comment_exchange* comments,
558 ui32 num_comments)
559 {
560 //finalize
561 siz.set_cod(cod);
562 // set the tile size if it was not set by the user
563 size tile_size = siz.get_tile_size();
564 if (tile_size.h == 0 && tile_size.w == 0)
565 {
566 point img_offset = siz.get_image_offset();
567 point img_extent = siz.get_image_extent();
568 size t(img_extent.x + img_offset.x, img_extent.y + img_offset.y);
569 siz.set_tile_size(t);
570 }
571 siz.check_validity();
572 cod.check_validity(siz);
573 cod.update_atk(&atk);
574 qcd.check_validity(siz, cod);
575 cap.check_validity(cod, qcd);
576 nlt.check_validity(siz);
577 if (profile == OJPH_PN_IMF)
578 check_imf_validity();
579 else if (profile == OJPH_PN_BROADCAST)
580 check_broadcast_validity();
581
582 int po = ojph::param_cod(&cod).get_progression_order();
583 if ((po == OJPH_PO_LRCP || po == OJPH_PO_RLCP) &&
584 tilepart_div == OJPH_TILEPART_COMPONENTS)
585 {
586 tilepart_div |= OJPH_TILEPART_RESOLUTIONS;
587 OJPH_INFO(0x00030021,
588 "For LRCP and RLCP progression orders, tilepart divisions at the "
589 "component level, means that we have a tilepart for every "
590 "resolution and component.\n");
591 }
592 if (po == OJPH_PO_RPCL && (tilepart_div & OJPH_TILEPART_COMPONENTS) != 0)
593 {
594 tilepart_div &= ~OJPH_TILEPART_COMPONENTS;
595 OJPH_WARN(0x00030021,
596 "For RPCL progression, having tilepart divisions at the component "
597 "level means a tilepart for every precinct, which does not "
598 "make sense, since we can have no more than 255 tile parts. This "
599 "has been corrected by removing tilepart divisions at the component "
600 "level.");
601 }
602 if (po == OJPH_PO_PCRL && tilepart_div != 0)
603 {
604 tilepart_div = 0;
605 OJPH_WARN(0x00030022,
606 "For PCRL progression, having tilepart divisions at the component "
607 "level or the resolution level means a tile part for every "
608 "precinct, which does not make sense, since we can have no more "
609 "than 255 tile parts. This has been corrected by removing tilepart "
610 "divisions; use another progression if you want tileparts.");
611 }
612 if (po == OJPH_PO_CPRL && (tilepart_div & OJPH_TILEPART_RESOLUTIONS) != 0)
613 {
614 tilepart_div &= ~OJPH_TILEPART_RESOLUTIONS;
615 OJPH_WARN(0x00030023,
616 "For CPRL progression, having tilepart divisions at the resolution "
617 "level means a tile part for every precinct, which does not "
618 "make sense, since we can have no more than 255 tile parts. This "
619 "has been corrected by removing tilepart divisions at the "
620 "resolution level.");
621 }
622
623 if (planar == -1) //not initialized
624 planar = cod.is_employing_color_transform() ? 1 : 0;
625 else if (planar == 0) //interleaved is chosen
626 {
627 }
628 else if (planar == 1) //plannar is chosen
629 {
630 if (cod.is_employing_color_transform() == true)
631 OJPH_ERROR(0x00030021,
632 "the planar interface option cannot be used when colour "
633 "transform is employed");
634 }
635 else
636 assert(0);
637
638 assert(this->outfile == NULL);
639 this->outfile = file;
640 this->pre_alloc();
641 this->finalize_alloc();
642
643 ui16 t = swap_bytes_if_le((ui16)JP2K_MARKER::SOC);
644 if (file->write(&t, 2) != 2)
645 OJPH_ERROR(0x00030022, "Error writing to file");
646
647 if (!siz.write(file))
648 OJPH_ERROR(0x00030023, "Error writing to file");
649
650 if (!cap.write(file))
651 OJPH_ERROR(0x00030024, "Error writing to file");
652
653 if (!cod.write(file))
654 OJPH_ERROR(0x00030025, "Error writing to file");
655
656 if (!cod.write_coc(file, num_comps))
657 OJPH_ERROR(0x0003002E, "Error writing to file");
658
659 if (!qcd.write(file))
660 OJPH_ERROR(0x00030026, "Error writing to file");
661
662 if (!qcd.write_qcc(file, num_comps))
663 OJPH_ERROR(0x0003002D, "Error writing to file");
664
665 if (!nlt.write(file))
666 OJPH_ERROR(0x00030027, "Error writing to file");
667
668 const char* version_str = "OpenJPH Ver "
669 OJPH_INT_TO_STRING(OPENJPH_VERSION_MAJOR) "."
670 OJPH_INT_TO_STRING(OPENJPH_VERSION_MINOR) "."
671 OJPH_INT_TO_STRING(OPENJPH_VERSION_PATCH) ".";
672 size_t data_len = strlen(version_str);
673
674 t = swap_bytes_if_le((ui16)JP2K_MARKER::COM);
675 if (file->write(&t, sizeof(ui16)) != sizeof(ui16))
676 OJPH_ERROR(0x00030028, "Error writing to file");
677 t = swap_bytes_if_le((ui16)(data_len + 4));
678 if (file->write(&t, sizeof(ui16)) != sizeof(ui16))
679 OJPH_ERROR(0x0003002D, "Error writing to file");
680 //1 for General use (IS 8859-15:1999 (Latin) values)
681 t = swap_bytes_if_le((ui16)(1));
682 if (file->write(&t, sizeof(ui16)) != sizeof(ui16))
683 OJPH_ERROR(0x0003002E, "Error writing to file");
684 if (file->write(version_str, data_len) != data_len)
685 OJPH_ERROR(0x0003002F, "Error writing to file");
686
687 if (comments != NULL) {
688 for (ui32 i = 0; i < num_comments; ++i)
689 {
690 t = swap_bytes_if_le((ui16)JP2K_MARKER::COM);
691 if (file->write(&t, 2) != 2)
692 OJPH_ERROR(0x00030029, "Error writing to file");
693 t = swap_bytes_if_le((ui16)(comments[i].len + 4));
694 if (file->write(&t, 2) != 2)
695 OJPH_ERROR(0x0003002A, "Error writing to file");
696 //1 for General use (IS 8859-15:1999 (Latin) values)
697 t = swap_bytes_if_le(comments[i].Rcom);
698 if (file->write(&t, 2) != 2)
699 OJPH_ERROR(0x0003002B, "Error writing to file");
700 if (file->write(comments[i].data, comments[i].len)!=comments[i].len)
701 OJPH_ERROR(0x0003002C, "Error writing to file");
702 }
703 }
704 }
705
707 static
708 int find_marker(infile_base *f, const ui16* char_list, int list_len)
709 {
710 //returns the marker index in char_list, or -1
711 while (!f->eof())
712 {
713 ui8 new_char;
714 size_t num_bytes = f->read(&new_char, 1);
715 if (num_bytes != 1)
716 return -1;
717 if (new_char == 0xFF)
718 {
719 size_t num_bytes = f->read(&new_char, 1);
720
721 if (num_bytes != 1)
722 return -1;
723
724 for (int i = 0; i < list_len; ++i)
725 if (new_char == (char_list[i] & 0xFF))
726 return i;
727 }
728 }
729 return -1;
730 }
731
733 static
734 int skip_marker(infile_base *file, const char *marker,
735 const char *msg, int msg_level, bool resilient)
736 {
737 ojph_unused(marker);
738 ui16 com_len;
739 if (file->read(&com_len, 2) != 2)
740 {
741 if (resilient)
742 return -1;
743 else
744 OJPH_ERROR(0x00030041, "error reading marker");
745 }
746 com_len = swap_bytes_if_le(com_len);
747 file->seek(com_len - 2, infile_base::OJPH_SEEK_CUR);
748 if (msg != NULL && msg_level != OJPH_MSG_NO_MSG)
749 {
750 if (msg_level == OJPH_MSG_INFO)
751 {
752 OJPH_INFO(0x00030001, "%s", msg);
753 }
754 else if (msg_level == OJPH_MSG_WARN)
755 {
756 OJPH_WARN(0x00030001, "%s", msg);
757 }
758 else if (msg_level == OJPH_MSG_ERROR)
759 {
760 OJPH_ERROR(0x00030001, "%s", msg);
761 }
762 else // there is the option of ALL_MSG but it should not be used here
763 assert(0);
764 }
765 return 0;
766 }
767
769 void codestream::read_headers(infile_base *file)
770 {
771 ui16 marker_list[20] = { SOC, SIZ, CAP, PRF, CPF, COD, COC, QCD, QCC,
772 RGN, POC, PPM, TLM, PLM, CRG, COM, DFS, ATK, NLT, SOT };
773 find_marker(file, marker_list, 1); //find SOC
774 find_marker(file, marker_list + 1, 1); //find SIZ
775 siz.read(file);
776 int marker_idx = 0;
777 int received_markers = 0; //check that COD, & QCD received
778 while (true)
779 {
780 marker_idx = find_marker(file, marker_list + 2, 18);
781 if (marker_idx == 0)
782 cap.read(file);
783 else if (marker_idx == 1)
784 //Skipping PRF marker segment; this should not cause any issues
785 skip_marker(file, "PRF", NULL, OJPH_MSG_NO_MSG, false);
786 else if (marker_idx == 2)
787 //Skipping CPF marker segment; this should not cause any issues
788 skip_marker(file, "CPF", NULL, OJPH_MSG_NO_MSG, false);
789 else if (marker_idx == 3)
790 {
791 cod.read(file);
792 received_markers |= 1;
793 ojph::param_cod c(&cod);
794 int num_qlayers = c.get_num_layers();
795 if (num_qlayers != 1)
796 OJPH_ERROR(0x00030053, "The current implementation supports "
797 "1 quality layer only. This codestream has %d quality layers",
798 num_qlayers);
799 }
800 else if (marker_idx == 4)
801 {
802 param_cod* p = cod.add_coc_object(param_cod::OJPH_COD_UNKNOWN);
803 p->read_coc(file, siz.get_num_components(), &cod);
804 if (p->get_comp_idx() >= siz.get_num_components())
805 OJPH_INFO(0x00030056, "The codestream carries a COC marker "
806 "segment for a component indexed by %d, which is more than the "
807 "allowed index number, since the codestream has %d components",
808 p->get_comp_idx(), num_comps);
809 param_cod *q = cod.get_coc(p->get_comp_idx());
810 if (p != q && p->get_comp_idx() == q->get_comp_idx())
811 OJPH_ERROR(0x00030057, "The codestream has two COC marker "
812 "segments for one component of index %d", p->get_comp_idx());
813 }
814 else if (marker_idx == 5)
815 {
816 qcd.read(file);
817 received_markers |= 2;
818 }
819 else if (marker_idx == 6)
820 {
821 param_qcd* p = qcd.add_qcc_object(param_qcd::OJPH_QCD_UNKNOWN);
822 p->read_qcc(file, siz.get_num_components());
823 if (p->get_comp_idx() >= siz.get_num_components())
824 OJPH_ERROR(0x00030054, "The codestream carries a QCC marker "
825 "segment for a component indexed by %d, which is more than the "
826 "allowed index number, since the codestream has %d components",
827 p->get_comp_idx(), num_comps);
828 param_qcd *q = qcd.get_qcc(p->get_comp_idx());
829 if (p != q && p->get_comp_idx() == q->get_comp_idx())
830 OJPH_ERROR(0x00030055, "The codestream has two QCC marker "
831 "segments for one component of index %d", p->get_comp_idx());
832 }
833 else if (marker_idx == 7)
834 skip_marker(file, "RGN", "RGN is not supported yet",
835 OJPH_MSG_WARN, false);
836 else if (marker_idx == 8)
837 skip_marker(file, "POC", "POC is not supported yet",
838 OJPH_MSG_WARN, false);
839 else if (marker_idx == 9)
840 skip_marker(file, "PPM", "PPM is not supported yet",
841 OJPH_MSG_WARN, false);
842 else if (marker_idx == 10)
843 //Skipping TLM marker segment; this should not cause any issues
844 skip_marker(file, "TLM", NULL, OJPH_MSG_NO_MSG, false);
845 else if (marker_idx == 11)
846 //Skipping PLM marker segment; this should not cause any issues
847 skip_marker(file, "PLM", NULL, OJPH_MSG_NO_MSG, false);
848 else if (marker_idx == 12)
849 //Skipping CRG marker segment;
850 skip_marker(file, "CRG", "CRG has been ignored; CRG is related to"
851 " where the Cb and Cr colour components are co-sited or located"
852 " with respect to the Y' luma component. Perhaps, it is better"
853 " to get the individual components and assemble the samples"
854 " according to your needs",
855 OJPH_MSG_INFO, false);
856 else if (marker_idx == 13)
857 skip_marker(file, "COM", NULL, OJPH_MSG_NO_MSG, false);
858 else if (marker_idx == 14)
859 dfs.read(file);
860 else if (marker_idx == 15)
861 atk.read(file);
862 else if (marker_idx == 16)
863 nlt.read(file);
864 else if (marker_idx == 17)
865 break;
866 else
867 OJPH_ERROR(0x00030051, "File ended before finding a tile segment");
868 }
869
870 cod.update_atk(&atk);
871 siz.link(&cod);
872 if (dfs.exists())
873 siz.link(&dfs);
874
875 if (received_markers != 3)
876 OJPH_ERROR(0x00030052, "markers error, COD and QCD are required");
877
878 this->infile = file;
879 planar = cod.is_employing_color_transform() ? 0 : 1;
880 }
881
883 void codestream::restrict_input_resolution(ui32 skipped_res_for_read,
884 ui32 skipped_res_for_recon)
885 {
886 if (skipped_res_for_read < skipped_res_for_recon)
887 OJPH_ERROR(0x000300A1,
888 "skipped_resolution for data %d must be equal or smaller than "
889 " skipped_resolution for reconstruction %d\n",
890 skipped_res_for_read, skipped_res_for_recon);
891 if (skipped_res_for_read > cod.get_num_decompositions())
892 OJPH_ERROR(0x000300A2,
893 "skipped_resolution for data %d must be smaller than "
894 " the number of decomposition levels %d\n",
895 skipped_res_for_read, cod.get_num_decompositions());
896
897 this->skipped_res_for_read = skipped_res_for_read;
898 this->skipped_res_for_recon = skipped_res_for_recon;
899 siz.set_skipped_resolutions(skipped_res_for_recon);
900 }
901
903 void codestream::enable_resilience()
904 {
905 if (infile != NULL)
906 OJPH_ERROR(0x000300A3, "Codestream resilience must be enabled before"
907 " reading file headers.\n");
908 this->resilient = true;
909 }
910
912 void codestream::read()
913 {
914 this->pre_alloc();
915 this->finalize_alloc();
916
917 while (true)
918 {
919 param_sot sot;
920 if (sot.read(infile, resilient))
921 {
922 ui64 tile_start_location = (ui64)infile->tell();
923 bool skip_tile = false;
924
925 if (sot.get_tile_index() >= (int)num_tiles.area())
926 {
927 if (resilient) {
928 OJPH_INFO(0x00030061, "wrong tile index")
929 skip_tile = true; // skip the faulty tile
930 }
931 else
932 OJPH_ERROR(0x00030061, "wrong tile index")
933 }
934
935 if (!skip_tile)
936 {
937 if (sot.get_tile_part_index())
938 { //tile part
939 if (sot.get_num_tile_parts() &&
940 sot.get_tile_part_index() >= sot.get_num_tile_parts())
941 {
942 if (resilient)
943 OJPH_INFO(0x00030062,
944 "error in tile part number, should be smaller than total"
945 " number of tile parts")
946 else
947 OJPH_ERROR(0x00030062,
948 "error in tile part number, should be smaller than total"
949 " number of tile parts")
950 }
951
952 bool sod_found = false;
953 ui16 other_tile_part_markers[7] = { SOT, POC, PPT, PLT, COM,
954 NLT, SOD };
955 while (true)
956 {
957 int marker_idx = 0;
958 int result = 0;
959 marker_idx = find_marker(infile, other_tile_part_markers+1, 6);
960 if (marker_idx == 0)
961 result = skip_marker(infile, "POC",
962 "POC marker segment in a tile is not supported yet",
963 OJPH_MSG_WARN, resilient);
964 else if (marker_idx == 1)
965 result = skip_marker(infile, "PPT",
966 "PPT marker segment in a tile is not supported yet",
967 OJPH_MSG_WARN, resilient);
968 else if (marker_idx == 2)
969 //Skipping PLT marker segment;this should not cause any issues
970 result = skip_marker(infile, "PLT", NULL,
971 OJPH_MSG_NO_MSG, resilient);
972 else if (marker_idx == 3)
973 result = skip_marker(infile, "COM", NULL,
974 OJPH_MSG_NO_MSG, resilient);
975 else if (marker_idx == 4)
976 result = skip_marker(infile, "NLT",
977 "NLT marker in tile is not supported yet",
978 OJPH_MSG_WARN, resilient);
979 else if (marker_idx == 5)
980 {
981 sod_found = true;
982 break;
983 }
984
985 if (marker_idx == -1) //marker not found
986 {
987 if (resilient)
988 OJPH_INFO(0x00030063,
989 "File terminated early before start of data is found"
990 " for tile indexed %d and tile part %d",
991 sot.get_tile_index(), sot.get_tile_part_index())
992 else
993 OJPH_ERROR(0x00030063,
994 "File terminated early before start of data is found"
995 " for tile indexed %d and tile part %d",
996 sot.get_tile_index(), sot.get_tile_part_index())
997 break;
998 }
999 if (result == -1) //file terminated during marker seg. skipping
1000 {
1001 if (resilient)
1002 OJPH_INFO(0x00030064,
1003 "File terminated during marker segment skipping")
1004 else
1005 OJPH_ERROR(0x00030064,
1006 "File terminated during marker segment skipping")
1007 break;
1008 }
1009 }
1010 if (sod_found)
1011 tiles[sot.get_tile_index()].parse_tile_header(sot, infile,
1012 tile_start_location);
1013 }
1014 else
1015 { //first tile part
1016 bool sod_found = false;
1017 ui16 first_tile_part_markers[12] = { SOT, COD, COC, QCD, QCC, RGN,
1018 POC, PPT, PLT, COM, NLT, SOD };
1019 while (true)
1020 {
1021 int marker_idx = 0;
1022 int result = 0;
1023 marker_idx = find_marker(infile, first_tile_part_markers+1, 11);
1024 if (marker_idx == 0)
1025 result = skip_marker(infile, "COD",
1026 "COD marker segment in a tile is not supported yet",
1027 OJPH_MSG_WARN, resilient);
1028 else if (marker_idx == 1)
1029 result = skip_marker(infile, "COC",
1030 "COC marker segment in a tile is not supported yet",
1031 OJPH_MSG_WARN, resilient);
1032 else if (marker_idx == 2)
1033 result = skip_marker(infile, "QCD",
1034 "QCD marker segment in a tile is not supported yet",
1035 OJPH_MSG_WARN, resilient);
1036 else if (marker_idx == 3)
1037 result = skip_marker(infile, "QCC",
1038 "QCC marker segment in a tile is not supported yet",
1039 OJPH_MSG_WARN, resilient);
1040 else if (marker_idx == 4)
1041 result = skip_marker(infile, "RGN",
1042 "RGN marker segment in a tile is not supported yet",
1043 OJPH_MSG_WARN, resilient);
1044 else if (marker_idx == 5)
1045 result = skip_marker(infile, "POC",
1046 "POC marker segment in a tile is not supported yet",
1047 OJPH_MSG_WARN, resilient);
1048 else if (marker_idx == 6)
1049 result = skip_marker(infile, "PPT",
1050 "PPT marker segment in a tile is not supported yet",
1051 OJPH_MSG_WARN, resilient);
1052 else if (marker_idx == 7)
1053 //Skipping PLT marker segment;this should not cause any issues
1054 result = skip_marker(infile, "PLT", NULL,
1055 OJPH_MSG_NO_MSG, resilient);
1056 else if (marker_idx == 8)
1057 result = skip_marker(infile, "COM", NULL,
1058 OJPH_MSG_NO_MSG, resilient);
1059 else if (marker_idx == 9)
1060 result = skip_marker(infile, "NLT",
1061 "PPT marker segment in a tile is not supported yet",
1062 OJPH_MSG_WARN, resilient);
1063 else if (marker_idx == 10)
1064 {
1065 sod_found = true;
1066 break;
1067 }
1068
1069 if (marker_idx == -1) //marker not found
1070 {
1071 if (resilient)
1072 OJPH_INFO(0x00030065,
1073 "File terminated early before start of data is found"
1074 " for tile indexed %d and tile part %d",
1075 sot.get_tile_index(), sot.get_tile_part_index())
1076 else
1077 OJPH_ERROR(0x00030065,
1078 "File terminated early before start of data is found"
1079 " for tile indexed %d and tile part %d",
1080 sot.get_tile_index(), sot.get_tile_part_index())
1081 break;
1082 }
1083 if (result == -1) //file terminated during marker seg. skipping
1084 {
1085 if (resilient)
1086 OJPH_INFO(0x00030066,
1087 "File terminated during marker segment skipping")
1088 else
1089 OJPH_ERROR(0x00030066,
1090 "File terminated during marker segment skipping")
1091 break;
1092 }
1093 }
1094 if (sod_found)
1095 tiles[sot.get_tile_index()].parse_tile_header(sot, infile,
1096 tile_start_location);
1097 }
1098 }
1099 }
1100
1101 // check the next marker; either SOT or EOC,
1102 // if something is broken, just an end of file
1103 ui16 next_markers[2] = { SOT, EOC };
1104 int marker_idx = find_marker(infile, next_markers, 2);
1105 if (marker_idx == -1)
1106 {
1107 OJPH_INFO(0x00030067, "File terminated early");
1108 break;
1109 }
1110 else if (marker_idx == 0)
1111 ;
1112 else if (marker_idx == 1)
1113 break;
1114 }
1115 }
1116
1118 void codestream::set_planar(int planar)
1119 {
1120 this->planar = planar;
1121 }
1122
1124 void codestream::set_profile(const char *s)
1125 {
1126 size_t len = strlen(s);
1127 if (len == 9 && strncmp(s, OJPH_PN_STRING_BROADCAST, 9) == 0)
1128 profile = OJPH_PN_BROADCAST;
1129 else if (len == 3 && strncmp(s, OJPH_PN_STRING_IMF, 3) == 0)
1130 profile = OJPH_PN_IMF;
1131 else
1132 OJPH_ERROR(0x000300A1, "unkownn or unsupported profile");
1133 }
1134
1136 void codestream::set_tilepart_divisions(ui32 value)
1137 {
1138 tilepart_div = value;
1139 }
1140
1142 void codestream::request_tlm_marker(bool needed)
1143 {
1144 need_tlm = needed;
1145 }
1146
1148 void codestream::flush()
1149 {
1150 si32 repeat = (si32)num_tiles.area();
1151 for (si32 i = 0; i < repeat; ++i)
1152 tiles[i].prepare_for_flush();
1153 if (need_tlm)
1154 { //write tlm
1155 for (si32 i = 0; i < repeat; ++i)
1156 tiles[i].fill_tlm(&tlm);
1157 tlm.write(outfile);
1158 }
1159 for (si32 i = 0; i < repeat; ++i)
1160 tiles[i].flush(outfile);
1161 ui16 t = swap_bytes_if_le((ui16)JP2K_MARKER::EOC);
1162 if (!outfile->write(&t, 2))
1163 OJPH_ERROR(0x00030071, "Error writing to file");
1164 }
1165
1167 void codestream::close()
1168 {
1169 if (infile)
1170 infile->close();
1171 if (outfile)
1172 outfile->close();
1173 }
1174
1176 line_buf* codestream::exchange(line_buf *line, ui32 &next_component)
1177 {
1178 if (line)
1179 {
1180 bool success = false;
1181 while (!success)
1182 {
1183 success = true;
1184 for (ui32 i = 0; i < num_tiles.w; ++i)
1185 {
1186 ui32 idx = i + cur_tile_row * num_tiles.w;
1187 if ((success &= tiles[idx].push(line, cur_comp)) == false)
1188 break;
1189 }
1190 cur_tile_row += success == false ? 1 : 0;
1191 if (cur_tile_row >= num_tiles.h)
1192 cur_tile_row = 0;
1193 }
1194
1195 if (planar) //process one component at a time
1196 {
1197 if (++cur_line >= comp_size[cur_comp].h)
1198 {
1199 cur_line = 0;
1200 cur_tile_row = 0;
1201 if (++cur_comp >= num_comps)
1202 {
1203 next_component = 0;
1204 return NULL;
1205 }
1206 }
1207 }
1208 else //process all component for a line
1209 {
1210 if (++cur_comp >= num_comps)
1211 {
1212 cur_comp = 0;
1213 if (++cur_line >= comp_size[cur_comp].h)
1214 {
1215 next_component = 0;
1216 return NULL;
1217 }
1218 }
1219 }
1220 }
1221
1222 next_component = cur_comp;
1223 return this->lines + cur_comp;
1224 }
1225
1227 line_buf* codestream::pull(ui32 &comp_num)
1228 {
1229 bool success = false;
1230 while (!success)
1231 {
1232 success = true;
1233 for (ui32 i = 0; i < num_tiles.w; ++i)
1234 {
1235 ui32 idx = i + cur_tile_row * num_tiles.w;
1236 if ((success &= tiles[idx].pull(lines + cur_comp, cur_comp)) == false)
1237 break;
1238 }
1239 cur_tile_row += success == false ? 1 : 0;
1240 if (cur_tile_row >= num_tiles.h)
1241 cur_tile_row = 0;
1242 }
1243 comp_num = cur_comp;
1244
1245 if (planar) //process one component at a time
1246 {
1247 if (++cur_line >= recon_comp_size[cur_comp].h)
1248 {
1249 cur_line = 0;
1250 cur_tile_row = 0;
1251 if (cur_comp++ >= num_comps)
1252 {
1253 comp_num = 0;
1254 return NULL;
1255 }
1256 }
1257 }
1258 else //process all component for a line
1259 {
1260 if (++cur_comp >= num_comps)
1261 {
1262 cur_comp = 0;
1263 if (cur_line++ >= recon_comp_size[cur_comp].h)
1264 {
1265 comp_num = 0;
1266 return NULL;
1267 }
1268 }
1269 }
1270
1271 return lines + comp_num;
1272 }
1273
1274 }
1275}
ojph::comment_exchange
Definition ojph_params.h:291
ojph::comment_exchange::len
ui16 len
Definition ojph_params.h:300
ojph::comment_exchange::data
const char * data
Definition ojph_params.h:299
ojph::infile_base
Definition ojph_file.h:267
ojph::infile_base::eof
virtual bool eof()=0
ojph::infile_base::seek
seek
Definition ojph_file.h:269
ojph::infile_base::OJPH_SEEK_CUR
@ OJPH_SEEK_CUR
Definition ojph_file.h:271
ojph::infile_base::read
virtual size_t read(void *ptr, size_t size)=0
ojph::line_buf
Definition ojph_mem.h:161
ojph::local::codestream::cap
param_cap cap
Definition ojph_codestream_local.h:155
ojph::local::codestream::qcd
param_qcd qcd
Definition ojph_codestream_local.h:156
ojph::local::codestream::outfile
outfile_base * outfile
Definition ojph_codestream_local.h:167
ojph::local::codestream::read
void read()
Definition ojph_codestream_local.cpp:912
ojph::local::codestream::nlt
param_nlt nlt
Definition ojph_codestream_local.h:158
ojph::local::codestream::atk
param_atk atk
Definition ojph_codestream_local.h:162
ojph::local::codestream::infile
infile_base * infile
Definition ojph_codestream_local.h:168
ojph::local::codestream::~codestream
~codestream()
Definition ojph_codestream_local.cpp:69
ojph::local::codestream::tiles
tile * tiles
Definition ojph_codestream_local.h:141
ojph::local::codestream::skipped_res_for_recon
ui32 skipped_res_for_recon
Definition ojph_codestream_local.h:137
ojph::local::codestream::pre_alloc
void pre_alloc()
Definition ojph_codestream_local.cpp:113
ojph::local::codestream::resilient
bool resilient
Definition ojph_codestream_local.h:136
ojph::local::codestream::access_siz
ojph::param_siz access_siz()
Definition ojph_codestream_local.h:77
ojph::local::codestream::tilepart_div
ui32 tilepart_div
Definition ojph_codestream_local.h:149
ojph::local::codestream::tlm
param_tlm tlm
Definition ojph_codestream_local.h:157
ojph::local::codestream::profile
int profile
Definition ojph_codestream_local.h:148
ojph::local::codestream::planar
int planar
Definition ojph_codestream_local.h:147
ojph::local::codestream::close
void close()
Definition ojph_codestream_local.cpp:1167
ojph::local::codestream::request_tlm_marker
void request_tlm_marker(bool needed)
Definition ojph_codestream_local.cpp:1142
ojph::local::codestream::exchange
line_buf * exchange(line_buf *line, ui32 &next_component)
Definition ojph_codestream_local.cpp:1176
ojph::local::codestream::set_planar
void set_planar(int planar)
Definition ojph_codestream_local.cpp:1118
ojph::local::codestream::precinct_scratch
ui8 * precinct_scratch
Definition ojph_codestream_local.h:130
ojph::local::codestream::lines
line_buf * lines
Definition ojph_codestream_local.h:142
ojph::local::codestream::check_imf_validity
void check_imf_validity()
Definition ojph_codestream_local.cpp:293
ojph::local::codestream::restart
void restart()
Definition ojph_codestream_local.cpp:78
ojph::local::codestream::restrict_input_resolution
void restrict_input_resolution(ui32 skipped_res_for_data, ui32 skipped_res_for_recon)
Definition ojph_codestream_local.cpp:883
ojph::local::codestream::need_tlm
bool need_tlm
Definition ojph_codestream_local.h:150
ojph::local::codestream::elastic_alloc
mem_elastic_allocator * elastic_alloc
Definition ojph_codestream_local.h:166
ojph::local::codestream::cur_comp
ui32 cur_comp
Definition ojph_codestream_local.h:134
ojph::local::codestream::siz
param_siz siz
Definition ojph_codestream_local.h:153
ojph::local::codestream::cur_tile_row
ui32 cur_tile_row
Definition ojph_codestream_local.h:135
ojph::local::codestream::allocator
mem_fixed_allocator * allocator
Definition ojph_codestream_local.h:165
ojph::local::codestream::flush
void flush()
Definition ojph_codestream_local.cpp:1148
ojph::local::codestream::write_headers
void write_headers(outfile_base *file, const comment_exchange *comments, ui32 num_comments)
Definition ojph_codestream_local.cpp:556
ojph::local::codestream::recon_comp_size
size * recon_comp_size
Definition ojph_codestream_local.h:145
ojph::local::codestream::precinct_scratch_needed_bytes
ui32 precinct_scratch_needed_bytes
Definition ojph_codestream_local.h:129
ojph::local::codestream::cod
param_cod cod
Definition ojph_codestream_local.h:154
ojph::local::codestream::check_broadcast_validity
void check_broadcast_validity()
Definition ojph_codestream_local.cpp:456
ojph::local::codestream::read_headers
void read_headers(infile_base *file)
Definition ojph_codestream_local.cpp:769
ojph::local::codestream::codestream
codestream()
Definition ojph_codestream_local.cpp:56
ojph::local::codestream::num_comps
ui32 num_comps
Definition ojph_codestream_local.h:143
ojph::local::codestream::set_profile
void set_profile(const char *s)
Definition ojph_codestream_local.cpp:1124
ojph::local::codestream::employ_color_transform
bool employ_color_transform
Definition ojph_codestream_local.h:146
ojph::local::codestream::set_tilepart_divisions
void set_tilepart_divisions(ui32 value)
Definition ojph_codestream_local.cpp:1136
ojph::local::codestream::finalize_alloc
void finalize_alloc()
Definition ojph_codestream_local.cpp:221
ojph::local::codestream::dfs
param_dfs dfs
Definition ojph_codestream_local.h:161
ojph::local::codestream::num_tiles
size num_tiles
Definition ojph_codestream_local.h:140
ojph::local::codestream::cur_line
ui32 cur_line
Definition ojph_codestream_local.h:133
ojph::local::codestream::pull
line_buf * pull(ui32 &comp_num)
Definition ojph_codestream_local.cpp:1227
ojph::local::codestream::enable_resilience
void enable_resilience()
Definition ojph_codestream_local.cpp:903
ojph::local::codestream::skipped_res_for_read
ui32 skipped_res_for_read
Definition ojph_codestream_local.h:137
ojph::local::codestream::comp_size
size * comp_size
Definition ojph_codestream_local.h:144
ojph::local::tile
Definition ojph_tile.h:61
ojph::local::tile::pre_alloc
static void pre_alloc(codestream *codestream, const rect &tile_rect, const rect &recon_tile_rect, ui32 &num_tileparts)
Definition ojph_tile.cpp:56
ojph::mem_elastic_allocator
Definition ojph_mem.h:218
ojph::mem_fixed_allocator
Definition ojph_mem.h:59
ojph::outfile_base
Definition ojph_file.h:75
ojph::outfile_base::write
virtual size_t write(const void *ptr, size_t size)=0
ojph::param_cod
Definition ojph_params.h:104
ojph::param_cod::get_progression_order
int get_progression_order() const
Definition ojph_params.cpp:300
ojph::param_cod::get_num_decompositions
ui32 get_num_decompositions() const
Definition ojph_params.cpp:264
ojph::param_cod::get_log_block_dims
size get_log_block_dims() const
Definition ojph_params.cpp:276
ojph::param_cod::is_reversible
bool is_reversible() const
Definition ojph_params.cpp:282
ojph::param_cod::get_log_precinct_size
size get_log_precinct_size(ui32 level_num) const
Definition ojph_params.cpp:294
ojph::param_cod::get_num_layers
int get_num_layers() const
Definition ojph_params.cpp:324
ojph::param_siz
Definition ojph_params.h:71
ojph::param_siz::get_image_extent
point get_image_extent() const
Definition ojph_params.cpp:97
ojph::param_siz::get_bit_depth
ui32 get_bit_depth(ui32 comp_num) const
Definition ojph_params.cpp:127
ojph::param_siz::get_image_offset
point get_image_offset() const
Definition ojph_params.cpp:103
ojph::param_siz::get_tile_size
size get_tile_size() const
Definition ojph_params.cpp:109
ojph::param_siz::get_downsampling
point get_downsampling(ui32 comp_num) const
Definition ojph_params.cpp:139
ojph::param_siz::get_tile_offset
point get_tile_offset() const
Definition ojph_params.cpp:115
ojph::param_siz::is_signed
bool is_signed(ui32 comp_num) const
Definition ojph_params.cpp:133
ojph::param_siz::get_num_components
ui32 get_num_components() const
Definition ojph_params.cpp:121
ojph::local
Definition ojph_bitbuffer_read.h:53
ojph::local::find_marker
static int find_marker(infile_base *f, const ui16 *char_list, int list_len)
Definition ojph_codestream_local.cpp:708
ojph::local::skip_marker
static int skip_marker(infile_base *file, const char *marker, const char *msg, int msg_level, bool resilient)
Definition ojph_codestream_local.cpp:734
ojph::local::init_wavelet_transform_functions
void init_wavelet_transform_functions()
Definition ojph_transform.cpp:98
ojph::local::init_colour_transform_functions
void init_colour_transform_functions()
Definition ojph_colour.cpp:109
ojph::local::SOD
@ SOD
Definition ojph_params_local.h:146
ojph::local::SIZ
@ SIZ
Definition ojph_params_local.h:123
ojph::local::ATK
@ ATK
Definition ojph_params_local.h:142
ojph::local::PRF
@ PRF
Definition ojph_params_local.h:127
ojph::local::NLT
@ NLT
Definition ojph_params_local.h:141
ojph::local::TLM
@ TLM
Definition ojph_params_local.h:126
ojph::local::PPM
@ PPM
Definition ojph_params_local.h:135
ojph::local::QCC
@ QCC
Definition ojph_params_local.h:132
ojph::local::CRG
@ CRG
Definition ojph_params_local.h:137
ojph::local::DFS
@ DFS
Definition ojph_params_local.h:139
ojph::local::RGN
@ RGN
Definition ojph_params_local.h:133
ojph::local::SOC
@ SOC
Definition ojph_params_local.h:121
ojph::local::QCD
@ QCD
Definition ojph_params_local.h:131
ojph::local::PPT
@ PPT
Definition ojph_params_local.h:136
ojph::local::COC
@ COC
Definition ojph_params_local.h:125
ojph::local::POC
@ POC
Definition ojph_params_local.h:134
ojph::local::PLT
@ PLT
Definition ojph_params_local.h:129
ojph::local::COD
@ COD
Definition ojph_params_local.h:124
ojph::local::CAP
@ CAP
Definition ojph_params_local.h:122
ojph::local::CPF
@ CPF
Definition ojph_params_local.h:130
ojph::local::PLM
@ PLM
Definition ojph_params_local.h:128
ojph::local::SOT
@ SOT
Definition ojph_params_local.h:143
ojph::local::COM
@ COM
Definition ojph_params_local.h:138
ojph::local::EOC
@ EOC
Definition ojph_params_local.h:147
ojph
Definition ojph_img_io.h:52
ojph::OJPH_PN_STRING_BROADCAST
const char OJPH_PN_STRING_BROADCAST[]
Definition ojph_params_local.h:94
ojph::swap_bytes_if_le
static ui16 swap_bytes_if_le(ui16 t)
Definition ojph_arch.h:414
ojph::OJPH_PO_LRCP
@ OJPH_PO_LRCP
Definition ojph_params_local.h:59
ojph::OJPH_PO_RLCP
@ OJPH_PO_RLCP
Definition ojph_params_local.h:60
ojph::OJPH_PO_CPRL
@ OJPH_PO_CPRL
Definition ojph_params_local.h:63
ojph::OJPH_PO_PCRL
@ OJPH_PO_PCRL
Definition ojph_params_local.h:62
ojph::OJPH_PO_RPCL
@ OJPH_PO_RPCL
Definition ojph_params_local.h:61
ojph::OJPH_PN_STRING_IMF
const char OJPH_PN_STRING_IMF[]
Definition ojph_params_local.h:95
ojph::ui64
uint64_t ui64
Definition ojph_defs.h:56
ojph::OJPH_MSG_INFO
@ OJPH_MSG_INFO
Definition ojph_message.h:55
ojph::OJPH_MSG_ERROR
@ OJPH_MSG_ERROR
Definition ojph_message.h:57
ojph::OJPH_MSG_WARN
@ OJPH_MSG_WARN
Definition ojph_message.h:56
ojph::OJPH_MSG_NO_MSG
@ OJPH_MSG_NO_MSG
Definition ojph_message.h:58
ojph::ui16
uint16_t ui16
Definition ojph_defs.h:52
ojph::OJPH_TILEPART_RESOLUTIONS
@ OJPH_TILEPART_RESOLUTIONS
Definition ojph_params_local.h:100
ojph::OJPH_TILEPART_NO_DIVISIONS
@ OJPH_TILEPART_NO_DIVISIONS
Definition ojph_params_local.h:99
ojph::OJPH_TILEPART_COMPONENTS
@ OJPH_TILEPART_COMPONENTS
Definition ojph_params_local.h:101
ojph::OJPH_PN_BROADCAST
@ OJPH_PN_BROADCAST
Definition ojph_params_local.h:83
ojph::OJPH_PN_UNDEFINED
@ OJPH_PN_UNDEFINED
Definition ojph_params_local.h:76
ojph::OJPH_PN_IMF
@ OJPH_PN_IMF
Definition ojph_params_local.h:84
ojph::si32
int32_t si32
Definition ojph_defs.h:55
ojph::ui32
uint32_t ui32
Definition ojph_defs.h:54
ojph::ui8
uint8_t ui8
Definition ojph_defs.h:50
ojph_codestream_local.h
ojph_colour.h
ojph_max
#define ojph_max(a, b)
Definition ojph_defs.h:73
OJPH_INT_TO_STRING
#define OJPH_INT_TO_STRING(I)
Definition ojph_defs.h:61
ojph_div_ceil
#define ojph_div_ceil(a, b)
Definition ojph_defs.h:70
ojph_min
#define ojph_min(a, b)
Definition ojph_defs.h:76
ojph_unused
#define ojph_unused(x)
Definition ojph_defs.h:78
ojph_mem.h
OJPH_INFO
#define OJPH_INFO(t,...)
MACROs to insert file and line number for info, warning, and error.
Definition ojph_message.h:284
OJPH_ERROR
#define OJPH_ERROR(t,...)
Definition ojph_message.h:288
OJPH_WARN
#define OJPH_WARN(t,...)
Definition ojph_message.h:286
ojph_params.h
ojph_tile.h
ojph_transform.h
OPENJPH_VERSION_PATCH
#define OPENJPH_VERSION_PATCH
Definition ojph_version.h:38
OPENJPH_VERSION_MAJOR
#define OPENJPH_VERSION_MAJOR
Definition ojph_version.h:36
OPENJPH_VERSION_MINOR
#define OPENJPH_VERSION_MINOR
Definition ojph_version.h:37
ojph::local::param_cod
Definition ojph_params_local.h:385
ojph::local::param_cod::get_log_block_dims
size get_log_block_dims() const
Definition ojph_params_local.h:526
ojph::local::param_cod::get_comp_idx
ui32 get_comp_idx() const
Definition ojph_params_local.h:618
ojph::local::param_cod::OJPH_COD_UNKNOWN
@ OJPH_COD_UNKNOWN
Definition ojph_params_local.h:389
ojph::local::param_cod::get_log_precinct_size
size get_log_precinct_size(ui32 res_num) const
Definition ojph_params_local.h:553
ojph::local::param_cod::read_coc
void read_coc(infile_base *file, ui32 num_comps, param_cod *top_cod)
Definition ojph_params.cpp:1002
ojph::local::param_cod::get_num_decompositions
ui8 get_num_decompositions() const
Definition ojph_params_local.h:504
ojph::local::param_qcd
Definition ojph_params_local.h:677
ojph::local::param_qcd::get_comp_idx
ui16 get_comp_idx() const
Definition ojph_params_local.h:728
ojph::local::param_qcd::read_qcc
void read_qcc(infile_base *file, ui32 num_comps)
Definition ojph_params.cpp:1728
ojph::local::param_qcd::OJPH_QCD_UNKNOWN
@ OJPH_QCD_UNKNOWN
Definition ojph_params_local.h:681
ojph::local::param_sot
Definition ojph_params_local.h:925
ojph::local::param_sot::get_num_tile_parts
ui8 get_num_tile_parts() const
Definition ojph_params_local.h:944
ojph::local::param_sot::get_tile_index
ui16 get_tile_index() const
Definition ojph_params_local.h:941
ojph::local::param_sot::read
bool read(infile_base *file, bool resilient)
Definition ojph_params.cpp:2141
ojph::local::param_sot::get_tile_part_index
ui8 get_tile_part_index() const
Definition ojph_params_local.h:943
ojph::local::param_tlm::Ttlm_Ptlm_pair
Definition ojph_params_local.h:964
ojph::point
Definition ojph_base.h:58
ojph::point::y
ui32 y
Definition ojph_base.h:60
ojph::point::x
ui32 x
Definition ojph_base.h:60
ojph::rect
Definition ojph_base.h:65
ojph::rect::siz
size siz
Definition ojph_base.h:67
ojph::rect::org
point org
Definition ojph_base.h:66
ojph::size
Definition ojph_base.h:48
ojph::size::w
ui32 w
Definition ojph_base.h:50
ojph::size::h
ui32 h
Definition ojph_base.h:51