OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimKakaduCompressor.cpp
Go to the documentation of this file.
1 //---
2 //
3 // License: MIT
4 //
5 // Author: David Burken
6 //
7 // Description: Wrapper class to compress whole tiles using kdu_analysis
8 // object.
9 //
10 //---
11 // $Id$
12 
13 #include "ossimKakaduCompressor.h"
14 #include "ossimKakaduCommon.h"
16 #include "ossimKakaduKeywords.h"
17 
19 #include <ossim/base/ossimCommon.h>
21 #include <ossim/base/ossimIpt.h>
24 #include <ossim/base/ossimNotify.h>
28 #include <ossim/base/ossimTrace.h>
29 
32 
36 
37 #include <jp2.h>
38 #include <cmath> /* ceil */
39 
40 RTTI_DEF1_INST(ossimKakaduCompressor, "ossimKakaduCompressor", ossimObject)
41 
42 
43 //---
44 // For trace debugging (to enable at runtime do:
45 // your_app -T "ossimKakaduCompressor:debug" your_app_args
46 //---
47 static ossimTrace traceDebug("ossimKakaduCompressor:debug");
48 
49 static const ossim_int32 DEFAULT_LEVELS = 5;
50 
51 //---
52 // Matches ossimKakaduCompressionQuality enumeration:
53 // EPJE = Exploitation Preferred J2K Encoding
54 //---
55 static const ossimString COMPRESSION_QUALITY[] = { "unknown",
56  "user_defined",
57  "numerically_lossless",
58  "visually_lossless",
59  "lossy",
60  "lossy2",
61  "lossy3",
62  "epje" };
63 
64 static void transfer_bytes(
65  kdu_core::kdu_line_buf &dest, kdu_core::kdu_byte *src,
66  int num_samples, int sample_gap, int src_bits, int original_bits)
67 {
68  if (dest.get_buf16() != 0)
69  {
70  kdu_core::kdu_sample16 *dp = dest.get_buf16();
71  kdu_core::kdu_int16 off = ((kdu_core::kdu_int16)(1<<src_bits))>>1;
72  kdu_core::kdu_int16 mask = ~((kdu_core::kdu_int16)((-1)<<src_bits));
73  if (!dest.is_absolute())
74  {
75  int shift = KDU_FIX_POINT - src_bits; assert(shift >= 0);
76  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
77  dp->ival = ((((kdu_core::kdu_int16) *src) & mask) - off) << shift;
78  }
79  else if (src_bits < original_bits)
80  { // Reversible processing; source buffer has too few bits
81  int shift = original_bits - src_bits;
82  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
83  dp->ival = ((((kdu_core::kdu_int16) *src) & mask) - off) << shift;
84  }
85  else if (src_bits > original_bits)
86  { // Reversible processing; source buffer has too many bits
87  int shift = src_bits - original_bits;
88  off -= (1<<shift)>>1; // For rounded down-shifting
89  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
90  dp->ival = ((((kdu_core::kdu_int16) *src) & mask) - off) >> shift;
91  }
92  else
93  { // Reversible processing, `src_bits'=`original_bits'
94  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
95  dp->ival = (((kdu_core::kdu_int16) *src) & mask) - off;
96  }
97  }
98  else
99  {
100  kdu_core::kdu_sample32 *dp = dest.get_buf32();
101  kdu_core::kdu_int32 off = ((kdu_core::kdu_int32)(1<<src_bits))>>1;
102  kdu_core::kdu_int32 mask = ~((kdu_core::kdu_int32)((-1)<<src_bits));
103  if (!dest.is_absolute())
104  {
105  float scale = 1.0F / (float)(1<<src_bits);
106  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
107  dp->fval = scale * (float)((((kdu_core::kdu_int32) *src) & mask) - off);
108  }
109  else if (src_bits < original_bits)
110  { // Reversible processing; source buffer has too few bits
111  int shift = original_bits - src_bits;
112  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
113  dp->ival = ((((kdu_core::kdu_int32) *src) & mask) - off) << shift;
114  }
115  else if (src_bits > original_bits)
116  { // Reversible processing; source buffer has too many bits
117  int shift = src_bits - original_bits;
118  off -= (1<<shift)>>1; // For rounded down-shifting
119  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
120  dp->ival = ((((kdu_core::kdu_int32) *src) & mask) - off) >> shift;
121  }
122  else
123  { // Reversible processing, `src_bits'=`original_bits'
124  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
125  dp->ival = (((kdu_core::kdu_int32) *src) & mask) - off;
126  }
127  }
128 }
129 
130 static void transfer_words(
131  kdu_core::kdu_line_buf &dest, kdu_core::kdu_int16 *src, int num_samples,
132  int sample_gap, int src_bits, int original_bits,
133  bool is_signed)
134 {
135  if (dest.get_buf16() != 0)
136  {
137  kdu_core::kdu_sample16 *dp = dest.get_buf16();
138  int upshift = 16-src_bits; assert(upshift >= 0);
139  if (!dest.is_absolute())
140  {
141  if (is_signed)
142  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
143  dp->ival = ((*src) << upshift) >> (16-KDU_FIX_POINT);
144  else
145  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
146  dp->ival = (((*src) << upshift) - 0x8000) >> (16-KDU_FIX_POINT);
147  }
148  else
149  {
150  // Reversible processing
151  int downshift = 16-original_bits; assert(downshift >= 0);
152  if (is_signed)
153  {
154  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
155  {
156  dp->ival = ((*src) << upshift) >> downshift;
157  }
158  }
159  else
160  {
161  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
162  {
163  dp->ival = (((*src) << upshift) - 0x8000) >> downshift;
164  }
165  }
166  }
167  }
168  else
169  {
170  kdu_core::kdu_sample32 *dp = dest.get_buf32();
171  int upshift = 32-src_bits; assert(upshift >= 0);
172 
173  if (!dest.is_absolute())
174  {
175  float scale = 1.0F / (((float)(1<<16)) * ((float)(1<<16)));
176  if (is_signed)
177  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
178  dp->fval = scale * (float)(((kdu_core::kdu_int32) *src)<<upshift);
179  else
180  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
181  dp->fval = scale * (float)((((kdu_core::kdu_int32) *src)<<upshift)-(1<<31));
182  }
183  else
184  {
185  int downshift = 32-original_bits; assert(downshift >= 0);
186 
187  if (is_signed)
188  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
189  {
190  dp->ival = (((kdu_core::kdu_int32) *src)<<upshift) >> downshift;
191  }
192  else
193  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
194  dp->ival = ((((kdu_core::kdu_int32) *src)<<upshift)-(1<<31)) >> downshift;
195  }
196  }
197 }
198 
199 void transfer_dwords(kdu_core::kdu_line_buf &dest, kdu_core::kdu_int32 *src,
200  int num_samples, int sample_gap, int src_bits, int original_bits,
201  bool is_signed)
202 {
203  if (dest.get_buf16() != NULL)
204  {
205  kdu_core::kdu_sample16 *dp = dest.get_buf16();
206  int upshift = 32-src_bits; assert(upshift >= 0);
207  if (!dest.is_absolute())
208  {
209  if (is_signed)
210  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
211  dp->ival = (kdu_core::kdu_int16)
212  (((*src) << upshift) >> (32-KDU_FIX_POINT));
213  else
214  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
215  dp->ival = (kdu_core::kdu_int16)
216  ((((*src) << upshift)-0x80000000) >> (32-KDU_FIX_POINT));
217  }
218  else
219  { // Reversible processing
220  int downshift = 32-original_bits; assert(downshift >= 0);
221  if (is_signed)
222  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
223  dp->ival = (kdu_core::kdu_int16)
224  (((*src) << upshift) >> downshift);
225  else
226  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
227  dp->ival = (kdu_core::kdu_int16)
228  ((((*src) << upshift) - 0x80000000) >> downshift);
229  }
230  }
231  else
232  {
233  kdu_core::kdu_sample32 *dp = dest.get_buf32();
234  int upshift = 32-src_bits; assert(upshift >= 0);
235  if (!dest.is_absolute())
236  {
237  float scale = 1.0F / (((float)(1<<16)) * ((float)(1<<16)));
238  if (is_signed)
239  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
240  dp->fval = scale * (float)((*src)<<upshift);
241  else
242  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
243  dp->fval = scale * (float)(((*src)<<upshift)-(1<<31));
244  }
245  else
246  {
247  int downshift = 32-original_bits; assert(downshift >= 0);
248  if (is_signed)
249  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
250  dp->ival = ((*src)<<upshift) >> downshift;
251  else
252  for (; num_samples > 0; num_samples--, src+=sample_gap, dp++)
253  dp->ival = (((*src)<<upshift)-(1<<31)) >> downshift;
254  }
255  }
256 }
257 
258 
259 
261  :
262  ossimObject(),
263  m_target(0),
264  m_jp2FamTgt(0),
265  m_jp2Target(0),
266  m_codestream(),
267  m_threadEnv(0),
268  m_threadQueue(0),
269  m_layerSpecCount(0),
270  m_layerByteSizes(0),
271  m_imageRect(),
272  m_reversible(true),
273  m_alpha(false),
274  m_levels(0),
275  m_threads(1),
276  m_options(),
277  m_qualityType(ossimKakaduCompressor::OKP_NUMERICALLY_LOSSLESS),
278  m_normTile(0)
279 {
280 }
281 
283 {
284  finish();
285 }
286 
288 {
289  return ossimString("ossim kakadu compressor");
290 }
291 
293 {
294  return ossimString("ossimKakaduCompressor");
295 }
296 
297 
299  ossimScalarType scalar,
300  ossim_uint32 bands,
301  const ossimIrect& imageRect,
302  const ossimIpt& tileSize,
303  ossim_uint32 tilesToWrite,
304  bool jp2)
305 {
306  static const char MODULE[] = "ossimKakaduCompressor::create";
307  if ( traceDebug() )
308  {
309  ossimNotify(ossimNotifyLevel_WARN) << MODULE << " entered...\n";
310  }
311 
312 #if 0 /* Please leave for debug. (drb) */
313  cout << "levels: " << m_levels
314  << "\nreversible: " << m_reversible
315  << "\nthreads: " << m_threads
316  << "\nscalar: " << scalar
317  << "\nbands: " << bands
318  << "\nimageRect: " << imageRect
319  << "\ntileSize: " << tileSize
320  << "\njp2: " << jp2
321  << endl;
322 #endif
323 
324  // In case we were reused.
325  finish();
326 
327  if ( !os )
328  {
329  std::string errMsg = MODULE;
330  errMsg += " ERROR: Null stream passed to method!";
331  throw ossimException(errMsg);
332  }
333 
334  if ( !os->good() )
335  {
336  std::string errMsg = MODULE;
337  errMsg += " ERROR: Stream state has error!";
338  throw ossimException(errMsg);
339  }
340 
341  if ( ossim::getActualBitsPerPixel(scalar) > 31 )
342  {
343  // Data is not reversible.
344  if ( m_reversible )
345  {
346  std::string errMsg = MODULE;
347  errMsg += " ERROR: Reversible processing not possible with 32 bit data!";
348  throw ossimException(errMsg);
349  }
350 
351  // Create a tile for normalization.
352  m_normTile = new ossimImageData(0,
354  bands,
355  static_cast<ossim_uint32>(tileSize.x),
356  static_cast<ossim_uint32>(tileSize.y));
358  }
359 
360  // Store for tile clip.
361  m_imageRect = imageRect;
362 
364  m_target->setStream(os);
365 
366  if (jp2)
367  {
368  //---
369  // Note the jp2_family_tgt and the jp2_target classes merely store
370  // the target and do not delete on close or destroy.
371  //---
372  m_jp2FamTgt = new kdu_supp::jp2_family_tgt();
373  m_jp2FamTgt->open(m_target);
374  m_jp2Target = new kdu_supp::jp2_target();
375  m_jp2Target->open(m_jp2FamTgt);
376  }
377 
378  if (m_alpha)
379  {
380  if ( (bands != 1) && (bands != 3) )
381  {
382  m_alpha = false;
383  // if ( traceDebug() )
384  {
386  << "Alpha channel being unset! Can only be used with "
387  << "one or three band data.\n"
388  << "Source image bands: " << bands << "\n";
389  }
390  }
391  }
392 
393  kdu_core::siz_params siz;
394 
395  // Set the number of components adding in alpha if set.
396  siz.set(Scomponents, 0, 0, static_cast<ossim_int32>( (m_alpha?bands+1:bands) ) );
397 
398  // Set the verical size.
399  siz.set(Ssize, 0, 0, static_cast<ossim_int32>(imageRect.height()));
400  siz.set(Sdims, 0, 0, static_cast<ossim_int32>(imageRect.height()));
401 
402  // Set the horizontal size.
403  siz.set(Ssize, 0, 1, static_cast<ossim_int32>(imageRect.width()));
404  siz.set(Sdims, 0, 1, static_cast<ossim_int32>(imageRect.width()));
405 
406  // Set the tile verical size.
407  siz.set(Stiles, 0, 0, tileSize.y);
408 
409  // Set the tile horizontal size.
410  siz.set(Stiles, 0, 1, tileSize.x);
411 
412  // Set the signed bit.
413  siz.set(Ssigned, 0, 0, ossim::isSigned(scalar));
414 
415  // Set the precision bits.
416  siz.set(Sprecision, 0, 0,
417  static_cast<ossim_int32>(ossim::getActualBitsPerPixel(scalar)) );
418 
419  siz.finalize_all();
420 
421  // Set up threads:
422  m_threadEnv = new kdu_core::kdu_thread_env();
423  m_threadEnv->create();
424  if ( m_threads == 1 )
425  {
426  // Look in prefs for threads:
427  const char* lookup = ossimPreferences::instance()->findPreference("kakadu_threads");
428  if ( lookup )
429  {
431  }
432  }
433  if ( m_threads > 1 )
434  {
435  for (int nt=1; nt < m_threads; ++nt)
436  {
437  if ( !m_threadEnv->add_thread() )
438  {
439  if (traceDebug())
440  {
442  << "Unable to create thread!\n";
443  }
444  }
445  }
446  }
447 
448  m_threadQueue = m_threadEnv->add_queue(0, 0, "tile-compressor-root");
449 
450  kdu_supp::jp2_dimensions dims;
451 
452  if (jp2)
453  {
454  //---
455  // Configure jp2 header attributes jp2_dimensions', `
456  // jp2_colour', `jp2_channels', etc.) as appropriate.
457  //---
458 
459  //---
460  // Set dimensional information
461  // (all redundant with the SIZ marker segment)
462  //---
463  dims = m_jp2Target->access_dimensions();
464  dims.init(&siz);
465 
466  //---
467  // Set colour space information (mandatory)
468  // Since JP2 can only describe one and three band data if not three
469  // band we will use the first channel only.
470  //----
471  kdu_supp::jp2_colour colour = m_jp2Target->access_colour();
472  if (bands == 3)
473  {
474  colour.init( kdu_supp::JP2_sRGB_SPACE );
475  }
476  else
477  {
478  colour.init( kdu_supp::JP2_sLUM_SPACE );
479  }
480 
481  //---
482  // Set the channel mapping. See note on colour space.
483  //---
484  int num_colours = static_cast<int>( (bands==3)?bands:1 );
485  kdu_supp::jp2_channels channels = m_jp2Target->access_channels();
486  channels.init(num_colours);
487  for (int c=0; c < num_colours; ++c)
488  {
489  channels.set_colour_mapping(c,c);
490  }
491 
492  if (m_alpha)
493  {
494  if (bands == 1)
495  {
496  channels.set_opacity_mapping(0,1);
497  }
498  else if (bands == 3)
499  {
500  channels.set_opacity_mapping(0,3);
501  channels.set_opacity_mapping(1,3);
502  channels.set_opacity_mapping(2,3);
503  }
504  }
505 
506  m_codestream.create(&siz, m_jp2Target, 0, 0, 0, m_threadEnv);
507  }
508  else // Not a jp2
509  {
510  m_codestream.create(&siz, m_target, 0, 0, 0, m_threadEnv);
511  }
512 
513  // Requests the insertion of TLM (tile-part-length) marker.
514  setTlmTileCount(tilesToWrite);
515 
516  //---
517  // Set up coding defaults.
518  //---
519  kdu_core::kdu_params* cod = m_codestream.access_siz()->access_cluster(COD_params);
520  if (cod)
521  {
522  initializeCodingParams(cod, imageRect);
523  }
524 
525 
526  // Set options if any.
527  std::vector<ossimString>::const_iterator optionIter = m_options.begin();
528  while ( optionIter != m_options.end() )
529  {
530  m_codestream.access_siz()->parse_string( (*optionIter).c_str() );
531  ++optionIter;
532  }
533 
534  // Finalize preparation for compression
535  m_codestream.access_siz()->finalize_all();
536 
537  if (jp2)
538  {
539  // Call `write_header' to write the JP2 header.
540  m_jp2Target->write_header();
541  m_jp2Target->close();
542 
543  // Write out the geotiff_box:
544  // writeGeotffBox(m_jp2Target);
545 
546  //---
547  // Optionally write additional boxes, opening them using the base
548  // object's
549  // `jp2_output_box::open_next' function, writing their contents (or
550  // sub-boxes) and closing them using `jp2_output_box::close'.
551  //---
552  }
553 
554  if ( traceDebug() )
555  {
556  ossimNotify(ossimNotifyLevel_WARN) << MODULE << " exiting...\n";
557  }
558 }
559 
561 {
562  if (m_jp2Target)
563 
564  {
565  //---
566  // Call `open_codestream' prior to any call to
567  // `kdu_codestream::flush'.
568  //---
569  m_jp2Target->open_codestream(true);
570  }
571 }
572 
574 {
575  bool result = true;
576 
577  if (srcTile.getDataObjectStatus() != OSSIM_NULL)
578  {
579  // tile samples:
580  const ossim_int32 TILE_SAMPS =
581  static_cast<ossim_int32>(srcTile.getWidth());
582 
583  // Samples to copy clipping to image width:
584  const ossim_int32 SAMPS =
585  ossim::min(TILE_SAMPS, m_imageRect.lr().x-srcTile.getOrigin().x+1);
586 
587  // tile lines:
588  const ossim_int32 TILE_LINES =
589  static_cast<ossim_int32>(srcTile.getHeight());
590 
591  // Lines to copy:
592  const ossim_int32 LINES =
593  ossim::min(TILE_LINES, m_imageRect.lr().y-srcTile.getOrigin().y+1);
594 
595  // Get the tile index.
596  kdu_core::kdu_coords tileIndex;
597  tileIndex.x = (srcTile.getOrigin().x - m_imageRect.ul().x) / TILE_SAMPS;
598  tileIndex.y = (srcTile.getOrigin().y - m_imageRect.ul().y) / TILE_LINES;
599 
600  kdu_core::kdu_tile tile = m_codestream.open_tile(tileIndex);
601 
602  kdu_core::kdu_dims tile_dims;
603  m_codestream.get_tile_dims(tileIndex, 0, tile_dims);
604 
605  if ( tile.exists() )
606  {
607  // Bands:
608  const ossim_int32 BANDS =
609  static_cast<ossim_int32>(m_alpha?srcTile.getNumberOfBands()+1:
610  srcTile.getNumberOfBands());
611  tile.set_components_of_interest(BANDS);
612 
613  // Scalar:
614  const ossimScalarType SCALAR = srcTile.getScalarType();
615 
616  // Signed:
617  const bool SIGNED = ossim::isSigned(SCALAR);
618 
619  // Set up common things to both scalars.
620  std::vector<kdu_core::kdu_push_ifc> engine(BANDS);
621  std::vector<kdu_core::kdu_line_buf> lineBuf(BANDS);
622 
623  // Precision:
624  ossim_int32 src_bits = ossim::getActualBitsPerPixel(SCALAR);
625 
626  std::vector<ossim_int32> original_bits(BANDS);
627 
628  // Initialize tile-components
629  kdu_core::kdu_tile_comp tc;
630  kdu_core::kdu_resolution res;
631  bool reversible;
632  bool use_shorts;
633  kdu_core::kdu_sample_allocator allocator;
634 
635  ossim_int32 band;
636  for (band = 0; band < BANDS; ++band)
637  {
638  original_bits[band] = m_codestream.get_bit_depth(band,true);
639 
640  tc = tile.access_component(band);
641  res = tc.access_resolution();
642  if ( ossim::getActualBitsPerPixel(SCALAR) > 31 )
643  {
644  // Data is not reversible.
645  reversible = false;
646  use_shorts = false;
647  }
648  else
649  {
650  reversible = tc.get_reversible();
651  use_shorts = (tc.get_bit_depth(true) <= 16);
652  }
653 
654  res.get_dims(tile_dims);
655 
656  engine[band] = kdu_core::kdu_analysis(res,
657  &allocator,
658  use_shorts,
659  1.0F,
660  0,
661  m_threadEnv,
662  m_threadQueue);
663 
664  lineBuf[band].pre_create(&allocator,
665  SAMPS,
666  reversible, // tmp drb
667  use_shorts,
668  0, // extend_left
669  0); // extend_right
670  }
671 
672  // Complete sample buffer allocation
673  allocator.finalize( m_codestream );
674 
675  for (band = 0; band < BANDS; ++band)
676  {
677  lineBuf[band].create();
678  }
679 
680  switch (SCALAR)
681  {
682  case OSSIM_UINT8:
683  {
684  std::vector<kdu_core::kdu_byte*> srcBuf(BANDS);
685  for (band = 0; band < BANDS; ++band)
686  {
687  void* p = const_cast<void*>(srcTile.getBuf(band));
688  srcBuf[band] = static_cast<kdu_core::kdu_byte*>(p);
689  }
690  if (m_alpha)
691  {
692  // Ugly casting...
693  const void* cp =
694  static_cast<const void*>(srcTile.getAlphaBuf());
695  void* p = const_cast<void*>(cp);
696  srcBuf[BANDS-1] = static_cast<kdu_core::kdu_byte*>(p);
697  }
698  for (ossim_int32 line = 0; line < LINES; ++line)
699  {
700  for (band = 0; band < BANDS; ++band)
701  {
702  transfer_bytes(lineBuf[band],
703  srcBuf[band],
704  SAMPS,
705  1,
706  src_bits,
707  original_bits[band]);
708 
709  engine[band].push(lineBuf[band], m_threadEnv);
710 
711  // Increment the line buffers.
712  srcBuf[band] = srcBuf[band]+TILE_SAMPS;
713  }
714  }
715  break;
716  }
717  case OSSIM_UINT11:
718  case OSSIM_UINT12:
719  case OSSIM_UINT13:
720  case OSSIM_UINT14:
721  case OSSIM_UINT15:
722  case OSSIM_UINT16:
723  {
724  if (!m_alpha)
725  {
726  std::vector<kdu_core::kdu_int16*> srcBuf(BANDS);
727  for (band = 0; band < BANDS; ++band)
728  {
729  void* p = const_cast<void*>(srcTile.getBuf(band));
730  srcBuf[band] = static_cast<kdu_core::kdu_int16*>(p);
731  }
732 
733  for (ossim_int32 line = 0; line < LINES; ++line)
734  {
735  for (band = 0; band < BANDS; ++band)
736  {
737  transfer_words(lineBuf[band],
738  srcBuf[band],
739  SAMPS,
740  1,
741  src_bits,
742  original_bits[band],
743  SIGNED);
744 
745  engine[band].push(lineBuf[band], m_threadEnv);
746 
747  // Increment the line buffers.
748  srcBuf[band] = srcBuf[band]+TILE_SAMPS;
749  }
750  }
751  }
752  else // Need to write an alpha channel.
753  {
754  //---
755  // Alpha currently stored a eight bit so we must move 255 to
756  // 2047 (11 bit) or 255 to 65535 for 16 bit.
757  //---
758  const ossim_float64 SCALAR_MAX = ossim::defaultMax( SCALAR );
759  ossim_float64 d = SCALAR_MAX / 255.0;
760 
761  ossim_int32 dataBands = BANDS-1;
762  std::vector<kdu_core::kdu_int16*> srcBuf(dataBands);
763  for (band = 0; band < dataBands; ++band)
764  {
765  void* p = const_cast<void*>(srcTile.getBuf(band));
766  srcBuf[band] = static_cast<kdu_core::kdu_int16*>(p);
767  }
768 
769  const ossim_uint8* alphaPtr = srcTile.getAlphaBuf();;
770  std::vector<kdu_core::kdu_int16> alphaLine(SAMPS);
771 
772  for (ossim_int32 line = 0; line < LINES; ++line)
773  {
774  for (band = 0; band < dataBands; ++band)
775  {
776  transfer_words(lineBuf[band],
777  srcBuf[band],
778  SAMPS,
779  1,
780  src_bits,
781  original_bits[band],
782  SIGNED);
783 
784  engine[band].push(lineBuf[band], m_threadEnv);
785 
786  // Increment the line buffers.
787  srcBuf[band] = srcBuf[band]+TILE_SAMPS;
788  }
789 
790  // Transfer alpha channel:
791  for (ossim_int32 samp = 0; samp < SAMPS; ++samp)
792  {
793  alphaLine[samp] = static_cast<kdu_core::kdu_int16>(alphaPtr[samp]*d);
794  }
795 
796  transfer_words(lineBuf[band],
797  &alphaLine.front(),
798  SAMPS,
799  1,
800  src_bits,
801  original_bits[band],
802  SIGNED);
803 
804  engine[band].push(lineBuf[band], m_threadEnv);
805 
806  alphaPtr = alphaPtr+TILE_SAMPS;
807  }
808  } // End of alpha section.
809  break;
810  }
811  case OSSIM_SINT16:
812  {
813  std::vector<ossim_sint16*> srcBuf(BANDS);
814  for (band = 0; band < BANDS; ++band)
815  {
816  void* p = const_cast<void*>(srcTile.getBuf(band));
817  srcBuf[band] = static_cast<ossim_sint16*>(p);
818  }
819 
820  for (ossim_int32 line = 0; line < LINES; ++line)
821  {
822  for (band = 0; band < BANDS; ++band)
823  {
824  transfer_words(lineBuf[band],
825  srcBuf[band],
826  SAMPS,
827  1,
828  src_bits,
829  original_bits[band],
830  SIGNED);
831 
832  engine[band].push(lineBuf[band], m_threadEnv);
833 
834  // Increment the line buffers.
835  srcBuf[band] = srcBuf[band]+TILE_SAMPS;
836  }
837  }
838  break;
839  }
840 
841  //---
842  // ??? This should probably take the same path as OSSIM_SINT32 data.
843  // Need test case.
844  //---
845  case OSSIM_UINT32:
846  {
847  std::vector<kdu_core::kdu_int32*> srcBuf(BANDS);
848  for (band = 0; band < BANDS; ++band)
849  {
850  void* p = const_cast<void*>(srcTile.getBuf(band));
851  srcBuf[band] = static_cast<kdu_core::kdu_int32*>(p);
852  }
853 
854  for (ossim_int32 line = 0; line < LINES; ++line)
855  {
856  for (band = 0; band < BANDS; ++band)
857  {
858  transfer_dwords(lineBuf[band],
859  srcBuf[band],
860  SAMPS,
861  1,
862  src_bits,
863  original_bits[band],
864  SIGNED);
865 
866  engine[band].push(lineBuf[band], m_threadEnv);
867 
868  // Increment the line buffers.
869  srcBuf[band] = srcBuf[band]+TILE_SAMPS;
870  }
871  }
872  break;
873  }
874 
875  case OSSIM_SINT32:
876  case OSSIM_FLOAT32:
877  {
878  //---
879  // Kakadu wants float data normalized between -0.5 and 0.5:
880  // 1) Normalize between 0.0 and 1.0 using ossim code.
881  // 2) Copy applying -0.5 offset.
882  //---
884 
885  std::vector<ossim_float32*> srcBuf(BANDS);
886  for (band = 0; band < BANDS; ++band)
887  {
888  srcBuf[band] = m_normTile->getFloatBuf(band);
889  }
890 
891  for (ossim_int32 line = 0; line < LINES; ++line)
892  {
893  for (band = 0; band < BANDS; ++band)
894  {
895  kdu_core::kdu_sample32* dp = lineBuf[band].get_buf32();
896  for (ossim_int32 samp = 0; samp < SAMPS; ++samp)
897  {
898  dp[samp].fval = srcBuf[band][samp] - 0.5; // -.5 for kakadu.
899  }
900  engine[band].push(lineBuf[band], m_threadEnv);
901 
902  // Increment the line buffers.
903  srcBuf[band] = srcBuf[band]+TILE_SAMPS;
904  }
905  }
906  break;
907  }
908  default:
909  {
911  << __FILE__ << " " << __LINE__ << " Unhandle scalar!\n";
912  result = false;
913  break;
914  }
915 
916  } // End: switch(scalar)
917 
918  if (m_threadEnv)
919  {
920  // m_threadEnv->synchronize(m_threadQueue);
921 
922  //---
923  // Snip from kdu_threads.h:
924  // If `descendants_only' is true, the function waits for all queues
925  // descended from `root_queue' to identify themselves as "finished"
926  // via the `kdu_thread_queue::all_done' function.
927  //---
929  true); // descendants_only flag
930  }
931 
932  for (band = 0; band < BANDS; ++band)
933  {
934  engine[band].destroy();
935  lineBuf[band].destroy();
936  }
937  tile.close();
938  allocator.restart();
939 
940  // Done with tile flush it...
941  m_codestream.flush( &(m_layerByteSizes.front()), // layerbytes,
942  m_layerSpecCount, // num_layer_specs
943  0, // layer_thresholds
944  true, // trim_to_rate
945  true, // record_in_comseg
946  0.0, // tolerence,
947  m_threadEnv); // env
948 
949  } // if (tile.exists())
950  else
951  {
952  result = false;
953  }
954  }
955  else // srcTile has null status...
956  {
957  result = false;
958  }
959 
960  return result;
961 
962 } // End: ossimKakaduCompressor::writeTile
963 
965 {
966  // Kakadu kdu_thread_entity::terminate throws exceptions...
967  try
968  {
969  // Cleanup processing environment
970  if ( m_threadEnv )
971  {
972  m_threadEnv->join(NULL,true); // Wait until all internal processing is complete.
973  m_threadEnv->terminate(m_threadQueue, true);
974  m_threadEnv->cs_terminate(m_codestream); // Terminates background codestream processing.
975 
976  // kdu_codestream::destroy causing "double free or corruption" exception.
977  // m_codestream.destroy();
978 
979  m_threadEnv->destroy();
980  delete m_threadEnv;
981  m_threadEnv = 0;
982  }
983 
984  m_normTile = 0;
985 
986  if (m_threadQueue)
987  {
988  m_threadQueue = 0;
989  }
990 
991  if (m_jp2FamTgt)
992  {
993  delete m_jp2FamTgt;
994  m_jp2FamTgt = 0;
995  }
996 
997  if (m_jp2Target)
998  {
999  delete m_jp2Target;
1000  m_jp2Target = 0;
1001  }
1002 
1003  if (m_target)
1004  {
1005  delete m_target;
1006  m_target = 0;
1007  }
1008  }
1009  catch ( kdu_core::kdu_exception exc )
1010  {
1011  // kdu_exception is an int typedef.
1012  if ( m_threadEnv != 0 )
1013  {
1014  m_threadEnv->handle_exception(exc);
1015  }
1016  ostringstream e;
1017  e << "ossimKakaduNitfReader::~ossimKakaduNitfReader\n"
1018  << "Caught exception from kdu_region_decompressor: " << exc << "\n";
1019  ossimNotify(ossimNotifyLevel_WARN) << e.str() << std::endl;
1020  }
1021  catch ( std::bad_alloc& )
1022  {
1023  if ( m_threadEnv != 0 )
1024  {
1025  m_threadEnv->handle_exception(KDU_MEMORY_EXCEPTION);
1026  }
1027  std::string e =
1028  "Caught exception from kdu_region_decompressor: std::bad_alloc";
1029  ossimNotify(ossimNotifyLevel_WARN) << e << std::endl;
1030  }
1031  catch( ... )
1032  {
1033  std::string e =
1034  "Caught unhandled exception from kdu_region_decompressor";
1035  ossimNotify(ossimNotifyLevel_WARN) << e << std::endl;
1036  }
1037 
1038  m_layerByteSizes.clear();
1039 }
1040 
1042 {
1043  m_qualityType = type;
1044 
1045  //---
1046  // Set the reversible flag for appropriate type.
1047  // Not sure what to set for unknown and user defined but visually lossless
1048  // and lossy need to set the reversible flag to false.
1049  //---
1053  {
1054  setReversibleFlag(false);
1055  }
1056  else
1057  {
1058  setReversibleFlag(true);
1059  }
1060 }
1061 
1063 {
1064  return m_qualityType;
1065 
1066 }
1067 
1069 {
1070  m_reversible = reversible;
1071 }
1072 
1074 {
1075  return m_reversible;
1076 }
1077 
1079 {
1080  m_alpha = flag;
1081 }
1082 
1084 {
1085  return m_alpha;
1086 }
1087 
1089 {
1090  if (levels)
1091  {
1092  m_levels = levels;
1093  }
1094 }
1095 
1097 {
1098  return m_levels;
1099 }
1100 
1102 {
1103  if (threads)
1104  {
1105  m_threads = threads;
1106  }
1107 }
1108 
1110 {
1111  return m_threads;
1112 }
1113 
1114 void ossimKakaduCompressor::setOptions(const std::vector<ossimString>& options)
1115 {
1116  std::vector<ossimString>::const_iterator i = options.begin();
1117  while ( i != options.end() )
1118  {
1119  m_options.push_back( (*i) );
1120  ++i;
1121  }
1122 }
1123 
1125 {
1126  bool consumed = false;
1127 
1128  if ( property.valid() )
1129  {
1130  ossimString key = property->getName();
1131 
1132  if ( traceDebug() )
1133  {
1135  << "ossimKakaduCompressor::setProperty DEBUG:"
1136  << "\nkey: " << key
1137  << " values: " << property->valueToString() << std::endl;
1138  }
1139 
1141  {
1142  setQualityTypeString(property->valueToString());
1143  consumed = true;
1144  }
1145  else if ( (key == LEVELS_KW) || (key == "Clevels") )
1146  {
1147  m_levels = property->valueToString().toInt32();
1148  consumed = true;
1149  }
1150  else if( (key == REVERSIBLE_KW) || (key == "Creversible") )
1151  {
1152  setReversibleFlag(property->valueToString().toBool());
1153  consumed = true;
1154  }
1155  else if (key == ADD_ALPHA_CHANNEL_KW)
1156  {
1157  m_alpha = property->valueToString().toBool();
1158  consumed = true;
1159  }
1160  else if ( key == THREADS_KW)
1161  {
1162  m_threads = property->valueToString().toInt32();
1163  consumed = true;
1164  }
1165  else if ( (key == "Clayers") ||
1166  (key == "Cprecincts") )
1167  {
1168  // Generic options passed through kdu_params::parse_string.
1169 
1170  // Make in the form of "key=value" for kdu_params::parse_string.
1171  ossimString option = key;
1172  option += "=";
1173  option += property->valueToString();
1174 
1175  // Add to list.
1176  m_options.push_back(option);
1177 
1178  consumed = true;
1179  }
1180  }
1181 
1182  return consumed;
1183 }
1184 
1186  const ossimString& name)const
1187 {
1189 
1191  {
1192  // property value
1194 
1195  if ( (value == COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_USER_DEFINED] ) ||
1196  (value == COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_UNKNOWN])
1197  )
1198  {
1199  value = COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_NUMERICALLY_LOSSLESS];
1200  }
1201 
1202  // constraint list
1203  vector<ossimString> constraintList;
1204  constraintList.push_back(
1206  constraintList.push_back(
1207  COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_VISUALLY_LOSSLESS]);
1208  constraintList.push_back(
1209  COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_LOSSY]);
1210  constraintList.push_back(
1211  COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_LOSSY2]);
1212  constraintList.push_back(
1213  COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_LOSSY3]);
1214  constraintList.push_back(
1215  COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_EPJE]);
1216 
1217  p = new ossimStringProperty(name,
1218  value,
1219  false, // not editable
1220  constraintList);
1221  }
1222  else if (name == LEVELS_KW)
1223  {
1225  }
1226  else if (name == REVERSIBLE_KW)
1227  {
1228  p = new ossimBooleanProperty(name, m_reversible);
1229  }
1230  else if (name == ADD_ALPHA_CHANNEL_KW)
1231  {
1232  p = new ossimBooleanProperty(name, m_alpha);
1233  }
1234  else if (name == THREADS_KW)
1235  {
1237  }
1238 
1239  return p;
1240 }
1241 
1243  std::vector<ossimString>& propertyNames)const
1244 {
1245  propertyNames.push_back(ossimKeywordNames::COMPRESSION_QUALITY_KW);
1246  propertyNames.push_back(LEVELS_KW);
1247  propertyNames.push_back(REVERSIBLE_KW);
1248  propertyNames.push_back(THREADS_KW);
1249 }
1250 
1252  const char* prefix)const
1253 {
1254  kwl.add( prefix,
1256  getQualityTypeString().c_str(),
1257  true );
1258 
1259  kwl.add( prefix,
1260  LEVELS_KW,
1262  true );
1263 
1264  kwl.add( prefix,
1265  REVERSIBLE_KW,
1267  true );
1268 
1269  kwl.add( prefix,
1270  ADD_ALPHA_CHANNEL_KW,
1272  true );
1273 
1274  kwl.add( prefix,
1275  THREADS_KW,
1277  true );
1278 
1279  std::vector<ossimString>::size_type size = m_options.size();
1280  for (ossim_uint32 i = 0; i < size; ++i)
1281  {
1282  ossimString key = "option";
1283  key += ossimString::toString(i);
1284 
1285  kwl.add( prefix,
1286  key.c_str(),
1287  m_options[i].c_str(),
1288  true );
1289  }
1290 
1291  return true;
1292 }
1293 
1295  const char* prefix)
1296 {
1297  const char* value = 0;
1298 
1299  value = kwl.find(prefix, ossimKeywordNames::COMPRESSION_QUALITY_KW);
1300  if(value)
1301  {
1303  }
1304 
1305  value = kwl.find(prefix, LEVELS_KW);
1306  if(value)
1307  {
1308  m_levels = ossimString(value).toInt32();
1309  }
1310 
1311  value = kwl.find(prefix, REVERSIBLE_KW);
1312  if(value)
1313  {
1314  setReversibleFlag(ossimString(value).toBool());
1315  }
1316 
1317  value = kwl.find(prefix, ADD_ALPHA_CHANNEL_KW);
1318  if(value)
1319  {
1320  m_alpha = ossimString(value).toBool();
1321  }
1322 
1323  value = kwl.find(prefix, THREADS_KW);
1324  if(value)
1325  {
1326  m_threads = ossimString(value).toInt32();
1327  }
1328 
1329  ossimString searchKey;
1330  if (prefix)
1331  {
1332  searchKey = prefix;
1333  }
1334  searchKey += "option";
1335  ossim_uint32 nOptions = kwl.numberOf(searchKey);
1336  for (ossim_uint32 i = 0; i < nOptions; ++i)
1337  {
1338  ossimString key = searchKey;
1339  key += ossimString::toString(i);
1340 
1341  const char* lookup = kwl.find(key.c_str());
1342  if (lookup)
1343  {
1344  m_options.push_back(ossimString(lookup));
1345  }
1346  }
1347 
1348  return true;
1349 }
1350 
1352  const ossimIrect& rect,
1353  const ossimFilename& tmpFile,
1354  ossimPixelType pixelType)
1355 {
1356  bool result = false;
1357 
1358  if ( geom && m_jp2Target )
1359  {
1362  if ( proj.valid() )
1363  {
1364  //---
1365  // Make a temp file. No means currently write a tiff straight to
1366  // memory.
1367  //---
1368 
1369  // Buffer to hold the tiff box.
1370  std::vector<ossim_uint8> buf;
1371 
1372  // Write to buffer.
1373  if ( ossimGeoTiff::writeJp2GeotiffBox(tmpFile,
1374  rect,
1375  proj.get(),
1376  buf,
1377  pixelType) )
1378  {
1379  //---
1380  // JP2 box type uuid in ascii expressed as an int.
1381  // "u(75), u(75), i(69), d(64"
1382  //---
1383  const ossim_uint32 UUID_TYPE = 0x75756964;
1384 
1385  // Write to a box on the JP2 file.
1386  m_jp2Target->open_next( UUID_TYPE );
1387  m_jp2Target->write(
1388  static_cast<kdu_core::kdu_byte*>(&buf.front()), static_cast<int>(buf.size()));
1389  m_jp2Target->close();
1390  result = true;
1391  }
1392  }
1393  }
1394 
1395  return result;
1396 
1397 } // End: ossimKakaduCompressor::writeGeotiffBox
1398 
1400  const ossimIrect& rect )
1401 {
1402  bool result = false;
1403 
1404  if ( geom && m_jp2Target )
1405  {
1407  if ( gml->initialize( geom, rect ) )
1408  {
1409  // Write the xml to a stream.
1410  ostringstream xmlStr;
1411  if ( gml->write( xmlStr ) )
1412  {
1413  const ossim_uint8 ASOC_BOX_ID[4] =
1414  {
1415  0x61, 0x73, 0x6F, 0x63
1416  };
1417 
1418  const ossim_uint8 LBL_BOX_ID[4] =
1419  {
1420  0x6C, 0x62, 0x6C, 0x20
1421  };
1422 
1423  const ossim_uint8 XML_BOX_ID[4] =
1424  {
1425  0x78, 0x6D, 0x6C, 0x20
1426  };
1427 
1428  ossim_uint32 xmlDataSize = xmlStr.str().size();
1429 
1430  // Set the 1st asoc box size and type
1431  ossim_uint32 boxSize = xmlDataSize + 17 + 8 + 8 + 8 + 8 + 8 + 8;
1433  {
1434  ossimEndian endian;
1435  endian.swap( boxSize );
1436  }
1437 
1438  const ossim_uint32 ASOC_BOX = 0x61736f63;
1439 
1440  m_jp2Target->open_next( ASOC_BOX );
1441 
1442  //m_jp2Target->close();
1443  //m_jp2Target->write( (const kdu_core::kdu_byte*)&boxSize, 4); // 1st asoc size
1444  // m_jp2Target->write( (const kdu_core::kdu_byte*)ASOC_BOX_ID, 4); // 1st asoc type
1445 
1446  // Set the 1st lbl box size, type, and data
1447  boxSize = 8 + 8;
1449  {
1450  ossimEndian endian;
1451  endian.swap( boxSize );
1452  }
1453 
1454  m_jp2Target->write((kdu_core::kdu_byte*)&boxSize, 4); // 1st lbl size
1455  m_jp2Target->write((const kdu_core::kdu_byte*)LBL_BOX_ID, 4); // 1st lbl type
1456  m_jp2Target->write((const kdu_core::kdu_byte*)"gml.data", 8); // 1st lbl data
1457 
1458  // Set the 2nd asoc box size and type
1459  boxSize = xmlDataSize + 17 + 8 + 8 + 8;
1461  {
1462  ossimEndian endian;
1463  endian.swap( boxSize );
1464  }
1465  m_jp2Target->write((kdu_core::kdu_byte*)&boxSize, 4); // 2nd asoc size
1466  m_jp2Target->write((const kdu_core::kdu_byte*)ASOC_BOX_ID, 4); // 2nd asoc type
1467 
1468  // Set the 2nd lbl box size, type, and data
1469  boxSize = 17 + 8;
1471  {
1472  ossimEndian endian;
1473  endian.swap( boxSize );
1474  }
1475  m_jp2Target->write((kdu_core::kdu_byte*)&boxSize, 4); // 2nd lbl size
1476  m_jp2Target->write((const kdu_core::kdu_byte*)LBL_BOX_ID, 4); // 2nd lbl type
1477  m_jp2Target->write((const kdu_core::kdu_byte*)"gml.root-instance", 17); // 2nd lbl data
1478 
1479  // Set the xml box size, type, and data
1480  boxSize = xmlDataSize + 8;
1482  {
1483  ossimEndian endian;
1484  endian.swap( boxSize );
1485  }
1486  m_jp2Target->write((kdu_core::kdu_byte*)&boxSize, 4); // xml size
1487  m_jp2Target->write((const kdu_core::kdu_byte*)XML_BOX_ID, 4); // xml type
1488  m_jp2Target->write((const kdu_core::kdu_byte*)xmlStr.str().data(),
1489  xmlDataSize); // xml data
1490 
1491  m_jp2Target->close();
1492  result = true;
1493  }
1494  }
1495 
1496  // cleanup:
1497  delete gml;
1498  gml = 0;
1499 
1500  } // if ( geom && m_jp2Target )
1501 
1502  return result;
1503 
1504 } // End: ossimKakaduCompressor::writeGmlBox
1505 
1507  ossim_uint32 actualBitsPerPixel ) const
1508 {
1509  if ( j2klraTag )
1510  {
1511  j2klraTag->setOrigin(0);
1512  j2klraTag->setLevelsO( (ossim_uint32)m_levels );
1513  // bands set in writer.
1514  j2klraTag->setLayersO( (ossim_uint32)m_layerSpecCount );
1515 
1516  const ossim_float64 TP = m_imageRect.area();
1517  if ( TP )
1518  {
1519  for (ossim_uint32 id = 0; id < (ossim_uint32)m_layerSpecCount; ++id)
1520  {
1521  j2klraTag->setLayerId( id, id);
1522 
1523  if ( m_layerByteSizes[id] != KDU_LONG_MAX )
1524  {
1525  j2klraTag->setLayerBitRate(
1526  id, ( m_layerByteSizes[id] / (TP * 0.125) ) );
1527  }
1528  else
1529  {
1530  //---
1531  // KDU_LONG_MAX indicates that the final quality layer should
1532  // include all compressed bits. (abpp=actuall bits per pixel)
1533  //---
1534  j2klraTag->setLayerBitRate( id, actualBitsPerPixel );
1535  }
1536  }
1537  }
1538  }
1539 }
1540 
1541 void ossimKakaduCompressor::initializeCodingParams(kdu_core::kdu_params* cod,
1542  const ossimIrect& imageRect)
1543 {
1544  static const char MODULE[] = "ossimKakaduCompressor::initializeCodingParams";
1545 
1546  if ( traceDebug() )
1547  {
1548  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
1549  }
1550 
1551  if (cod)
1552  {
1553  // No ycc.
1554  cod->set(Cycc, 0, 0, false);
1555 
1556  // Set the number of levels
1557  setLevels(cod, imageRect, m_levels);
1558 
1559  // Set the block size. Note 64x64 is the current kakadu default.
1560  setCodeBlockSize(cod, 64, 64);
1561 
1562  //---
1563  // Set the compression order. Note LRCP is the current kakadu default.
1564  // L=layer; R=resolution C=component; P=position
1565  //---
1566  if ( m_qualityType != OKP_EPJE )
1567  {
1568  setProgressionOrder(cod, Corder_LRCP);
1569  }
1570  else
1571  {
1572  setProgressionOrder(cod, Corder_RLCP);
1573  }
1574 
1575  // total pixels
1576  const ossim_float64 TP = imageRect.area();
1577 
1578  if ( traceDebug() )
1579  {
1581  << "quality type: " << getQualityTypeString() << endl;
1582  }
1583 
1584  //---
1585  // Rate is a ratio of desired bytes / total bytes. So if you
1586  // want 4 bits per pixels it's total_pixels * 4 / 8 or
1587  // total_pixels * 4 * 0.125.
1588  //---
1589 
1590  switch (m_qualityType)
1591  {
1594  {
1595  setReversibleFlag(true);
1596 
1597  setWaveletKernel(cod, Ckernels_W5X3);
1598 
1599  m_layerSpecCount = 20;
1601 
1602  m_layerByteSizes[0] =
1603  static_cast<kdu_core::kdu_long>(std::ceil( TP * 0.03125 * 0.125 ));
1604  m_layerByteSizes[1] =
1605  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.0625* 0.125 ));
1606  m_layerByteSizes[2] =
1607  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.125* 0.125 ));
1608  m_layerByteSizes[3] =
1609  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.25* 0.125 ));
1610  m_layerByteSizes[4] =
1611  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.5* 0.125 ));
1612  m_layerByteSizes[5] =
1613  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.6* 0.125 ));
1614  m_layerByteSizes[6] =
1615  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.7* 0.125 ));
1616  m_layerByteSizes[7] =
1617  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.8* 0.125 ));
1618  m_layerByteSizes[8] =
1619  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.9* 0.125 ));
1620  m_layerByteSizes[9] =
1621  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.0* 0.125 ));
1622  m_layerByteSizes[10] =
1623  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.1* 0.125 ));
1624  m_layerByteSizes[11] =
1625  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.2* 0.125 ));
1626  m_layerByteSizes[12] =
1627  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.3* 0.125 ));
1628  m_layerByteSizes[13] =
1629  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.5* 0.125 ));
1630  m_layerByteSizes[14] =
1631  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.7* 0.125 ));
1632  m_layerByteSizes[15] =
1633  static_cast<kdu_core::kdu_long>(std::ceil(TP * 2.0* 0.125 ));
1634  m_layerByteSizes[16] =
1635  static_cast<kdu_core::kdu_long>(std::ceil(TP * 2.3* 0.125 ));
1636  m_layerByteSizes[17] =
1637  static_cast<kdu_core::kdu_long>(std::ceil(TP * 2.8* 0.125 ));
1638  m_layerByteSizes[18] =
1639  static_cast<kdu_core::kdu_long>(std::ceil(TP * 3.5* 0.125 ));
1640 
1641  //---
1642  // Indicate that the final quality layer should include all
1643  // compressed bits.
1644  //---
1645  m_layerByteSizes[19] = KDU_LONG_MAX;
1646 
1647  break;
1648  }
1650  {
1651  setReversibleFlag(false);
1652 
1653  setWaveletKernel(cod, Ckernels_W9X7);
1654 
1655  m_layerSpecCount = 19;
1657  m_layerByteSizes[0] =
1658  static_cast<kdu_core::kdu_long>(std::ceil( TP * 0.03125 * 0.125 ));
1659  m_layerByteSizes[1] =
1660  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.0625* 0.125 ));
1661  m_layerByteSizes[2] =
1662  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.125* 0.125 ));
1663  m_layerByteSizes[3] =
1664  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.25* 0.125 ));
1665  m_layerByteSizes[4] =
1666  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.5* 0.125 ));
1667  m_layerByteSizes[5] =
1668  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.6* 0.125 ));
1669  m_layerByteSizes[6] =
1670  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.7* 0.125 ));
1671  m_layerByteSizes[7] =
1672  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.8* 0.125 ));
1673  m_layerByteSizes[8] =
1674  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.9* 0.125 ));
1675  m_layerByteSizes[9] =
1676  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.0* 0.125 ));
1677  m_layerByteSizes[10] =
1678  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.1* 0.125 ));
1679  m_layerByteSizes[11] =
1680  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.2* 0.125 ));
1681  m_layerByteSizes[12] =
1682  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.3* 0.125 ));
1683  m_layerByteSizes[13] =
1684  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.5* 0.125 ));
1685  m_layerByteSizes[14] =
1686  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.7* 0.125 ));
1687  m_layerByteSizes[15] =
1688  static_cast<kdu_core::kdu_long>(std::ceil(TP * 2.0* 0.125 ));
1689  m_layerByteSizes[16] =
1690  static_cast<kdu_core::kdu_long>(std::ceil(TP * 2.3* 0.125 ));
1691  m_layerByteSizes[17] =
1692  static_cast<kdu_core::kdu_long>(std::ceil(TP * 2.8* 0.125 ));
1693  m_layerByteSizes[18] =
1694  static_cast<kdu_core::kdu_long>(std::ceil(TP * 3.5* 0.125 ));
1695  break;
1696  }
1697 #if 0
1699  {
1700  //---
1701  // Exploitation Preferred J2K Encoding(EPJE):
1702  // This is currently the same as VISUALLY_LOSSLESS but making
1703  // separate code block as I anticipate tweaking this.
1704  // drb - 16 Mar. 2016
1705  //---
1706  setReversibleFlag(false);
1707 
1708  setWaveletKernel(cod, Ckernels_W9X7);
1709 
1710  m_layerSpecCount = 19;
1712  m_layerByteSizes[0] =
1713  static_cast<kdu_core::kdu_long>(std::ceil( TP * 0.03125 * 0.125 ));
1714  m_layerByteSizes[1] =
1715  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.0625* 0.125 ));
1716  m_layerByteSizes[2] =
1717  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.125* 0.125 ));
1718  m_layerByteSizes[3] =
1719  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.25* 0.125 ));
1720  m_layerByteSizes[4] =
1721  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.5* 0.125 ));
1722  m_layerByteSizes[5] =
1723  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.6* 0.125 ));
1724  m_layerByteSizes[6] =
1725  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.7* 0.125 ));
1726  m_layerByteSizes[7] =
1727  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.8* 0.125 ));
1728  m_layerByteSizes[8] =
1729  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.9* 0.125 ));
1730  m_layerByteSizes[9] =
1731  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.0* 0.125 ));
1732  m_layerByteSizes[10] =
1733  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.1* 0.125 ));
1734  m_layerByteSizes[11] =
1735  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.2* 0.125 ));
1736  m_layerByteSizes[12] =
1737  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.3* 0.125 ));
1738  m_layerByteSizes[13] =
1739  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.5* 0.125 ));
1740  m_layerByteSizes[14] =
1741  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.7* 0.125 ));
1742  m_layerByteSizes[15] =
1743  static_cast<kdu_core::kdu_long>(std::ceil(TP * 2.0* 0.125 ));
1744  m_layerByteSizes[16] =
1745  static_cast<kdu_core::kdu_long>(std::ceil(TP * 2.3* 0.125 ));
1746  m_layerByteSizes[17] =
1747  static_cast<kdu_core::kdu_long>(std::ceil(TP * 2.8* 0.125 ));
1748  m_layerByteSizes[18] =
1749  static_cast<kdu_core::kdu_long>(std::ceil(TP * 3.5* 0.125 ));
1750  break;
1751  }
1752 #endif
1754  {
1755  setReversibleFlag(false);
1756 
1757  setWaveletKernel(cod, Ckernels_W9X7);
1758 
1759  m_layerSpecCount = 10;
1761 
1762  m_layerByteSizes[0] =
1763  static_cast<kdu_core::kdu_long>(std::ceil( TP * 0.03125 * 0.125 ));
1764  m_layerByteSizes[1] =
1765  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.0625* 0.125 ));
1766  m_layerByteSizes[2] =
1767  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.125* 0.125 ));
1768  m_layerByteSizes[3] =
1769  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.25* 0.125 ));
1770  m_layerByteSizes[4] =
1771  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.5* 0.125 ));
1772  m_layerByteSizes[5] =
1773  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.6* 0.125 ));
1774  m_layerByteSizes[6] =
1775  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.7* 0.125 ));
1776  m_layerByteSizes[7] =
1777  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.8* 0.125 ));
1778  m_layerByteSizes[8] =
1779  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.9* 0.125 ));
1780  m_layerByteSizes[9] =
1781  static_cast<kdu_core::kdu_long>(std::ceil(TP * 1.0* 0.125 ));
1782  break;
1783  }
1784 
1786  {
1787  setReversibleFlag(false);
1788 
1789  setWaveletKernel(cod, Ckernels_W9X7);
1790 
1791  m_layerSpecCount = 5;
1793 
1794  m_layerByteSizes[0] =
1795  static_cast<kdu_core::kdu_long>(std::ceil( TP * 0.03125 * 0.125 ));
1796  m_layerByteSizes[1] =
1797  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.0625 * 0.125 ));
1798  m_layerByteSizes[2] =
1799  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.125 * 0.125 ));
1800  m_layerByteSizes[3] =
1801  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.25 * 0.125 ));
1802  m_layerByteSizes[4] =
1803  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.5 * 0.125 ));
1804  break;
1805  }
1806 
1808  {
1809  setReversibleFlag(false);
1810 
1811  setWaveletKernel(cod, Ckernels_W9X7);
1812 
1813  m_layerSpecCount = 4;
1815 
1816  m_layerByteSizes[0] =
1817  static_cast<kdu_core::kdu_long>(std::ceil( TP * 0.03125 * 0.125 ));
1818  m_layerByteSizes[1] =
1819  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.0625 * 0.125 ));
1820  m_layerByteSizes[2] =
1821  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.125 * 0.125 ));
1822  m_layerByteSizes[3] =
1823  static_cast<kdu_core::kdu_long>(std::ceil(TP * 0.25 * 0.125 ));
1824  break;
1825  }
1826 
1827  default:
1828  {
1829  m_layerSpecCount = 1;
1831  m_layerByteSizes[0] = 0;
1832 
1834  << MODULE << "unhandled compression_quality type! Valid types:\n";
1836  }
1837 
1838  } // matches: switch (m_qualityType)
1839 
1840  //---
1841  // Set reversible flag, note, this controls the kernel.
1842  // W5X3(default) if reversible = true, W9X7 if reversible is false.
1843  //---
1844  cod->set(Creversible, 0, 0, m_reversible);
1845 
1846  // Set the quality layers.
1848 
1849  if ( traceDebug() )
1850  {
1852  << "reversible: " << m_reversible
1853  << "\nLevels: " << m_levels
1854  << "\nLayers: " << m_layerSpecCount;
1855  for (int n = 0; n < m_layerSpecCount; ++n)
1856  {
1858  << "\nsize: " << m_layerByteSizes[n];
1859  }
1860  ossimNotify(ossimNotifyLevel_DEBUG) << std::endl;
1861  }
1862 
1863 
1864  } // matches: if (cod)
1865 
1866  if ( traceDebug() )
1867  {
1868  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " exited...\n";
1869  }
1870 }
1871 
1873 {
1874  return m_layerSpecCount;
1875 }
1876 
1878 {
1879  return COMPRESSION_QUALITY[m_qualityType];
1880 }
1881 
1883 {
1884  ossimString type = s;
1885  type.downcase();
1886 
1887  if ( type == COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_UNKNOWN] )
1888  {
1890  }
1891  else if ( type == COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_USER_DEFINED] )
1892  {
1894  }
1895  else if ( type == COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_NUMERICALLY_LOSSLESS] )
1896  {
1898  }
1899  else if ( type == COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_VISUALLY_LOSSLESS] )
1900  {
1902  }
1903  else if (type == "lossy")
1904  {
1906  }
1907  else if (type == "lossy2")
1908  {
1910  }
1911  else if (type == "lossy3")
1912  {
1914  }
1915  else if (type == "epje")
1916  {
1918  }
1919  else
1920  {
1922  << "ossimKakaduCompressor::setQualityTypeString WARNING"
1923  << "\nUnhandled compression_quality type: " << type
1924  << "\n";
1926  }
1927 }
1928 
1929 void ossimKakaduCompressor::setLevels(kdu_core::kdu_params* cod,
1930  const ossimIrect& imageRect,
1931  ossim_int32 levels)
1932 {
1933  //---
1934  // Number of wavelet decomposition levels, or stages. May not exceed 32.
1935  // Default is 5
1936  //---
1937  if (cod)
1938  {
1939  if (levels == 0)
1940  {
1941  levels = (ossim_int32)ossim::computeLevels(imageRect);
1942  if (levels == 0)
1943  {
1944  levels = 1; // Must have at least one.
1945  }
1946  }
1947  if ( (levels < 1) || (levels > 32) )
1948  {
1949  levels = 5;
1950  }
1951  cod->set(Clevels, 0, 0, levels);
1952 
1953  // Set the class attribute:
1954  setLevels(levels);
1955  }
1956 }
1957 
1958 void ossimKakaduCompressor::setCodeBlockSize(kdu_core::kdu_params* cod,
1959  ossim_int32 xSize,
1960  ossim_int32 ySize)
1961 {
1962  //---
1963  // Nominal code-block dimensions (must be powers of 2 no less than 4 and
1964  // no greater than 1024).
1965  // Default block dimensions are {64,64}
1966  //---
1967  if (cod)
1968  {
1969  cod->set(Cblk,0,0,ySize);
1970  cod->set(Cblk,0,1,xSize);
1971  }
1972 }
1973 
1974 void ossimKakaduCompressor::setProgressionOrder(kdu_core::kdu_params* cod,
1975  ossim_int32 corder)
1976 {
1977  //---
1978  // Default progression order (may be overridden by Porder).
1979  // The four character identifiers have the following interpretation:
1980  // L=layer; R=resolution; C=component; P=position.
1981  // The first character in the identifier refers to the index which
1982  // progresses most slowly, while the last refers to the index which
1983  // progresses most quickly. [Default is LRCP]
1984  // Enumerations: (LRCP=0,RLCP=1,RPCL=2,PCRL=3,CPRL=4)
1985  //---
1986  if (cod)
1987  {
1988  if ( (corder < 0) || (corder > 5) )
1989  {
1990  corder = Corder_LRCP;
1991  }
1992  cod->set(Corder,0,0,corder);
1993  }
1994 }
1995 
1996 void ossimKakaduCompressor::setWaveletKernel(kdu_core::kdu_params* cod,
1997  ossim_int32 kernel)
1998 {
1999  //---
2000  // Wavelet kernels to use. The special value, `ATK' means that an ATK
2001  // (Arbitrary Transform Kernel) marker segment is used to store the DWT
2002  // kernel. In this case, the `Catk' attribute must be non-zero.
2003  // [Default is W5X3 if `Creversible' is true, W9X7 if `Creversible' is
2004  // false, and ATK if `Catk' is non-zero.
2005  // Enumerations: (W9X7=0,W5X3=1,ATK=-1)
2006  //---
2007  if (cod)
2008  {
2009  if ( (kernel < -1) || (kernel > 1) )
2010  {
2011  if ( m_reversible )
2012  {
2013  kernel = Ckernels_W5X3;
2014  }
2015  else
2016  {
2017  kernel = Ckernels_W9X7;
2018  }
2019  }
2020  cod->set(Ckernels,0,0,kernel);
2021  }
2022 }
2023 
2024 void ossimKakaduCompressor::setQualityLayers(kdu_core::kdu_params* cod,
2025  ossim_int32 layers)
2026 {
2027  //---
2028  // Number of quality layers. May not exceed 16384. Kakadu default is 1.
2029  //---
2030  if (cod)
2031  {
2032  if ( (layers < 1) || (layers > 16384) )
2033  {
2034  layers = 1;
2035  }
2036  cod->set(Clayers,0,0,layers);
2037  }
2038 }
2039 
2041 {
2042  //---
2043  // Identifies the maximum number of tile-parts which will be written to the
2044  // code-stream for each tile.
2045  //
2046  // See Kakadu kdu_params.h "Macro = `ORGgen_tlm'" for more.
2047  //---
2048  ossimString s = "ORGgen_tlm=1";
2049  m_codestream.access_siz()->parse_string( s.c_str() );
2050 }
2051 
2053 {
2054  out << "compression_quality="
2055  << COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_NUMERICALLY_LOSSLESS]
2056  << "\ncompression_quality="
2057  << COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_VISUALLY_LOSSLESS]
2058  << "\ncompression_quality="
2059  << COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_LOSSY]
2060  << "\ncompression_quality="
2061  << COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_LOSSY2]
2062  << "\ncompression_quality="
2063  << COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_LOSSY3]
2064  << "\ncompression_quality="
2065  << COMPRESSION_QUALITY[ossimKakaduCompressor::OKP_EPJE]
2066  << "\n";
2067 }
virtual void valueToString(ossimString &valueResult) const =0
virtual ossim_uint32 getWidth() const
void setQualityLayers(kdu_core::kdu_params *cod, ossim_int32 layers)
Sets the number of quality layers.
virtual void create(ossim::ostream *os, ossimScalarType scalar, ossim_uint32 bands, const ossimIrect &imageRect, const ossimIpt &tileSize, ossim_uint32 tilesToWrite, bool jp2)
Create method.
OSSIM_DLL ossim_uint32 computeLevels(const ossimIrect &rect)
Computes the number of decimation levels to get to the overview stop dimension.
bool m_reversible
Lossless or lossy.
void setReversibleFlag(bool reversible)
Sets the m_reversible flag.
16 bit unsigned integer (12 bits used)
ossim_uint32 numberOf(const char *str) const
std::basic_ostringstream< char > ostringstream
Class for char output memory streams.
Definition: ossimIosFwd.h:35
virtual ossim_uint32 getNumberOfBands() const
16 bit unsigned integer
virtual void setLevels(ossim_int32 levels)
Sets the number of levels.
Represents serializable keyword/value map.
ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
void initialize(ossimNitfJ2klraTag *j2klraTag, ossim_uint32 actualBitsPerPixel) const
Initializes the tag.
bool writeGmlBox(const ossimImageGeometry *geom, const ossimIrect &rect)
Writes the GML box to the jp2.
bool valid() const
Definition: ossimRefPtr.h:75
const char * find(const char *key) const
virtual void finish()
Finish method.
16 bit unsigned integer (14 bits used)
void setQualityTypeString(const ossimString &s)
bool setOrigin(ossim_uint32 origin)
Sets origin:
virtual ossimString getLongName() const
std::vector< ossimString > m_options
Container for kakadu options to pass to kdu_params::parse_string.
ossim_uint32 height() const
Definition: ossimIrect.h:487
virtual ~ossimKakaduCompressor()
destructor
static ossimString toString(bool aValue)
Numeric to string methods.
16 bit signed integer
const ossimIpt & ul() const
Definition: ossimIrect.h:274
void setStream(std::ostream *stream)
Sets the output stream.
virtual ossimDataObjectStatus getDataObjectStatus() const
bool m_alpha
If true write alpha channel.
virtual ossim_uint32 getHeight() const
OSSIM_DLL ossimByteOrder byteOrder()
Definition: ossimCommon.cpp:54
OSSIM_DLL ossim_uint32 getActualBitsPerPixel(ossimScalarType scalarType)
Get actual bits per pixel for a given scalar type.
ossim_uint32 toUInt32() const
16 bit unsigned integer (13 bits used)
32 bit floating point
32 bit unsigned integer
virtual void initialize()
Initialize the data buffer.
bool write(std::ostream &os)
Write xml doc to stream.
void getPropertyNames(std::vector< ossimString > &propertyNames) const
Pushes this&#39;s names onto the list of property names.
std::vector< kdu_core::kdu_long > m_layerByteSizes
Layer sizes provided in &#39;flush&#39; calls.
ossim_int32 toInt32() const
GML support data class.
void push_back(char c)
Equivalent to insert(end(), c).
Definition: ossimString.h:905
double ossim_float64
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
#define RTTI_DEF1_INST(cls, name, b1)
Definition: ossimRtti.h:481
virtual ossimString getClassName() const
ossimRefPtr< ossimImageData > m_normTile
tile to use for normalized float data.
bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
saves the state of the object.
OSSIM_DLL bool isSigned(ossimScalarType scalarType)
void setProgressionOrder(kdu_core::kdu_params *cod, ossim_int32 corder)
Sets progression order.
const char * findPreference(const char *key) const
yy_size_t size
void setWaveletKernel(kdu_core::kdu_params *cod, ossim_int32 kernel)
Sets the wavelet kernel to use.
signed short ossim_sint16
os2<< "> n<< " > nendobj n
void setThreads(ossim_int32 threads)
Sets the number of threads.
ossimKakaduCompressor()
default constructor
static bool writeJp2GeotiffBox(const ossimFilename &tmpFile, const ossimIrect &rect, const ossimProjection *proj, std::vector< ossim_uint8 > &buf, ossimPixelType pixelType)
Writes a geotiff box to a buffer.
kdu_supp::jp2_target * m_jp2Target
32 bit signed integer
bool toBool() const
String to numeric methods.
kdu_core::kdu_thread_env * m_threadEnv
unsigned int ossim_uint32
32 bit normalized floating point
ossim_int32 m_levels
Reduced resolution levels.
void openJp2Codestream()
Calls "open_codestream" on the m_jp2Target.
bool setLayerBitRate(ossim_uint32 index, ossim_float64 bitRate)
Sets the bitrate from index.
virtual void copyTileToNormalizedBuffer(ossim_float64 *buf) const
Copies entire tile to buf passed in.
bool getAlphaChannelFlag() const
Retrieve the writer&#39;s setting for whether or not to add an alpha channel to the output png image...
const ossimIpt & lr() const
Definition: ossimIrect.h:276
void printCompressionQualityTypes(std::ostream &out) const
bool setLevelsO(ossim_uint32 levels)
Sets the number of wavelet levels in the original image.
static ossimString downcase(const ossimString &aString)
Definition: ossimString.cpp:48
ossimKakaduCompressionQuality getQualityType() const
virtual void setAlphaChannelFlag(bool flag)
Set the writer to add an alpha channel to the output.
T min(T a, T b)
Definition: ossimCommon.h:203
bool initialize(const ossimImageGeometry *geom, const ossimIrect &rect)
Initializes gml block from geometry file.
ossim_uint32 width() const
Definition: ossimIrect.h:500
virtual void setQualityType(ossimKakaduCompressionQuality type)
Sets the quality type.
static ossimPreferences * instance()
ossimIrect m_imageRect
Layer slopes array provided in &#39;flush&#39; calls.
Container class that holds both 2D transform and 3D projection information for an image Only one inst...
ossimScalarType
bool writeGeotiffBox(const ossimImageGeometry *geom, const ossimIrect &rect, const ossimFilename &tmpFile, ossimPixelType pixelType)
Writes the geotiff box to the jp2.
ossimString getQualityTypeString() const
virtual bool setProperty(ossimRefPtr< ossimProperty > property)
Will set the property whose name matches the argument "property->getName()".
virtual const ossim_float32 * getFloatBuf() const
virtual bool writeTile(ossimImageData &srcTile)
Write tile method.
virtual ossimScalarType getScalarType() const
const ossimProjection * getProjection() const
Access methods for projection (may be NULL pointer).
16 bit unsigned integer (15 bits used)
void transfer_dwords(kdu_core::kdu_line_buf &dest, kdu_core::kdu_int32 *src, int num_samples, int sample_gap, int src_bits, int original_bits, bool is_signed)
ossim_int32 getThreads() const
ossimPixelType
OSSIM_DLL double defaultMax(ossimScalarType scalarType)
void initializeCodingParams(kdu_core::kdu_params *cod, const ossimIrect &imageRect)
ossimKakaduCompressedTarget * m_target
ossimKakaduCompressionQuality m_qualityType
int m_layerSpecCount
Num specs provided in &#39;flush&#39; calls.
ossim_int32 y
Definition: ossimIpt.h:142
ossimKakaduCompressedTarget JPEG2000 (J2K) kdu_compressed_target that uses an ostream for writing to ...
virtual const void * getBuf() const
static const char * COMPRESSION_QUALITY_KW
ossim_uint32 area() const
Definition: ossimIrect.h:396
kdu_supp::jp2_family_tgt * m_jp2FamTgt
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
ossim_int32 x
Definition: ossimIpt.h:141
bool setLayersO(ossim_uint32 layers)
Sets the number of layers in the original image.
8 bit unsigned integer
kdu_core::kdu_thread_queue * m_threadQueue
bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
kdu_core::kdu_codestream m_codestream
virtual const ossim_uint8 * getAlphaBuf() const
void setTlmTileCount(ossim_uint32 tilesToWrite)
void setOptions(const std::vector< ossimString > &options)
Sets the options array.
16 bit unsigned integer (11 bits used)
void swap(ossim_sint8 &)
Definition: ossimEndian.h:26
ossim_int32 m_threads
Number of threads.
virtual const ossimIpt & getOrigin() const
unsigned char ossim_uint8
void setCodeBlockSize(kdu_core::kdu_params *cod, ossim_int32 xSize, ossim_int32 ySize)
Set code block size.
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
int ossim_int32
bool setLayerId(ossim_uint32 index, ossim_uint32 id)
Sets the layer id for index.