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);
93  if (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;
104  int& 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);
151  if (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);
257  if (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 {
275  si32_to_bool_list_interpreter(const ojph::ui32 max_num_elements,
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);
307  if (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 
326 bool 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 
414 const 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 
429 int 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)
568  siz.set_component(c, ppm.get_comp_subsampling(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)
618  siz.set_component(c, ppm.get_comp_subsampling(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)
Definition: ojph_img_io.cpp:90
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[])
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)
const char * get_file_extension(const char *filename)
#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