Isis 3 Programmer Reference
JP2Decoder.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include <float.h>
8 #include <iostream>
9 #include <string>
10 #include <sstream>
11 
12 #include "IException.h"
13 #include "IString.h"
14 #include "JP2Decoder.h"
15 #include "JP2Error.h"
16 
17 using namespace std;
18 
19 #if ENABLEJP2K
20 using namespace kdu_core;
21 using namespace kdu_supp;
22 #endif
23 
24 namespace Isis {
25 
32  JP2Decoder::JP2Decoder(const QString &jp2file) {
33 
34 #if ENABLEJP2K
35  p_jp2File = jp2file;
36  p_resolutionLevel = 1;
37  JP2_Source = NULL;
38 
39  // Register the Kakadu error handler
40  Kakadu_Error = new JP2Error;
41  kdu_customize_errors(Kakadu_Error);
42 #else
43  std::string msg = "JPEG2000 has not been enabled with this build of ISIS3";
44  throw IException(IException::Programmer, msg, _FILEINFO_);
45 #endif
46  }
47 
52  void JP2Decoder::OpenFile() {
53 #if ENABLEJP2K
54  // Make sure file isn't already open
55  if(JP2_Source == NULL) {
56 
57  // Open the JP2 file stream
58  JP2_Stream = new jp2_family_src();
59  JP2_Stream->open(p_jp2File.toLatin1().data());
60 
61  // Open the JP2 source
62  JP2_Source = new jp2_source();
63  if(!JP2_Source->open(JP2_Stream)) {
64  QString msg = "Unable to open the decoder because the source file ";
65  msg += "does not have valid JP2 format content [" + p_jp2File + "]";
66  throw IException(IException::User, msg, _FILEINFO_);
67  }
68 
69  // Initialize the JP2 header boxes up to the first codestream box
70  JP2_Source->read_header();
71 
72  // Open the JP2 codestream
73  JPEG2000_Codestream = new kdu_codestream();
74  JPEG2000_Codestream->create(JP2_Source);
75 
76  // Get the image characteristics
77  // Number of components (bands)
78  p_numBands = JPEG2000_Codestream->get_num_components(true);
79 
80  // Image dimensions (sample offset, line offset, number of samples,
81  // number of lines) at full resolution
82  JPEG2000_Codestream->get_dims(0, p_imageDims, true); //dims.pos.x, dims.size.x
83 
84  // Pixel data structure
85  p_pixelBits = JPEG2000_Codestream->get_bit_depth(0, true);
86  p_pixelBytes = (p_pixelBits >> 3) + ((p_pixelBits % 8) ? 1 : 0);
87  if(p_pixelBytes == 3) p_pixelBytes = 4;
88  if(p_pixelBits > 16 || p_pixelBytes > 2) {
89  QString msg = "The source file has unsupported pixel type ";
90  msg += "[" + p_jp2File + "]";
91  throw IException(IException::User, msg, _FILEINFO_);
92  }
93  p_signedData = JPEG2000_Codestream->get_signed(0, true);
94 
95  // Check all bands in the JP2 file to make sure they all have the same
96  // dimensions, bit depth, and signedness
97  kdu_dims dims;
98  unsigned int pixel_bits;
99  bool signed_data;
100  for(unsigned int band = 1; band < p_numBands; ++band) {
101  JPEG2000_Codestream->get_dims(band, dims, true);
102  pixel_bits = JPEG2000_Codestream->get_bit_depth(band, true);
103  signed_data = JPEG2000_Codestream->get_signed(band, true);
104  if(dims.size.x != p_imageDims.size.x || dims.size.y != p_imageDims.size.y ||
105  dims.pos.x != p_imageDims.pos.x || dims.pos.y != p_imageDims.pos.y ||
106  pixel_bits != p_pixelBits || signed_data != p_signedData) {
107  std::string msg = "The source file does not have bands with matching ";
108  msg += "characteristics";
109  throw IException(IException::User, msg, _FILEINFO_);
110  }
111  }
112 
113  // Get the total available resolution levels and set the effective
114  // resolution and image region
115  p_highestResLevel = JPEG2000_Codestream->get_min_dwt_levels() + 1;
116  SetResolutionAndRegion();
117 
118  // Initialize the JP2 decoder
119  // Initialize the codestream stripe decompressor
120  p_decompressor.start(*JPEG2000_Codestream);
121 
122  // Determine optimum stripe heights for accessing data - the
123  // optimum stripe heights are ignored. We are instead reading
124  // the file a line at a time.
125  p_stripeHeights = new int[p_numBands];
126  p_maxStripeHeights = new int[p_numBands];
127  p_precisions = new int[p_numBands];
128  p_isSigned = new bool[p_numBands];
129  p_decompressor.get_recommended_stripe_heights(MIN_STRIPE_HEIGHT,
130  MAX_STRIPE_HEIGHT, p_stripeHeights, p_maxStripeHeights);
131  for(unsigned int i = 0; i < p_numBands; i++) {
132  p_precisions[i] = p_pixelBits;
133  p_stripeHeights[i] = 1;
134  p_isSigned[i] = p_signedData;
135  }
136  }
137 #endif
138  }
139 
145  void JP2Decoder::SetResolutionAndRegion() {
146 #if ENABLEJP2K
147  // Determine size of image at requested resolution and reset requested image
148  // area if it falls outside of image boundaries
149  JPEG2000_Codestream->apply_input_restrictions(0, 0, p_resolutionLevel - 1, 0, NULL,
150  KDU_WANT_OUTPUT_COMPONENTS);
151 
152  JPEG2000_Codestream->get_dims(0, p_imageDims, true);
153  p_numSamples = p_imageDims.size.x;
154  p_numLines = p_imageDims.size.y;
155 #endif
156  }
157 
168  void JP2Decoder::Read(unsigned char **inbuf) {
169 #if ENABLEJP2K
170  p_readStripes = p_decompressor.pull_stripe(inbuf, p_stripeHeights, NULL, NULL,
171  p_precisions);
172 #endif
173  }
174 
185  void JP2Decoder::Read(short int **inbuf) {
186 #if ENABLEJP2K
187  p_readStripes = p_decompressor.pull_stripe(inbuf, p_stripeHeights, NULL, NULL,
188  p_precisions, p_isSigned);
189 #endif
190  }
191 
196  JP2Decoder::~JP2Decoder() {
197 #if ENABLEJP2K
198  // See kdu_stripe_decompressor::reset documentation:
199  // "You should be sure to call this function or finish before destroying the kdu_codestream
200  // inteface that was passed to start."
201  // i.e. Make sure to finish the decompressor before destroying the kdu_codestream.
202  p_decompressor.finish();
203  if(JPEG2000_Codestream) {
204  JPEG2000_Codestream->destroy();
205  }
206  JPEG2000_Codestream = NULL;
207  if(JP2_Source) {
208  JP2_Source->close();
209  delete JP2_Source;
210  }
211  JP2_Source = NULL;
212  if(JP2_Stream) {
213  JP2_Stream->close();
214  delete JP2_Stream;
215  }
216  JP2_Stream = NULL;
217  if(Kakadu_Error) {
218  delete Kakadu_Error;
219  }
220  delete [] p_stripeHeights;
221  delete [] p_maxStripeHeights;
222  delete [] p_precisions;
223  delete [] p_isSigned;
224 #endif
225  }
226 
227 
228  bool JP2Decoder::IsJP2(QString filename) {
229 #if ENABLEJP2K
230  jp2_family_src *stream = new jp2_family_src();
231  stream->open(filename.toLatin1().data());
232  jp2_source *source = new jp2_source();
233 
234  bool result = source->open(stream);
235 
236  source->close();
237  delete source;
238 
239  stream->close();
240  delete stream;
241 
242  return result;
243 #else
244  return (false);
245 #endif
246  }
247 }
Isis::JP2Error
Kakadu error messaging class.
Definition: JP2Error.h:38
Isis::IException
Isis exception class.
Definition: IException.h:91
std
Namespace for the standard library.
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16