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