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
323
324
326bool get_arguments(int argc, char *argv[], char *&input_filename,
327 char *&output_filename, char *&progression_order,
328 char *&profile_string, ojph::ui32 &num_decompositions,
329 float &quantization_step, bool &reversible,
330 int &employ_color_transform,
331 const int max_num_precincts, int &num_precincts,
332 ojph::size *precinct_size, ojph::size& block_size,
333 ojph::size& dims, ojph::point& image_offset,
334 ojph::size& tile_size, ojph::point& tile_offset,
335 ojph::ui32& max_num_comps, ojph::ui32& num_comps,
336 ojph::ui32& num_comp_downsamps, ojph::point*& comp_downsamp,
337 ojph::ui32& num_bit_depths, ojph::ui32*& bit_depth,
338 ojph::ui32& num_is_signed, ojph::si32*& is_signed)
339{
340 ojph::cli_interpreter interpreter;
341 interpreter.init(argc, argv);
342
343 interpreter.reinterpret("-i", input_filename);
344 interpreter.reinterpret("-o", output_filename);
345 interpreter.reinterpret("-prog_order", progression_order);
346 interpreter.reinterpret("-profile", profile_string);
347 interpreter.reinterpret("-num_decomps", num_decompositions);
348 interpreter.reinterpret("-qstep", quantization_step);
349 interpreter.reinterpret("-reversible", reversible);
350 interpreter.reinterpret_to_bool("-colour_trans", employ_color_transform);
351 interpreter.reinterpret("-num_comps", num_comps);
352
353 size_interpreter block_interpreter(block_size);
354 size_interpreter dims_interpreter(dims);
355 size_list_interpreter sizelist(max_num_precincts, num_precincts,
356 precinct_size);
357
358 if (num_comps > 255)
359 throw "more than 255 components is not supported";
360 if (num_comps > max_num_comps)
361 {
362 max_num_comps = num_comps;
363 comp_downsamp = new ojph::point[num_comps];
364 bit_depth = new ojph::ui32[num_comps];
365 is_signed = new ojph::si32[num_comps];
366 for (ojph::ui32 i = 0; i < num_comps; ++i)
367 {
368 comp_downsamp[i] = ojph::point(0, 0);
369 bit_depth[i] = 0;
370 is_signed[i] = -1;
371 }
372 }
373
374 point_list_interpreter pointlist(max_num_comps, num_comp_downsamps,
375 comp_downsamp);
376 ui32_list_interpreter ilist(max_num_comps, num_bit_depths, bit_depth);
377 si32_to_bool_list_interpreter blist(max_num_comps, num_is_signed, is_signed);
378 point_interpreter img_off_interpreter(image_offset);
379 size_interpreter tile_size_interpreter(tile_size);
380 point_interpreter tile_off_interpreter(tile_offset);
381
382 try
383 {
384 interpreter.reinterpret("-block_size", &block_interpreter);
385 interpreter.reinterpret("-dims", &dims_interpreter);
386 interpreter.reinterpret("-image_offset", &img_off_interpreter);
387 interpreter.reinterpret("-tile_size", &tile_size_interpreter);
388 interpreter.reinterpret("-tile_offset", &tile_off_interpreter);
389 interpreter.reinterpret("-precincts", &sizelist);
390 interpreter.reinterpret("-downsamp", &pointlist);
391 interpreter.reinterpret("-bit_depth", &ilist);
392 interpreter.reinterpret("-signed", &blist);
393 }
394 catch (const char *s)
395 {
396 printf("%s\n",s);
397 return false;
398 }
399
400 if (interpreter.is_exhausted() == false) {
401 printf("The following arguments were not interpreted:\n");
402 ojph::argument t = interpreter.get_argument_zero();
403 t = interpreter.get_next_avail_argument(t);
404 while (t.is_valid()) {
405 printf("%s\n", t.arg);
406 t = interpreter.get_next_avail_argument(t);
407 }
408 return false;
409 }
410 return true;
411}
412
414const char* get_file_extension(const char* filename)
415{
416 size_t len = strlen(filename);
417 const char* p = strrchr(filename, '.');
418 if (p == NULL || p == filename + len - 1)
419 OJPH_ERROR(0x01000071,
420 "no file extension is found, or there are no characters "
421 "after the dot \'.\' for filename \"%s\" \n", filename);
422 return p;
423}
424
426// main
428
429int main(int argc, char * argv[]) {
430 char *input_filename = NULL;
431 char *output_filename = NULL;
432 char prog_order_store[] = "RPCL";
433 char *prog_order = prog_order_store;
434 char profile_string_store[] = "";
435 char *profile_string = profile_string_store;
436 ojph::ui32 num_decompositions = 5;
437 float quantization_step = -1.0f;
438 bool reversible = false;
439 int employ_color_transform = -1;
440
441 const int max_precinct_sizes = 33; //maximum number of decompositions is 32
442 ojph::size precinct_size[max_precinct_sizes];
443 int num_precincts = -1;
444
445 ojph::size block_size(64,64);
446 ojph::size dims(0, 0);
447 ojph::size tile_size(0, 0);
448 ojph::point tile_offset(0, 0);
449 ojph::point image_offset(0, 0);
450 const ojph::ui32 initial_num_comps = 4;
451 ojph::ui32 max_num_comps = initial_num_comps;
452 ojph::ui32 num_components = 0;
453 ojph::ui32 num_is_signed = 0;
454 ojph::si32 is_signed_store[initial_num_comps] = {-1, -1, -1, -1};
455 ojph::si32 *is_signed = is_signed_store;
456 ojph::ui32 num_bit_depths = 0;
457 ojph::ui32 bit_depth_store[initial_num_comps] = {0, 0, 0, 0};
458 ojph::ui32 *bit_depth = bit_depth_store;
459 ojph::ui32 num_comp_downsamps = 0;
460 ojph::point downsampling_store[initial_num_comps];
461 ojph::point *comp_downsampling = downsampling_store;
462
463 if (argc <= 1) {
464 std::cout <<
465 "\nThe following arguments are necessary:\n"
466#ifdef OJPH_ENABLE_TIFF_SUPPORT
467 " -i input file name (either pgm, ppm, tif(f), or raw(yuv))\n"
468#else
469 " -i input file name (either pgm, ppm, or raw(yuv))\n"
470#endif // !OJPH_ENABLE_TIFF_SUPPORT
471 " -o output file name\n\n"
472
473 "The following option has a default value (optional):\n"
474 " -num_decomps (5) number of decompositions\n"
475 " -qstep (0.00001...0.5) quantization step size for lossy\n"
476 " compression; quantization steps size for all subbands are\n"
477 " derived from this value. {The default value for 8bit\n"
478 " images is 0.0039}\n"
479 " -reversible (false) for irreversible; this should be false to perform\n"
480 " lossy compression using the 9/7 wavelet transform;\n"
481 " or true to perform reversible compression, where\n"
482 " the 5/3 wavelet is employed with lossless compression.\n"
483 " -colour_trans (true) this option employs a color transform, to\n"
484 " transform RGB color images into the YUV domain.\n"
485 " This option should not be used with YUV images, because\n"
486 " they have already been transformed.\n"
487 " If there are three color components that are\n"
488 " downsampled by the same amount then the color transform\n"
489 " can be true or false. This option is also available\n"
490 " when there are more than three colour components,\n"
491 " where it is applied to the first three colour\n"
492 " components.\n"
493 " it has already been applied to convert the original RGB\n"
494 " or whatever the original format to YUV.\n"
495 " -prog_order (RPCL) is the progression order, and can be one of:\n"
496 " LRCP, RLCP, RPCL, PCRL, CPRL\n"
497 " -block_size {x,y} (64,64) where x and y are the height and width of\n"
498 " a codeblock. In unix-like environment, { and } must be\n"
499 " proceeded by a ""\\""\n"
500 " -precincts {x,y},{x,y},...,{x,y} where {x,y} is the precinct size\n"
501 " starting from the coarest resolution; the last precinct\n"
502 " is repeated for all finer resolutions\n"
503 " -tile_offset {x,y} tile offset. \n"
504 " -tile_size {x,y} tile width and height. \n"
505 " -image_offset {x,y} image offset from origin. \n"
506 " -profile (None) is the profile, the code will check if the \n"
507 " selected options meet the profile. Currently only \n"
508 " BROADCAST and IMF are supported\n"
509 "\n"
510
511 "When the input file is a YUV file, these arguments need to be \n"
512 " supplied: \n"
513 " -dims {x,y} x is image width, y is height\n"
514 " -num_comps number of components\n"
515 " -signed a comma-separated list of true or false parameters, one\n"
516 " for each component; for example: true,false,false\n"
517 " -bit_depth a comma-separated list of bit depth values, one per \n"
518 " component; for example: 12,10,10\n"
519 " -downsamp {x,y},{x,y},...,{x,y} a list of x,y points, one for each\n"
520 " component; for example {1,1},{2,2},{2,2}\n\n"
521 ;
522 return -1;
523 }
524 if (!get_arguments(argc, argv, input_filename, output_filename,
525 prog_order, profile_string, num_decompositions,
526 quantization_step, reversible, employ_color_transform,
527 max_precinct_sizes, num_precincts, precinct_size,
528 block_size, dims, image_offset, tile_size, tile_offset,
529 max_num_comps, num_components,
530 num_comp_downsamps, comp_downsampling,
531 num_bit_depths, bit_depth, num_is_signed, is_signed))
532 {
533 return -1;
534 }
535
536 clock_t begin = clock();
537
538 try
539 {
540 ojph::codestream codestream;
541
542 ojph::ppm_in ppm;
543 ojph::yuv_in yuv;
544#ifdef OJPH_ENABLE_TIFF_SUPPORT
545 ojph::tif_in tif;
546#endif // !OJPH_ENABLE_TIFF_SUPPORT
547 ojph::image_in_base *base = NULL;
548 if (input_filename == NULL)
549 OJPH_ERROR(0x01000007, "please specify an input file name using"
550 " the -i command line option");
551 if (output_filename == NULL)
552 OJPH_ERROR(0x01000008, "please specify an output file name using"
553 " the -o command line option");
554 const char *v = get_file_extension(input_filename);
555
556 if (v)
557 {
558 if (strncmp(".pgm", v, 4) == 0)
559 {
560 ppm.open(input_filename);
561 ojph::param_siz siz = codestream.access_siz();
562 siz.set_image_extent(ojph::point(image_offset.x + ppm.get_width(),
563 image_offset.y + ppm.get_height()));
564 ojph::ui32 num_comps = ppm.get_num_components();
565 assert(num_comps == 1);
566 siz.set_num_components(num_comps);
567 for (ojph::ui32 c = 0; c < num_comps; ++c)
569 ppm.get_bit_depth(c), ppm.get_is_signed(c));
570 siz.set_image_offset(image_offset);
571 siz.set_tile_size(tile_size);
572 siz.set_tile_offset(tile_offset);
573
574 ojph::param_cod cod = codestream.access_cod();
575 cod.set_num_decomposition(num_decompositions);
576 cod.set_block_dims(block_size.w, block_size.h);
577 if (num_precincts != -1)
578 cod.set_precinct_size(num_precincts, precinct_size);
579 cod.set_progression_order(prog_order);
580 cod.set_color_transform(false);
581 cod.set_reversible(reversible);
582 if (!reversible && quantization_step != -1.0f)
583 codestream.access_qcd().set_irrev_quant(quantization_step);
584 if (profile_string[0] != '\0')
585 codestream.set_profile(profile_string);
586
587 if (employ_color_transform != -1)
588 OJPH_WARN(0x01000001,
589 "-colour_trans option is not needed and was not used\n");
590 if (dims.w != 0 || dims.h != 0)
591 OJPH_WARN(0x01000002,
592 "-dims option is not needed and was not used\n");
593 if (num_components != 0)
594 OJPH_WARN(0x01000003,
595 "-num_comps is not needed and was not used\n");
596 if (is_signed[0] != -1)
597 OJPH_WARN(0x01000004,
598 "-signed is not needed and was not used\n");
599 if (bit_depth[0] != 0)
600 OJPH_WARN(0x01000005,
601 "-bit_depth is not needed and was not used\n");
602 if (comp_downsampling[0].x != 0 || comp_downsampling[0].y != 0)
603 OJPH_WARN(0x01000006,
604 "-downsamp is not needed and was not used\n");
605
606 base = &ppm;
607 }
608 else if (strncmp(".ppm", v, 4) == 0)
609 {
610 ppm.open(input_filename);
611 ojph::param_siz siz = codestream.access_siz();
612 siz.set_image_extent(ojph::point(image_offset.x + ppm.get_width(),
613 image_offset.y + ppm.get_height()));
614 ojph::ui32 num_comps = ppm.get_num_components();
615 assert(num_comps == 3);
616 siz.set_num_components(num_comps);
617 for (ojph::ui32 c = 0; c < num_comps; ++c)
619 ppm.get_bit_depth(c), ppm.get_is_signed(c));
620 siz.set_image_offset(image_offset);
621 siz.set_tile_size(tile_size);
622 siz.set_tile_offset(tile_offset);
623
624 ojph::param_cod cod = codestream.access_cod();
625 cod.set_num_decomposition(num_decompositions);
626 cod.set_block_dims(block_size.w, block_size.h);
627 if (num_precincts != -1)
628 cod.set_precinct_size(num_precincts, precinct_size);
629 cod.set_progression_order(prog_order);
630 if (employ_color_transform == -1)
631 cod.set_color_transform(true);
632 else
633 cod.set_color_transform(employ_color_transform == 1);
634 cod.set_reversible(reversible);
635 if (!reversible && quantization_step != -1.0f)
636 codestream.access_qcd().set_irrev_quant(quantization_step);
637 codestream.set_planar(false);
638 if (profile_string[0] != '\0')
639 codestream.set_profile(profile_string);
640
641 if (dims.w != 0 || dims.h != 0)
642 OJPH_WARN(0x01000011,
643 "-dims option is not needed and was not used\n");
644 if (num_components != 0)
645 OJPH_WARN(0x01000012,
646 "-num_comps is not needed and was not used\n");
647 if (is_signed[0] != -1)
648 OJPH_WARN(0x01000013,
649 "-signed is not needed and was not used\n");
650 if (bit_depth[0] != 0)
651 OJPH_WARN(0x01000014,
652 "-bit_depth is not needed and was not used\n");
653 if (comp_downsampling[0].x != 0 || comp_downsampling[0].y != 0)
654 OJPH_WARN(0x01000015,
655 "-downsamp is not needed and was not used\n");
656
657 base = &ppm;
658 }
659#ifdef OJPH_ENABLE_TIFF_SUPPORT
660 else if (strncmp(".tif", v, 4) == 0 || strncmp(".tiff", v, 5) == 0)
661 {
662 tif.open(input_filename);
663 ojph::param_siz siz = codestream.access_siz();
664 siz.set_image_extent(ojph::point(image_offset.x + tif.get_size().w,
665 image_offset.y + tif.get_size().h));
666 ojph::ui32 num_comps = tif.get_num_components();
667 siz.set_num_components(num_comps);
668 if(num_bit_depths > 0 )
669 tif.set_bit_depth(num_bit_depths, bit_depth);
670 for (ojph::ui32 c = 0; c < num_comps; ++c)
671 siz.set_component(c, tif.get_comp_subsampling(c),
672 tif.get_bit_depth(c), tif.get_is_signed(c));
673 siz.set_image_offset(image_offset);
674 siz.set_tile_size(tile_size);
675 siz.set_tile_offset(tile_offset);
676
677 ojph::param_cod cod = codestream.access_cod();
678 cod.set_num_decomposition(num_decompositions);
679 cod.set_block_dims(block_size.w, block_size.h);
680 if (num_precincts != -1)
681 cod.set_precinct_size(num_precincts, precinct_size);
682 cod.set_progression_order(prog_order);
683 if (employ_color_transform == -1 && num_comps >= 3)
684 cod.set_color_transform(true);
685 else
686 cod.set_color_transform(employ_color_transform == 1);
687 cod.set_reversible(reversible);
688 if (!reversible && quantization_step != -1)
689 codestream.access_qcd().set_irrev_quant(quantization_step);
690 codestream.set_planar(false);
691 if (profile_string[0] != '\0')
692 codestream.set_profile(profile_string);
693
694 if (dims.w != 0 || dims.h != 0)
695 OJPH_WARN(0x01000061,
696 "-dims option is not needed and was not used\n");
697 if (num_components != 0)
698 OJPH_WARN(0x01000062,
699 "-num_comps is not needed and was not used\n");
700 if (is_signed[0] != -1)
701 OJPH_WARN(0x01000063,
702 "-signed is not needed and was not used\n");
703 if (comp_downsampling[0].x != 0 || comp_downsampling[0].y != 0)
704 OJPH_WARN(0x01000065,
705 "-downsamp is not needed and was not used\n");
706
707 base = &tif;
708 }
709#endif // !OJPH_ENABLE_TIFF_SUPPORT
710 else if (strncmp(".yuv", v, 4) == 0 || strncmp(".raw", v, 4) == 0)
711 {
712 ojph::param_siz siz = codestream.access_siz();
713 if (dims.w == 0 || dims.h == 0)
714 OJPH_ERROR(0x01000021,
715 "-dims option must have positive dimensions\n");
716 siz.set_image_extent(ojph::point(image_offset.x + dims.w,
717 image_offset.y + dims.h));
718 if (num_components <= 0)
719 OJPH_ERROR(0x01000022,
720 "-num_comps option is missing and must be provided\n");
721 if (num_is_signed <= 0)
722 OJPH_ERROR(0x01000023,
723 "-signed option is missing and must be provided\n");
724 if (num_bit_depths <= 0)
725 OJPH_ERROR(0x01000024,
726 "-bit_depth option is missing and must be provided\n");
727 if (num_comp_downsamps <= 0)
728 OJPH_ERROR(0x01000025,
729 "-downsamp option is missing and must be provided\n");
730
731 yuv.set_img_props(dims, num_components, num_comp_downsamps,
732 comp_downsampling);
733 yuv.set_bit_depth(num_bit_depths, bit_depth);
734
735 ojph::ui32 last_signed_idx = 0, last_bit_depth_idx = 0;
736 ojph::ui32 last_downsamp_idx = 0;
737 siz.set_num_components(num_components);
738 for (ojph::ui32 c = 0; c < num_components; ++c)
739 {
740 ojph::point cp_ds = comp_downsampling
741 [c < num_comp_downsamps ? c : last_downsamp_idx];
742 last_downsamp_idx += last_downsamp_idx+1 < num_comp_downsamps ? 1:0;
743 ojph::ui32 bd = bit_depth[c<num_bit_depths ? c : last_bit_depth_idx];
744 last_bit_depth_idx += last_bit_depth_idx + 1 < num_bit_depths ? 1:0;
745 int is = is_signed[c < num_is_signed ? c : last_signed_idx];
746 last_signed_idx += last_signed_idx + 1 < num_is_signed ? 1 : 0;
747 siz.set_component(c, cp_ds, bd, is == 1);
748 }
749 siz.set_image_offset(image_offset);
750 siz.set_tile_size(tile_size);
751 siz.set_tile_offset(tile_offset);
752
753 ojph::param_cod cod = codestream.access_cod();
754 cod.set_num_decomposition(num_decompositions);
755 cod.set_block_dims(block_size.w, block_size.h);
756 if (num_precincts != -1)
757 cod.set_precinct_size(num_precincts, precinct_size);
758 cod.set_progression_order(prog_order);
759 if (employ_color_transform == -1)
760 cod.set_color_transform(false);
761 else
762 OJPH_ERROR(0x01000031,
763 "We currently do not support color transform on raw(yuv) files."
764 " In any case, this not a normal usage scenario. The OpenJPH "
765 "library however does support that, but ojph_compress.cpp must be "
766 "modified to send all lines from one component before moving to "
767 "the next component; this requires buffering components outside"
768 " of the OpenJPH library");
769 cod.set_reversible(reversible);
770 if (!reversible && quantization_step != -1.0f)
771 codestream.access_qcd().set_irrev_quant(quantization_step);
772 codestream.set_planar(true);
773 if (profile_string[0] != '\0')
774 codestream.set_profile(profile_string);
775
776 yuv.open(input_filename);
777 base = &yuv;
778 }
779 else
780#ifdef OJPH_ENABLE_TIFF_SUPPORT
781 OJPH_ERROR(0x01000041,
782 "unknown input file extension; only pgm, ppm, tif(f), or"
783 " raw(yuv) are supported\n");
784#else
785 OJPH_ERROR(0x01000041,
786 "unknown input file extension; only pgm, ppm, and raw(yuv)) are"
787 " supported\n");
788#endif // !OJPH_ENABLE_TIFF_SUPPORT
789 }
790 else
791 OJPH_ERROR(0x01000051,
792 "Please supply a proper input filename with a proper three-letter "
793 "extension\n");
794
795 ojph::j2c_outfile j2c_file;
796 j2c_file.open(output_filename);
797 codestream.write_headers(&j2c_file);
798
799 ojph::ui32 next_comp;
800 ojph::line_buf* cur_line = codestream.exchange(NULL, next_comp);
801 if (codestream.is_planar())
802 {
803 ojph::param_siz siz = codestream.access_siz();
804 for (ojph::ui32 c = 0; c < siz.get_num_components(); ++c)
805 {
806 ojph::point p = siz.get_downsampling(c);
807 ojph::ui32 height = ojph_div_ceil(siz.get_image_extent().y, p.y);
808 height -= ojph_div_ceil(siz.get_image_offset().y, p.y);
809 for (ojph::ui32 i = height; i > 0; --i)
810 {
811 assert(c == next_comp);
812 base->read(cur_line, next_comp);
813 cur_line = codestream.exchange(cur_line, next_comp);
814 }
815 }
816 }
817 else
818 {
819 ojph::param_siz siz = codestream.access_siz();
820 ojph::ui32 height = siz.get_image_extent().y;
821 height -= siz.get_image_offset().y;
822 for (ojph::ui32 i = 0; i < height; ++i)
823 {
824 for (ojph::ui32 c = 0; c < siz.get_num_components(); ++c)
825 {
826 assert(c == next_comp);
827 base->read(cur_line, next_comp);
828 cur_line = codestream.exchange(cur_line, next_comp);
829 }
830 }
831 }
832
833 codestream.flush();
834 codestream.close();
835 base->close();
836
837 if (max_num_comps != initial_num_comps)
838 {
839 delete[] comp_downsampling;
840 delete[] bit_depth;
841 delete[] is_signed;
842 }
843 }
844 catch (const std::exception& e)
845 {
846 const char *p = e.what();
847 if (strncmp(p, "ojph error", 10) != 0)
848 printf("%s\n", p);
849 exit(-1);
850 }
851
852 clock_t end = clock();
853 double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
854 printf("Elapsed time = %f\n", elapsed_secs);
855
856 return 0;
857
858}
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 set_profile(const char *s)
OJPH_EXPORT void write_headers(outfile_base *file)
OJPH_EXPORT param_qcd access_qcd()
OJPH_EXPORT bool is_planar() const
OJPH_EXPORT void flush()
virtual void close()
Definition: ojph_img_io.h:71
virtual ui32 read(const line_buf *line, ui32 comp_num)=0
OJPH_EXPORT 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 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[])
const char * get_file_extension(const char *filename)
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)
#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)
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