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
17using namespace std;
18
19#if ENABLEJP2K
20using namespace kdu_core;
21using namespace kdu_supp;
22#endif
23
24namespace 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
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
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;
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
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
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 exception class.
Definition IException.h:91
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition IException.h:126
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
unsigned int p_numBands
Number of bands in JP2 file.
Definition JP2Decoder.h:133
void SetResolutionAndRegion()
Sets resolution of data that will be decompressed. Also determines the image dimensions at the reques...
bool p_signedData
Set to true if data in JP2 file is signed.
Definition JP2Decoder.h:135
unsigned int p_numSamples
Number of samples in JP2 file.
Definition JP2Decoder.h:131
void OpenFile()
Open the JPEG2000 file.
JP2Decoder(const QString &jp2file)
Constructs a JPEG2000 decoder object.
JP2Error * Kakadu_Error
JP2 Error handling facility.
Definition JP2Decoder.h:162
unsigned int p_numLines
Number of lines in JP2 file.
Definition JP2Decoder.h:132
unsigned int p_pixelBytes
Number of bytes per pixel in JP2 file.
Definition JP2Decoder.h:134
QString p_jp2File
Input file name.
Definition JP2Decoder.h:130
void Read(unsigned char **inbuf)
Read data from JP2 file containing 8-bit data.
~JP2Decoder()
JP2Decoder destructor.
Kakadu error messaging class.
Definition JP2Error.h:38
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
Namespace for the standard library.