Isis 3.0 Programmer Reference
Back | Home
JP2Encoder.cpp
Go to the documentation of this file.
1 
23 #include <float.h>
24 #include <iostream>
25 #include <string>
26 #include <sstream>
27 
28 #include "IException.h"
29 #include "IString.h"
30 #include "JP2Encoder.h"
31 #include "JP2Error.h"
32 
33 using namespace std;
34 namespace Isis {
35 
46  JP2Encoder::JP2Encoder(const QString &jp2file, const unsigned int nsamps,
47  const unsigned int nlines, const unsigned int nbands,
48  const Isis::PixelType type) {
49 
50 #if ENABLEJP2K
51  p_jp2File = jp2file;
52  p_sampleDimension = nsamps;
53  p_lineDimension = nlines;
54  p_bandDimension = nbands;
55 
56  if(p_sampleDimension == 0 || p_lineDimension == 0 || p_bandDimension == 0) {
57  string msg = "Invalid sample/line/band dimensions specified for output file";
58  throw IException(IException::Programmer, msg, _FILEINFO_);
59  }
60 
61  if(type == Isis::SignedWord) {
62  p_signedData = true;
63  p_pixelBits = 16;
64  p_pixelBytes = 2;
65  }
66  else if(type == Isis::UnsignedWord) {
67  p_signedData = false;
68  p_pixelBits = 16;
69  p_pixelBytes = 2;
70  }
71  else if(type == Isis::UnsignedByte) {
72  p_signedData = false;
73  p_pixelBits = 8;
74  p_pixelBytes = 1;
75  }
76  else {
77  string msg = "Invalid pixel type specified for output file";
78  throw IException(IException::Programmer, msg, _FILEINFO_);
79  }
80 
81  // Determine number of resolution levels. The sample/line dimension at the
82  // smallest resolution must not be smaller than 64. The number of resolution
83  // levels must not exceed 32.
84  p_resolutionLevels = 1;
85  int mindim =
86  (p_sampleDimension > p_lineDimension) ? p_lineDimension : p_sampleDimension;
87  while(mindim > 64 && p_resolutionLevels < 32) {
88  ++p_resolutionLevels;
89  mindim >>= 1;
90  }
91 
92  // Precinct size will be set to 256 for all resolution levels
93  p_precinctSize.resize(p_resolutionLevels, 256);
94 
95  // The progression order, code block size, and tile size are all set to
96  // values that allow incremental flushing to work. Incremental flushing
97  // prevents us from having to store the entire compressed codestream in
98  // memory before writing it to disk.
99  p_progressionOrder = "PCRL";
100  p_codeBlockSize = 64;
101  p_tileSizeWidth = p_sampleDimension; // untiled - size of image
102  p_tileSizeHeight = p_lineDimension;
103 
104  // Register the Kakadu error handler
105  Kakadu_Error = new JP2Error;
106  kdu_customize_errors(Kakadu_Error);
107 #else
108  std::string msg = "JPEG2000 has not been enabled with this build of ISIS3";
109  throw IException(IException::Programmer, msg, _FILEINFO_);
110 #endif
111  }
112 
113 
118  void JP2Encoder::OpenFile() {
119 #if ENABLEJP2K
120  // Open the JP2 file stream
121  JP2_Stream = new jp2_family_tgt();
122  JP2_Stream->open(p_jp2File.toLatin1().data());
123 
124  // Open the JP2 boxes
125  JP2_Boxes = new jp2_target();
126  JP2_Boxes->open(JP2_Stream);
127 
128  // Configure and write all required JP2 boxes up to, but not including,
129  // the JPEG2000 codestream (jp2c) box. This includes the Signature,
130  // File_Type, and JP2_Header boxes with the latter including the
131  // Image_Header and Colour_Specification subboxes.
132 
133  // Set the codestream SIZ parameters - this includes the image data
134  // organization, resolution levels, reversible (lossless) discrete
135  // wavelet transform, and encoding progression order.
136  siz_params *codestream_parameters = new siz_params();
137  codestream_parameters->set(Sdims, 0, 0, (int)p_lineDimension);
138  codestream_parameters->set(Sdims, 0, 1, (int)p_sampleDimension);
139  codestream_parameters->set(Sprecision, 0, 0, (int)p_pixelBits);
140  codestream_parameters->set(Stiles, 0, 0, (int)p_tileSizeHeight);
141  codestream_parameters->set(Stiles, 0, 1, (int)p_tileSizeWidth);
142  codestream_parameters->set(Ssigned, 0, 0, p_signedData);
143  codestream_parameters->set(Scomponents, 0, 0, (int)p_bandDimension);
144  ostringstream levels;
145  levels << "Clevels=" << (p_resolutionLevels - 1);
146  codestream_parameters->parse_string(levels.str().c_str());
147  codestream_parameters->parse_string("Creversible=yes");
148  string progression = "Corder=" + p_progressionOrder;
149  codestream_parameters->parse_string(progression.c_str());
150 
151  // Determine the number of tile length marker segments. This is
152  // necessary if incremental flushing of the codestream is to be
153  // employed. Incremental flushing prevents the software from
154  // having to store the entire codestream in memory before writing
155  // it to disk. The number of tile length marker segments is
156  // estimated by dividing the tile height by the number of lines
157  // requested for incremental flushing rounded up to the next whole
158  // number.
159  int TLM_segments;
160  int p_flushLines = 0;
161  long long line_bytes = (long long)p_sampleDimension * p_pixelBytes;
162  if(INCREMENTAL_FLUSH_BYTES < (p_lineDimension * line_bytes)) {
163  p_flushLines = p_tileSizeHeight;
164  while((p_flushLines * line_bytes) > INCREMENTAL_FLUSH_BYTES) {
165  p_flushLines -= 1024;
166  if(p_flushLines < 0) p_flushLines = 0;
167  }
168  }
169  if(p_flushLines) {
170  TLM_segments = (int)(((double)p_tileSizeHeight / (double)p_flushLines) + 0.5);
171  if(!TLM_segments) TLM_segments = 1;
172  }
173  else {
174  TLM_segments = 1;
175  }
176 
177  ostringstream segments;
178  segments << "ORGgen_tlm=" << TLM_segments;
179  codestream_parameters->parse_string(segments.str().c_str());
180 
181  // Include packet length markers in tile headers
182  codestream_parameters->parse_string("ORGgen_plt=yes");
183 
184  // Finalize the codestream parameters
185  codestream_parameters->finalize_all();
186 
187  // Construct the JPEG2000 codestream object
188  JPEG2000_Codestream = new kdu_codestream();
189  JPEG2000_Codestream->create(codestream_parameters, JP2_Boxes);
190 
191  // Some parameters must be set again after creating the codestream.
192  // It was not clear if they need to be set twice or only after
193  // creating the codestream.
194  codestream_parameters = JPEG2000_Codestream->access_siz();
195  codestream_parameters->parse_string(levels.str().c_str());
196  codestream_parameters->parse_string("Creversible=yes");
197  codestream_parameters->parse_string(progression.c_str());
198  codestream_parameters->parse_string(segments.str().c_str());
199  codestream_parameters->parse_string("ORGgen_plt=yes");
200 
201  // Set precinct sizes - vertical dimension gets set first. In our
202  // case, both dimensions are the same.
203  ostringstream sizes;
204  sizes << "Cprecincts=";
205  for(unsigned int i = 0; i < p_precinctSize.size(); i++) {
206  if(i != 0) sizes << ",";
207  sizes << "{" << p_precinctSize[i] << "," << p_precinctSize[i] << "}";
208  }
209  codestream_parameters->parse_string(sizes.str().c_str());
210 
211  // Set code block size - vertical dimension gets set first. In our
212  // case, both dimensions are the same.
213  ostringstream size;
214  size << "Cblk={" << p_codeBlockSize << "," << p_codeBlockSize << "}";
215  codestream_parameters->parse_string(size.str().c_str());
216 
217  codestream_parameters->finalize_all();
218 
219  // Finalize image dimensions
220  jp2_dimensions dimensions = JP2_Boxes->access_dimensions();
221  dimensions.init(codestream_parameters);
222  dimensions.finalize_compatibility(codestream_parameters);
223 
224  // Set colour definition
225  jp2_colour colour = JP2_Boxes->access_colour();
226  colour.init((p_bandDimension >= 3) ? JP2_sRGB_SPACE : JP2_sLUM_SPACE);
227 
228  // Write all JP2 boxes up to, but not including, the codestream box
229  JP2_Boxes->write_header();
230 
231  // Initialize the encoder
232  // Open the JPEG2000 codestream (jp2c) box
233  JP2_Boxes->open_codestream();
234 
235  // Set number of quality layers to 1
236  int layers;
237  kdu_params *COD = JPEG2000_Codestream->access_siz()->access_cluster(COD_params);
238  if(!(COD->get(Clayers, 0, 0, layers) && (layers > 0)))
239  COD->set(Clayers, 0, 0, layers = 1);
240  kdu_long *layer_sizes = new kdu_long[layers];
241  memset(layer_sizes, 0, sizeof(kdu_long)*layers);
242 
243  // Initialize the codestream stripe compressor
244  p_compressor.start(*JPEG2000_Codestream, layers, layer_sizes, NULL, 0, false,
245  p_pixelBytes == 4); // Force precise for 32-bit values
246 
247  // Determine optimum stripe heights for accessing data
248  p_stripeHeights = new int[p_bandDimension];
249  p_maxStripeHeights = new int[p_bandDimension];
250  p_precisions = new int[p_bandDimension];
251  p_isSigned = new bool[p_bandDimension];
252  p_compressor.get_recommended_stripe_heights(MIN_STRIPE_HEIGHT,
253  MAX_STRIPE_HEIGHT, p_stripeHeights, p_maxStripeHeights);
254  for(unsigned int i = 0; i < p_bandDimension; i++) {
255  p_precisions[i] = p_pixelBits;
256  p_isSigned[i] = p_signedData;
257  p_stripeHeights[i] = 1;
258  }
259 #endif
260  }
261 
270  void JP2Encoder::Write(unsigned char **inbuf) {
271 #if ENABLEJP2K
272  p_writeStripes = p_compressor.push_stripe(inbuf, p_stripeHeights, NULL, NULL,
273  p_precisions, p_flushLines);
274 #endif
275  }
276 
285  void JP2Encoder::Write(short int **inbuf) {
286 #if ENABLEJP2K
287  p_writeStripes = p_compressor.push_stripe(inbuf, p_stripeHeights, NULL, NULL,
288  p_precisions, p_isSigned, p_flushLines);
289 #endif
290  }
291 
296  JP2Encoder::~JP2Encoder() {
297 #if ENABLEJP2K
298  p_compressor.finish();
299  JPEG2000_Codestream->destroy();
300  JP2_Boxes->close();
301  JP2_Stream->close();
302  delete [] p_stripeHeights;
303  delete [] p_maxStripeHeights;
304  delete [] p_precisions;
305  delete [] p_isSigned;
306 #endif
307  }
308 }
Kakadu error messaging class.
Definition: JP2Error.h:52
PixelType
Enumerations for Isis Pixel Types.
Definition: PixelType.h:43
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:38
Isis exception class.
Definition: IException.h:99

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:21:22