OpenJPH
Open-source implementation of JPEG2000 Part-15
ojph_compress.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_compress.cpp
34// Author: Aous Naman
35// Date: 28 August 2019
36//***************************************************************************/
37
38
39#include <ctime>
40#include <iostream>
41
42#include "ojph_arg.h"
43#include "ojph_mem.h"
44#include "ojph_img_io.h"
45#include "ojph_file.h"
46#include "ojph_codestream.h"
47#include "ojph_params.h"
48#include "ojph_message.h"
49
52{
53 size_list_interpreter(const int max_num_elements, int& num_elements,
54 ojph::size* list)
55 : max_num_eles(max_num_elements), sizelist(list), num_eles(num_elements)
56 {}
57
58 virtual void operate(const char *str)
59 {
60 const char *next_char = str;
61 num_eles = 0;
62 do
63 {
64 if (num_eles)
65 {
66 if (*next_char != ',') //separate sizes by a comma
67 throw "sizes in a sizes list must be separated by a comma";
68 next_char++;
69 }
70
71 if (*next_char != '{')
72 throw "size must start with {";
73 next_char++;
74 char *endptr;
75 sizelist[num_eles].w = (ojph::ui32)strtoul(next_char, &endptr, 10);
76 if (endptr == next_char)
77 throw "size number is improperly formatted";
78 next_char = endptr;
79 if (*next_char != ',')
80 throw "size must have a "","" between the two numbers";
81 next_char++;
82 sizelist[num_eles].h = (ojph::ui32)strtoul(next_char, &endptr, 10);
83 if (endptr == next_char)
84 throw "number is improperly formatted";
85 next_char = endptr;
86 if (*next_char != '}')
87 throw "size must end with }";
88 next_char++;
89
90 ++num_eles;
91 }
92 while (*next_char == ',' && num_eles < max_num_eles);
94 {
95 if (*next_char)
96 throw "size elements must separated by a "",""";
97 }
98 else if (*next_char)
99 throw "there are too many elements in the size list";
100 }
101
102 const int max_num_eles;
105};
106
109{
110 point_list_interpreter(const ojph::ui32 max_num_elements,
111 ojph::ui32& num_elements,
112 ojph::point* list)
113 : max_num_eles(max_num_elements), pointlist(list), num_eles(num_elements)
114 { }
115
116 virtual void operate(const char *str)
117 {
118 const char *next_char = str;
119 num_eles = 0;
120 do
121 {
122 if (num_eles)
123 {
124 if (*next_char != ',') //separate sizes by a comma
125 throw "sizes in a sizes list must be separated by a comma";
126 next_char++;
127 }
128
129 if (*next_char != '{')
130 throw "size must start with {";
131 next_char++;
132 char *endptr;
133 pointlist[num_eles].x = (ojph::ui32)strtoul(next_char, &endptr, 10);
134 if (endptr == next_char)
135 throw "point number is improperly formatted";
136 next_char = endptr;
137 if (*next_char != ',')
138 throw "point must have a "","" between the two numbers";
139 next_char++;
140 pointlist[num_eles].y = (ojph::ui32)strtoul(next_char, &endptr, 10);
141 if (endptr == next_char)
142 throw "number is improperly formatted";
143 next_char = endptr;
144 if (*next_char != '}')
145 throw "point must end with }";
146 next_char++;
147
148 ++num_eles;
149 }
150 while (*next_char == ',' && num_eles < max_num_eles);
152 {
153 if (*next_char)
154 throw "size elements must separated by a "",""";
155 }
156 else if (*next_char)
157 throw "there are too many elements in the size list";
158 }
159
163};
164
167{
169 virtual void operate(const char *str)
170 {
171 const char *next_char = str;
172 if (*next_char != '{')
173 throw "size must start with {";
174 next_char++;
175 char *endptr;
176 val.w = (ojph::ui32)strtoul(next_char, &endptr, 10);
177 if (endptr == next_char)
178 throw "size number is improperly formatted";
179 next_char = endptr;
180 if (*next_char != ',')
181 throw "size must have a "","" between the two numbers";
182 next_char++;
183 val.h = (ojph::ui32)strtoul(next_char, &endptr, 10);
184 if (endptr == next_char)
185 throw "number is improperly formatted";
186 next_char = endptr;
187 if (*next_char != '}')
188 throw "size must end with }";
189 next_char++;
190 if (*next_char != '\0') //must be end of string
191 throw "size has extra characters";
192 }
194};
195
198{
200 virtual void operate(const char *str)
201 {
202 const char *next_char = str;
203 if (*next_char != '{')
204 throw "size must start with {";
205 next_char++;
206 char *endptr;
207 val.x = (ojph::ui32)strtoul(next_char, &endptr, 10);
208 if (endptr == next_char)
209 throw "size number is improperly formatted";
210 next_char = endptr;
211 if (*next_char != ',')
212 throw "size must have a "","" between the two numbers";
213 next_char++;
214 val.y = (ojph::ui32)strtoul(next_char, &endptr, 10);
215 if (endptr == next_char)
216 throw "number is improperly formatted";
217 next_char = endptr;
218 if (*next_char != '}')
219 throw "size must end with }";
220 next_char++;
221 if (*next_char != '\0') //must be end of string
222 throw "size has extra characters";
223 }
225};
226
227
230{
231 ui32_list_interpreter(const ojph::ui32 max_num_elements,
232 ojph::ui32& num_elements,
233 ojph::ui32* list)
234 : max_num_eles(max_num_elements), ui32list(list), num_eles(num_elements)
235 {}
236
237 virtual void operate(const char *str)
238 {
239 const char *next_char = str;
240 num_eles = 0;
241 do
242 {
243 if (num_eles)
244 {
245 if (*next_char != ',') //separate sizes by a comma
246 throw "sizes in a sizes list must be separated by a comma";
247 next_char++;
248 }
249 char *endptr;
250 ui32list[num_eles] = (ojph::ui32)strtoul(next_char, &endptr, 10);
251 if (endptr == next_char)
252 throw "size number is improperly formatted";
253 next_char = endptr;
254 ++num_eles;
255 }
256 while (*next_char == ',' && num_eles < max_num_eles);
258 {
259 if (*next_char)
260 throw "list elements must separated by a "",""";
261 }
262 else if (*next_char)
263 throw "there are too many elements in the size list";
264 }
265
269};
270
274{
276 ojph::ui32& num_elements,
277 ojph::si32* list)
278 : max_num_eles(max_num_elements), boollist(list), num_eles(num_elements) {}
279
280 virtual void operate(const char *str)
281 {
282 const char *next_char = str;
283 num_eles = 0;
284 do
285 {
286 if (num_eles)
287 {
288 if (*next_char != ',') //separate sizes by a comma
289 throw "sizes in a sizes list must be separated by a comma";
290 next_char++;
291 }
292 if (strncmp(next_char, "true", 4) == 0)
293 {
294 boollist[num_eles] = 1;
295 next_char += 4;
296 }
297 else if (strncmp(next_char, "false", 5) == 0)
298 {
299 boollist[num_eles] = 0;
300 next_char += 5;
301 }
302 else
303 throw "unknown bool value";
304 ++num_eles;
305 }
306 while (*next_char == ',' && num_eles < max_num_eles);
308 {
309 if (*next_char)
310 throw "size elements must separated by a "",""";
311 }
312 else if (*next_char)
313 throw "there are too many elements in the size list";
314 }
315
317
321};
322
326{
328 bool& at_components)
330
331 virtual void operate(const char *str)
332 {
333 size_t len = strlen(str);
334 if (len == 1 && strncmp(str, "C", 2) == 0)
335 {
336 at_resolutions = false;
337 at_components = true;
338 }
339 else if (len == 1 && strncmp(str, "R", 2) == 0)
340 {
341 at_resolutions = true;
342 at_components = false;
343 }
344 else if (len == 2 &&
345 (strncmp(str, "RC", 3) == 0 || strncmp(str, "CR", 3) == 0))
346 {
347 at_resolutions = true;
348 at_components = true;
349 }
350 else
351 throw "could not interpret -tileparts fields; allowed values are "
352 "\"R\" \"C\" and \"RC\"";
353 }
354
357};
358
360static
361bool get_arguments(int argc, char *argv[], char *&input_filename,
362 char *&output_filename, char *&progression_order,
363 char *&profile_string, ojph::ui32 &num_decompositions,
364 float &quantization_step, bool &reversible,
365 int &employ_color_transform,
366 const int max_num_precincts, int &num_precincts,
367 ojph::size *precinct_size, ojph::size& block_size,
368 ojph::size& dims, ojph::point& image_offset,
369 ojph::size& tile_size, ojph::point& tile_offset,
370 ojph::ui32& max_num_comps, ojph::ui32& num_comps,
371 ojph::ui32& num_comp_downsamps, ojph::point*& comp_downsamp,
372 ojph::ui32& num_bit_depths, ojph::ui32*& bit_depth,
373 ojph::ui32& num_is_signed, ojph::si32*& is_signed,
374 bool& tlm_marker, bool& tileparts_at_resolutions,
375 bool& tileparts_at_components, char *&com_string)
376{
377 ojph::cli_interpreter interpreter;
378 interpreter.init(argc, argv);
379
380 interpreter.reinterpret("-i", input_filename);
381 interpreter.reinterpret("-o", output_filename);
382 interpreter.reinterpret("-prog_order", progression_order);
383 interpreter.reinterpret("-profile", profile_string);
384 interpreter.reinterpret("-num_decomps", num_decompositions);
385 interpreter.reinterpret("-qstep", quantization_step);
386 interpreter.reinterpret("-reversible", reversible);
387 interpreter.reinterpret_to_bool("-colour_trans", employ_color_transform);
388 interpreter.reinterpret("-num_comps", num_comps);
389 interpreter.reinterpret("-tlm_marker", tlm_marker);
390 interpreter.reinterpret("-com", com_string);
391
392 size_interpreter block_interpreter(block_size);
393 size_interpreter dims_interpreter(dims);
394 size_list_interpreter sizelist(max_num_precincts, num_precincts,
395 precinct_size);
396
397 if (num_comps > 255)
398 throw "more than 255 components is not supported";
399 if (num_comps > max_num_comps)
400 {
401 max_num_comps = num_comps;
402 comp_downsamp = new ojph::point[num_comps];
403 bit_depth = new ojph::ui32[num_comps];
404 is_signed = new ojph::si32[num_comps];
405 for (ojph::ui32 i = 0; i < num_comps; ++i)
406 {
407 comp_downsamp[i] = ojph::point(0, 0);
408 bit_depth[i] = 0;
409 is_signed[i] = -1;
410 }
411 }
412
413 point_list_interpreter pointlist(max_num_comps, num_comp_downsamps,
414 comp_downsamp);
415 ui32_list_interpreter ilist(max_num_comps, num_bit_depths, bit_depth);
416 si32_to_bool_list_interpreter blist(max_num_comps, num_is_signed, is_signed);
417 point_interpreter img_off_interpreter(image_offset);
418 size_interpreter tile_size_interpreter(tile_size);
419 point_interpreter tile_off_interpreter(tile_offset);
420 tileparts_division_interpreter tp_div_interpreter(tileparts_at_resolutions,
421 tileparts_at_components);
422 try
423 {
424 interpreter.reinterpret("-block_size", &block_interpreter);
425 interpreter.reinterpret("-dims", &dims_interpreter);
426 interpreter.reinterpret("-image_offset", &img_off_interpreter);
427 interpreter.reinterpret("-tile_size", &tile_size_interpreter);
428 interpreter.reinterpret("-tile_offset", &tile_off_interpreter);
429 interpreter.reinterpret("-precincts", &sizelist);
430 interpreter.reinterpret("-downsamp", &pointlist);
431 interpreter.reinterpret("-bit_depth", &ilist);
432 interpreter.reinterpret("-signed", &blist);
433 interpreter.reinterpret("-tileparts", &tp_div_interpreter);
434 }
435 catch (const char *s)
436 {
437 printf("%s\n",s);
438 return false;
439 }
440
441 if (interpreter.is_exhausted() == false) {
442 printf("The following arguments were not interpreted:\n");
443 ojph::argument t = interpreter.get_argument_zero();
444 t = interpreter.get_next_avail_argument(t);
445 while (t.is_valid()) {
446 printf("%s\n", t.arg);
447 t = interpreter.get_next_avail_argument(t);
448 }
449 return false;
450 }
451 return true;
452}
453
455static
456const char* get_file_extension(const char* filename)
457{
458 size_t len = strlen(filename);
459 const char* p = strrchr(filename, '.');
460 if (p == NULL || p == filename + len - 1)
461 OJPH_ERROR(0x01000071,
462 "no file extension is found, or there are no characters "
463 "after the dot \'.\' for filename \"%s\" \n", filename);
464 return p;
465}
466
468static
469bool is_matching(const char *ref, const char *other)
470{
471 size_t num_ele = strlen(ref);
472
473 if (num_ele != strlen(other))
474 return false;
475
476 for (ojph::ui32 i = 0; i < num_ele; ++i)
477 if (ref[i] != other[i] && ref[i] != tolower(other[i]))
478 return false;
479
480 return true;
481}
482
484// main
486
487int main(int argc, char * argv[]) {
488 char *input_filename = NULL;
489 char *output_filename = NULL;
490 char prog_order_store[] = "RPCL";
491 char *prog_order = prog_order_store;
492 char profile_string_store[] = "";
493 char *profile_string = profile_string_store;
494 char *com_string = NULL;
495 ojph::ui32 num_decompositions = 5;
496 float quantization_step = -1.0f;
497 bool reversible = false;
498 int employ_color_transform = -1;
499
500 const int max_precinct_sizes = 33; //maximum number of decompositions is 32
501 ojph::size precinct_size[max_precinct_sizes];
502 int num_precincts = -1;
503
504 ojph::size block_size(64,64);
505 ojph::size dims(0, 0);
506 ojph::size tile_size(0, 0);
507 ojph::point tile_offset(0, 0);
508 ojph::point image_offset(0, 0);
509 const ojph::ui32 initial_num_comps = 4;
510 ojph::ui32 max_num_comps = initial_num_comps;
511 ojph::ui32 num_components = 0;
512 ojph::ui32 num_is_signed = 0;
513 ojph::si32 is_signed_store[initial_num_comps] = {-1, -1, -1, -1};
514 ojph::si32 *is_signed = is_signed_store;
515 ojph::ui32 num_bit_depths = 0;
516 ojph::ui32 bit_depth_store[initial_num_comps] = {0, 0, 0, 0};
517 ojph::ui32 *bit_depth = bit_depth_store;
518 ojph::ui32 num_comp_downsamps = 0;
519 ojph::point downsampling_store[initial_num_comps];
520 ojph::point *comp_downsampling = downsampling_store;
521 bool tlm_marker = false;
522 bool tileparts_at_resolutions = false;
523 bool tileparts_at_components = false;
524
525 if (argc <= 1) {
526 std::cout <<
527 "\nThe following arguments are necessary:\n"
528#ifdef OJPH_ENABLE_TIFF_SUPPORT
529 " -i input file name (either pgm, ppm, tif(f), or raw(yuv))\n"
530#else
531 " -i input file name (either pgm, ppm, or raw(yuv))\n"
532#endif // !OJPH_ENABLE_TIFF_SUPPORT
533 " -o output file name\n\n"
534
535 "The following option has a default value (optional):\n"
536 " -num_decomps (5) number of decompositions\n"
537 " -qstep (0.00001...0.5) quantization step size for lossy\n"
538 " compression; quantization steps size for all subbands are\n"
539 " derived from this value. {The default value for 8bit\n"
540 " images is 0.0039}\n"
541 " -reversible (false) for irreversible; this should be false to perform\n"
542 " lossy compression using the 9/7 wavelet transform;\n"
543 " or true to perform reversible compression, where\n"
544 " the 5/3 wavelet is employed with lossless compression.\n"
545 " -colour_trans (true) this option employs a color transform, to\n"
546 " transform RGB color images into the YUV domain.\n"
547 " This option should not be used with YUV images, because\n"
548 " they have already been transformed.\n"
549 " If there are three color components that are\n"
550 " downsampled by the same amount then the color transform\n"
551 " can be true or false. This option is also available\n"
552 " when there are more than three colour components,\n"
553 " where it is applied to the first three colour\n"
554 " components.\n"
555 " it has already been applied to convert the original RGB\n"
556 " or whatever the original format to YUV.\n"
557 " -prog_order (RPCL) is the progression order, and can be one of:\n"
558 " LRCP, RLCP, RPCL, PCRL, CPRL\n"
559 " -block_size {x,y} (64,64) where x and y are the height and width of\n"
560 " a codeblock. In unix-like environment, { and } must be\n"
561 " proceeded by a ""\\""\n"
562 " -precincts {x,y},{x,y},...,{x,y} where {x,y} is the precinct size\n"
563 " starting from the coarest resolution; the last precinct\n"
564 " is repeated for all finer resolutions\n"
565 " -tile_offset {x,y} tile offset. \n"
566 " -tile_size {x,y} tile width and height. \n"
567 " -image_offset {x,y} image offset from origin. \n"
568 " -tileparts (None) employ tilepart divisions at each resolution, \n"
569 " indicated by the letter R, and/or component, indicated \n"
570 " by the letter C. For both, use \"-tileparts RC\".\n"
571 " -tlm_marker (false) insert a TLM marker, either \"true\" or \"false\"\n"
572 " -profile (None) is the profile, the code will check if the \n"
573 " selected options meet the profile. Currently only \n"
574 " BROADCAST and IMF are supported. This automatically \n"
575 " sets tlm_marker to true and tileparts to C.\n"
576 " -com (None) if set, inserts a COM marker with the specified\n"
577 " string. If the string has spaces, please use\n"
578 " double quotes, as in -com \"This is a comment\"\n"
579 "\n"
580
581 "When the input file is a YUV file, these arguments need to be \n"
582 " supplied: \n"
583 " -dims {x,y} x is image width, y is height\n"
584 " -num_comps number of components\n"
585 " -signed a comma-separated list of true or false parameters, one\n"
586 " for each component; for example: true,false,false\n"
587 " -bit_depth a comma-separated list of bit depth values, one per \n"
588 " component; for example: 12,10,10\n"
589 " -downsamp {x,y},{x,y},...,{x,y} a list of x,y points, one for each\n"
590 " component; for example {1,1},{2,2},{2,2}\n\n"
591 ;
592 return -1;
593 }
594 if (!get_arguments(argc, argv, input_filename, output_filename,
595 prog_order, profile_string, num_decompositions,
596 quantization_step, reversible, employ_color_transform,
597 max_precinct_sizes, num_precincts, precinct_size,
598 block_size, dims, image_offset, tile_size, tile_offset,
599 max_num_comps, num_components,
600 num_comp_downsamps, comp_downsampling,
601 num_bit_depths, bit_depth, num_is_signed, is_signed,
602 tlm_marker, tileparts_at_resolutions,
603 tileparts_at_components, com_string))
604 {
605 return -1;
606 }
607
608 clock_t begin = clock();
609
610 try
611 {
612 ojph::codestream codestream;
613
614 ojph::ppm_in ppm;
615 ojph::yuv_in yuv;
616 ojph::raw_in raw;
617 ojph::dpx_in dpx;
618#ifdef OJPH_ENABLE_TIFF_SUPPORT
619 ojph::tif_in tif;
620#endif // !OJPH_ENABLE_TIFF_SUPPORT
621
622 ojph::image_in_base *base = NULL;
623 if (input_filename == NULL)
624 OJPH_ERROR(0x01000007, "please specify an input file name using"
625 " the -i command line option");
626 if (output_filename == NULL)
627 OJPH_ERROR(0x01000008, "please specify an output file name using"
628 " the -o command line option");
629 const char *v = get_file_extension(input_filename);
630
631 if (v)
632 {
633 if (is_matching(".pgm", v))
634 {
635 ppm.open(input_filename);
636 ojph::param_siz siz = codestream.access_siz();
637 siz.set_image_extent(ojph::point(image_offset.x + ppm.get_width(),
638 image_offset.y + ppm.get_height()));
639 ojph::ui32 num_comps = ppm.get_num_components();
640 assert(num_comps == 1);
641 siz.set_num_components(num_comps);
642 for (ojph::ui32 c = 0; c < num_comps; ++c)
644 ppm.get_bit_depth(c), ppm.get_is_signed(c));
645 siz.set_image_offset(image_offset);
646 siz.set_tile_size(tile_size);
647 siz.set_tile_offset(tile_offset);
648
649 ojph::param_cod cod = codestream.access_cod();
650 cod.set_num_decomposition(num_decompositions);
651 cod.set_block_dims(block_size.w, block_size.h);
652 if (num_precincts != -1)
653 cod.set_precinct_size(num_precincts, precinct_size);
654 cod.set_progression_order(prog_order);
655 cod.set_color_transform(false);
656 cod.set_reversible(reversible);
657 if (!reversible && quantization_step != -1.0f)
658 codestream.access_qcd().set_irrev_quant(quantization_step);
659 if (profile_string[0] != '\0')
660 codestream.set_profile(profile_string);
661 codestream.set_tilepart_divisions(tileparts_at_resolutions,
662 tileparts_at_components);
663 codestream.request_tlm_marker(tlm_marker);
664
665 if (employ_color_transform != -1)
666 OJPH_WARN(0x01000001,
667 "-colour_trans option is not needed and was not used\n");
668 if (dims.w != 0 || dims.h != 0)
669 OJPH_WARN(0x01000002,
670 "-dims option is not needed and was not used\n");
671 if (num_components != 0)
672 OJPH_WARN(0x01000003,
673 "-num_comps is not needed and was not used\n");
674 if (is_signed[0] != -1)
675 OJPH_WARN(0x01000004,
676 "-signed is not needed and was not used\n");
677 if (bit_depth[0] != 0)
678 OJPH_WARN(0x01000005,
679 "-bit_depth is not needed and was not used\n");
680 if (comp_downsampling[0].x != 0 || comp_downsampling[0].y != 0)
681 OJPH_WARN(0x01000006,
682 "-downsamp is not needed and was not used\n");
683
684 base = &ppm;
685 }
686 else if (is_matching(".ppm", v))
687 {
688 ppm.open(input_filename);
689 ojph::param_siz siz = codestream.access_siz();
690 siz.set_image_extent(ojph::point(image_offset.x + ppm.get_width(),
691 image_offset.y + ppm.get_height()));
692 ojph::ui32 num_comps = ppm.get_num_components();
693 assert(num_comps == 3);
694 siz.set_num_components(num_comps);
695 for (ojph::ui32 c = 0; c < num_comps; ++c)
697 ppm.get_bit_depth(c), ppm.get_is_signed(c));
698 siz.set_image_offset(image_offset);
699 siz.set_tile_size(tile_size);
700 siz.set_tile_offset(tile_offset);
701
702 ojph::param_cod cod = codestream.access_cod();
703 cod.set_num_decomposition(num_decompositions);
704 cod.set_block_dims(block_size.w, block_size.h);
705 if (num_precincts != -1)
706 cod.set_precinct_size(num_precincts, precinct_size);
707 cod.set_progression_order(prog_order);
708 if (employ_color_transform == -1)
709 cod.set_color_transform(true);
710 else
711 cod.set_color_transform(employ_color_transform == 1);
712 cod.set_reversible(reversible);
713 if (!reversible && quantization_step != -1.0f)
714 codestream.access_qcd().set_irrev_quant(quantization_step);
715 codestream.set_planar(false);
716 if (profile_string[0] != '\0')
717 codestream.set_profile(profile_string);
718 codestream.set_tilepart_divisions(tileparts_at_resolutions,
719 tileparts_at_components);
720 codestream.request_tlm_marker(tlm_marker);
721
722 if (dims.w != 0 || dims.h != 0)
723 OJPH_WARN(0x01000011,
724 "-dims option is not needed and was not used\n");
725 if (num_components != 0)
726 OJPH_WARN(0x01000012,
727 "-num_comps is not needed and was not used\n");
728 if (is_signed[0] != -1)
729 OJPH_WARN(0x01000013,
730 "-signed is not needed and was not used\n");
731 if (bit_depth[0] != 0)
732 OJPH_WARN(0x01000014,
733 "-bit_depth is not needed and was not used\n");
734 if (comp_downsampling[0].x != 0 || comp_downsampling[0].y != 0)
735 OJPH_WARN(0x01000015,
736 "-downsamp is not needed and was not used\n");
737
738 base = &ppm;
739 }
740#ifdef OJPH_ENABLE_TIFF_SUPPORT
741 else if (is_matching(".tif", v) || is_matching(".tiff", v))
742 {
743 tif.open(input_filename);
744 ojph::param_siz siz = codestream.access_siz();
745 siz.set_image_extent(ojph::point(image_offset.x + tif.get_size().w,
746 image_offset.y + tif.get_size().h));
747 ojph::ui32 num_comps = tif.get_num_components();
748 siz.set_num_components(num_comps);
749 if(num_bit_depths > 0 )
750 tif.set_bit_depth(num_bit_depths, bit_depth);
751 for (ojph::ui32 c = 0; c < num_comps; ++c)
752 siz.set_component(c, tif.get_comp_subsampling(c),
753 tif.get_bit_depth(c), tif.get_is_signed(c));
754 siz.set_image_offset(image_offset);
755 siz.set_tile_size(tile_size);
756 siz.set_tile_offset(tile_offset);
757
758 ojph::param_cod cod = codestream.access_cod();
759 cod.set_num_decomposition(num_decompositions);
760 cod.set_block_dims(block_size.w, block_size.h);
761 if (num_precincts != -1)
762 cod.set_precinct_size(num_precincts, precinct_size);
763 cod.set_progression_order(prog_order);
764 if (employ_color_transform == -1 && num_comps >= 3)
765 cod.set_color_transform(true);
766 else
767 cod.set_color_transform(employ_color_transform == 1);
768 cod.set_reversible(reversible);
769 if (!reversible && quantization_step != -1)
770 codestream.access_qcd().set_irrev_quant(quantization_step);
771 codestream.set_planar(false);
772 if (profile_string[0] != '\0')
773 codestream.set_profile(profile_string);
774 codestream.set_tilepart_divisions(tileparts_at_resolutions,
775 tileparts_at_components);
776 codestream.request_tlm_marker(tlm_marker);
777
778 if (dims.w != 0 || dims.h != 0)
779 OJPH_WARN(0x01000061,
780 "-dims option is not needed and was not used\n");
781 if (num_components != 0)
782 OJPH_WARN(0x01000062,
783 "-num_comps is not needed and was not used\n");
784 if (is_signed[0] != -1)
785 OJPH_WARN(0x01000063,
786 "-signed is not needed and was not used\n");
787 if (comp_downsampling[0].x != 0 || comp_downsampling[0].y != 0)
788 OJPH_WARN(0x01000065,
789 "-downsamp is not needed and was not used\n");
790
791 base = &tif;
792 }
793#endif // !OJPH_ENABLE_TIFF_SUPPORT
794 else if (is_matching(".yuv", v))
795 {
796 ojph::param_siz siz = codestream.access_siz();
797 if (dims.w == 0 || dims.h == 0)
798 OJPH_ERROR(0x01000021,
799 "-dims option must have positive dimensions\n");
800 siz.set_image_extent(ojph::point(image_offset.x + dims.w,
801 image_offset.y + dims.h));
802 if (num_components <= 0)
803 OJPH_ERROR(0x01000022,
804 "-num_comps option is missing and must be provided\n");
805 if (num_is_signed <= 0)
806 OJPH_ERROR(0x01000023,
807 "-signed option is missing and must be provided\n");
808 if (num_bit_depths <= 0)
809 OJPH_ERROR(0x01000024,
810 "-bit_depth option is missing and must be provided\n");
811 if (num_comp_downsamps <= 0)
812 OJPH_ERROR(0x01000025,
813 "-downsamp option is missing and must be provided\n");
814
815 yuv.set_img_props(dims, num_components, num_comp_downsamps,
816 comp_downsampling);
817 yuv.set_bit_depth(num_bit_depths, bit_depth);
818
819 ojph::ui32 last_signed_idx = 0, last_bit_depth_idx = 0;
820 ojph::ui32 last_downsamp_idx = 0;
821 siz.set_num_components(num_components);
822 for (ojph::ui32 c = 0; c < num_components; ++c)
823 {
824 ojph::point cp_ds = comp_downsampling
825 [c < num_comp_downsamps ? c : last_downsamp_idx];
826 last_downsamp_idx += last_downsamp_idx+1 < num_comp_downsamps ? 1:0;
827 ojph::ui32 bd = bit_depth[c<num_bit_depths ? c : last_bit_depth_idx];
828 last_bit_depth_idx += last_bit_depth_idx + 1 < num_bit_depths ? 1:0;
829 int is = is_signed[c < num_is_signed ? c : last_signed_idx];
830 last_signed_idx += last_signed_idx + 1 < num_is_signed ? 1 : 0;
831 siz.set_component(c, cp_ds, bd, is == 1);
832 }
833 siz.set_image_offset(image_offset);
834 siz.set_tile_size(tile_size);
835 siz.set_tile_offset(tile_offset);
836
837 ojph::param_cod cod = codestream.access_cod();
838 cod.set_num_decomposition(num_decompositions);
839 cod.set_block_dims(block_size.w, block_size.h);
840 if (num_precincts != -1)
841 cod.set_precinct_size(num_precincts, precinct_size);
842 cod.set_progression_order(prog_order);
843 if (employ_color_transform == -1)
844 cod.set_color_transform(false);
845 else
846 OJPH_ERROR(0x01000031,
847 "We currently do not support color transform on raw(yuv) files."
848 " In any case, this not a normal usage scenario. The OpenJPH "
849 "library however does support that, but ojph_compress.cpp must be "
850 "modified to send all lines from one component before moving to "
851 "the next component; this requires buffering components outside"
852 " of the OpenJPH library");
853 cod.set_reversible(reversible);
854 if (!reversible && quantization_step != -1.0f)
855 codestream.access_qcd().set_irrev_quant(quantization_step);
856 codestream.set_planar(true);
857 if (profile_string[0] != '\0')
858 codestream.set_profile(profile_string);
859 codestream.set_tilepart_divisions(tileparts_at_resolutions,
860 tileparts_at_components);
861 codestream.request_tlm_marker(tlm_marker);
862
863 yuv.open(input_filename);
864 base = &yuv;
865 }
866 else if (is_matching(".raw", v))
867 {
868 ojph::param_siz siz = codestream.access_siz();
869 if (dims.w == 0 || dims.h == 0)
870 OJPH_ERROR(0x01000081,
871 "-dims option must have positive dimensions\n");
872 siz.set_image_extent(ojph::point(image_offset.x + dims.w,
873 image_offset.y + dims.h));
874 if (num_components != 1)
875 OJPH_ERROR(0x01000082,
876 "-num_comps must be 1\n");
877 if (num_is_signed <= 0)
878 OJPH_ERROR(0x01000083,
879 "-signed option is missing and must be provided\n");
880 if (num_bit_depths <= 0)
881 OJPH_ERROR(0x01000084,
882 "-bit_depth option is missing and must be provided\n");
883 if (num_comp_downsamps <= 0)
884 OJPH_ERROR(0x01000085,
885 "-downsamp option is missing and must be provided\n");
886
887 raw.set_img_props(dims, bit_depth[0], is_signed);
888
889 siz.set_num_components(num_components);
890 siz.set_component(0, comp_downsampling[0], bit_depth[0], is_signed[0]);
891 siz.set_image_offset(image_offset);
892 siz.set_tile_size(tile_size);
893 siz.set_tile_offset(tile_offset);
894
895 ojph::param_cod cod = codestream.access_cod();
896 cod.set_num_decomposition(num_decompositions);
897 cod.set_block_dims(block_size.w, block_size.h);
898 if (num_precincts != -1)
899 cod.set_precinct_size(num_precincts, precinct_size);
900 cod.set_progression_order(prog_order);
901 if (employ_color_transform != -1)
902 OJPH_ERROR(0x01000086,
903 "color transform is not meaningless since .raw files are single "
904 "component files");
905 cod.set_reversible(reversible);
906 if (!reversible && quantization_step != -1.0f)
907 codestream.access_qcd().set_irrev_quant(quantization_step);
908 codestream.set_planar(true);
909 if (profile_string[0] != '\0')
910 codestream.set_profile(profile_string);
911 codestream.set_tilepart_divisions(tileparts_at_resolutions,
912 tileparts_at_components);
913 codestream.request_tlm_marker(tlm_marker);
914
915 raw.open(input_filename);
916 base = &raw;
917 }
918 else if (is_matching(".dpx", v))
919 {
920 dpx.open(input_filename);
921 ojph::param_siz siz = codestream.access_siz();
922 siz.set_image_extent(ojph::point(image_offset.x + dpx.get_size().w,
923 image_offset.y + dpx.get_size().h));
924 ojph::ui32 num_comps = dpx.get_num_components();
925 siz.set_num_components(num_comps);
926 //if (num_bit_depths > 0)
927 // dpx.set_bit_depth(num_bit_depths, bit_depth);
928 for (ojph::ui32 c = 0; c < num_comps; ++c)
930 dpx.get_bit_depth(c), dpx.get_is_signed(c));
931 siz.set_image_offset(image_offset);
932 siz.set_tile_size(tile_size);
933 siz.set_tile_offset(tile_offset);
934
935 ojph::param_cod cod = codestream.access_cod();
936 cod.set_num_decomposition(num_decompositions);
937 cod.set_block_dims(block_size.w, block_size.h);
938 if (num_precincts != -1)
939 cod.set_precinct_size(num_precincts, precinct_size);
940 cod.set_progression_order(prog_order);
941 if (employ_color_transform == -1 && num_comps >= 3)
942 cod.set_color_transform(true);
943 else
944 cod.set_color_transform(employ_color_transform == 1);
945 cod.set_reversible(reversible);
946 if (!reversible && quantization_step != -1)
947 codestream.access_qcd().set_irrev_quant(quantization_step);
948 codestream.set_planar(false);
949 if (profile_string[0] != '\0')
950 codestream.set_profile(profile_string);
951 codestream.set_tilepart_divisions(tileparts_at_resolutions,
952 tileparts_at_components);
953 codestream.request_tlm_marker(tlm_marker);
954
955 if (dims.w != 0 || dims.h != 0)
956 OJPH_WARN(0x01000071,
957 "-dims option is not needed and was not used\n");
958 if (num_components != 0)
959 OJPH_WARN(0x01000072,
960 "-num_comps is not needed and was not used\n");
961 if (is_signed[0] != -1)
962 OJPH_WARN(0x01000073,
963 "-signed is not needed and was not used\n");
964 if (comp_downsampling[0].x != 0 || comp_downsampling[0].y != 0)
965 OJPH_WARN(0x01000075,
966 "-downsamp is not needed and was not used\n");
967
968 base = &dpx;
969 }
970 else
971#if defined( OJPH_ENABLE_TIFF_SUPPORT)
972 OJPH_ERROR(0x01000041,
973 "unknown input file extension; only pgm, ppm, dpx, tif(f),"
974 " or raw(yuv) are supported\n");
975#else
976 OJPH_ERROR(0x01000041,
977 "unknown input file extension; only pgm, ppm, dpx,"
978 " or raw(yuv) are supported\n");
979#endif // !OJPH_ENABLE_TIFF_SUPPORT
980 }
981 else
982 OJPH_ERROR(0x01000051,
983 "Please supply a proper input filename with a proper three-letter "
984 "extension\n");
985
987 if (com_string)
988 com_ex.set_string(com_string);
989 ojph::j2c_outfile j2c_file;
990 j2c_file.open(output_filename);
991 codestream.write_headers(&j2c_file, &com_ex, com_string ? 1 : 0);
992
993 ojph::ui32 next_comp;
994 ojph::line_buf* cur_line = codestream.exchange(NULL, next_comp);
995 if (codestream.is_planar())
996 {
997 ojph::param_siz siz = codestream.access_siz();
998 for (ojph::ui32 c = 0; c < siz.get_num_components(); ++c)
999 {
1000 ojph::point p = siz.get_downsampling(c);
1001 ojph::ui32 height = ojph_div_ceil(siz.get_image_extent().y, p.y);
1002 height -= ojph_div_ceil(siz.get_image_offset().y, p.y);
1003 for (ojph::ui32 i = height; i > 0; --i)
1004 {
1005 assert(c == next_comp);
1006 base->read(cur_line, next_comp);
1007 cur_line = codestream.exchange(cur_line, next_comp);
1008 }
1009 }
1010 }
1011 else
1012 {
1013 ojph::param_siz siz = codestream.access_siz();
1014 ojph::ui32 height = siz.get_image_extent().y;
1015 height -= siz.get_image_offset().y;
1016 for (ojph::ui32 i = 0; i < height; ++i)
1017 {
1018 for (ojph::ui32 c = 0; c < siz.get_num_components(); ++c)
1019 {
1020 assert(c == next_comp);
1021 base->read(cur_line, next_comp);
1022 cur_line = codestream.exchange(cur_line, next_comp);
1023 }
1024 }
1025 }
1026
1027 codestream.flush();
1028 codestream.close();
1029 base->close();
1030
1031 if (max_num_comps != initial_num_comps)
1032 {
1033 delete[] comp_downsampling;
1034 delete[] bit_depth;
1035 delete[] is_signed;
1036 }
1037 }
1038 catch (const std::exception& e)
1039 {
1040 const char *p = e.what();
1041 if (strncmp(p, "ojph error", 10) != 0)
1042 printf("%s\n", p);
1043 exit(-1);
1044 }
1045
1046 clock_t end = clock();
1047 double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
1048 printf("Elapsed time = %f\n", elapsed_secs);
1049
1050 return 0;
1051
1052}
bool is_valid()
Definition: ojph_arg.h:58
char * arg
Definition: ojph_arg.h:57
void init(int argc, char *argv[])
Definition: ojph_arg.h:73
void reinterpret_to_bool(const char *str, int &val)
Definition: ojph_arg.h:205
void reinterpret(const char *str, int &val)
Definition: ojph_arg.h:146
argument get_argument_zero()
Definition: ojph_arg.h:126
argument get_next_avail_argument(const argument &arg)
Definition: ojph_arg.h:133
OJPH_EXPORT param_siz access_siz()
OJPH_EXPORT param_cod access_cod()
OJPH_EXPORT void close()
OJPH_EXPORT void set_planar(bool planar)
OJPH_EXPORT line_buf * exchange(line_buf *line, ui32 &next_component)
OJPH_EXPORT void request_tlm_marker(bool needed)
OJPH_EXPORT void set_profile(const char *s)
OJPH_EXPORT param_qcd access_qcd()
OJPH_EXPORT void set_tilepart_divisions(bool at_resolutions, bool at_components)
OJPH_EXPORT void write_headers(outfile_base *file, const comment_exchange *comments=NULL, ui32 num_comments=0)
OJPH_EXPORT bool is_planar() const
OJPH_EXPORT void flush()
OJPH_EXPORT void set_string(char *str)
ui32 get_num_components()
Definition: ojph_img_io.h:284
bool get_is_signed(ui32 comp_num)
Definition: ojph_img_io.h:289
void open(const char *filename)
ui32 get_bit_depth(ui32 comp_num)
Definition: ojph_img_io.h:285
size get_size()
Definition: ojph_img_io.h:283
point get_comp_subsampling(ui32 comp_num)
Definition: ojph_img_io.h:293
virtual void close()
Definition: ojph_img_io.h:71
virtual ui32 read(const line_buf *line, ui32 comp_num)=0
void open(const char *filename)
Definition: ojph_file.cpp:60
OJPH_EXPORT void set_num_decomposition(ui32 num_decompositions)
OJPH_EXPORT void set_precinct_size(int num_levels, size *precinct_size)
OJPH_EXPORT void set_progression_order(const char *name)
OJPH_EXPORT void set_block_dims(ui32 width, ui32 height)
OJPH_EXPORT void set_color_transform(bool color_transform)
OJPH_EXPORT void set_reversible(bool reversible)
OJPH_EXPORT void set_irrev_quant(float delta)
OJPH_EXPORT void set_tile_size(size s)
Definition: ojph_params.cpp:66
OJPH_EXPORT point get_image_extent() const
OJPH_EXPORT void set_component(ui32 comp_num, const point &downsampling, ui32 bit_depth, bool is_signed)
Definition: ojph_params.cpp:93
OJPH_EXPORT void set_num_components(ui32 num_comps)
Definition: ojph_params.cpp:87
OJPH_EXPORT void set_tile_offset(point offset)
Definition: ojph_params.cpp:80
OJPH_EXPORT point get_image_offset() const
OJPH_EXPORT void set_image_offset(point offset)
Definition: ojph_params.cpp:73
OJPH_EXPORT point get_downsampling(ui32 comp_num) const
OJPH_EXPORT void set_image_extent(point extent)
Definition: ojph_params.cpp:59
OJPH_EXPORT ui32 get_num_components() const
ui32 get_height()
Definition: ojph_img_io.h:117
void open(const char *filename)
ui32 get_num_components()
Definition: ojph_img_io.h:119
ui32 get_width()
Definition: ojph_img_io.h:116
ui32 get_bit_depth(ui32 comp_num)
Definition: ojph_img_io.h:120
point get_comp_subsampling(ui32 comp_num)
Definition: ojph_img_io.h:124
bool get_is_signed(ui32 comp_num)
Definition: ojph_img_io.h:122
void set_img_props(const size &s, ui32 bit_depth, bool is_signed)
void open(const char *filename)
void open(const char *filename)
void set_img_props(const size &s, ui32 num_components, ui32 num_downsampling, const point *downsampling)
void set_bit_depth(ui32 num_bit_depths, ui32 *bit_depth)
int32_t si32
Definition: ojph_defs.h:55
uint32_t ui32
Definition: ojph_defs.h:54
int main(int argc, char *argv[])
static const char * get_file_extension(const char *filename)
static bool get_arguments(int argc, char *argv[], char *&input_filename, char *&output_filename, char *&progression_order, char *&profile_string, ojph::ui32 &num_decompositions, float &quantization_step, bool &reversible, int &employ_color_transform, const int max_num_precincts, int &num_precincts, ojph::size *precinct_size, ojph::size &block_size, ojph::size &dims, ojph::point &image_offset, ojph::size &tile_size, ojph::point &tile_offset, ojph::ui32 &max_num_comps, ojph::ui32 &num_comps, ojph::ui32 &num_comp_downsamps, ojph::point *&comp_downsamp, ojph::ui32 &num_bit_depths, ojph::ui32 *&bit_depth, ojph::ui32 &num_is_signed, ojph::si32 *&is_signed, bool &tlm_marker, bool &tileparts_at_resolutions, bool &tileparts_at_components, char *&com_string)
static bool is_matching(const char *ref, const char *other)
#define ojph_div_ceil(a, b)
Definition: ojph_defs.h:70
#define OJPH_ERROR(t,...)
Definition: ojph_message.h:131
#define OJPH_WARN(t,...)
Definition: ojph_message.h:128
ui32 w
Definition: ojph_base.h:50
ui32 h
Definition: ojph_base.h:51
point_interpreter(ojph::point &val)
virtual void operate(const char *str)
ojph::point & val
const ojph::ui32 max_num_eles
virtual void operate(const char *str)
point_list_interpreter(const ojph::ui32 max_num_elements, ojph::ui32 &num_elements, ojph::point *list)
si32_to_bool_list_interpreter(const ojph::ui32 max_num_elements, ojph::ui32 &num_elements, ojph::si32 *list)
virtual void operate(const char *str)
virtual void operate(const char *str)
size_interpreter(ojph::size &val)
ojph::size & val
virtual void operate(const char *str)
size_list_interpreter(const int max_num_elements, int &num_elements, ojph::size *list)
tileparts_division_interpreter(bool &at_resolutions, bool &at_components)
virtual void operate(const char *str)
virtual void operate(const char *str)
ui32_list_interpreter(const ojph::ui32 max_num_elements, ojph::ui32 &num_elements, ojph::ui32 *list)
const ojph::ui32 max_num_eles