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