OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimNitfTileSource.cpp
Go to the documentation of this file.
1 //---
2 //
3 // License: MIT
4 //
5 // See LICENSE.txt file in the top level directory for more details.
6 //
7 // Author: David Burken
8 //
9 // Description: Contains class definition for ossimNitfTileSource.
10 //
11 //---
12 // $Id$
13 
16 #include <ossim/base/ossimCommon.h>
17 #include <ossim/base/ossimTrace.h>
19 #include <ossim/base/ossimIpt.h>
20 #include <ossim/base/ossimDpt.h>
21 #include <ossim/base/ossimIrect.h>
27 #include <ossim/base/ossimEndian.h>
43 
44 #include <cstdlib> /* free, malloc, size_t (jpeglib.h) */
45 #include <cstdio> /* FILE* (jpeglib.h) */
46 #include <csetjmp>
47 #include <jerror.h>
48 #include <jpeglib.h>
49 #include <fstream>
50 #include <algorithm> /* for std::fill */
51 
53 
54 #ifdef OSSIM_ID_ENABLED
55  static const char OSSIM_ID[] = "$Id: ossimNitfTileSource.cpp 22925 2014-10-28 22:01:09Z dburken $";
56 #endif
57 
58 //---
59 // NOTE: This should match the enumerations for ReadMode.
60 //---
61 static const char* READ_MODE[] = { "READ_MODE_UNKNOWN",
62  "READ_BIB_BLOCK",
63  "READ_BIP_BLOCK",
64  "READ_BIR_BLOCK",
65  "READ_BSQ_BLOCK",
66  "READ_BIB",
67  "READ_BIP",
68  "READ_BIR",
69  "READ_JPEG_BLOCK" };
70 
71 //***
72 // Static trace for debugging
73 //***
74 static ossimTrace traceDebug("ossimNitfTileSource:debug");
75 
76 // 64x64*12bits
77 // divide by 8 bits to get bytes gives you 6144 bytes
78 static const ossim_uint32 OSSIM_NITF_VQ_BLOCKSIZE = 6144;
79 
81 struct ossimJpegErrorMgr
82 {
83  struct jpeg_error_mgr pub; /* "public" fields */
84  jmp_buf setjmp_buffer; /* for return to caller */
85 };
86 
87 
89  :
91  theTile(0),
92  theCacheTile(0),
93  theNitfFile(0),
94  theNitfImageHeader(0),
95  theReadMode(READ_MODE_UNKNOWN),
96  theScalarType(OSSIM_SCALAR_UNKNOWN),
97  theSwapBytesFlag(false),
98  theNumberOfInputBands(0),
99  theNumberOfOutputBands(0),
100  theBlockSizeInBytes(0),
101  theReadBlockSizeInBytes(0),
102  theNumberOfImages(0),
103  theCurrentEntry(0),
104  theImageRect(0,0,0,0),
105  theFileStr(0),
106  theOutputBandList(),
107  theCacheSize(0, 0),
108  theCacheTileInterLeaveType(OSSIM_INTERLEAVE_UNKNOWN),
109  theCacheEnabledFlag(false),
110  theEntryList(0),
111  theCacheId(-1),
112  thePackedBitsFlag(false),
113  theCompressedBuf(0),
114  theNitfBlockOffset(0),
115  theNitfBlockSize(0),
116  m_jpegOffsetsDirty(false)
117 {
118  if (traceDebug())
119  {
121  << "ossimNitfTileSource::ossimNitfTileSource entered..." << endl;
122 #ifdef OSSIM_ID_ENABLED
123  ossimNotify(ossimNotifyLevel_DEBUG)<< "OSSIM_ID: " << OSSIM_ID << endl;
124 #endif
125  }
126 
127 }
128 
130 {
131  destroy();
132 }
133 
135 {
136  if (theCacheId != -1)
137  {
139  theCacheId = -1;
140  }
141 
142  // Delete the list of image headers.
143  theNitfImageHeader.clear();
144 
145  theNitfFile = 0;
146 
147  shared_ptr<ossim::ifstream> str = std::dynamic_pointer_cast<ossim::ifstream>( theFileStr );
148  if ( str )
149  {
150  if(str->is_open())
151  {
152  str->close();
153  }
154  }
155 
156  theCacheTile = 0;
157  theTile = 0;
158  theOverview = 0;
159  }
160 
162 {
163 
164  return (theNitfImageHeader.size() > 0);
165 }
166 
168 {
169  bool result = false;
170 
171  if(isOpen())
172  {
173  close();
174  }
175 
177 
178  std::shared_ptr<ossim::istream> nitfStream= ossim::StreamFactoryRegistry::instance()->createIstream(getFilename().c_str());
179 
180  result = open(nitfStream, getFilename().c_str());
181  // if ( parseFile() )
182  // {
183  // result = allocate();
184  // }
185  // if (result)
186  // {
187  // completeOpen();
188  // }
189 
190  return result;
191 }
192 
193 bool ossimNitfTileSource::open( std::shared_ptr<ossim::istream>& str,
194  const std::string& connectionString )
195 {
196  static const char MODULE[] = "ossimNitfTileSource::open( stream, ...)";
197 
198  bool result = false;
199  if(!str) return result;
200  ossimFilename file = connectionString;
201 
202  if (traceDebug())
203  {
205  << MODULE << " entered...\nFile = " << file << "\n";
206  }
207 
208  if( isOpen() )
209  {
210  close();
211  }
212 
214 
215 
216  theNitfFile = new ossimNitfFile();
217 
218  result = theNitfFile->parseStream( file, *str);
219 
220  if ( result )
221  {
222  // Get the number of images within the file.
224 
225  if(traceDebug())
226  {
228  << "DEBUG:\nNumber of images " << theNumberOfImages << "\n";
229  }
230 
231  theEntryList.clear();
232 
233  //---
234  // Get image header pointers. Note there can be multiple images in one
235  // image file.
236  //---
237 
238  for (ossim_uint32 i = 0; i < theNumberOfImages; ++i)
239  {
241  if (!hdr)
242  {
243  result = false;
244  setErrorStatus();
245  if (traceDebug())
246  {
248  << MODULE << " ERROR:\nNull image header!" << endl;
249  }
250  break;
251  }
252 
253  if (traceDebug())
254  {
255  if(hdr.valid())
256  {
258  << MODULE << "DEBUG:"
259  << "\nImage header[" << i << "]:\n" << *(hdr.get())
260  << "\n";
261  }
262  }
263  if(hdr->isValid())
264  {
265  if( !hdr->isCompressed() )
266  {
267  // GP: I will remove the NODISPLY check for if there is
268  // any kind of data OSSIM should allow it through.
269  // filterting for this data should be at a higher level.
270  // SICD data is labeled as NODISPLY but we need to process
271  // it in order for it to be used in other algorithms
272 
273  // Skip entries tagged NODISPLAY, e.g. cloud mask entries.
274  // if (hdr->getRepresentation() != "NODISPLY")
275  // {
276  theEntryList.push_back(i);
277  theNitfImageHeader.push_back(hdr);
278  // }
279  // else
280  // {
281  // ossimString cat = hdr->getCategory().trim().downcase();
282  // // this is an NGA Highr Resoluion Digital Terrain Model NITF format
283  // if(cat == "dtem")
284  // {
285  // theEntryList.push_back(i);
286  // theNitfImageHeader.push_back(hdr);
287  // }
288  // }
289 
290  }
291  else if ( canUncompress(hdr.get()) )
292  {
293  theEntryList.push_back(i);
294  theCacheEnabledFlag = true;
295  theNitfImageHeader.push_back(hdr);
296  }
297  else
298  {
299  //std::cout << "COMPRESSION CODE: "<< hdr->getCompressionCode() << "\n";
300  if(traceDebug())
301  {
303  << "Entry " << i
304  <<" has an unsupported compression code = "
305  << hdr->getCompressionCode() << std::endl;
306  }
307  theNitfImageHeader.clear();
308  theEntryList.clear();
309  // break out
310  break;
311  }
312  }
313 
314  } // End: image header loop
315  // Reset the number of images in case we skipped some, e.g. tagged "NODISPLAY"
316  if ( theNitfImageHeader.size() )
317  {
319  }
320  else
321  {
322  result = false;
323  }
324 
325 
326 
327  if ( result )
328  {
329  // Save the stream and connection/file name.
330  theFileStr = str;
331  theImageFile = file;
332 
333  // Initialize the lut to the current entry if the current entry has a lut.
334  initializeLut();
335 
336  result = allocate();
337 
338  if (result)
339  {
340  completeOpen();
341  }
342  }
343  else
344  {
345  setErrorStatus();
346  if (traceDebug())
347  {
349  << MODULE << "DEBUG:\nNo images in file!" << endl;
350  }
351  }
352  }
353 
354  if (traceDebug())
355  {
357  << MODULE << " exit status: " << (result?"true":"false") << "\n";
358  }
359  return result;
360 }
361 
363 {
364  destroy();
365 }
366 
368 {
369  static const char MODULE[] = "ossimNitfTileSource::parseFile";
370 
371  ossimFilename file = getFilename();
372 
373  if (traceDebug())
374  {
376  << MODULE << " DEBUG: Nitf file = " << file << endl;
377  }
378 
379  if (file.empty())
380  {
381  setErrorStatus();
382  return false;
383  }
384 
385  if ( !theNitfFile ) // A close deletes "theNitfFile".
386  {
387  theNitfFile = new ossimNitfFile();
388  }
389 
390  if ( !theNitfFile->parseFile(file) )
391  {
392  setErrorStatus();
393  if (traceDebug())
394  {
396  << MODULE << "DEBUG:" << "\nError parsing file!" << endl;
397  }
398 
399  return false;
400  }
401 
402  // Get the number of images within the file.
404 
405  if(traceDebug())
406  {
408  << MODULE << "DEBUG:\nNumber of images "
409  <<theNumberOfImages << std::endl;
410  }
411 
412  if ( theNumberOfImages == 0 )
413  {
414  setErrorStatus();
415  if (traceDebug())
416  {
418  << MODULE << "DEBUG:\nNo images in file!" << endl;
419  }
420 
421  return false;
422  }
423  theEntryList.clear();
424  //---
425  // Get image header pointers. Note there can be multiple images in one
426  // image file.
427  //---
428  for (ossim_uint32 i = 0; i < theNumberOfImages; ++i)
429  {
431  if (!hdr)
432  {
433  setErrorStatus();
434  if (traceDebug())
435  {
437  << MODULE << " ERROR:\nNull image header!" << endl;
438  }
439 
440  return false;
441  }
442  if (traceDebug())
443  {
444  if(hdr.valid())
445  {
447  << MODULE << "DEBUG:"
448  << "\nImage header[" << i << "]:\n" << *hdr
449  << endl;
450  }
451  }
452 
453  if(hdr->isValid())
454  {
455  if( !hdr->isCompressed() )
456  {
457  // GP: I will remove the NODISPLYU check for if there is
458  // any kind of data OSSIM should allow it through.
459  // filterting for this data should be at a higher level.
460  // SICD data is labeled as NODISPLY but we need to process
461  // it in order for it to be used in other algorithms
462  //
463  // Skip entries tagged NODISPLAY, e.g. cloud mask entries.
464  // if (hdr->getRepresentation() != "NODISPLY")
465  // {
466  theEntryList.push_back(i);
467  theNitfImageHeader.push_back(hdr);
468  // }
469  // else
470  // {
471  // ossimString cat = hdr->getCategory().trim().downcase();
472  // // this is an NGA Highr Resoluion Digital Terrain Model NITF format
473  // if(cat == "dtem")
474  // {
475  // theEntryList.push_back(i);
476  // theNitfImageHeader.push_back(hdr);
477  // }
478  // }
479 
480  }
481  else if ( canUncompress(hdr.get()) )
482  {
483  theEntryList.push_back(i);
484  theCacheEnabledFlag = true;
485  theNitfImageHeader.push_back(hdr);
486  }
487  else
488  {
489  theEntryList.clear();
490  theNitfImageHeader.clear();
491  if(traceDebug())
492  {
494  << "Entry " << i
495  <<" has an unsupported compression code = "
496  << hdr->getCompressionCode() << std::endl;
497  }
498  break;
499  }
500  }
501  else
502  {
503  if(traceDebug())
504  {
506  << "Entry " << i
507  <<" has an invalid image header\n";
508 
509  }
510  }
511  }
512 
513  if(theEntryList.size()<1)
514  {
515  return false;
516  }
517 
518  //### WHY IS THIS HERE? THIS CAUSED A BUG BECAUSE theCurrentEntry was previously initialized
519  //### in loadState() according to a KWL. Any entry index in the KWL was being ignored.
520  //if(theEntryList.size()>0)
521  //{
522  // theCurrentEntry = theEntryList[0];
523  //}
524 
526 
528  {
529  setErrorStatus();
530  if (traceDebug())
531  {
533  << MODULE
534  << "DEBUG:\nNumber of header not equal number of images!"
535  << endl;
536  }
537 
538  return false;
539  }
540 
541  // Check the current entry range.
543  {
544  if(theEntryList.size())
545  {
547  }
548  }
549 
550  // Initialize the lut to the current entry if the current entry has a lut.
551  initializeLut();
552 
553  if (traceDebug())
554  {
556  << MODULE << " DEBUG:"
557  << "\nCurrent entry: " << theCurrentEntry
558  << endl;
559  }
560 
561 
562  // Open up a stream to the file.
564  file, ios::in | ios::binary);
565  if (!theFileStr)
566  {
568  if(traceDebug())
569  {
571  << MODULE << " ERROR:"
572  << "\nCannot open: " << file.c_str() << endl;
573  }
574  return false;
575  }
576 
577  if(traceDebug())
578  {
580  << MODULE << " leaving with true..." << endl;
581 
582  }
583 
584  return true;
585 }
586 
588 {
589  // Clear out the cache if there was any.
590  if (theCacheId != -1)
591  {
593  theCacheId = -1;
594  }
595 
596  // Clear buffers:
597  theTile = 0;
598  theCacheTile = 0;
599  theCompressedBuf.clear();
600 
601  // Set the scalar type.
604  {
605  return false;
606  }
607 
608  // Set the swap bytes flag.
610 
611  // Set the read mode.
614  {
615  return false;
616  }
617 
618  // Set the number of bands.
620  if (theNumberOfInputBands == 0)
621  {
622  return false;
623  }
624 
625  // Initialize the image rectangle. before the cache size is done
626  if (initializeImageRect() == false)
627  {
628  return false;
629  }
630 
631  // Initialize the cache size. Must be done before
632  // setting the blocksize. Since bit encoded data may very
633  // and we need to know if the nitf file needs to be accessed
634  // like a general raster.
635  //
637  if ( (theCacheSize.x == 0) || (theCacheSize.y == 0) )
638  {
639  return false;
640  }
641 
642  // Initialize the block size.
643  if (initializeBlockSize() == false)
644  {
645  return false;
646  }
647 
648  // Initialize the cache tile interleave type.
651  {
652  return false;
653  }
654 
655  return true;
656 }
657 
659 {
660  //---
661  // Initialize the cache tile. This will be used for a block buffer even
662  // if the cache is disabled.
663  //---
665  if (!theCacheTile.valid())
666  {
667  return false;
668  }
669 
670  // Initialize the cache if enabled.
672  {
674  newTileCache(theBlockImageRect, theCacheSize);
675  }
676 
677  //---
678  // Initialize the compressed buffer if needed.
679  //---
681 
682  //---
683  // Make the output tile.
684  //---
686 
687  return true;
688 }
689 
691 {
692 
693  bool result = false;
694  if (hdr)
695  {
696  ossimString code = hdr->getCompressionCode();
697 
698  if (code == "C3") // jpeg
699  {
700  if (hdr->getBitsPerPixelPerBand() == 8)
701  {
702  result = true;
703  }
704  else
705  {
706  if(traceDebug())
707  {
709  << "Entry with jpeg compression (C3) has an unsupported "
710  << "JPEG data precision: " << hdr->getBitsPerPixelPerBand()
711  << std::endl;
712  }
713  }
714  }
715  else if(isVqCompressed( code ) &&
716  (hdr->getCompressionHeader().valid()) )
717  {
718  // we will only support single band vq compressed NITFS
719  // basically CIB and CADRG products are single band code words.
720  //
721  if(hdr->getNumberOfBands() == 1)
722  {
723  result = true;
724  }
725  }
726  }
727  return result;
728 }
729 
731 {
732  // Initialize the read mode.
734 
736  if (!hdr)
737  {
738  return;
739  }
740 
741  ossim_uint32 numberOfBlocks = getNumberOfBlocks();
742  ossimString imode = hdr->getIMode();
743  ossimString compressionCode = hdr->getCompressionCode();
744 
745  if ( (compressionCode == "C3") && ((imode == "B")||(imode == "P")) )
746  {
748  }
749  else if (numberOfBlocks > 1)
750  {
751  if (imode == "B")
752  {
754  }
755  else if (imode == "P")
756  {
758  }
759  else if (imode == "R")
760  {
762  }
763  else if (imode == "S")
764  {
766  }
767  }
768  else // The entire image comprises one block.
769  {
770  if (imode == "B")
771  {
773  }
774  else if (imode == "P")
775  {
777  }
778  else if (imode == "R")
779  {
781  }
782  else if (imode == "S")
783  {
785  }
786  }
787  if (traceDebug())
788  {
790  << "ossimNitfTileSource::initializeReadMode DEBUG:"
791  << "\nnumberOfBlocks: " << numberOfBlocks
792  << "\nIMODE: " << imode
793  << "\nRead Mode: " << READ_MODE[theReadMode]
794  << endl;
795  }
796 }
797 
799 {
800  thePackedBitsFlag = false;
801  // Initialize the read mode.
803 
805  if (!hdr)
806  {
807  return;
808  }
809 
810  ossim_int32 bitsPerPixel = hdr->getActualBitsPerPixelPerBand();
811  if (bitsPerPixel < 1)
812  {
813  bitsPerPixel = hdr->getBitsPerPixelPerBand();
814  }
815 
816  ossimString pixelValueType = hdr->getPixelValueType().upcase();
817 
818  switch (bitsPerPixel)
819  {
820  case 8:
821  {
823  break;
824  }
825  case 11:
826  {
827  if(pixelValueType == "SI")
828  {
830  }
831  else
832  {
834  }
835  break;
836  }
837  case 12:
838  {
839  if(pixelValueType == "SI")
840  {
842  }
843  else
844  {
846  }
847  break;
848  }
849  case 13:
850  {
851  if(pixelValueType == "SI")
852  {
854  }
855  else
856  {
858  }
859  break;
860  }
861  case 14:
862  {
863  if(pixelValueType == "SI")
864  {
866  }
867  else
868  {
870  }
871  break;
872  }
873  case 15:
874  {
875  if(pixelValueType == "SI")
876  {
878  }
879  else
880  {
882  }
883  break;
884  }
885  case 9:
886  case 10:
887  case 16:
888  {
889  if(pixelValueType == "SI")
890  {
892  }
893  else
894  {
896  }
897  break;
898  }
899  case 32:
900  {
901  if(pixelValueType == "SI")
902  {
904  }
905  else if(pixelValueType == "R")
906  {
908  }
909  break;
910  }
911  case 64:
912  {
913  if(pixelValueType == "R")
914  {
916  }
917 
918  break;
919  }
920  default:
921  {
922  if(hdr->isCompressed())
923  {
924  thePackedBitsFlag = true;
925  if(bitsPerPixel < 8)
926  {
928  }
929  else if(bitsPerPixel < 16)
930  {
932  }
933  else if(bitsPerPixel < 32)
934  {
936  }
937  }
938  else
939  {
940  if(bitsPerPixel<8)
941  {
943  }
944  }
945  break;
946  }
947  }
948 
949  if (traceDebug())
950  {
952  << "ossimNitfTileSource::initializeScalarType DEBUG:"
953  << "\nScalar type: "
955  << "\nPacked bits: " << (thePackedBitsFlag?"true":"false")
956  << endl;
957  }
958 }
959 
961 {
962  if ( (theScalarType != OSSIM_UINT8) &&
964  {
965  theSwapBytesFlag = true;
966  }
967  else
968  {
969  theSwapBytesFlag = false;
970  }
971 }
972 
974 {
975  // Initialize the read mode.
978  //theOutputBandList.clear();
979 
981  if (!hdr)
982  {
983  return;
984  }
985 
987  {
990  if(hdr->getRepresentation().contains("LUT")&&(theNumberOfInputBands == 1))
991  {
993  }
994  }
995  else
996  {
998  if ( bandInfo.valid() )
999  {
1002  }
1003  }
1004 
1005  //for (ossim_uint32 i=0; i < theNumberOfOutputBands; ++i)
1006  // Need to take bands from loadState to pass to Kakadu to avoid decompressing all bands
1008  else
1009  {
1011  for (ossim_uint32 i=0; i < theNumberOfOutputBands; ++i)
1012  {
1013  theOutputBandList[i] = i; // One to one for initial setup.
1014  }
1015  }
1016 
1017  if (traceDebug())
1018  {
1020  << "ossimNitfTileSource::initializeBandCount DEBUG:"
1021  << "\nInput Band count: " << theNumberOfInputBands
1022  << "\nOutput Band count: " << theNumberOfOutputBands
1023  << endl;
1024  }
1025 }
1026 
1028 {
1029  theBlockSizeInBytes = 0;
1031 
1033  if (!hdr)
1034  {
1035  return false;
1036  }
1037 
1038  ossim_uint32 bytesRowCol = 0;
1039  ossim_uint32 bytesRowColCacheTile = 0;
1040 
1042  {
1043  bytesRowCol = OSSIM_NITF_VQ_BLOCKSIZE;
1044  }
1045  else
1046  {
1047  //---
1048  // Busting int32 limit on single block data.
1049  // Need a new read method to handle this. (drb - 09 May 2016)
1050  //---
1053  ossim_uint64 bpp = hdr->getBitsPerPixelPerBand();
1054  ossim_uint64 bytes = x * y * bpp / 8;
1055  if ( bytes > 2147483647 )
1056  {
1057  if (traceDebug())
1058  {
1060  << "ossimNitfTileSource::initializeBlockSize WARNING!"
1061  << "\nBusting 2 GIG block size: " << bytes
1062  << std::endl;
1063  }
1064  return false;
1065  }
1066  bytesRowCol = (ossim_uint32)bytes;
1067  }
1068 
1069  if ( !bytesRowColCacheTile )
1070  {
1071  //---
1072  // Busting int32 limit on single block data.
1073  // Need a new read method to handle this. (drb - 09 May 2016)
1074  //---
1077  ossim_uint64 bpp = hdr->getBitsPerPixelPerBand();
1078  ossim_uint64 bytes = x * y * bpp / 8;
1079  if ( bytes > 2147483647 )
1080  {
1081  if (traceDebug())
1082  {
1084  << "ossimNitfTileSource::initializeBlockSize WARNING!"
1085  << "\nBusting 2 GIG cache bytes: " << bytes
1086  << std::endl;
1087  }
1088  return false;
1089  }
1090 
1091  bytesRowColCacheTile = bytes;
1092  }
1093 
1094 #if 0
1095  if (traceDebug())
1096  {
1098  << "DEBUG:"
1099  // << "\ncompressionHeader: " << compressionHeader
1100  << "\ngetNumberOfPixelsPerBlockHoriz(): "
1102  << "\ngetNumberOfPixelsPerBlockVert(): "
1104  << "\ngetBitsPerPixelPerBand(): "
1105  << hdr->getBitsPerPixelPerBand()
1106  << "\nbytesRowCol: " << bytesRowCol
1107  << "\nbytesRowColCacheTile: " << bytesRowColCacheTile
1108  << endl;
1109  }
1110 #endif
1111 
1112  theBlockSizeInBytes = bytesRowCol;
1114  switch (theReadMode)
1115  {
1116  case READ_BSQ_BLOCK:
1117  case READ_BIB_BLOCK:
1118  {
1119  break;
1120  }
1121  case READ_BIB:
1122  {
1123  theReadBlockSizeInBytes = bytesRowColCacheTile;
1124  break;
1125  }
1126 
1127  case READ_BIP_BLOCK:
1128  case READ_BIR_BLOCK:
1129  {
1132  break;
1133  }
1134  case READ_BIP:
1135  case READ_BIR:
1136  {
1138  theReadBlockSizeInBytes = bytesRowColCacheTile*theNumberOfInputBands;
1139  break;
1140  }
1141  case READ_JPEG_BLOCK:
1142  {
1144  ossimString code = hdr->getCompressionCode();
1145  if (code == "C3") // jpeg
1146  {
1147  m_jpegOffsetsDirty = true;
1148  }
1149  break;
1150  }
1151  default:
1152  {
1153  return false;
1154  }
1155  }
1156 
1157 #if 0
1158  if (traceDebug())
1159  {
1161  << "ossimNitfTileSource::initializeBlockSize DEBUG:"
1162  << "\nNumber of input bands: " << theNumberOfInputBands
1163  << "\nNumber of output bands: " << theNumberOfOutputBands
1164  << "\nBlock size in bytes: " << theBlockSizeInBytes
1165  << "\nRead block size in bytes: " << theReadBlockSizeInBytes
1166  << endl;
1167  }
1168 #endif
1169 
1170  return true;
1171 }
1172 
1173 //*************************************************************************************************
1174 // Virtual method determines the decimation factors at each resolution level.
1175 // This implementation derives the R0 decimation from the image metadata if available, then hands
1176 // off the computation of remaining R-levels to the base class implementation.
1177 //*************************************************************************************************
1179 {
1180  theDecimationFactors.clear();
1182  if (hdr)
1183  {
1184  double decimation;
1185  hdr->getDecimationFactor(decimation);
1186  if ((decimation != 0.0) && !ossim::isnan(decimation))
1187  {
1188  //---
1189  // Note: Commented out as other code is picking up the resolution and then we're applying
1190  // a decimation on top of that. (drb Aug. 2011)
1191  // ossimDpt dec_2d (decimation, decimation);
1192  //---
1193  ossimDpt dec_2d (1.0, 1.0);
1194  theDecimationFactors.push_back(dec_2d);
1195  }
1196  }
1197 
1198  // Just needed to set the first R level here, the base class can do the rest:
1200 }
1201 
1202 #if 0
1204 {
1205  //---
1206  // Call base class getImageGeometry which will check for external geometry
1207  // or an already set geometry.
1208  //---
1210 
1211  if (result)
1212  {
1213  if ( !result->getTransform() )
1214  {
1215  ossimRefPtr<ossim2dTo2dTransform> transform = 0;
1216 
1218  if (hdr)
1219  {
1220  //---
1221  // Test for the ichipb tag and set the sub image if needed.
1222  //
1223  // NOTE # 1:
1224  //
1225  // There are nitf writers that set the ichipb offsets and only have
1226  // IGEOLO field present. For these it has been determined
1227  // (but still in question) that we should not apply the sub image
1228  // offset.
1229  //
1230  // See trac # 1578
1231  // http://trac.osgeo.org/ossim/ticket/1578
1232  //
1233  // NOTE # 2:
1234  //
1235  // Let the ICHIPB have precedence over the STDIDC tag as we could
1236  // have a chip of a segment.
1237  //---
1239  hdr->getTagData(ossimString("ICHIPB"));
1240  if (tag.valid())
1241  {
1242  ossimNitfIchipbTag* ichipb =
1244  if (ichipb)
1245  {
1246 // const ossimRefPtr<ossimNitfRegisteredTag> blocka =
1247 // hdr->getTagData(ossimString("BLOCKA"));
1248 // const ossimRefPtr<ossimNitfRegisteredTag> rpc00a =
1249 // hdr->getTagData(ossimString("RPC00A"));
1250 // const ossimRefPtr<ossimNitfRegisteredTag> rpc00b =
1251 // hdr->getTagData(ossimString("RPC00B"));
1252 
1253  //---
1254  // If any of these tags are present we will use the sub
1255  // image from the ichipb tag.
1256  //---
1257 // if ( blocka.get() || rpc00a.get() || rpc00b.get() )
1258  // ************************* THERE ARE PROBLEMS NOT SETTING THIS AT SITE. GO AHEAD AND ALWAYS INIT THE SHIFT
1259  {
1260  transform = ichipb->newTransform();
1261  }
1262  }
1263  }
1264 
1265  if ( !transform)
1266  {
1267  //---
1268  // Look for the STDIDC tag for a sub image (segment) offset.
1269  //
1270  // See: STDI-002 Table 7.3 for documentation.
1271  //---
1272  tag = hdr->getTagData(ossimString("STDIDC"));
1273  if (tag.valid() && (hdr->getIMode() == "B") )
1274  {
1275  ossimDpt shift;
1276  ossimNitfStdidcTag* stdidc =
1278  if (stdidc)
1279  {
1280  ossim_int32 startCol = stdidc->getStartColumn().toInt32();
1281  ossim_int32 startRow = stdidc->getStartRow().toInt32();
1282  if ( (startCol > 0) && (startRow > 0) )
1283  {
1284 
1285  // field are one based; hence, the - 1.
1286  shift.x = (startCol-1) *
1288  shift.y = (startRow-1) *
1290  }
1291  if(shift.x > 0 ||
1292  shift.y > 0)
1293  {
1294  transform = new ossim2dTo2dShiftTransform(shift);
1295  }
1296  }
1297  }
1298  }
1299 
1300  } // matches: if (hdr)
1301 
1302  if ( transform.valid() )
1303  {
1304  result->setTransform( transform.get() );
1305  }
1306  //else
1307  //{
1308  // ossimImageGeometryRegistry::instance()->createTransform(this);
1309  //}
1310 
1311 
1312  } // matches: if ( !result->getTransform() )
1313 
1314  if ( !result->getProjection() )
1315  {
1318  createProjection(this);
1319  if ( proj.valid() )
1320  {
1321  result->setProjection( proj.get() );
1322  }
1323  //else
1324  //{
1325  // ossimImageGeometryRegistry::instance()->createProjection(this);
1326  //}
1327 
1328  }
1329 
1330  } // matches: if (result)
1331 
1332  if (traceDebug())
1333  {
1335  << "ossimNitfTileSource::createImageGeometry DEBUG:\n";
1336 
1337  if (result)
1338  {
1339  result->print(ossimNotify(ossimNotifyLevel_DEBUG)) << "\n";
1340  }
1341  }
1342 
1343  return result;
1344 }
1345 #endif
1346 
1348 {
1350  if (!hdr)
1351  {
1353  return false;
1354  }
1355 
1357  theImageRect = hdr->getImageRect();
1358 
1359  if (traceDebug())
1360  {
1361  ossimIpt iloc;
1362  hdr->getImageLocation(iloc); // for temp debug (drb)
1364  << "ossimNitfTileSource::initializeImageRect DEBUG:"
1365  << "\noffset from ILOC field: " << iloc
1366  << "\nImage Rect: " << theImageRect
1367  << "\nBlock rect: " << theBlockImageRect
1368  << endl;
1369  }
1370  return true;
1371 }
1372 
1374 {
1375  theCacheSize.x = 0;
1376  theCacheSize.y = 0;
1377 
1379  if (!hdr)
1380  {
1381  return;
1382  }
1383  switch (theReadMode)
1384  {
1385  case READ_BIB_BLOCK:
1386  case READ_BIP_BLOCK:
1387  case READ_BIR_BLOCK:
1388  case READ_BSQ_BLOCK:
1389  case READ_JPEG_BLOCK:
1392  break;
1393 
1394  case READ_BIB:
1395  case READ_BIP:
1396  case READ_BIR:
1399  if(getNumberOfBlocks() == 1)
1400  {
1401  // is it larger than 4kx4k then we will for now error out so
1402  // we can't continue
1403  if((theCacheSize.x*theCacheSize.y) > 16777216)
1404  {
1405  if(traceDebug())
1406  {
1407  ossimNotify(ossimNotifyLevel_WARN) << "We currently do not support single blocks with block sizes larger than 4kx4k";
1408  ossimNotify(ossimNotifyLevel_WARN) << "Current size is: " << theCacheSize << std::endl;
1409  }
1410  theCacheSize.x = 0;
1411  theCacheSize.y = 0;
1412  }
1413  }
1414 // theCacheSize.x = getNumberOfSamples(0);
1415 // theCacheSize.y = getTileHeight();
1416 // if(theCacheSize.y > hdr->getNumberOfPixelsPerBlockVert())
1417 // {
1418 // theCacheSize.y = hdr->getNumberOfPixelsPerBlockVert();
1419 // }
1420  break;
1421 
1422  default:
1423  break;
1424  }
1425 
1426  if (traceDebug())
1427  {
1429  << "ossimNitfTileSource::initializeCacheSize DEBUG:"
1430  << "\nCache size: " << theCacheSize
1431  << endl;
1432  }
1433 }
1434 
1436 {
1438 
1440  if (!hdr)
1441  {
1442  return;
1443  }
1444 
1445  switch (theReadMode)
1446  {
1447  case READ_BIB_BLOCK:
1448  case READ_BSQ_BLOCK:
1449  case READ_BIB:
1450  case READ_JPEG_BLOCK:
1452  break;
1453 
1454  case READ_BIP_BLOCK:
1455  case READ_BIP:
1457  break;
1458 
1459  case READ_BIR_BLOCK:
1460  case READ_BIR:
1462  break;
1463 
1464  default:
1465  break;
1466  }
1467 
1468  if (traceDebug())
1469  {
1471 
1473  << "ossimNitfTileSource::initializeCacheTileInterLeaveType DEBUG:"
1474  << "\nCache tile interleave type: "
1476  << endl;
1477  }
1478 }
1479 
1481 {
1483  this,
1484  theScalarType,
1486  theCacheSize.x,
1487  theCacheSize.y);
1488 
1490 }
1491 
1493 {
1495  if (!hdr)
1496  {
1497  return;
1498  }
1499 
1500  if( (hdr->getRepresentation().upcase().contains("LUT")) ||
1501  ( isVqCompressed(hdr->getCompressionCode()) ) )
1502  {
1504  std::fill(theCompressedBuf.begin(), theCompressedBuf.end(), '\0');
1505  }
1506 }
1507 
1509 {
1510  //---
1511  // Make the output tile. This implementation will use default tile size.
1513  theTile = idf->create(this, this);
1514  theTile->initialize();
1515 }
1516 
1518 {
1520  if (hdr)
1521  {
1522  if ( hdr->hasLut() )
1523  {
1524  //---
1525  // NOTE: Only band 0 ??? (drb)
1526  //---
1527  theLut = theNitfImageHeader[theCurrentEntry]->createLut(0);
1528  }
1529  }
1530 }
1531 
1533  const ossimIrect& tileRect, ossim_uint32 resLevel)
1534 {
1535  // This tile source bypassed, or invalid res level, return a blank tile.
1536  if(!isSourceEnabled() || !isOpen() || !isValidRLevel(resLevel))
1537  {
1538  return ossimRefPtr<ossimImageData>();
1539  }
1540 
1541  if ( !theTile.valid() )
1542  {
1543  // First call to getTile:
1544  allocateBuffers();
1545  if ( !theTile.valid() )
1546  {
1547  return theTile;
1548  }
1549  }
1550 
1551  // Rectangle must be set prior to getOverviewTile call.
1552  theTile->setImageRectangle(tileRect);
1553 
1554  if (resLevel)
1555  {
1556  if ( getOverviewTile(resLevel, theTile.get() ) )
1557  {
1558  return theTile;
1559  }
1560  }
1561 
1562  ossim_uint32 level = resLevel;
1563  if (theStartingResLevel) // Used as overview.
1564  {
1565  if (theStartingResLevel <= resLevel)
1566  {
1567  //---
1568  // Adjust the level to be relative to the reader using this as
1569  // overview.
1570  //---
1571  level -= theStartingResLevel;
1572  }
1573  }
1574 
1575  //---
1576  // See if the whole tile is going to be filled, if not, start out with
1577  // a blank tile so data from a previous load gets wiped out.
1578  //---
1579  if ( !tileRect.completely_within(theImageRect) )
1580  {
1581  // Start with a blank tile.
1582  theTile->makeBlank();
1583  }
1584 
1585  //---
1586  // See if any point of the requested tile is in the image.
1587  //---
1588  if ( tileRect.intersects(theBlockImageRect) )
1589  {
1590  ossimIrect clipRect = tileRect.clipToRect(theImageRect);
1591 
1592  // See if the requested clip rect is already in the cache tile.
1593  if ( (clipRect.completely_within(theCacheTile->getImageRectangle()))&&
1595  (theCacheTile->getBuf()))
1596  {
1597  //---
1598  // Note: Clip the cache tile(nitf block) to the image clipRect since
1599  // there are nitf blocks that go beyond the image dimensions, i.e.,
1600  // edge blocks.
1601  //---
1602  ossimIrect cr =
1606  cr,
1608  //---
1609  // Validate the tile. This will set the status to full, partial
1610  // or empty. Must be performed if any type of combining is to be
1611  // performed down the chain.
1612  //---
1613  theTile->validate();
1614  }
1615  else
1616  {
1617  if ( loadTile(clipRect) == true )
1618  {
1619  //---
1620  // Validate the tile. This will set the status to full, partial
1621  // or empty. Must be performed if any type of combining is to be
1622  // performed down the chain.
1623  //---
1624  theTile->validate();
1625  }
1626  else
1627  {
1628  //---
1629  // Commented setting error status out for jpeg data that had several bad
1630  // blocks but the rest of the image was good. If the error status is
1631  // set the overview builder stops! (drb) 10 May 2013
1632  // Flag an error for callers:
1633  // setErrorStatus();
1634 
1636  << __FILE__ << " " << __LINE__
1637  << " loadTile failed!"
1638  << std::endl;
1639 
1640  theTile->makeBlank(); // loadTile failed...
1641  }
1642  }
1643  } // End of if ( tileRect.intersects(image_rect) )
1644 
1645  return theTile;
1646 }
1647 
1649 {
1650  ossimIrect zbClipRect = clipRect;
1651 
1652  const ossim_uint32 BLOCK_HEIGHT = theCacheSize.y;
1653  const ossim_uint32 BLOCK_WIDTH = theCacheSize.x;
1654 
1655  zbClipRect.stretchToTileBoundary(ossimIpt(BLOCK_WIDTH, BLOCK_HEIGHT));
1656 
1657  //---
1658  // Shift the upper left corner of the "clip_rect" to the an even nitf
1659  // block boundry.
1660  //---
1661  ossimIpt nitfBlockOrigin = zbClipRect.ul();
1662 
1663  // Vertical block loop.
1664  ossim_int32 y = nitfBlockOrigin.y;
1665  while (y < zbClipRect.lr().y)
1666  {
1667  // Horizontal block loop.
1668  ossim_int32 x = nitfBlockOrigin.x;
1669  while (x < zbClipRect.lr().x)
1670  {
1671  if ( loadBlockFromCache(x, y, clipRect) == false )
1672  {
1673  if ( loadBlock(x, y) )
1674  {
1675  //---
1676  // Note: Clip the cache tile(nitf block) to the image clipRect
1677  // since there are nitf blocks that go beyond the image
1678  // dimensions, i.e., edge blocks.
1679  //---
1680  ossimIrect cr =
1682 
1685  cr,
1687  }
1688  else
1689  {
1690  // Error loading...
1691  return false;
1692  }
1693  }
1694 
1695  x += BLOCK_WIDTH; // Go to next block.
1696  }
1697 
1698  y += BLOCK_HEIGHT; // Go to next row of blocks.
1699  }
1700 
1701  return true;
1702 }
1703 
1705  const ossimIrect& clipRect)
1706 {
1707  bool result = false;
1708 
1709  if (theCacheEnabledFlag)
1710  {
1711  //---
1712  // The origin set in the cache tile must have the sub image offset in it
1713  // since "theTile" is relative to any sub image offset. This is so that
1714  // "theTile->loadTile(theCacheTile)" will work.
1715  //---
1716  ossimIpt origin(x, y);
1717 
1718  ossimRefPtr<ossimImageData> tempTile =
1720  if (tempTile.valid())
1721  {
1722  //---
1723  // Note: Clip the cache tile(nitf block) to the image clipRect since
1724  // there are nitf blocks that go beyond the image dimensions, i.e.,
1725  // edge blocks.
1726  //---
1727  ossimIrect cr =
1728  tempTile->getImageRectangle().clipToRect(clipRect);
1729 
1730  theTile->loadTile(tempTile.get()->getBuf(),
1731  tempTile->getImageRectangle(),
1732  cr,
1734  result = true;
1735  }
1736  }
1737 
1738  return result;
1739 }
1740 
1742 {
1743 #if 0
1744  if (traceDebug())
1745  {
1747  << "ossimNitfTileSource::loadBlock DEBUG:"
1748  << " x: " << x << " y: " << y << endl;
1749  }
1750 #endif
1751 
1752  //---
1753  // The origin set in the cache tile must have the sub image offset in it
1754  // since "theTile" is relative to any sub image offset. This is so that
1755  // "theTile->loadTile(theCacheTile)" will work.
1756  //---
1757  ossimIpt origin(x, y);
1758 
1760  theCacheTile->setOrigin(origin);
1763  {
1764  readSize = getPartialReadSize(origin);
1765  }
1766  if((hdr->hasBlockMaskRecords())||
1767  (readSize != theReadBlockSizeInBytes))
1768  {
1770  }
1771 
1772  switch (theReadMode)
1773  {
1774  case READ_BIR:
1775  case READ_BIR_BLOCK:
1776  case READ_BIP:
1777  case READ_BIP_BLOCK:
1778  {
1779  std::streamoff p;
1780  if(getPosition(p, x, y, 0))
1781  {
1782  theFileStr->seekg(p, ios::beg);
1783  char* buf = (char*)(theCacheTile->getBuf());
1784  if (!theFileStr->read(buf, readSize))
1785  {
1786  theFileStr->clear();
1788  << "ossimNitfTileSource::loadBlock BIP Read Error!"
1789  << "\nReturning error..." << endl;
1791 
1792  return false;
1793  }
1794  }
1795  break;
1796  }
1797  case READ_BSQ_BLOCK:
1798  case READ_BIB_BLOCK:
1799  case READ_BIB:
1800  {
1801  //---
1802  // NOTE:
1803  // With some of these types we could do one read and get all bands.
1804  // The reads are done per for future enabling on band selection
1805  // at the image handler level.
1806  //---
1807  for (ossim_uint32 band = 0; band < theNumberOfInputBands; ++band)
1808  {
1809  ossim_uint8* buf =0;
1810  if(isVqCompressed(hdr->getCompressionCode())||
1811  hdr->getRepresentation().upcase().contains("LUT"))
1812  {
1813  buf = (ossim_uint8*)&(theCompressedBuf.front());
1814  }
1815  else
1816  {
1817  buf = (ossim_uint8*)(theCacheTile->getBuf(band));
1818  }
1819  std::streamoff p;
1820  if(getPosition(p, x, y, band))
1821  {
1822  theFileStr->seekg(p, ios::beg);
1823  if (!theFileStr->read((char*)buf, readSize))
1824  {
1825  theFileStr->clear();
1827  << "ossimNitfTileSource::loadBlock Read Error!"
1828  << "\nReturning error..." << endl;
1830  return false;
1831  }
1832  else if(hdr->getCompressionCode() == "C4")
1833  {
1835  (ossim_uint8*)&(theCompressedBuf.front()));
1836  }
1837 
1838  else if(hdr->getCompressionCode() == "M4")
1839  {
1841  (ossim_uint8*)&(theCompressedBuf.front()));
1842  }
1843  else if(hdr->getRepresentation().upcase().contains("LUT"))
1844  {
1846  (ossim_uint8*)&(theCompressedBuf.front()));
1847  }
1848  }
1849  }
1850  break;
1851  }
1852  case READ_JPEG_BLOCK:
1853  {
1854  if (uncompressJpegBlock(x, y) == false)
1855  {
1857  theFileStr->clear();
1859  << "ossimNitfTileSource::loadBlock Read Error!"
1860  << "\nReturning error..." << endl;
1861  return false;
1862  }
1863  break;
1864  }
1865  default:
1866  break;
1867  }
1868 
1869  if(thePackedBitsFlag)
1870  {
1872  }
1873  // Check for swap bytes.
1874  if (theSwapBytesFlag)
1875  {
1876  ossimEndian swapper;
1877  swapper.swap(theScalarType,
1878  theCacheTile->getBuf(),
1879  theCacheTile->getSize());
1880  }
1881 
1882  if ( !isVqCompressed(hdr->getCompressionCode()) )
1883  {
1885  }
1886 
1887  // Set the origin of the cache tile.
1889  if (theCacheEnabledFlag)
1890  {
1891  // Add it to the cache for the next time.
1893  }
1894 
1895  return true;
1896 }
1897 
1899 {
1900  ossim_uint8* tempBuf = new ossim_uint8[packedBuffer->getSizePerBandInBytes()];
1901  ossim_uint32 idx = 0;
1902  ossim_uint32 bandIdx = 0;
1903  ossim_uint32 h = packedBuffer->getHeight();
1904  ossim_uint32 w = packedBuffer->getWidth();
1905  ossim_uint32 maxIdx = w*h;
1906  ossim_uint32 bandCount = packedBuffer->getNumberOfBands();
1907  switch(packedBuffer->getScalarType())
1908  {
1909  case OSSIM_UINT8:
1910  {
1911 
1912  ossim_uint8* outputBuf = (ossim_uint8*)tempBuf;
1913  for(bandIdx = 0; bandIdx < bandCount; ++bandIdx)
1914  {
1915  ossimPackedBits packedBits((ossim_uint8*)packedBuffer->getBuf(bandIdx),
1917  for(idx = 0; idx < maxIdx; ++idx)
1918  {
1919  *outputBuf = (ossim_uint8)packedBits.getValueAsUint32(idx);
1920  ++outputBuf;
1921  }
1922 
1923  memcpy((char*)packedBuffer->getBuf(bandIdx),
1924  (char*)tempBuf,
1925  theCacheTile->getSizePerBandInBytes()*bandCount);
1926  }
1927  break;
1928  }
1929  case OSSIM_UINT16:
1930  {
1931 
1932  ossim_uint16* outputBuf = (ossim_uint16*)tempBuf;
1933  for(bandIdx = 0; bandIdx < bandCount; ++bandIdx)
1934  {
1935  ossimPackedBits packedBits((ossim_uint8*)packedBuffer->getBuf(bandIdx),
1937  for(idx = 0; idx < maxIdx; ++idx)
1938  {
1939  *outputBuf = (ossim_uint16)packedBits.getValueAsUint32(idx);
1940  ++outputBuf;
1941  }
1942 
1943  memcpy((char*)packedBuffer->getBuf(bandIdx),
1944  (char*)tempBuf,
1945  theCacheTile->getSizePerBandInBytes()*bandCount);
1946  }
1947  break;
1948  }
1949  case OSSIM_FLOAT:
1950  {
1951  ossim_float32* outputBuf = (ossim_float32*)tempBuf;
1952  for(bandIdx = 0; bandIdx < bandCount; ++bandIdx)
1953  {
1954  ossimPackedBits packedBits((ossim_uint8*)packedBuffer->getBuf(bandIdx),
1956  for(idx = 0; idx < maxIdx; ++idx)
1957  {
1958  *outputBuf = (ossim_float32)packedBits.getValueAsUint32(idx);
1959  ++outputBuf;
1960  }
1961 
1962  memcpy((char*)packedBuffer->getBuf(bandIdx),
1963  (char*)tempBuf,
1964  theCacheTile->getSizePerBandInBytes()*bandCount);
1965  }
1966  break;
1967  }
1968  default:
1969  {
1970  break;
1971  }
1972  }
1973  delete [] tempBuf;
1974 }
1975 
1977 {
1979 
1980  if(!hdr||!tile) return;
1981 
1982  if(!tile->getBuf()) return;
1983  ossimIpt tempOrigin = tile->getOrigin();
1984  ossim_uint32 blockNumber = getBlockNumber(tempOrigin);
1985  ossim_uint32 numberOfBands = tile->getNumberOfBands();
1986  ossim_uint32 band = 0;
1987 
1988  if(hdr->hasPadPixelMaskRecords())
1989  {
1990  if(hdr->hasTransparentCode())
1991  {
1992  ossim_uint32 idx = 0;
1993  ossim_uint32 maxIdx = tile->getWidth()*tile->getHeight();
1994 
1995  for (band = 0; band < numberOfBands; ++band)
1996  {
1997  if(hdr->getPadPixelMaskRecordOffset(blockNumber,
1998  band)!=0xffffffff)
1999  {
2000  switch(tile->getScalarType())
2001  {
2002  case OSSIM_UINT8:
2003  {
2004  ossim_uint8 transparentValue = hdr->getTransparentCode();
2005  ossim_uint8* buf = (ossim_uint8*)tile->getBuf(band);
2006  ossim_uint8 nullPix = (ossim_uint8)tile->getNullPix(band);
2007  for(idx = 0; idx < maxIdx; ++idx)
2008  {
2009  if(*buf == transparentValue)
2010  {
2011  *buf = nullPix;
2012  }
2013  ++buf;
2014  }
2015  break;
2016  }
2017  case OSSIM_USHORT11:
2018  case OSSIM_USHORT12:
2019  case OSSIM_USHORT13:
2020  case OSSIM_USHORT14:
2021  case OSSIM_USHORT15:
2022  case OSSIM_UINT16:
2023  {
2024  ossim_uint16 transparentValue = hdr->getTransparentCode();
2025  ossim_uint16* buf = (ossim_uint16*)tile->getBuf(band);
2026  ossim_uint16 nullPix = (ossim_uint16)tile->getNullPix(band);
2027  for(idx = 0; idx < maxIdx; ++idx)
2028  {
2029  if(*buf == transparentValue)
2030  {
2031  *buf = nullPix;
2032  }
2033  ++buf;
2034  }
2035  break;
2036  }
2037  case OSSIM_SINT16:
2038  {
2039  ossim_sint16 transparentValue = hdr->getTransparentCode();
2040  ossim_sint16* buf = (ossim_sint16*)tile->getBuf(band);
2041  ossim_sint16 nullPix = (ossim_sint16)tile->getNullPix(band);
2042  for(idx = 0; idx < maxIdx; ++idx)
2043  {
2044  if(*buf == transparentValue)
2045  {
2046  *buf = nullPix;
2047  }
2048  ++buf;
2049  }
2050  break;
2051  }
2052  default:
2053  {
2054  break;
2055  }
2056  }
2057  }
2058  }
2059  }
2060  }
2061 }
2062 
2063 
2065 {
2066  double result = ossimImageHandler::getMinPixelValue(band);
2067 
2068  if(thePackedBitsFlag)
2069  {
2070  if(result < 1.0) result = 1.0;
2071  }
2072 
2073  return result;
2074 }
2075 
2077 {
2078  double result = ossimImageHandler::getMaxPixelValue(band);
2079 
2081  if(hdr)
2082  {
2083  if(thePackedBitsFlag)
2084  {
2085  double test = 1<<(hdr->getBitsPerPixelPerBand());
2086 
2087  if(result > test) result = test;
2088  }
2089  else
2090  {
2091  ossim_int32 bitsPerPixel = hdr->getActualBitsPerPixelPerBand();
2092  switch (bitsPerPixel)
2093  {
2094  case 11:
2095  {
2096  if (result > 2047.0)
2097  {
2098  result = 2047.0;
2099  }
2100  break;
2101  }
2102  case 12:
2103  {
2104  if (result > 4095.0)
2105  {
2106  result = 4095.0;
2107  }
2108  break;
2109  }
2110  default:
2111  break;
2112  }
2113  }
2114  }
2115 
2116  return result;
2117 }
2118 
2120 {
2121  double result = ossimImageHandler::getNullPixelValue(band);
2122 
2123  if(thePackedBitsFlag)
2124  {
2125  if((result < 0) ||
2126  (result > getMaxPixelValue(band)))
2127  {
2128  result = 0.0;
2129  }
2130  }
2131 
2132 
2133  return result;
2134 }
2135 
2136 
2137 bool ossimNitfTileSource::getPosition(std::streamoff& streamPosition,
2138  ossim_uint32 x,
2139  ossim_uint32 y,
2140  ossim_uint32 band) const
2141 {
2142  //
2143  // NOTE: "theCacheSize is always relative to a block size except in
2144  // the case where a block is the entire image.
2145  //
2146  streamPosition = 0;
2147 
2149  if (!hdr)
2150  {
2151  return streamPosition;
2152  }
2153 
2154  ossim_uint64 blockNumber = getBlockNumber(ossimIpt(x,y));
2155 
2156 #if 0
2157  cout << "ossimNitfTileSource::getPosition blockNumber: "
2158  << blockNumber << endl;
2159 #endif
2160 
2161  streamPosition = (std::streamoff)hdr->getDataLocation(); // Position to first block.
2162  if(hdr->hasBlockMaskRecords())
2163  {
2164  ossim_uint64 blockOffset = hdr->getBlockMaskRecordOffset(blockNumber,
2165  band);
2166  if(blockOffset == 0xffffffff)
2167  {
2168  return false;
2169  }
2170  streamPosition += blockOffset;
2171  }
2172 
2173  switch (theReadMode)
2174  {
2175  case READ_BIB_BLOCK:
2176  {
2177  if(!hdr->hasBlockMaskRecords())
2178  {
2179  streamPosition +=
2180  (std::streamoff)((ossim_uint64)blockNumber *
2182  ((ossim_uint64)getBandOffset() * band);
2183  }
2184  else
2185  {
2186  streamPosition += (std::streamoff)((ossim_uint64)getBandOffset() * (ossim_uint64)band);
2187 
2188  }
2189  break;
2190  }
2191 
2192  case READ_BIB:
2193  {
2194  streamPosition +=
2195  (std::streamoff) ((ossim_uint64)blockNumber * (ossim_uint64)theReadBlockSizeInBytes)+
2197  break;
2198  }
2199 
2200  case READ_BSQ_BLOCK:
2201  {
2202 
2203  if(!hdr->hasBlockMaskRecords())
2204  {
2205  streamPosition += (std::streamoff)((ossim_uint64)blockNumber *
2208  (ossim_uint64)band);
2209  }
2210 
2211  break;
2212  }
2213  case READ_JPEG_BLOCK:
2214  {
2215  streamPosition += (std::streamoff)((ossim_uint64)blockNumber * (ossim_uint64)theReadBlockSizeInBytes);
2216  break;
2217  }
2218  default:
2219  {
2220  if(!hdr->hasBlockMaskRecords())
2221  {
2222  streamPosition += (std::streamoff)((ossim_uint64)blockNumber*(ossim_uint64)getBlockOffset());
2223  }
2224 
2225  break;
2226  }
2227  }
2228 
2229  return true;
2230 }
2231 
2233 {
2234  std::streampos bandOffset = 0;
2235 
2236  switch (theReadMode)
2237  {
2238  case READ_BIB_BLOCK:
2239  case READ_BIP_BLOCK:
2240  case READ_BIR_BLOCK:
2241  case READ_BIB:
2242  case READ_BIP:
2243  case READ_BIR:
2244  bandOffset = theBlockSizeInBytes;
2245  break;
2246 
2247  case READ_BSQ_BLOCK:
2248  bandOffset = getNumberOfBlocks() * theBlockSizeInBytes;
2249  break;
2250 
2251  default:
2252  break;
2253  }
2254 
2255  return bandOffset;
2256 }
2257 
2259 {
2260  std::streampos blockOffset = 0;
2261  std::streampos blockSizeInBytes = 0;
2262  if (getNumberOfBlocks() == 1)
2263  {
2264  blockSizeInBytes = theReadBlockSizeInBytes;
2265  }
2266  else
2267  {
2268  blockSizeInBytes = theBlockSizeInBytes;
2269  }
2270 
2271  switch (theReadMode)
2272  {
2273  case READ_BIB_BLOCK:
2274  case READ_BIB:
2275  // Band interleaved by block.
2276  blockOffset = blockSizeInBytes * theNumberOfInputBands;
2277  break;
2278 
2279  case READ_BIR_BLOCK:
2280  case READ_BSQ_BLOCK:
2281  case READ_BIP_BLOCK:
2282  case READ_BIP:
2283  case READ_BIR:
2284  // Blocks side by side.
2285  blockOffset = blockSizeInBytes;
2286  break;
2287  case READ_JPEG_BLOCK:
2288  blockSizeInBytes = theReadBlockSizeInBytes;
2289  break;
2290 
2291  default:
2292  break;
2293  }
2294 
2295  return blockOffset;
2296 }
2297 
2299 {
2301  if (!hdr)
2302  {
2303  return 0;
2304  }
2305 
2306  return static_cast<ossim_uint32>( hdr->getNumberOfBlocksPerRow() *
2307  hdr->getNumberOfBlocksPerCol() );
2308 }
2309 
2311  const char* prefix)
2312 {
2313  if ( !ossimImageHandler::loadState(kwl, prefix) )
2314  {
2315  if(traceDebug())
2316  {
2318  << "ossimNitfTileSource::loadState(kwl, prefix) DEBUG:"
2319  << "\nUnable to load, exiting..." << std::endl;
2320  }
2321  return false;
2322  }
2323 
2324  const char* lookup = kwl.find(prefix, "entry");
2325  if (lookup)
2326  {
2327  ossimString s(lookup);
2328  theCurrentEntry = s.toUInt32();
2329  }
2330 
2331  theOutputBandList.clear();
2332  ossimString bands = kwl.find(prefix, ossimKeywordNames::BANDS_KW);
2333  if (!bands.empty())
2334  {
2336  }
2337 
2338  lookup = kwl.find(prefix,ossimKeywordNames::ENABLE_CACHE_KW);
2339  if (lookup)
2340  {
2341  ossimString s(lookup);
2343  }
2344 
2345  if(traceDebug())
2346  {
2348  << "ossimNitfTileSource::loadState(kwl, prefix) DEBUG:"
2349  << "\nCurrent entry: " << theCurrentEntry
2350  << "\nCache enable flag: " << theCacheEnabledFlag
2351  << std::endl;
2352  }
2353 
2354  return open();
2355 }
2356 
2358  const char* prefix) const
2359 {
2360  // Add the entry number.
2361  kwl.add(prefix, "entry", theCurrentEntry, true);
2362 
2363  // Add the cache_enable flag.
2365 
2366  // Call the base class save state.
2367  return ossimImageHandler::saveState(kwl, prefix);
2368 }
2369 
2371 {
2372  return theScalarType;
2373 }
2374 
2376 {
2377  ossim_uint32 result = 0;
2378  bool needDefault = false;
2379  if(!theCacheSize.hasNans()&& theCacheSize.x > 0)
2380  {
2381  result = theCacheSize.x;
2382  if(result >= getBoundingRect().width())
2383  {
2384  needDefault = true;
2385  }
2386  }
2387  else
2388  {
2389  needDefault = true;
2390  }
2391  if(needDefault)
2392  {
2393  ossimIpt tileSize;
2394  ossim::defaultTileSize(tileSize);
2395  result = static_cast<ossim_uint32>(tileSize.x);
2396  }
2397  return result;
2398 }
2399 
2401 {
2402  ossim_uint32 result = 0;
2403  bool needDefault = false;
2404  if(!theCacheSize.hasNans()&& theCacheSize.y > 0)
2405  {
2406  result = theCacheSize.y;
2407  if(result >= getBoundingRect().height())
2408  {
2409  needDefault = true;
2410  }
2411  }
2412  else
2413  {
2414  needDefault = true;
2415  }
2416  if(needDefault)
2417  {
2418  ossimIpt tileSize;
2419  ossim::defaultTileSize(tileSize);
2420  result = static_cast<ossim_uint32>(tileSize.y);
2421  }
2422  return result;
2423 }
2424 
2426 {
2427  return theNumberOfInputBands;
2428 }
2429 
2431 {
2432  return theNumberOfOutputBands;
2433 }
2434 
2436 {
2437  ossim_uint32 result = 0;
2438  if (resLevel == 0)
2439  {
2441  if (hdr)
2442  {
2443  result = hdr->getNumberOfRows();
2444  }
2445  }
2446  else if (theOverview.valid())
2447  {
2448  result = theOverview->getNumberOfLines(resLevel);
2449  }
2450  return result;
2451 }
2452 
2454 {
2455  ossim_uint32 result = 0;
2456  if (resLevel == 0)
2457  {
2459  if (hdr)
2460  {
2461  result = hdr->getNumberOfCols();
2462  }
2463  }
2464  else if (theOverview.valid())
2465  {
2466  result = theOverview->getNumberOfSamples(resLevel);
2467  }
2468  return result;
2469 }
2470 
2472 {
2473  ossim_uint32 blockNumber = 0;
2474 
2476  if (!hdr)
2477  {
2478  return blockNumber;
2479  }
2480 
2481  ossim_uint32 blockY;
2482  ossim_uint32 blockX;
2483  blockX = (block_origin.x /
2484  theCacheSize.x);
2485  blockY= (block_origin.y /
2486  theCacheSize.y);
2487 
2488  switch (theReadMode)
2489  {
2490  case READ_BIB_BLOCK:
2491  case READ_BIP_BLOCK:
2492  case READ_BIR_BLOCK:
2493  case READ_BSQ_BLOCK:
2494  case READ_JPEG_BLOCK:
2495  {
2496  blockNumber = ((blockY*hdr->getNumberOfBlocksPerRow()) + blockX);
2497  break;
2498  }
2499  case READ_BIB:
2500  case READ_BIP:
2501  case READ_BIR:
2502  //---
2503  // These read modes are for a single block image. The cache size will
2504  // be set to the width of the image (block) by the height of one tile.
2505  //
2506  // This is to avoid reading an entire large image with a single block
2507  // into memory.
2508  //---
2509  blockNumber = blockY;
2510  break;
2511 
2512  default:
2513  break;
2514  }
2515  return blockNumber;
2516 }
2517 
2519 {
2520  ossim_uint32 result = 0;
2522  if (!hdr)
2523  {
2524  return result;
2525  }
2526 
2528  {
2529  return theReadBlockSizeInBytes;
2530  }
2532 
2533  result = (theCacheSize.x*
2534  clipRect.height()*
2535  hdr->getBitsPerPixelPerBand())/8;
2536 
2537  switch (theReadMode)
2538  {
2539  case READ_BSQ_BLOCK:
2540  case READ_BIB_BLOCK:
2541  case READ_BIB:
2542  {
2543  // purposely left blank. only hear for clarity.
2544  break;
2545  }
2546 
2547  case READ_BIP_BLOCK:
2548  case READ_BIR_BLOCK:
2549  case READ_BIP:
2550  case READ_BIR:
2551  {
2552  result *= theNumberOfInputBands;
2553  break;
2554  }
2555  default:
2556  {
2557  break;
2558  }
2559  }
2560  return result;
2561 }
2562 
2563 bool ossimNitfTileSource::isVqCompressed(const ossimString& compressionCode)const
2564 {
2565  return((compressionCode == "C4")||
2566  (compressionCode == "M4"));
2567 }
2568 
2569 
2571 {
2573  ossim_uint32 tileSize = 0;
2574  if (!hdr)
2575  {
2576  return tileSize;
2577  }
2578  tileSize = hdr->getNumberOfPixelsPerBlockHoriz();
2579 
2580  if(tileSize >= getBoundingRect().width()) tileSize = 0;
2581  return tileSize;
2582 }
2583 
2585 {
2587  ossim_uint32 tileSize = 0;
2588  if (!hdr)
2589  {
2590  return tileSize;
2591  }
2592  tileSize = hdr->getNumberOfPixelsPerBlockVert();
2593  if(tileSize >= getBoundingRect().height()) tileSize = 0;
2594  return tileSize;
2595 }
2596 
2598 {
2599  return ossimString("ossim_nitf");
2600 }
2601 
2603 {
2604  return ossimString("ossim nitf reader");
2605 }
2606 
2608 {
2609  return theCurrentEntry;
2610 }
2611 
2613 {
2614  return (ossim_uint32)theEntryList.size();
2615 }
2616 
2617 void ossimNitfTileSource::getEntryList(std::vector<ossim_uint32>& entryList)const
2618 {
2619  entryList = theEntryList;
2620 // entryList.resize(theNumberOfImages);
2621 // for (ossim_uint32 i = 0; i < theNumberOfImages; ++i)
2622 // {
2623 // entryList[i] = i;
2624 // }
2625 }
2626 
2628 {
2629  bool result = true;
2630  if (theCurrentEntry != entryIdx)
2631  {
2632  if ( isOpen() )
2633  {
2634  if ( entryIdx < theNumberOfImages )
2635  {
2636  // Clear the geometry.
2637  theGeometry = 0;
2638 
2639  // Must clear or openOverview will use last entries.
2641 
2642  theCurrentEntry = entryIdx;
2643  theOutputBandList.clear();
2644  //---
2645  // Since we were previously open and the the entry has changed we
2646  // need to reinitialize some things.
2647  //---
2648  result = allocate();
2649  if (result)
2650  {
2651  completeOpen();
2652  }
2653  }
2654  else
2655  {
2656  result = false; // Entry index out of range.
2657  }
2658  }
2659  else
2660  {
2661  //---
2662  // Not open.
2663  // Allow this knowing that the parseFile will check for out of range.
2664  //---
2665  theCurrentEntry = entryIdx;
2666  }
2667  }
2668 
2669  if(result)
2670  {
2671  if(theNitfImageHeader[theCurrentEntry]->getRepresentation().contains("LUT"))
2672  {
2673  theLut = theNitfImageHeader[theCurrentEntry]->createLut(0);
2674  }
2675 
2676 
2677  }
2678  return result;
2679 }
2680 
2682 {
2683  return theCacheEnabledFlag;
2684 }
2685 
2687 {
2688  if (flag != theCacheEnabledFlag)
2689  {
2690  // State of caching has changed...
2691 
2692  theCacheEnabledFlag = flag;
2693 
2694  if ( theCacheEnabledFlag) // Cache enabled.
2695  {
2697  newTileCache(theBlockImageRect, theCacheSize);
2698  }
2699  else // Cache disabled...
2700  {
2701  // Clean out the cache if there was one.
2702  if (theCacheId != -1)
2703  {
2705  theCacheId = -1;
2706  }
2707  }
2708  }
2709 }
2710 
2712 {
2713  if(theNitfFile.valid())
2714  {
2715  return theNitfFile->getHeader();
2716  }
2717 
2718  return 0;
2719 }
2720 
2722 {
2723  if(theNitfFile.valid())
2724  {
2725  return theNitfFile->getHeader();
2726  }
2727 
2728  return 0;
2729 }
2730 
2732 {
2733  if(theNitfImageHeader.size())
2734  {
2735  return theNitfImageHeader[theCurrentEntry].get();
2736  }
2737 
2738  return 0;
2739 }
2740 
2742 {
2743  if(theNitfImageHeader.size())
2744  {
2745  return theNitfImageHeader[theCurrentEntry].get();
2746  }
2747 
2748  return 0;
2749 }
2750 
2751 bool ossimNitfTileSource::getRgbBandList(std::vector<ossim_uint32>& bandList) const
2752 {
2753  bool result = false;
2755  const ossim_uint32 BANDS = getNumberOfOutputBands();
2756  const ossim_uint32 BOGUS = 99999;
2757  if ( hdr && (BANDS > 2) )
2758  {
2759  ossim_uint32 r = BOGUS;
2760  ossim_uint32 g = BOGUS;
2761  ossim_uint32 b = BOGUS;
2762 
2763  for ( ossim_uint32 i = 0; i < BANDS; ++i )
2764  {
2765  const ossimRefPtr<ossimNitfImageBand> imageBand = hdr->getBandInformation( i );
2766  if ( imageBand.valid() )
2767  {
2768  ossimString os = imageBand->getBandRepresentation();
2769  os.trim(); // Remove trailing spaces.
2770  os.upcase();
2771  if ( os == "R" )
2772  {
2773  r = i;
2774  }
2775  else if ( os == "G" )
2776  {
2777  g = i;
2778  }
2779  else if ( os == "B" )
2780  {
2781  b = i;
2782  }
2783 
2784  if ( ( i > 1 ) &&
2785  ( r != BOGUS ) && ( g != BOGUS ) && ( b != BOGUS ) )
2786  {
2787  result = true;
2788  bandList.resize(3);
2789  bandList[0] = r;
2790  bandList[1] = g;
2791  bandList[2] = b;
2792  break; // done...
2793  }
2794  }
2795  }
2796  // TODO: Derive rgb from ISUBCAT wavelength or other nitf tags.
2797  }
2798 
2799  return result;
2800 
2801 } // End: ossimNitfTileSource::getRgbBandList( ... )
2802 
2804 {
2805  theImageRect = imageRect;
2806  // now shift the internal block rect as well
2808 }
2809 
2811 {
2813  {
2815  return ossimRefPtr<ossimProperty>(p);
2816  }
2817  else
2818  {
2819  if(theNitfFile.valid())
2820  {
2821  if(getFileHeader())
2822  {
2824  if(p.valid())
2825  {
2826  p->setReadOnlyFlag(true);
2827  return p;
2828  }
2829  }
2830  }
2831  const ossimNitfImageHeader* imageHeader = getCurrentImageHeader();
2832  if(imageHeader)
2833  {
2834  ossimRefPtr<ossimProperty> p = imageHeader->getProperty(name);
2835  if(p.valid())
2836  {
2837  p->setReadOnlyFlag(true);
2838  return p;
2839  }
2840  }
2841  }
2842 
2843  return ossimImageHandler::getProperty(name);
2844 }
2845 
2847 {
2848  if (!property) return;
2849 
2850  ossimString name = property->getName();
2851 
2853  {
2855  property.get());
2856  if (obj)
2857  {
2859  }
2860  }
2861  else
2862  {
2864  }
2865 }
2866 
2867 void ossimNitfTileSource::getPropertyNames(std::vector<ossimString>& propertyNames)const
2868 {
2869  ossimImageHandler::getPropertyNames(propertyNames);
2870  propertyNames.push_back(ossimKeywordNames::ENABLE_CACHE_KW);
2871  if(getFileHeader())
2872  {
2873  getFileHeader()->getPropertyNames(propertyNames);
2874  }
2875  const ossimNitfImageHeader* imageHeader = getCurrentImageHeader();
2876  if(imageHeader)
2877  {
2878  imageHeader->getPropertyNames(propertyNames);
2879  }
2880 }
2881 
2883 {
2884  if(getCurrentImageHeader())
2885  {
2887  }
2888 
2889  return "U";
2890 }
2891 
2893 {
2895  if (!hdr||!destination)
2896  {
2897  return;
2898  }
2899  if((destination->getNumberOfBands()<3)||
2900  (!destination->getBuf())||
2901  (destination->getScalarType()!=OSSIM_UINT8)||
2902  (!theLut.valid()))
2903  {
2904  return;
2905  }
2906 
2907  if(destination->getNumberOfBands()!=theLut->getNumberOfBands())
2908  {
2909  return;
2910  }
2911 
2912  ossim_uint8* tempRows[3];
2913  tempRows[0] = (ossim_uint8*)destination->getBuf(0);
2914  tempRows[1] = (ossim_uint8*)destination->getBuf(1);
2915  tempRows[2] = (ossim_uint8*)destination->getBuf(2);
2916 
2917  ossim_uint8* srcPtr = source;
2918  ossim_uint32 compressionYidx = 0;
2919  ossim_uint32 compressionXidx = 0;
2920  ossim_uint32 uncompressIdx = 0;
2921  ossim_uint32 h = destination->getHeight();
2922  ossim_uint32 w = destination->getWidth();
2923 
2924  for(compressionYidx = 0; compressionYidx < h; ++compressionYidx)
2925  {
2926  for(compressionXidx = 0; compressionXidx < w; ++compressionXidx)
2927  {
2928  tempRows[0][uncompressIdx] = (*theLut)[*srcPtr][0];
2929  tempRows[1][uncompressIdx] = (*theLut)[*srcPtr][1];
2930  tempRows[2][uncompressIdx] = (*theLut)[*srcPtr][2];
2931  ++srcPtr;
2932  ++uncompressIdx;
2933  }
2934  }
2935 }
2936 
2938  ossimRefPtr<ossimImageData> destination, ossim_uint8* source)
2939 {
2941  if (!hdr||!destination)
2942  {
2943  return;
2944  }
2945 
2946  const ossim_uint32 BANDS = destination->getNumberOfBands();
2947 
2948  if( ( (BANDS != 1) && (BANDS!=3) ) ||
2949  (!destination->getBuf()) ||
2950  (destination->getScalarType()!=OSSIM_UINT8) ||
2951  !theLut.valid() ||
2952  (theLut->getNumberOfBands() != BANDS) )
2953  {
2954  return;
2955  }
2956 
2957  ossimNitfVqCompressionHeader* compressionHeader =
2959  hdr->getCompressionHeader().get());
2960 
2961  if(!compressionHeader)
2962  {
2963  return;
2964  }
2965 
2966  const std::vector<ossimNitfVqCompressionOffsetTableData>& table =
2967  compressionHeader->getTable();
2968 
2970 
2971  if(!bandInfo.valid()) return;
2972 
2973  std::vector<ossimRefPtr<ossimNitfImageLut> > luts(BANDS);
2974  std::vector<ossim_uint8*> tempRows(BANDS);
2975 
2976  ossim_uint32 band;
2977  for (band =0; band<BANDS; ++band)
2978  {
2979  luts[band] = bandInfo->getLut(band);
2980  if ( luts[band].valid() )
2981  {
2982  tempRows[band] = (ossim_uint8*)destination->getBuf(band);
2983  }
2984  else
2985  {
2986  return;
2987  }
2988  }
2989 
2990  ossimPackedBits bits(source, compressionHeader->getImageCodeBitLength());
2991 
2992 
2993  const ossim_uint32 ROWS = static_cast<ossim_uint32>(table.size());
2994  const ossim_uint32 COLS =
2995  static_cast<ossim_uint32>(table[0].
2996  theNumberOfValuesPerCompressionLookup);
2997  const ossim_uint32 COMPRESSION_HEIGHT =
2998  compressionHeader->getNumberOfImageRows();
2999  const ossim_uint32 COMPRESSION_WIDTH =
3000  compressionHeader->getNumberOfImageCodesPerRow();
3001  ossim_uint32 DEST_WIDTH = destination->getWidth();
3002 
3003  ossim_uint32 compressionIdx = 0;
3004  ossim_uint32 uncompressIdx = 0;
3005  ossim_uint32 uncompressYidx = 0;
3006  ossim_uint8 lutValue = 0;
3007  ossim_uint8* data = 0;
3008  ossim_uint32 codeWord = 0;
3009 
3010  for(ossim_uint32 compressionYidx = 0;
3011  compressionYidx < COMPRESSION_HEIGHT;
3012  ++compressionYidx)
3013  {
3014  uncompressYidx = compressionYidx * ROWS * DEST_WIDTH;
3015 
3016  for(ossim_uint32 compressionXidx = 0;
3017  compressionXidx < COMPRESSION_WIDTH;
3018  ++compressionXidx)
3019  {
3020  uncompressIdx = uncompressYidx + COLS * compressionXidx;
3021 
3022  codeWord = bits.getValueAsUint32(compressionIdx++);
3023  codeWord *= COLS;
3024 
3025  for(ossim_uint32 rowIdx = 0; rowIdx < ROWS; ++rowIdx)
3026  {
3027  data = &(table[rowIdx].theData[codeWord]);
3028 
3029  for(ossim_uint32 colIdx = 0; colIdx < COLS; ++colIdx)
3030  {
3031  lutValue = (*data)&0xff;
3032 
3033  for (band = 0; band < BANDS; ++band)
3034  {
3035  ossim_uint8 p = (*theLut.get())[lutValue][band];
3036  tempRows[band][uncompressIdx+colIdx] = p;
3037  }
3038  ++data;
3039 
3040  } // column loop
3041 
3042  uncompressIdx += DEST_WIDTH;
3043 
3044  } // row loop
3045 
3046  } // x compression loop
3047 
3048  } // y compression loop
3049 }
3050 
3052  ossimRefPtr<ossimImageData> destination, ossim_uint8* source)
3053 {
3055  if (!hdr||!destination)
3056  {
3057  return;
3058  }
3059 
3060  const ossim_uint32 BANDS = destination->getNumberOfBands();
3061 
3062  if(( (BANDS != 1)&&(BANDS!=3) ) ||
3063  (!destination->getBuf())||
3064  (destination->getScalarType()!=OSSIM_UINT8))
3065  {
3066  return;
3067  }
3068 
3069  ossimNitfVqCompressionHeader* compressionHeader =
3071  hdr->getCompressionHeader().get());
3072 
3073  if(!compressionHeader)
3074  {
3075  return;
3076  }
3077 
3078  const std::vector<ossimNitfVqCompressionOffsetTableData>& table =
3079  compressionHeader->getTable();
3080 
3082 
3083  if(!bandInfo.valid()) return;
3084 
3085  std::vector<ossimRefPtr<ossimNitfImageLut> > luts(BANDS);
3086  std::vector<ossim_uint8*> tempRows(BANDS);
3087 
3088  ossim_uint32 band;
3089  for (band =0; band<BANDS; ++band)
3090  {
3091  luts[band] = bandInfo->getLut(band);
3092  if ( luts[band].valid() )
3093  {
3094  tempRows[band] = (ossim_uint8*)destination->getBuf(band);
3095  }
3096  else
3097  {
3098  return;
3099  }
3100  }
3101 
3102  const ossim_uint8 NI = 216; // null index (transparency index).
3103  const ossim_uint8 NP = 0; // null pixel
3104 
3105  ossim_uint32 destWidth = destination->getWidth();
3106  ossimPackedBits bits(source, compressionHeader->getImageCodeBitLength());
3107 
3108  ossim_uint32 compressionYidx = 0;
3109  ossim_uint32 compressionXidx = 0;
3110  ossim_uint32 compressionIdx = 0;
3111  ossim_uint32 uncompressIdx = 0;
3112  ossim_uint32 uncompressYidx = 0;
3113  ossim_uint32 rows = (ossim_uint32)table.size();
3114  ossim_uint32 cols = 0;
3115  ossim_uint32 rowIdx = 0;
3116  ossim_uint32 colIdx = 0;
3117  if(rows)
3118  {
3119  cols = table[0].theNumberOfValuesPerCompressionLookup;
3120  }
3121  ossim_uint32 compressionHeight = compressionHeader->getNumberOfImageRows();
3122  ossim_uint32 compressionWidth =
3123  compressionHeader->getNumberOfImageCodesPerRow();
3124  ossim_uint8 lutValue = 0;
3125  ossim_uint8* data=0;
3126 
3127  for(compressionYidx = 0;
3128  compressionYidx < compressionHeight;
3129  ++compressionYidx)
3130  {
3131  uncompressYidx = compressionYidx*rows*destWidth;
3132 
3133  for(compressionXidx = 0;
3134  compressionXidx < compressionWidth;
3135  ++compressionXidx)
3136  {
3137  uncompressIdx = uncompressYidx + cols*compressionXidx;
3138  ossim_uint32 codeWord = bits.getValueAsUint32(compressionIdx);
3139 
3140  bool transparent = false;
3141  if (codeWord == 4095)
3142  {
3143  //---
3144  // Check to see if the whole kernel is transparent. If no, the
3145  // null index '216' could be used for valid pixels.
3146  //
3147  // For more see docs:
3148  // MIL-PRF-89041A 3.13.1.2 Transparent pixels
3149  // MIL-STD-2411
3150  //---
3151  codeWord *= cols;
3152  transparent = true;
3153  for(rowIdx = 0; rowIdx < rows; ++rowIdx)
3154  {
3155  data = &table[rowIdx].theData[codeWord];
3156 
3157  for(colIdx = 0; colIdx < cols; ++colIdx)
3158  {
3159  lutValue = (*data)&0xff;
3160  if (lutValue != NI)
3161  {
3162  // Not a kernel full of transparent pixels.
3163  transparent = false;
3164  break;
3165  }
3166  ++data;
3167  }
3168  if (!transparent)
3169  {
3170  break;
3171  }
3172  uncompressIdx += destWidth;
3173  }
3174  }
3175 
3176  // Reset everyone for loop to copy pixel data from lut.
3177  uncompressIdx = uncompressYidx + cols*compressionXidx;
3178  codeWord = bits.getValueAsUint32(compressionIdx);
3179  codeWord *= cols;
3180 
3181  for(rowIdx = 0; rowIdx < rows; ++rowIdx)
3182  {
3183  data = &table[rowIdx].theData[codeWord];
3184 
3185  for(colIdx = 0; colIdx < cols; ++colIdx)
3186  {
3187  lutValue = (*data)&0xff;
3188 
3189  for (band = 0; band < BANDS; ++band)
3190  {
3191  ossim_uint8 p = luts[band]->getValue(lutValue);
3192  tempRows[band][uncompressIdx+colIdx] = (!transparent?p:NP);
3193  }
3194  ++data;
3195  }
3196 
3197  uncompressIdx += destWidth;
3198  }
3199  ++compressionIdx;
3200 
3201  } // x loop
3202 
3203  } // y loop
3204 }
3205 
3207 {
3208  // Find, capture all jpeg block offsets and sizes for an entry.
3209 
3210  bool allBlocksFound = false;
3211 
3213 
3214  if ( !hdr || (theReadMode != READ_JPEG_BLOCK) || !theFileStr )
3215  {
3216  return allBlocksFound; // Get out...
3217  }
3218 
3219  theNitfBlockOffset.clear();
3220  theNitfBlockSize.clear();
3221 
3222  //---
3223  // Get the totol blocks.
3224  // Note: There can be more than one jpeg image in the nitf. So after blocks
3225  // found equals total_blocks get out.
3226  //---
3227  ossim_uint32 total_blocks = hdr->getNumberOfBlocksPerRow()*hdr->getNumberOfBlocksPerCol();
3228 
3229  //---
3230  // NOTE:
3231  // SOI = 0xffd8 Start of image
3232  // EOI = 0xffd9 End of image
3233  // DHT = 0xffc4 Define Huffman Table(s)
3234  // DQT = 0xffdb Define Quantization Table(s)
3235  //---
3236 
3237  // Seek to the first block.
3238  theFileStr->seekg(hdr->getDataLocation(), ios::beg);
3239 
3240  if ( theFileStr->good() )
3241  {
3242  const ossim_uint8 AP6 = 0xe6;
3243  const ossim_uint8 AP7 = 0xe7;
3244  const ossim_uint8 DHT = 0xc4;
3245  const ossim_uint8 DQT = 0xdb;
3246  const ossim_uint8 EOI = 0xd9;
3247  const ossim_uint8 FF = 0xff;
3248  const ossim_uint8 SOI = 0xd8;
3249  const ossim_uint8 SOS = 0xda;
3250 
3251  union
3252  {
3253  char c;
3254  ossim_uint8 uc;
3255  } ct;
3256 
3257  std::streamoff soiOffset = 0;
3258  std::streamoff eoiOffset = 0;
3259  ossim_uint16 length = 0;
3260 
3261  ossimEndian* swapper = 0;
3263  {
3264  swapper = new ossimEndian();
3265  }
3266 
3267  // Find all the SOI markers.
3268  while ( theFileStr->get( ct.c ) && !allBlocksFound )
3269  {
3270  if ( ct.uc == FF ) // Found FF byte.
3271  {
3272  // Loop to skip multiple 0xff's in cases like FF FF D8
3273  while ( theFileStr->get( ct.c ) )
3274  {
3275  if ( ct.uc != FF)
3276  {
3277  break;
3278  }
3279  }
3280 
3281  if ( ct.uc == SOI )
3282  {
3283  // At SOI 0xFFD8 marker... SOI marker offset is two bytes back.
3284  soiOffset = ((std::streamoff)theFileStr->tellg()) - 2;
3285 
3286  // Now look for matching EOI.
3287  while ( theFileStr->get( ct.c ) )
3288  {
3289  if ( ct.uc == FF ) // Found FF byte.
3290  {
3291  // Loop to skip multiple 0xff's in cases like FF FF D8
3292  while ( theFileStr->get( ct.c ) )
3293  {
3294  if ( ct.uc != FF )
3295  {
3296  break;
3297  }
3298  }
3299 
3300  if ( ct.uc == EOI )
3301  {
3302  // At EOI 0xD9marker...
3303  eoiOffset = theFileStr->tellg();
3304 
3305  // Capture offset:
3306  theNitfBlockOffset.push_back( soiOffset );
3307 
3308  // Capture block size:
3309  theNitfBlockSize.push_back( eoiOffset - soiOffset );
3310 
3311  //---
3312  // Since there can be more than one jpeg entry in a file, breeak out of
3313  // loop when we hit block size.
3314  //---
3315  if ( theNitfBlockOffset.size() == total_blocks )
3316  {
3317  allBlocksFound = true;
3318  }
3319 
3320  break; // From "find EOI" while loop.
3321  }
3322  //---
3323  // These are things to skip to avoid hitting random sequence of FFD9
3324  // and picking up a false EOI.
3325  // Not a complete set of markers but all test data works.
3326  // drb - 14 May 2013.
3327  //---
3328  else if ( ( ct.uc == AP6 ) || ( ct.uc == AP7 ) || ( ct.uc == DHT ) ||
3329  ( ct.uc == DQT ) || ( ct.uc == SOS ) ||
3330  ( ( ct.uc >= 0xc0 ) && ( ct.uc <= 0xcF ) )
3331  )
3332  {
3333  // Length two byte big endian.
3334  theFileStr->read( (char*)&length, 2 );
3335  if ( swapper )
3336  {
3337  swapper->swap( length );
3338  }
3339  // Length includes two length bytes.
3340 
3341  // Seek to the end of the record.
3342  theFileStr->seekg( length - 2, std::ios_base::cur );
3343  }
3344 
3345  } // Matches: if ( ct.uc == FF )
3346 
3347  } // Matches: while ( theFileStr->get( ut.c ) ) "find EOI loop"
3348 
3349  } // Matches: if ( ut.uc == SOI ) "SOI marker found"
3350 
3351  } // Matches: if ( ut.uc == FF )
3352 
3353  } // Matches: while ( theFileStr->get( ut.c ) && !allBlocksFound )
3354 
3355  if ( swapper )
3356  {
3357  delete swapper;
3358  swapper = 0;
3359  }
3360 
3361  } // Matches: if ( theFileStr->good() )
3362 
3363  theFileStr->seekg(0, ios::beg);
3364  theFileStr->clear();
3365 
3366 #if 0 /* Please leave for debug. (drb) */
3367  std::streamoff startOfData = hdr->getDataLocation();
3368  ossimNotify(ossimNotifyLevel_WARN) << "current entry: " << theCurrentEntry << "\n";
3369  for (ossim_uint32 i = 0; i < total_blocks; ++i)
3370  {
3371  cout << "theNitfBlockOffset[" << i << "]: " << theNitfBlockOffset[i]
3372  << "\nrealative_offset[" << i << "]: " << (theNitfBlockOffset[i] - startOfData)
3373  << "\ntheNitfBlockSize[" << i << "]: " << theNitfBlockSize[i]
3374  << "\n";
3375  }
3376 #endif
3377 
3378  if ( !allBlocksFound )
3379  {
3380  if (traceDebug())
3381  {
3383  << "DEBUG:"
3384  << "\nBlock offset count wrong!"
3385  << "\nexpected blocks: " << total_blocks
3386  << "\noffset array count: " << theNitfBlockOffset.size()
3387  << "\nblock size array count: " << theNitfBlockSize.size()
3388  << std::endl;
3389  }
3390  theNitfBlockOffset.clear();
3391  theNitfBlockSize.clear();
3392  }
3393 
3394  return allBlocksFound;
3395 }
3396 
3398 {
3399  ossim_uint32 blockNumber = getBlockNumber( ossimIpt(x,y) );
3400 
3401  if (traceDebug())
3402  {
3404  << "ossimNitfTileSource::uncompressJpegBlock DEBUG:"
3405  << "\nblockNumber: " << blockNumber
3406  << std::endl;
3407  }
3408 
3409  //---
3410  // Logic to hold off on scanning for offsets until a block is actually needed
3411  // to speed up loads for things like ossim-info that don't actually read
3412  // pixel data.
3413  //---
3414  if ( m_jpegOffsetsDirty )
3415  {
3416  if ( scanForJpegBlockOffsets() )
3417  {
3418  m_jpegOffsetsDirty = false;
3419  }
3420  else
3421  {
3423  << "ossimNitfTileSource::uncompressJpegBlock scan for offsets error!"
3424  << "\nReturning error..." << endl;
3426  return false;
3427  }
3428  }
3429 
3430  if (traceDebug())
3431  {
3433  << "\noffset to block: " << theNitfBlockOffset[blockNumber]
3434  << "\nblock size: " << theNitfBlockSize[blockNumber]
3435  << std::endl;
3436  }
3437 
3438  // Seek to the block.
3439  theFileStr->seekg(theNitfBlockOffset[blockNumber], ios::beg);
3440 
3441  // Read the block into memory.
3442  std::vector<ossim_uint8> compressedBuf(theNitfBlockSize[blockNumber]);
3443  if (!theFileStr->read((char*)&(compressedBuf.front()),
3444  theNitfBlockSize[blockNumber]))
3445  {
3446  theFileStr->clear();
3448  << "ossimNitfTileSource::uncompressJpegBlock Read Error!"
3449  << "\nReturning error..." << endl;
3450  return false;
3451  }
3452 
3453  //---
3454  // Most of comments below from jpeg-6b "example.c" file.
3455  //---
3456 
3457  /* This struct contains the JPEG decompression parameters and pointers
3458  * to working space (which is allocated as needed by the JPEG library).
3459  */
3460  jpeg_decompress_struct cinfo;
3461 
3462  /* We use our private extension JPEG error handler.
3463  * Note that this struct must live as long as the main JPEG parameter
3464  * struct, to avoid dangling-pointer problems.
3465  */
3466  ossimJpegErrorMgr jerr;
3467 
3468  /* Step 1: allocate and initialize JPEG decompression object */
3469 
3470  /* We set up the normal JPEG error routines, then override error_exit. */
3471  cinfo.err = jpeg_std_error(&jerr.pub);
3472 
3473  jerr.pub.error_exit = ossimJpegErrorExit;
3474 
3475  /* Establish the setjmp return context for my_error_exit to use. */
3476  if (setjmp(jerr.setjmp_buffer))
3477  {
3478  /* If we get here, the JPEG code has signaled an error.
3479  * We need to clean up the JPEG object, close the input file, and return.
3480  */
3481  jpeg_destroy_decompress(&cinfo);
3482  return false;
3483  }
3484 
3485  /* Now we can initialize the JPEG decompression object. */
3486  jpeg_CreateDecompress(&cinfo, JPEG_LIB_VERSION, sizeof(cinfo));
3487 
3488  //---
3489  // Step 2: specify data source. In this case we will uncompress from
3490  // memory so we will use "ossimJpegMemorySrc" in place of " jpeg_stdio_src".
3491  //---
3492  ossimJpegMemorySrc (&cinfo,
3493  &(compressedBuf.front()),
3494  static_cast<size_t>(theReadBlockSizeInBytes));
3495 
3496  /* Step 3: read file parameters with jpeg_read_header() */
3497  jpeg_read_header(&cinfo, TRUE);
3498 
3499  // Check for Quantization tables.
3500  if (cinfo.quant_tbl_ptrs[0] == NULL)
3501  {
3502  // This will load table specified in COMRAT field.
3503  if (loadJpegQuantizationTables(cinfo) == false)
3504  {
3505  jpeg_destroy_decompress(&cinfo);
3506  return false;
3507  }
3508  }
3509 
3510  // Check for huffman tables.
3511  if (cinfo.ac_huff_tbl_ptrs[0] == NULL)
3512  {
3513  // This will load default huffman tables into .
3514  if (loadJpegHuffmanTables(cinfo) == false)
3515  {
3516  jpeg_destroy_decompress(&cinfo);
3517  return false;
3518  }
3519  }
3520 
3521  /* Step 4: set parameters for decompression */
3522 
3523  /* In this example, we don't need to change any of the defaults set by
3524  * jpeg_read_header(), so we do nothing here.
3525  */
3526 
3527  /* Step 5: Start decompressor */
3528  jpeg_start_decompress(&cinfo);
3529 
3530 #if 0 /* Please leave for debug. (drb) */
3531  if ( traceDebug() )
3532  {
3534  << "jpeg cinfo.output_width: " << cinfo.output_width
3535  << "\njpeg cinfo.output_height: " << cinfo.output_height
3536  << "\n";
3537  }
3538 #endif
3539 
3540  const ossim_uint32 SAMPLES = cinfo.output_width;
3541 
3542  //---
3543  // Note: Some nitf will be tagged with a given number of lines but the last
3544  // jpeg block may go beyond that to a complete block. So it you clamp to
3545  // last line of the nitf you will get a libjpeg error:
3546  //
3547  // "Application transferred too few scanlines"
3548  //
3549  // So here we will always read the full jpeg block even if it is beyond the
3550  // last line of the nitf.
3551  //---
3552  const ossim_uint32 LINES_TO_READ =
3553  min(static_cast<ossim_uint32>(theCacheSize.y), cinfo.output_height);
3554 
3555  /* JSAMPLEs per row in output buffer */
3556  const ossim_uint32 ROW_STRIDE = SAMPLES * cinfo.output_components;
3557 
3558  if ( (SAMPLES < theCacheTile->getWidth() ) ||
3559  (LINES_TO_READ < theCacheTile->getHeight()) )
3560  {
3562  }
3563 
3564  if ( (SAMPLES > theCacheTile->getWidth()) ||
3565  (LINES_TO_READ > theCacheTile->getHeight()) )
3566  {
3567  // Error...
3568  jpeg_finish_decompress(&cinfo);
3569  jpeg_destroy_decompress(&cinfo);
3570  return false;
3571  }
3572 
3573  // Get pointers to the cache tile buffers.
3574  std::vector<ossim_uint8*> destinationBuffer(theNumberOfInputBands);
3575  for (ossim_uint32 band = 0; band < theNumberOfInputBands; ++band)
3576  {
3577  destinationBuffer[band] = theCacheTile->getUcharBuf(band);
3578  }
3579 
3580  std::vector<ossim_uint8> lineBuffer(ROW_STRIDE);
3581  JSAMPROW jbuf[1];
3582  jbuf[0] = (JSAMPROW) &(lineBuffer.front());
3583 
3584  while (cinfo.output_scanline < LINES_TO_READ)
3585  {
3586  // Read a line from the jpeg file.
3587  jpeg_read_scanlines(&cinfo, jbuf, 1);
3588 
3589  //---
3590  // Copy the line which if band interleaved by pixel the the band
3591  // separate buffers.
3592  //
3593  // Note:
3594  // Not sure if IMODE of 'B' is interleaved the same as image with
3595  // IMODE of 'P'.
3596  //
3597  // This works with all samples with IMODE of B and P but I only have
3598  // one band 'B' and three band 'P'. So if we ever get a three band
3599  // 'B' it could be wrong here. (drb - 20090615)
3600  //---
3601  ossim_uint32 index = 0;
3602  for (ossim_uint32 sample = 0; sample < SAMPLES; ++sample)
3603  {
3604  for (ossim_uint32 band = 0; band < theNumberOfInputBands; ++band)
3605  {
3606  destinationBuffer[band][sample] = lineBuffer[index];
3607  ++index;
3608  }
3609  }
3610 
3611  for (ossim_uint32 band = 0; band < theNumberOfInputBands; ++band)
3612  {
3613  destinationBuffer[band] += theCacheSize.x;
3614  }
3615  }
3616 
3617  // clean up...
3618 
3619  jpeg_finish_decompress(&cinfo);
3620  jpeg_destroy_decompress(&cinfo);
3621 
3622  return true;
3623 }
3624 
3625 //---
3626 // Default JPEG quantization tables
3627 // Values from: MIL-STD-188-198, APPENDIX A
3628 //---
3630  jpeg_decompress_struct& cinfo) const
3631 {
3632  //---
3633  // Check to see if table is present. We will only look at the first table
3634  // in the array of arrays.
3635  //
3636  // NOTE: There are four tables in the array "cinfo.quant_tbl_ptrs". It
3637  // looks like the standard is to use the first table. (not sure though)
3638  //---
3639  if (cinfo.quant_tbl_ptrs[0] != NULL)
3640  {
3641  return false;
3642  }
3643 
3644  // Get the COMRAT (compression rate code) from the header:
3646  if (!hdr)
3647  {
3648  return false;
3649  }
3650 
3651  ossimString comrat = hdr->getCompressionRateCode();
3652  ossim_uint32 tableIndex = 0;
3653  if (comrat.size() >= 4)
3654  {
3655  // COMRAT string like: "00.2" = use table 2. (between 1 and 5).
3656  ossimString s;
3657  s.push_back(comrat[static_cast<std::string::size_type>(3)]);
3658  ossim_int32 comTbl = s.toInt32();
3659  if ( (comTbl > 0) && (comTbl < 6) )
3660  {
3661  tableIndex = comTbl-1;
3662  }
3663  else
3664  {
3666  << "ossimNitfTileSource::loadJpegQuantizationTables WARNING\n"
3667  << "\nNo quantization tables specified!"
3668  << endl;
3669  return false;
3670  }
3671  }
3672 
3673  cinfo.quant_tbl_ptrs[0] = jpeg_alloc_quant_table((j_common_ptr) &cinfo);
3674 
3675  JQUANT_TBL* quant_ptr = cinfo.quant_tbl_ptrs[0]; // quant_ptr is JQUANT_TBL*
3676 
3677  for (ossim_int32 i = 0; i < 64; ++i)
3678  {
3679  /* Qtable[] is desired quantization table, in natural array order */
3680  quant_ptr->quantval[i] = QTABLE_ARRAY[tableIndex][i];
3681  }
3682  return true;
3683 }
3684 
3685 //---
3686 // Default JPEG Huffman tables
3687 // Values from: MIL-STD-188-198, APPENDIX B
3688 //---
3690  jpeg_decompress_struct& cinfo) const
3691 {
3692  if ( (cinfo.ac_huff_tbl_ptrs[0] != NULL) &&
3693  (cinfo.dc_huff_tbl_ptrs[0] != NULL) )
3694  {
3695  return false;
3696  }
3697 
3698  cinfo.ac_huff_tbl_ptrs[0] = jpeg_alloc_huff_table((j_common_ptr)&cinfo);
3699  cinfo.dc_huff_tbl_ptrs[0] = jpeg_alloc_huff_table((j_common_ptr)&cinfo);
3700 
3701  ossim_int32 i;
3702  JHUFF_TBL* huff_ptr;
3703 
3704  // Copy the ac tables.
3705  huff_ptr = cinfo.ac_huff_tbl_ptrs[0]; /* huff_ptr is JHUFF_TBL* */
3706  for (i = 0; i < 16; ++i)
3707  {
3708  // huff_ptr->bits is array of 17 bits[0] is unused; hence, the i+1
3709  huff_ptr->bits[i+1] = AC_BITS[i];
3710  }
3711 
3712  for (i = 0; i < 256; ++i)
3713  {
3714  huff_ptr->huffval[i] = AC_HUFFVAL[i];
3715  }
3716 
3717  // Copy the dc tables.
3718  huff_ptr = cinfo.dc_huff_tbl_ptrs[0]; /* huff_ptr is JHUFF_TBL* */
3719  for (i = 0; i < 16; ++i)
3720  {
3721  // huff_ptr->bits is array of 17 bits[0] is unused; hence, the i+1
3722  huff_ptr->bits[i+1] = DC_BITS[i];
3723  }
3724 
3725  for (i = 0; i < 256; i++)
3726  {
3727  /* symbols[] is the list of Huffman symbols, in code-length order */
3728  huff_ptr->huffval[i] = DC_HUFFVAL[i];
3729  }
3730  return true;
3731 }
3732 
3733 // Protected to disallow use...
3735 {
3736 }
3737 
3738 // Protected to disallow use...
3740  const ossimNitfTileSource& /* rhs */)
3741 {
3742  return *this;
3743 }
virtual void deleteCache(ossimAppFixedCacheId cacheId)
bool parseStream(const ossimFilename &file, ossim::istream &in)
Parse stream method.
16 bit unsigned integer (15 bits used)
void clear()
Erases the entire container.
Definition: ossimString.h:432
virtual ossim_uint32 getWidth() const
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
ossim_uint32 x
virtual ossim_uint32 getTileWidth() const
Returns the width of the output tile.
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
ossim_uint32 getNumberOfEntries() const
ossimString getSecurityClassification() const
virtual ossim_int32 getNumberOfBands() const =0
ossimRefPtr< ossimImageGeometry > theGeometry
virtual double getMaxPixelValue(ossim_uint32 band=0) const
Returns the max pixel of the band.
virtual ossim_uint32 getNumberOfInputBands() const
bool loadJpegHuffmanTables(jpeg_decompress_struct &cinfo) const
Loads default huffman tables.
virtual ossimIrect getBlockImageRect() const =0
Blocks might not be the same size as the significant rows and cols used by the getImageRect.
std::vector< ossim_uint32 > theEntryList
virtual bool setCurrentEntry(ossim_uint32 entryIdx)
ossimString getStartRow() const
void setProjection(ossimProjection *projection)
Sets the projection to be used for local-to-world coordinate transformation.
virtual void initializeCacheTileInterLeaveType()
Initializes the data member "theCacheTileInterLeaveType".
virtual const ossimRefPtr< ossimNitfImageLut > getLut(ossim_uint32 idx) const =0
static ossimString upcase(const ossimString &aString)
Definition: ossimString.cpp:34
virtual ossim_uint32 getNumberOfBands() const
virtual ossim_int32 getNumberOfBlocksPerRow() const =0
virtual ossim_uint32 getNumberOfImageRows() const
virtual ossimString getRepresentation() const =0
64 bit floating point
virtual ossim_int32 getNumberOfRows() const =0
ossimFilename theImageFile
ossim_uint32 getNumberOfBands() const
virtual void setImageRectangle(const ossimIrect &rect)
void setBoundingRectangle(const ossimIrect &imageRect)
16 bit unsigned integer
ossimNitfImageHeader * getNewImageHeader(ossim_uint32 imageNumber) const
ossim_uint32 theNumberOfInputBands
virtual bool uncompressJpegBlock(ossim_uint32 x, ossim_uint32 y)
Uncompresses a jpeg block using the jpeg-6b library.
virtual const ossim_uint8 * getUcharBuf() const
virtual ossimString getPixelValueType() const =0
virtual void getDecimationFactor(ossim_float64 &result) const
Convenience method to get the decimation factor as a double from the string returned be the getImageM...
Represents serializable keyword/value map.
static const ossimErrorCode OSSIM_OK
ossim_uint32 y
virtual ossimString getIMode() const =0
std::basic_ifstream< char > ifstream
Class for char input file streams.
Definition: ossimIosFwd.h:44
bool valid() const
Definition: ossimRefPtr.h:75
std::shared_ptr< ossim::istream > theFileStr
virtual ossimString getCompressionRateCode() const =0
const char * find(const char *key) const
std::vector< ossimDpt > theDecimationFactors
IMODE = R "single block Band Interleaved By Row".
virtual const ossimRefPtr< ossimNitfImageBand > getBandInformation(ossim_uint32 idx) const =0
float ossim_float32
virtual ossimString getEntryString(ossim_int32 entry_number) const
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
std::ostream & print(std::ostream &out) const
Prints contents to output stream.
virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel=0) const =0
Pure virtual, derived classes must implement.
double y
Definition: ossimDpt.h:165
void setCacheEnabledFlag(bool flag)
ossim_uint32 height() const
Definition: ossimIrect.h:487
bool contains(char aChar) const
Definition: ossimString.h:58
ossimRefPtr< ossimNitfFile > theNitfFile
std::vector< ossim_uint32 > theNitfBlockSize
virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel=0) const
Returns the number of lines in the image.
ossim_uint32 theReadBlockSizeInBytes
virtual void initializeSwapBytesFlag()
Initializes the data member "theSwapBytesFlag" from the current entry.
virtual ossim_uint32 getTileHeight() const
Returns the height of the output tile.
void initializeLut()
Initializes "theLut" if applicable.
OSSIM_DLL void defaultTileSize(ossimIpt &tileSize)
16 bit signed integer
virtual ossimString getBandRepresentation() const =0
const ossimIpt & ul() const
Definition: ossimIrect.h:274
virtual ossimDataObjectStatus getDataObjectStatus() const
virtual ossim_uint32 getHeight() const
OSSIM_DLL ossimByteOrder byteOrder()
Definition: ossimCommon.cpp:54
16 bit unsigned integer (14 bits used)
static const ossimErrorCode OSSIM_ERROR
ossim_uint32 toUInt32() const
16 bit unsigned integer (13 bits used)
static StreamFactoryRegistry * instance()
virtual ossim_uint32 getNumberOfLuts() const =0
virtual void setReadOnlyFlag(bool flag)
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
ossim_uint32 getValueAsUint32(ossim_uint32 idx) const
Extract out the value at offset indicated by idx and convert the the vale to an ossim_uint32.
32 bit floating point
bool intersects(const ossimIrect &rect) const
Definition: ossimIrect.cpp:183
unsigned short ossim_uint16
virtual void setProperty(ossimRefPtr< ossimProperty > property)
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel=0) const
Returns the number of samples in the image.
virtual bool getRgbBandList(std::vector< ossim_uint32 > &bandList) const
Convenience method to get the zero based rgb output band list.
virtual double getNullPixelValue(ossim_uint32 band=0) const
Each band has a null pixel associated with it.
void initializeBandCount()
Initializes the data member "theNumberOfBands" from the current entry.
virtual ossim_uint32 getCurrentEntry() const
ossimInterleaveType theCacheTileInterLeaveType
std::vector< ossim_uint8 > theCompressedBuf
ossim_uint32 getNumberOfBlocks() const
IMODE = B, IC = C3 "JPEG compressed blocks".
virtual void initialize()
Initialize the data buffer.
virtual ossim_int32 getActualBitsPerPixelPerBand() const =0
virtual bool canUncompress(const ossimNitfImageHeader *hdr) const
static ossimAppFixedTileCache * instance(ossim_uint32 maxSize=0)
virtual bool hasPadPixelMaskRecords() const =0
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
virtual ossim_uint32 getSizePerBandInBytes() const
Returns the number of bytes in single band of the tile.
struct jpeg_error_mgr pub
virtual bool allocate()
Allocates everything for current entry.
virtual bool isValidRLevel(ossim_uint32 resLevel) const
Determines if the passed in reslution level is valid.
bool toSimpleVector(std::vector< T > &result, const ossimString &stringOfPoints)
Definition: ossimCommon.h:537
virtual double getMinPixelValue(ossim_uint32 band=0) const
Retuns the min pixel value.
ossim_int32 toInt32() const
bool completely_within(const ossimIrect &rect) const
Definition: ossimIrect.cpp:425
void vqUncompressM4(ossimRefPtr< ossimImageData > destination, ossim_uint8 *source)
Uncompresses Vector Quantization masked image data.
ossim_uint32 theBlockSizeInBytes
void push_back(char c)
Equivalent to insert(end(), c).
Definition: ossimString.h:905
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
virtual void loadTile(const void *src, const ossimIrect &src_rect, ossimInterleaveType il_type)
#define RTTI_DEF1_INST(cls, name, b1)
Definition: ossimRtti.h:481
virtual ossim_uint32 getNumberOfImageCodesPerRow() const
virtual ossimScalarType getOutputScalarType() const
Returns the output pixel type of the tile source.
static ossimScalarTypeLut * instance()
Returns the static instance of an ossimScalarTypeLut object.
virtual bool getOverviewTile(ossim_uint32 resLevel, ossimImageData *result)
Method to get an overview tile.
static ossimImageDataFactory * instance()
OSSIM_DLL void ossimJpegMemorySrc(jpeg_decompress_struct *cinfo, const ossim_uint8 *buffer, std::size_t bufsize)
Method which uses memory instead of a FILE* to read from.
virtual bool isOpen() const
Derived classes must implement this method to be concrete.
ossim_uint32 theNumberOfImages
ossimRefPtr< ossimImageData > getTile(ossimAppFixedCacheId cacheId, const ossimIpt &origin)
bool loadJpegQuantizationTables(jpeg_decompress_struct &cinfo) const
Loads one of the default tables based on COMRAT value.
virtual ossimDataObjectStatus validate() const
virtual ossimRefPtr< ossimImageGeometry > getImageGeometry()
Returns the image geometry object associated with this tile source or NULL if non defined...
virtual const ossimFilename & getFilename() const
Returns the filename.
signed short ossim_sint16
virtual ossim_uint32 getImageCodeBitLength() const
virtual ossimIrect getImageRect() const =0
IMODE = B of S "single block or one block for each band".
std::string::size_type size() const
Definition: ossimString.h:405
virtual void initializeScalarType()
Initializes the data member "theScalarType" from the current entry.
void initializeCacheTile()
Initializes the cache tile size(width and height).
32 bit signed integer
bool toBool() const
String to numeric methods.
virtual bool initializeImageRect()
Initializes the data members "theImageRect" and "theBlockRect" from the current entry.
unsigned long long ossim_uint64
const ossimNitfFileHeader * getHeader() const
const std::vector< ossimNitfVqCompressionOffsetTableData > & getTable() const
unsigned int ossim_uint32
virtual ossim_int32 getNumberOfCols() const =0
virtual const ossim_float64 * getNullPix() const
ossim_uint32 getPartialReadSize(const ossimIpt &blockOrigin) const
ossimString trim(const ossimString &valueToTrim=ossimString(" \\)) const
this will strip lead and trailing character passed in.
virtual void close()
Closes file and destroys all memory allocated.
bool isVqCompressed(const ossimString &compressionCode) const
virtual ossimString getLongName() const
IMODE = S "Band Sequential".
virtual const ossimRefPtr< ossimNitfCompressionHeader > getCompressionHeader() const =0
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
#define PTR_CAST(T, p)
Definition: ossimRtti.h:321
void initializeCacheSize()
Initializes the data member "theCacheSize".
ossimRefPtr< ossimImageData > theCacheTile
virtual ossimIrect getImageRectangle() const
virtual bool parseFile()
Parses "theImageFile" and initializes all nitf headers.
virtual ossim_uint64 getDataLocation() const =0
const ossimIpt & lr() const
Definition: ossimIrect.h:276
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
const ossimNitfImageHeader * getCurrentImageHeader() const
ossimAppFixedTileCache::ossimAppFixedCacheId theCacheId
virtual ossimRefPtr< ossimImageData > create(ossimSource *owner, ossimScalarType scalar, ossim_uint32 bands=1) const
ossim_uint32 width() const
Definition: ossimIrect.h:500
bool loadTile(const ossimIrect &clipRect)
Returns true on success, false on error.
static const char * BANDS_KW
ossimIrect clipToRect(const ossimIrect &rect) const
Definition: ossimIrect.cpp:501
virtual void initializeOutputTile()
Initializes the output tile size(width and height).
virtual void establishDecimationFactors()
Virtual method determines the decimation factors at each resolution level.
void explodePackedBits(ossimRefPtr< ossimImageData > packedBuffer) const
std::streampos getBandOffset() const
bool initializeBlockSize()
Initializes the data member "theBlockSize" from the current entry.
Container class that holds both 2D transform and 3D projection information for an image Only one inst...
ossimScalarType
virtual void setOrigin(const ossimIpt &origin)
virtual void initializeCompressedBuf()
Initializes the data member theCompressedBuf.
virtual ossim_uint32 getBlockMaskRecordOffset(ossim_uint32 blockNumber, ossim_uint32 bandNumber) const =0
static ossimProjectionFactoryRegistry * instance()
virtual void getImageLocation(ossimIpt &loc) const =0
Gets the ILOC field as an ossimIpt.
virtual void getEntryList(std::vector< ossim_uint32 > &entryList) const
const ossimNitfFileHeader * getFileHeader() const
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
ossimScalarType theScalarType
virtual ossimScalarType getScalarType() const
virtual void makeBlank()
Initializes data to null pixel values.
const ossimProjection * getProjection() const
Access methods for projection (may be NULL pointer).
ossimRefPtr< ossimImageData > theTile
virtual void completeOpen()
Will complete the opening process.
virtual ossim_int32 getNumberOfPixelsPerBlockVert() const =0
16 bit unsigned integer (11 bits used)
static const char * ENABLE_CACHE_KW
virtual ossimString getCompressionCode() const =0
bool loadBlockFromCache(ossim_uint32 x, ossim_uint32 y, const ossimIrect &clipRect)
Loads a block of data to theCacheTile.
ossimRefPtr< ossimImageHandler > theOverview
IMODE = P "Band Interleaved By Pixel".
void lutUncompress(ossimRefPtr< ossimImageData > destination, ossim_uint8 *source)
virtual ossim_uint32 getImageTileWidth() const
Returns the tile width of the image or 0 if the image is not tiled.
This class defines an abstract Handler which all image handlers(loaders) should derive from...
virtual bool open()
Returns true if the image_file can be opened and is a valid nitf file.
virtual ossimString getSecurityClassification() const =0
virtual ossim_uint32 getSize() const
Returns the total number of pixels in a tile for all bands.
virtual bool hasTransparentCode() const =0
This class will allow access to individual packed pixels given an offset and return as an ossim_uint3...
ossim_int32 y
Definition: ossimIpt.h:142
virtual bool scanForJpegBlockOffsets()
scans the file storing in offsets in "theNitfBlockOffset" and block sizes in "theNitfBlockSize".
void makeNan()
Definition: ossimIrect.h:329
virtual const void * getBuf() const
void setTransform(ossim2dTo2dTransform *transform)
Sets the transform to be used for local-to-full-image coordinate transformation.
ossimNitfTileSource & operator=(const ossimNitfTileSource &rhs)
Operator=, disallow...
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &tileRect, ossim_uint32 resLevel=0)
double x
Definition: ossimDpt.h:164
ossim_uint32 getBlockNumber(const ossimIpt &block_origin) const
ossimRefPtr< ossimNitfRegisteredTag > getTagData(const ossimString &tagName)
virtual ossim_int32 getBitsPerPixelPerBand() const =0
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
bool empty() const
Definition: ossimString.h:411
virtual ossim_uint32 getTransparentCode() const =0
void convertTransparentToNull(ossimRefPtr< ossimImageData > tile) const
void stretchToTileBoundary(const ossimIpt &tileWidthHeight)
Definition: ossimIrect.cpp:212
const ossim2dTo2dTransform * getTransform() const
Access methods for transform (may be NULL pointer).
virtual bool hasBlockMaskRecords() const =0
virtual ossim_uint32 getNumberOfOutputBands() const
ossim2dTo2dTransform * newTransform() const
ossimFilename theOverviewFile
virtual ossim_uint32 getImageTileHeight() const
Returns the tile width of the image or 0 if the image is not tiled.
void destroy()
Deletes all memory allocated by this object.
IMODE = B "Band Interleaved By Block or a single band".
virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel=0) const =0
Pure virtual, derived classes must implement.
bool parseFile(const ossimFilename &file)
virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0) const
Returns zero-based bounding rectangle of the image.
ossim_int32 x
Definition: ossimIpt.h:141
std::streampos getBlockOffset() const
virtual ossim_int32 getNumberOfBlocksPerCol() const =0
virtual double getMaxPixelValue(ossim_uint32 band=0) const
Returns the max pixel of the band.
ossimString getStartColumn() const
virtual std::shared_ptr< ossim::istream > createIstream(const std::string &connectionString, const ossimKeywordlist &options=ossimKeywordlist(), std::ios_base::openmode mode=std::ios_base::in|std::ios_base::binary) const
Will try to creates an istream interface to the connectionString passed in.
ossimRefPtr< ossimNBandLutDataObject > theLut
8 bit unsigned integer
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
virtual double getMinPixelValue(ossim_uint32 band=0) const
Retuns the min pixel value.
bool hasNans() const
Definition: ossimIpt.h:58
virtual ossim_int32 getNumberOfPixelsPerBlockHoriz() const =0
bool getPosition(std::streamoff &position, ossim_uint32 x, ossim_uint32 y, ossim_uint32 band) const
virtual bool isCompressed() const =0
32 bit floating point
virtual void initializeReadMode()
Initializes the data member "theReadMode" from the current entry.
virtual bool loadBlock(ossim_uint32 x, ossim_uint32 y)
Loads a block of data to theCacheTile.
virtual ossimString getShortName() const
virtual void setProperty(ossimRefPtr< ossimProperty > property)
virtual ossim_uint32 getPadPixelMaskRecordOffset(ossim_uint32 blockNumber, ossim_uint32 bandNumber) const =0
void vqUncompressC4(ossimRefPtr< ossimImageData > destination, ossim_uint8 *source)
Uncompresses Vector Quantization unmasked image data.
virtual bool allocateBuffers()
Allocates buffers for current entry.
IMODE = R "Band Interleaved By Row".
void swap(ossim_sint8 &)
Definition: ossimEndian.h:26
virtual double getNullPixelValue(ossim_uint32 band=0) const
Each band has a null pixel associated with it.
virtual const ossimIpt & getOrigin() const
unsigned char ossim_uint8
std::vector< ossim_uint32 > theOutputBandList
ossimRefPtr< ossimImageData > addTile(ossimAppFixedCacheId cacheId, ossimRefPtr< ossimImageData > data, bool duplicateData=true)
std::vector< ossimRefPtr< ossimNitfImageHeader > > theNitfImageHeader
std::vector< std::streamoff > theNitfBlockOffset
IMODE = P "single block Band Interleaved By Pixel".
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
virtual void establishDecimationFactors()
Virtual method determines the decimation factors at each resolution level.
OSSIM_DLL void ossimJpegErrorExit(jpeg_common_struct *cinfo)
Error routine that will replace jpeg&#39;s standard error_exit method.
#define min(a, b)
Definition: auxiliary.h:75
int ossim_int32
ossim_uint32 theStartingResLevel
theStartingResLevel If set to something other than zero(default) this is indicative that the reader i...
virtual bool isValid() const =0
isValid will test if the fields are valid and will return true or false.
ossim_uint32 theNumberOfOutputBands
16 bit unsigned integer (12 bits used)
bool isnan(const float &v)
isnan Test for floating point Not A Number (NAN) value.
Definition: ossimCommon.h:91
virtual ossim_int32 getNumberOfImages() const =0