OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimOpjNitfReader.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // License: See top level LICENSE.txt file.
4 //
5 // Author: David Burken
6 //
7 // Description: NITF reader for j2k images using OpenJPEG library.
8 //
9 // $Id$
10 //----------------------------------------------------------------------------
11 
12 
13 #include <openjpeg.h>
14 
15 #include <ossimOpjNitfReader.h>
16 #include <ossim/base/ossimCommon.h>
18 #include <ossim/base/ossimTrace.h>
19 #include <ossim/base/ossimEndian.h>
23 
24 #ifdef OSSIM_ID_ENABLED
25 static const char OSSIM_ID[] = "$Id";
26 #endif
27 
28 static ossimTrace traceDebug("ossimOpjNitfReader:debug");
29 
30 
31 static const ossim_uint16 SOC_MARKER = 0xff4f; // start of codestream
32 static const ossim_uint16 SIZ_MARKER = 0xff51; // start of tile-part
33 static const ossim_uint16 SOT_MARKER = 0xff90; // start of tile-part
34 
36  "ossimOpjNitfReader",
38 
39 
40 
43 {
44 }
45 
47 {
48  close();
49 }
50 
52  const ossimNitfImageHeader* hdr) const
53 {
54  if (!hdr)
55  {
56  return false;
57  }
58  if (hdr->getCompressionCode() == "C8") // jpeg
59  {
60  return true;
61  }
62  return false;
63 }
64 
66 {
67  // Initialize the read mode.
69 
71  if (!hdr)
72  {
73  return;
74  }
75 
76  if ( (hdr->getIMode() == "B") && (hdr->getCompressionCode()== "C8") )
77  {
79  }
80 }
81 
83 {
84  //---
85  // If all block sizes are the same initialize theCompressedBuf; else,
86  // we will allocate on each loadBlock.
87  //---
88  if (theNitfBlockSize.size() == 0)
89  {
90  theCompressedBuf.clear();
91  return;
92  }
93  std::vector<ossim_uint32>::const_iterator i = theNitfBlockSize.begin();
94  ossim_uint32 size = (*i);
95  ++i;
96  while (i != theNitfBlockSize.end())
97  {
98  if ((*i) != size)
99  {
100  theCompressedBuf.clear();
101  return; // block sizes different
102  }
103  ++i;
104  }
105  theCompressedBuf.resize(size); // block sizes all the same.
106 }
107 
109 {
111 
112  if ( !hdr || (theReadMode != READ_JPEG_BLOCK) || !theFileStr )
113  {
114  return false;
115  }
116 
117  theNitfBlockOffset.clear();
118  theNitfBlockSize.clear();
119 
120  //---
121  // NOTE:
122  // SOC = 0xff4f Start of Codestream
123  // SOT = 0xff90 Start of tile
124  // SOD = 0xff93 Last marker in each tile
125  // EOC = 0xffd9 End of Codestream
126  //---
127  char c;
128 
129  // Seek to the first block.
130  theFileStr->seekg(hdr->getDataLocation(), ios::beg);
131  if (theFileStr->fail())
132  {
133  return false;
134  }
135 
136  // Read the first two bytes and verify it is SOC; if not, get out.
137  theFileStr->get( c );
138  if (static_cast<ossim_uint8>(c) != 0xff)
139  {
140  return false;
141  }
142  theFileStr->get(c);
143  if (static_cast<ossim_uint8>(c) != 0x4f)
144  {
145  return false;
146  }
147 
148  ossim_uint32 blockSize = 2; // Read two bytes...
149 
150  // Add the first offset.
151  // theNitfBlockOffset.push_back(hdr->getDataLocation());
152 
153  // Find all the SOC markers.
154  while ( theFileStr->get(c) )
155  {
156  ++blockSize;
157  if (static_cast<ossim_uint8>(c) == 0xff)
158  {
159  if ( theFileStr->get(c) )
160  {
161  ++blockSize;
162 
163  if (static_cast<ossim_uint8>(c) == 0x90) // At SOC marker...
164  {
165  std::streamoff pos = theFileStr->tellg();
166  theNitfBlockOffset.push_back(pos-2);
167  }
168  else if (static_cast<ossim_uint8>(c) == 0x93) // At EOC marker...
169  {
170  // Capture the size of this block.
171  theNitfBlockSize.push_back(blockSize);
172  blockSize = 0;
173  }
174  }
175  }
176  }
177 
178  theFileStr->seekg(0, ios::beg);
179  theFileStr->clear();
180 
181  // We should have the same amount of offsets as we do blocks...
182  ossim_uint32 total_blocks =
184 
185  if (theNitfBlockOffset.size() != total_blocks)
186  {
187  if (traceDebug())
188  {
190  << "DEBUG:"
191  << "\nBlock offset count wrong!"
192  << "\nblocks: " << total_blocks
193  << "\noffsets: " << theNitfBlockOffset.size()
194  << std::endl;
195  }
196 
197  return false;
198  }
199  if (theNitfBlockSize.size() != total_blocks)
200  {
201  if (traceDebug())
202  {
204  << "DEBUG:"
205  << "\nBlock size count wrong!"
206  << "\nblocks: " << total_blocks
207  << "\nblock size array: " << theNitfBlockSize.size()
208  << std::endl;
209  }
210 
211  return false;
212  }
213 
214  return true;
215 }
216 
218  ossim_uint32 y)
219 {
220  ossim_uint32 blockNumber = getBlockNumber(ossimIpt(x,y));
221 
222  if (traceDebug())
223  {
225  << "ossimNitfTileSource::uncompressJpegBlock DEBUG:"
226  << "\nblockNumber: " << blockNumber
227  << "\noffset to block: " << theNitfBlockOffset[blockNumber]
228  << "\nblock size: " << theNitfBlockSize[blockNumber]
229  << std::endl;
230  }
231 
232  // Seek to the block.
233  theFileStr->seekg(theNitfBlockOffset[blockNumber], ios::beg);
234 
235  //---
236  // Get a buffer to read the compressed block into. If all the blocks are
237  // the same size this will be theCompressedBuf; else we will make our own.
238  //---
239  ossim_uint8* compressedBuf = &theCompressedBuf.front();
240  if (!compressedBuf)
241  {
242  compressedBuf = new ossim_uint8[theNitfBlockSize[blockNumber]];
243  }
244 
245 
246  // Read the block into memory. We could store this
247  if (!theFileStr->read((char*)compressedBuf, theNitfBlockSize[blockNumber]))
248  {
249  theFileStr->clear();
251  << "ossimNitfTileSource::loadBlock Read Error!"
252  << "\nReturning error..." << endl;
254  delete [] compressedBuf;
255  compressedBuf = 0;
256  return false;
257  }
258 
259  try
260  {
261  //theCacheTile = decoder.decodeBuffer(compressedBuf,
262  // theNitfBlockSize[blockNumber]);
263  }
264  catch (const ossimException& e)
265  {
267  << e.what() << std::endl;
269  }
270 
271  // If theCompressedBuf is null that means we allocated the compressedBuf.
272  if (theCompressedBuf.size() == 0)
273  {
274  delete [] compressedBuf;
275  compressedBuf = 0;
276  }
277 
279  {
280  return false;
281  }
282  return true;
283 }
ossim_uint32 x
virtual void initializeReadMode()
Initializes the data member "theReadMode" from the current entry.
virtual ossim_int32 getNumberOfBlocksPerRow() const =0
ossimOpjNitfReader()
default construtor
ossim_uint32 y
virtual ossimString getIMode() const =0
std::shared_ptr< ossim::istream > theFileStr
std::vector< ossim_uint32 > theNitfBlockSize
virtual void initializeCompressedBuf()
Initializes the data member theCompressedBuf.
static const ossimErrorCode OSSIM_ERROR
unsigned short ossim_uint16
std::vector< ossim_uint8 > theCompressedBuf
IMODE = B, IC = C3 "JPEG compressed blocks".
yy_size_t size
virtual const char * what() const
Returns the error message.
unsigned int ossim_uint32
virtual void close()
Closes file and destroys all memory allocated.
virtual ossim_uint64 getDataLocation() const =0
virtual bool scanForJpegBlockOffsets()
scans the file storing in offsets in "theNitfBlockOffset" and block sizes in "theNitfBlockSize".
virtual bool canUncompress(const ossimNitfImageHeader *hdr) const
const ossimNitfImageHeader * getCurrentImageHeader() const
virtual bool uncompressJpegBlock(ossim_uint32 x, ossim_uint32 y)
Uncompresses a jpeg block using the jpeg-6b library.
virtual ossimString getCompressionCode() const =0
ossim_uint32 getBlockNumber(const ossimIpt &block_origin) const
RTTI_DEF1_INST(ossimOpjNitfReader, "ossimOpjNitfReader", ossimNitfTileSource) ossimOpjNitfReader
virtual ossim_int32 getNumberOfBlocksPerCol() const =0
virtual ~ossimOpjNitfReader()
virtural destructor
unsigned char ossim_uint8
std::vector< std::streamoff > theNitfBlockOffset
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)