OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimRpfCacheTileSource.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 //
3 // License: LGPL
4 //
5 // See LICENSE.txt file in the top level directory for more details.
6 //
7 // Author: Garrett Potts
8 //
9 //********************************************************************
10 // $Id: ossimRpfCacheTileSource.cpp 1361 2010-08-26 00:24:22Z david.burken $
11 #include <algorithm>
12 using namespace std;
13 
15 
21 #include <ossim/base/ossimCommon.h>
27 #include <ossim/base/ossimDatum.h>
28 #include <ossim/base/ossimNotify.h>
36 #include <ossim/base/ossimEndian.h>
37 #include <ossim/base/ossimTrace.h>
39 
40 static ossimTrace traceDebug = ossimTrace("ossimRpfCacheTileSource:debug");
41 
42 #ifdef OSSIM_ID_ENABLED
43 static const char OSSIM_ID[] = "$Id: ossimRpfCacheTileSource.cpp 1361 2010-08-26 00:24:22Z david.burken $";
44 #endif
45 
46 RTTI_DEF1(ossimRpfCacheTileSource, "ossimRpfCacheTileSource", ossimImageHandler)
47 
50 
52  :
54 
55  // a CADRG and CIBis a 64*64*12 bit buffer and must divide by 8 to
56  // convert to bytes
57  m_compressedBuffer(new ossim_uint8[(64*64*12)/8]),
58 
59  // whether CIB or CADRG we will alocate the buffer
60  // to the larger of the 2 (CADRG is 3 bands)
61  m_uncompressedBuffer(new ossim_uint8[256*256*3]),
62 
63  m_numberOfLines(0),
64  m_numberOfSamples(0),
65  m_tile(0),
66  m_fileNames(),
67  m_tileSize(128, 128),
68  m_productType(OSSIM_PRODUCT_TYPE_UNKNOWN),
69  m_workFrame(new ossimRpfFrame),
70  m_bBox_LL_Lon(0.0),
71  m_bBox_LL_Lat(0.0),
72  m_bBox_UR_Lon(0.0),
73  m_bBox_UR_Lat(0.0),
74  m_numOfFramesVertical(0),
75  m_numOfFramesHorizontal(0),
76  m_frameEntryArray()
77 {
78  if (traceDebug())
79  {
81  << "ossimRpfCacheTileSource::ossimRpfCacheTileSource entered...\n";
82 #ifdef OSSIM_ID_ENABLED
84  << "OSSIM_ID: " << OSSIM_ID << "\n";
85 #endif
86  }
87 
89 
90 }
91 
93 {
95  {
96  delete [] m_compressedBuffer;
98  }
100  {
101  delete [] m_uncompressedBuffer;
103  }
104  if(m_workFrame)
105  {
106  delete m_workFrame;
107  m_workFrame = 0;
108  }
109  close();
110 }
111 
113 {
114  return ossimString("RpfCache");
115 }
116 
118 {
119  return ossimString("RpfCache reader");
120 }
121 
122 
124 {
125  deleteAll();
126 }
127 
129 {
130  //return (theTableOfContents!=0);
132 
133  if(ext == "rpf")
134  {
135  return true;
136  }
137  else
138  {
139  return false;
140  }
141 }
142 
144 {
145  if(traceDebug())
146  {
147  ossimNotify(ossimNotifyLevel_DEBUG) << "ossimRpfCacheTileSource::open(): Entered....." << std::endl;
148  }
149 
150  ossimFilename imageFile = theImageFile;
151  bool result = true;
152 
153  if(isOpen() == false)
154  {
155  close();
156  result = false;
157  }
158 
159  if(result)
160  {
161  if (m_fileNames.size() == 0 && m_frameEntryArray.size() == 0)
162  {
163  if (buildFrameEntryArray(imageFile) == false)
164  {
165  return false;
166  }
167  }
168 
169  setCurrentEntry(0);
170  //---
171  // Adjust image rect so not to go over the -180 to 180 and -90 to 90
172  // bounds.
173  //---
175 
176  // Set the base class image file name.
177  theImageFile = imageFile;
179  m_tile->initialize();
180  }
181 
182  if(traceDebug())
183  {
184  ossimNotify(ossimNotifyLevel_DEBUG) << "ossimRpfCacheTileSource::open(): Leaving at line" << __LINE__ << std::endl;
185  }
186 
187  return result;
188 }
189 
191 {
192  static const char MODULE[] = "ossimRpfCacheTileSource::buildFrameEntryArray";
193  if ( traceDebug() )
194  {
195  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered..." << endl;
196  }
197 
198  std::ifstream in((imageFile).c_str() );
199 
200  std::string line;
201  ossim_uint32 index = 0; // used throughout
202  while( in.good() )
203  {
204  // Read in a line.
205  std::getline(in, line);
206 
207  ossimString tmpStr = ossimString(line);
208  if (!tmpStr.empty())
209  {
210  if (index == 0)
211  {
212  std::vector<ossimString> box_lat_lon;
213  tmpStr.split(box_lat_lon, "|");
214 
215  if (box_lat_lon.size() > 2)
216  {
217  std::vector<ossimString> ll;
218  std::vector<ossimString> ur;
219 
220  box_lat_lon[0].split(ll, ",");
221  box_lat_lon[1].split(ur, ",");
222  ossimString bandStr = box_lat_lon[2];
223 
224  m_bBox_LL_Lon = ll[0].toFloat64();
225  m_bBox_LL_Lat = ll[1].toFloat64();
226  m_bBox_UR_Lon = ur[0].toFloat64();
227  m_bBox_UR_Lat = ur[1].toFloat64();
228 
230 
231  ossim_int32 bands = ossimString(bandStr).toInt32();
232  if (bands == 1)
233  {
235  }
236  else if (bands == 3)
237  {
239  }
240  }
241  else
242  {
243  return false;
244  }
245  }
246  else if (index == 1)
247  {
248  m_fileNames.push_back(tmpStr);
249  std::vector<ossimString> frame_lat_lon = tmpStr.split("|");
250  if (frame_lat_lon.size() > 2)
251  {
252  ossimString ll_lon_lat = frame_lat_lon[1];
253  ossimString ur_lon_lat = frame_lat_lon[2];
254  ossim_float64 ll_lon = ossimString(ll_lon_lat.split(",")[0]).toDouble();
255  ossim_float64 ll_lat = ossimString(ll_lon_lat.split(",")[1]).toDouble();
256  ossim_float64 ur_lon = ossimString(ur_lon_lat.split(",")[0]).toDouble();
257  ossim_float64 ur_lat = ossimString(ur_lon_lat.split(",")[1]).toDouble();
258 
259  checkLongitude(ll_lon, ur_lon);
260 
261  ossim_float64 bBox_lat_diff = std::fabs(m_bBox_UR_Lat - m_bBox_LL_Lat);
262  ossim_float64 bBox_lon_diff = std::fabs(m_bBox_UR_Lon - m_bBox_LL_Lon);
263 
264  ossim_float64 lat_diff = std::fabs(ur_lat - ll_lat);
265  ossim_float64 lon_diff = std::fabs(ur_lon - ll_lon);
266 
267  m_numOfFramesVertical = static_cast<ossim_uint32>(bBox_lat_diff/lat_diff + 0.5);
268  m_numOfFramesHorizontal = static_cast<ossim_uint32>(bBox_lon_diff/lon_diff + 0.5);
269 
272 
273  if ( traceDebug() )
274  {
276  << "\nscene height in degrees: " << bBox_lat_diff
277  << "\nscene width in degrees: " << bBox_lon_diff
278  << "\nframe height in degrees: " << lat_diff
279  << "\nframe width in degrees: " << lon_diff
280  << "\nframes vertical: " << m_numOfFramesVertical
281  << "\nframes horizontal: " << m_numOfFramesHorizontal
282  << "\nlines: " << m_numberOfLines
283  << "\nsamples: " << m_numberOfSamples << "\n";
284  }
285  }
286  else
287  {
288  return false;
289  }
290  }
291  else
292  {
293  m_fileNames.push_back(tmpStr);
294  }
295 
296  } // matches: if (!tmpStr.empty())
297 
298  ++index;
299 
300  } // matches: while( in.good() )
301  in.close();
302 
304  for(index = 0; index < m_frameEntryArray.size(); ++index)
305  {
307  }
308 
309  for(index = 0; index < m_fileNames.size(); ++index)
310  {
311  ossimString tmpStr = m_fileNames[index];
312  std::vector<ossimString> frameInfos = tmpStr.split("|");
313  if (frameInfos.size() > 1)
314  {
315  ossimString fileName = frameInfos[0];
316  ossimString ll_lon_lat = frameInfos[1];
317  ossimString ur_lon_lat = frameInfos[2];
318  double ll_lon = ossimString(ll_lon_lat.split(",")[0]).toDouble();
319  double ll_lat = ossimString(ll_lon_lat.split(",")[1]).toDouble();
320  double ur_lon = ossimString(ur_lon_lat.split(",")[0]).toDouble();
321  double ur_lat = ossimString(ur_lon_lat.split(",")[1]).toDouble();
322 
323  checkLongitude(ll_lon, ur_lon);
324 
325  ossim_float64 tmpColPostion = std::fabs(ll_lon - m_bBox_LL_Lon);
326  ossim_float64 tmpFrameLon = std::fabs(ur_lon - ll_lon);
327 
328  ossim_float64 tmpRowPostion = std::fabs(m_bBox_UR_Lat - ur_lat);
329  ossim_float64 tmpFrameLat = std::fabs(ur_lat - ll_lat);
330 
331  ossim_uint32 colNum = static_cast<ossim_uint32>(tmpColPostion/tmpFrameLon + 0.5);
332  ossim_uint32 rowNum = static_cast<ossim_uint32>(tmpRowPostion/tmpFrameLat + 0.5);
333 
334  if (colNum >= m_numOfFramesHorizontal)
335  {
336  colNum = m_numOfFramesHorizontal-1; // Clamp to last column.
337  }
338 
339  if (rowNum >= m_numOfFramesVertical)
340  {
341  rowNum = m_numOfFramesVertical-1; // Clamp to last row.
342  }
343 
344  ossimRpfFrameEntry tempEntry;
345  tempEntry.setEntry(ossimFilename(""), fileName);
346  m_frameEntryArray[rowNum][colNum] = tempEntry;
347  }
348  else
349  {
350  return false;
351  }
352  }
353 
354  return true;
355 }
356 
358  const ossim_float64& rightLon) const
359 {
360  //---
361  // Test for scene coordinates being 180 to 180 and adjust leftLon to -180
362  // if so.
363  //
364  // NOTE:
365  // Setting tolerance to 1/7200 about 15 meters.
366  // Not sure if this is too loose or not. (drb)
367  //---
368  const ossim_float64 TOLERANCE = 0.000138889; // 1/7200 about 15 meters.
369 
370  if ( ossim::almostEqual(leftLon, 180.0, TOLERANCE) )
371  {
372  if ( ossim::almostEqual(rightLon, 180.0, TOLERANCE) )
373  {
374  leftLon = -180.0;
375  }
376  }
377 }
378 
380  const ossimIrect& rect, ossim_uint32 resLevel)
381 {
382  if (m_tile.valid())
383  {
384  // Image rectangle must be set prior to calling getTile.
385  m_tile->setImageRectangle(rect);
386 
387  if ( getTile( m_tile.get(), resLevel ) == false )
388  {
390  {
391  m_tile->makeBlank();
392  }
393  }
394  }
395 
396  return m_tile;
397 }
398 
400  ossim_uint32 resLevel)
401 {
402  bool status = false;
403 
404  //---
405  // Not open, this tile source bypassed, or invalid res level,
406  // return a blank tile.
407  //---
408  if( isOpen() && isSourceEnabled() && isValidRLevel(resLevel) &&
409  result && (result->getNumberOfBands() == getNumberOfOutputBands()) &&
411  {
412  if ( resLevel > 0 )
413  {
414  //---
415  // Check for overview tile. Some overviews can contain r0 so always
416  // call even if resLevel is 0 (if overview is not virtual). Method
417  // returns true on success, false on error.
418  //---
419  status = getOverviewTile(resLevel, result);
420  }
421 
422  if (!status) // Did not get an overview tile.
423  {
424  status = true;
425 
426  ossimIrect rect = result->getImageRectangle();
427 
428  ossimIrect imageRect = getImageRectangle();
429 
430  if ( rect.intersects(imageRect) )
431  {
432  //---
433  // Start with a blank tile in case there is not total coverage
434  // for rect.
435  //---
436  result->makeBlank();
437 
438  vector<ossimFrameEntryData> frames = getIntersectingEntries(rect);
439  if(frames.size() > 0)
440  {
441  //---
442  // Now lets render each frame. Note we will have to find
443  // subframes
444  // that intersect the rectangle of interest for each frame.
445  //---
446  fillTile(rect, frames, result);
447 
448  // Revalidate tile status.
449  result->validate();
450  }
451  }
452  else
453  {
454  result->makeBlank();
455  }
456  }
457  }
458 
459  return status;
460 }
461 
463 {
464  switch(m_productType)
465  {
467  {
468  return 0;
469  }
471  {
472  return 1;
473  }
475  {
476  return 3;
477  }
478  }
479 
480  return 0;
481 }
482 
484 {
485  switch(m_productType)
486  {
488  {
489  return 0;
490  }
492  {
493  return 1;
494  }
496  {
497  return 3;
498  }
499  }
500 
501  return 0;
502 }
503 
505 {
506  if (reduced_res_level == 0)
507  {
508  return m_numberOfLines;
509  }
510  else if (theOverview.valid())
511  {
512  return theOverview->getNumberOfLines(reduced_res_level);
513  }
514 
515  return 0;
516 }
517 
519 {
520  if (reduced_res_level == 0)
521  {
522  return m_numberOfSamples;
523  }
524  else if (theOverview.valid())
525  {
526  return theOverview->getNumberOfSamples(reduced_res_level);
527  }
528 
529  return 0;
530 }
531 
533 {
535 }
536 
538 {
539  return ossimIrect(0, // upper left x
540  0, // upper left y
541  getNumberOfSamples(reduced_res_level) - 1, // lower right x
542  getNumberOfLines(reduced_res_level) - 1); // lower right y
543 }
544 
546 {
547  if (theGeometry.valid()) return theGeometry;
548 
549  // datum
550  // WGS 84
551  ossimKeywordlist kwl;
552  const char* prefix = 0; // legacy
553  kwl.add(prefix,
555  "WGE",
556  true);
557 
562 
563  double latInterval = fabs(ul.latd() - lr.latd())/ getNumberOfLines();
564  double lonInterval = fabs(ul.lond() - ur.lond())/ getNumberOfSamples();
565 
566  kwl.add(prefix,
568  ul.latd(),//-(latInterval/2.0),
569  true);
570 
571  kwl.add(prefix,
573  ul.lond(),//+(lonInterval/2.0),
574  true);
575 
576  kwl.add(prefix,
578  ll.latd(),//+(latInterval/2.0),
579  true);
580 
581  kwl.add(prefix,
583  ll.lond(),//+(lonInterval/2.0),
584  true);
585 
586  kwl.add(prefix,
588  lr.latd(),//+(latInterval/2.0),
589  true);
590 
591  kwl.add(prefix,
593  lr.lond(),//-(lonInterval/2.0),
594  true);
595 
596  kwl.add(prefix,
598  ur.latd(),//-(latInterval/2.0),
599  true);
600 
601  kwl.add(prefix,
603  ur.lond(),//-(latInterval/2.0),
604  true);
605 
606  kwl.add(prefix,
609  true);
610 
611  kwl.add(prefix,
614  true);
615 
616  kwl.add(prefix,
619  true);
620 
621  kwl.add(prefix,
624  true);
625 
626 
627  //---
628  // Make a projection to get the easting / northing of the tie point and
629  // the scale in meters. This will only be used by the CIB.
630  //---
631  kwl.add(prefix,
633  "WGE",
634  true);
635 
636  ossimGpt origin((ul.latd()+lr.latd())*.5,
637  (ul.lond()+lr.lond())*.5,
638  0.0);
639 
640  double deltaLatPerPixel = latInterval;
641  double deltaLonPerPixel = lonInterval;
642 
643  ossimDpt tie;
644 
645  tie.lat = ul.latd() - deltaLatPerPixel/2.0;
646  tie.lon = ul.lond() + deltaLonPerPixel/2.0;
647 
648  kwl.add(prefix,
650  tie.toString(),
651  true);
652 
653  kwl.add(prefix,
655  deltaLatPerPixel,
656  true);
657 
658  kwl.add(prefix,
660  deltaLonPerPixel,
661  true);
662 
663  kwl.add(prefix,
665  origin.latd(),
666  true);
667 
668  kwl.add(prefix,
670  origin.lond(),
671  true);
672 
673  kwl.add(prefix,
675  ul.latd()-(deltaLatPerPixel/2.0),
676  true);
677 
678  kwl.add(prefix,
680  ul.lond()+(deltaLonPerPixel/2.0),
681  true);
682 
683  kwl.add(prefix,
685  "ossimEquDistCylProjection",
686  true);
687 
688  // Capture this for next time.
690  theGeometry->loadState(kwl, prefix);
691 
692  // Set image things the geometry object should know about.
694 
695  return theGeometry;
696 }
697 
699 {
700  return OSSIM_UCHAR;
701 }
702 
704 {
705  return m_tileSize.x;
706 }
707 
709 {
710  return m_tileSize.y;
711 }
712 
714 {
715  // Clear the geometry.
716  theGeometry = 0;
717 
718  // Must clear or openOverview will use last entries.
720 
721  if(!setEntryToRender(entryIdx))
722  {
723  return false;
724  }
725  completeOpen();
726 
727  return true;
728 }
729 
730 void ossimRpfCacheTileSource::getEntryList(std::vector<ossim_uint32>& entryList)const
731 {
732  entryList.push_back(0);
733 }
734 
736 {
737  if(isOpen())
738  {
739  populateLut();
740  return true;
741  }
742 
743  return false;
744 }
745 
747 {
748  if (reduced_res_level == 0)
749  {
750  return true;
751  }
752  else if (theOverview.valid())
753  {
754  return theOverview->isValidRLevel(reduced_res_level);
755  }
756  else
757  {
758  return false;
759  }
760 }
761 
762 vector<ossimRpfCacheTileSource::ossimFrameEntryData> ossimRpfCacheTileSource::getIntersectingEntries(const ossimIrect& rect)
763 {
764  vector<ossimFrameEntryData> result;
765 
766  // make sure we have the Toc entry to render
767  if(!isOpen()) return result;
768 
769  ossimIrect imageRect = getImageRectangle();
770  if(rect.intersects(imageRect))
771  {
772  ossimIrect clipRect = rect.clipToRect(imageRect);
773  ossimIrect frameRect(clipRect.ul().x/CIBCADRG_FRAME_WIDTH,
774  clipRect.ul().y/CIBCADRG_FRAME_HEIGHT,
775  clipRect.lr().x/CIBCADRG_FRAME_WIDTH,
776  clipRect.lr().y/CIBCADRG_FRAME_HEIGHT);
777 
778  for(ossim_int32 row = frameRect.ul().y; row <= frameRect.lr().y; ++row)
779  {
780  for(ossim_int32 col = frameRect.ul().x; col <= frameRect.lr().x; ++col)
781  {
782  ossimRpfFrameEntry tempEntry = m_frameEntryArray[row][col];
783  if(tempEntry.exists())
784  {
785  result.push_back(ossimFrameEntryData(row,
786  col,
789  tempEntry));
790  }
791  }
792  }
793  }
794 
795  return result;
796 }
797 
799  const ossimIrect& tileRect,
800  const vector<ossimFrameEntryData>& framesInvolved,
801  ossimImageData* tile)
802 {
803  ossim_uint32 idx = 0;
804  for(idx = 0;
805  idx < framesInvolved.size();
806  ++idx)
807  {
808 
809  if(m_workFrame->parseFile(framesInvolved[idx].theFrameEntry.getFullPath())
811  {
812  // we will fill a subtile. We pass in which frame it is and the position of the frame.
813  // the actual pixel will be 1536*row and 1536 *col.
815  {
817  tileRect,
818  framesInvolved[idx],
819  tile);
820  }
821  else
822  {
824  tileRect,
825  framesInvolved[idx],
826  tile);
827  }
828  }
829  }
830 }
831 
833  const ossimRpfFrame& aFrame,
834  const ossimIrect& tileRect,
835  const ossimFrameEntryData& frameEntryData,
836  ossimImageData* tile)
837 {;
838 // first let's grab the absolute position of the frame rectangle in pixel space
839  ossimIrect frameRect(frameEntryData.thePixelCol,
840  frameEntryData.thePixelRow,
841  frameEntryData.thePixelCol + CIBCADRG_FRAME_WIDTH - 1,
842  frameEntryData.thePixelRow + CIBCADRG_FRAME_HEIGHT - 1);
843 
844 
845 // now clip it to the tile
846  ossimIrect clipRect = tileRect.clipToRect(frameRect);
847 
848  const ossimRpfCompressionSection* compressionSection = aFrame.getCompressionSection();
849 
850  if(!compressionSection)
851  {
852  return;
853  }
854 
855  const vector<ossimRpfColorGrayscaleTable>& colorTable =
856  aFrame.getColorGrayscaleTable();
857 
858 // ESH 03/2009 -- Partial fix for ticket #646.
859 // Crash fix on reading RPFs: Make sure the colorTable vector
860 // has entries before trying to make use of them.
861  int numTables = (int)colorTable.size();
862  if ( numTables <= 0 )
863  {
864  return;
865  }
866 
867  ossim_uint8 *tempRows[3];
868 
869  tempRows[0] = m_uncompressedBuffer;
870  tempRows[1] = (m_uncompressedBuffer + 256*256);
871  tempRows[2] = (tempRows[1] + 256*256);
872 
873 // find the shift to 0,0
874  ossimIpt tempDelta(clipRect.ul().x - frameEntryData.thePixelCol,
875  clipRect.ul().y - frameEntryData.thePixelRow);
876 
877 
878 // In order to compute the subframe we will need the corner offsets of
879 // the upper left of the frame and the upper left of the clip rect. The
880 // clip rect should be completely within the frame. This just translates the value
881 // to make the upper left of the frame be 0,0.
882 //
883  ossimIrect offsetRect(tempDelta.x,
884  tempDelta.y,
885  tempDelta.x + clipRect.width()-1,
886  tempDelta.y + clipRect.height()-1);
887 
888 // each subframe is 64x64. We will actually use 256x256 since
889 // we will be uncompressing them. Note CADRG is a 256x256 tile
890 // compressed to 64x64x12 bit data
891 //
892  ossimIrect subFrameRect(offsetRect.ul().x/256,
893  offsetRect.ul().y/256,
894  (offsetRect.lr().x)/256,
895  (offsetRect.lr().y)/256);
896 
897  ossim_uint32 readPtr = 0;
898 
899  ossim_int32 row = 0;
900  ossim_int32 col = 0;
901  ossim_uint32 i = 0;
902  ossim_uint32 j = 0;
903  ossim_int32 upperY = subFrameRect.lr().y;
904  ossim_int32 upperX = subFrameRect.lr().x;
905  ossim_int32 lowerY = subFrameRect.ul().y;
906  ossim_int32 lowerX = subFrameRect.ul().x;
907  for(row = lowerY; row <= upperY; ++row)
908  {
909  for(col = lowerX; col <= upperX; ++col)
910  {
911  readPtr = 0;
912  if(aFrame.fillSubFrameBuffer(m_compressedBuffer, 0, row, col))
913  {
914  for (i = 0; i < 256; i += 4)
915  {
916  for (j = 0; j < 256; j += 8)
917  {
918  ossim_uint16 firstByte = m_compressedBuffer[readPtr++] & 0xff;
919  ossim_uint16 secondByte = m_compressedBuffer[readPtr++] & 0xff;
920  ossim_uint16 thirdByte = m_compressedBuffer[readPtr++] & 0xff;
921 
922  //because dealing with half-bytes is hard, we
923  //uncompress two 4x4 tiles at the same time. (a
924  //4x4 tile compressed is 12 bits )
925  // this little code was grabbed from openmap software.
926 
927  /* Get first 12-bit value as index into VQ table */
928  // I think we need to swap
929  ossim_uint16 val1 = (firstByte << 4) | (secondByte >> 4);
930 
931  /* Get second 12-bit value as index into VQ table*/
932  ossim_uint16 val2 = ((secondByte & 0x000F) << 8) | thirdByte;
933 
934  for (ossim_uint32 t = 0; t < 4; ++t)
935  {
936  for (ossim_uint32 e = 0; e < 4; ++e)
937  {
938  ossim_uint16 tableVal1 = compressionSection->getTable()[t].theData[val1*4 + e] & 0xff;
939  ossim_uint16 tableVal2 = compressionSection->getTable()[t].theData[val2*4 + e] & 0xff;
940 
941  ossim_uint32 pixindex = ((i+t)*256) +
942  (j + e);
943  const ossim_uint8* color1 = colorTable[0].getStartOfData(tableVal1);
944  const ossim_uint8* color2 = colorTable[0].getStartOfData(tableVal2);
945 
946 
947  tempRows[0][pixindex] = color1[0];
948  tempRows[1][pixindex] = color1[1];
949  tempRows[2][pixindex] = color1[2];
950 
951  tempRows[0][pixindex+4] = color2[0];
952  tempRows[1][pixindex+4] = color2[1];
953  tempRows[2][pixindex+4] = color2[2];
954  } //for e
955  } //for t
956  } /* for j */
957  } //for i
958  }
959  else
960  {
961  memset(m_uncompressedBuffer, 0, 256*256*3);
962  }
963  ossim_int32 tempCol = col*256;
964  ossim_int32 tempRow = row*256;
965  ossimIrect subRectToFill(frameRect.ul().x + tempCol,
966  frameRect.ul().y + tempRow,
967  frameRect.ul().x + tempCol + 255,
968  frameRect.ul().y + tempRow + 255);
970  subRectToFill,
971  OSSIM_BSQ);
972  }
973  }
974 }
975 
977  const ossimRpfFrame& aFrame,
978  const ossimIrect& tileRect,
979  const ossimFrameEntryData& frameEntryData,
980  ossimImageData* tile)
981 {
982  // first let's grab the absolute position of the frame rectangle in pixel
983  // space
984  ossimIrect frameRect(frameEntryData.thePixelCol,
985  frameEntryData.thePixelRow,
986  frameEntryData.thePixelCol + CIBCADRG_FRAME_WIDTH - 1,
987  frameEntryData.thePixelRow + CIBCADRG_FRAME_HEIGHT - 1);
988 
989 
990  // now clip it to the tile
991  ossimIrect clipRect = tileRect.clipToRect(frameRect);
992 
993  const ossimRpfCompressionSection* compressionSection = aFrame.getCompressionSection();
994 
995  if(!compressionSection)
996  {
997  return;
998  }
999 
1000  const vector<ossimRpfColorGrayscaleTable>& colorTable =
1001  aFrame.getColorGrayscaleTable();
1002 
1003  // ESH 03/2009 -- Partial fix for ticket #646.
1004  // Crash fix on reading RPFs: Make sure the colorTable vector
1005  // has entries before trying to make use of them.
1006  int numTables = (int)colorTable.size();
1007  if ( numTables <= 0 )
1008  {
1009  return;
1010  }
1011 
1012  // check to see if it does overlap. If it doesn't then the width and height
1013  // will be a single point
1014  {
1015  ossim_uint8 *tempRow;
1016 
1017  tempRow = m_uncompressedBuffer;
1018 
1019  // find the shift to 0,0
1020  ossimIpt tempDelta(clipRect.ul().x - frameEntryData.thePixelCol,
1021  clipRect.ul().y - frameEntryData.thePixelRow);
1022 
1023  // In order to compute the subframe we will need the corner offsets of
1024  // the upper left of the frame and the upper left of the clip rect. The
1025  // clip rect should be completely within the frame. This just translates the value
1026  // to make the upper left of the frame be 0,0.
1027  //
1028  ossimIrect offsetRect(tempDelta.x,
1029  tempDelta.y,
1030  tempDelta.x + clipRect.width()-1,
1031  tempDelta.y + clipRect.height()-1);
1032 
1033  // each subframe is 64x64. We will actually use 256x256 since
1034  // we will be uncompressing them. Note CADRG is a 256x256 tile
1035  // compressed to 64x64x12 bit data
1036  //
1037  ossimIrect subFrameRect(offsetRect.ul().x/256,
1038  offsetRect.ul().y/256,
1039  (offsetRect.lr().x)/256,
1040  (offsetRect.lr().y)/256);
1041 
1042  ossim_int32 row = 0;
1043  ossim_int32 col = 0;
1044  ossim_uint32 i = 0;
1045  ossim_uint32 j = 0;
1046  ossim_uint32 readPtr = 0;
1047  for(row = subFrameRect.ul().y; row <= subFrameRect.lr().y; ++row)
1048  {
1049  for(col = subFrameRect.ul().x; col <= subFrameRect.lr().x; ++col)
1050  {
1051  readPtr = 0;
1052  if(aFrame.fillSubFrameBuffer(m_compressedBuffer, 0, row, col))
1053  {
1054  for (i = 0; i < 256; i += 4)
1055  {
1056  for (j = 0; j < 256; j += 8)
1057  {
1058  ossim_uint16 firstByte = m_compressedBuffer[readPtr++] & 0xff;
1059  ossim_uint16 secondByte = m_compressedBuffer[readPtr++] & 0xff;
1060  ossim_uint16 thirdByte = m_compressedBuffer[readPtr++] & 0xff;
1061 
1062  //because dealing with half-bytes is hard, we
1063  //uncompress two 4x4 tiles at the same time. (a
1064  //4x4 tile compressed is 12 bits )
1065  // this little code was grabbed from openmap software.
1066 
1067  /* Get first 12-bit value as index into VQ table */
1068  // I think we need to swap
1069  ossim_uint16 val1 = (firstByte << 4) | (secondByte >> 4);
1070 
1071  /* Get second 12-bit value as index into VQ table*/
1072  ossim_uint16 val2 = ((secondByte & 0x000F) << 8) | thirdByte;
1073 
1074  for (ossim_uint32 t = 0; t < 4; ++t)
1075  {
1076  for (ossim_uint32 e = 0; e < 4; ++e)
1077  {
1078  ossim_uint16 tableVal1 = compressionSection->getTable()[t].theData[val1*4 + e] & 0xff;
1079  ossim_uint16 tableVal2 = compressionSection->getTable()[t].theData[val2*4 + e] & 0xff;
1080 
1081  ossim_uint32 pixindex = ((i+t)*256) + (j + e);
1082  const ossim_uint8* color1 = colorTable[0].getStartOfData(tableVal1);
1083  const ossim_uint8* color2 = colorTable[0].getStartOfData(tableVal2);
1084 
1085 
1086  tempRow[pixindex] = color1[0];
1087  tempRow[pixindex + 4] = color2[0];
1088  } //for e
1089  } //for t
1090  } /* for j */
1091  } //for i
1092  }
1093  else
1094  {
1095  memset(m_uncompressedBuffer, 0, 256*256);
1096  }
1097  ossim_int32 tCol = col*256;
1098  ossim_int32 tRow = row*256;
1099  ossimIrect subRectToFill(frameRect.ul().x + tCol,
1100  frameRect.ul().y + tRow,
1101  frameRect.ul().x + tCol + 255,
1102  frameRect.ul().y + tRow + 255);
1104  subRectToFill,
1105  OSSIM_BSQ);
1106  }
1107  }
1108  }
1109 }
1110 
1112 {
1114  {
1115  return;
1116  }
1118  {
1119  delete [] m_uncompressedBuffer;
1121  }
1122  if(m_compressedBuffer)
1123  {
1124  delete [] m_compressedBuffer;
1125  m_compressedBuffer = 0;
1126  }
1127 
1128  // a CADRG and CIBis a 64*64*12 bit buffer and must divide by 8 to
1129  // convert to bytes
1130  m_compressedBuffer = new ossim_uint8[(64*64*12)/8];
1132  {
1133  m_uncompressedBuffer = new ossim_uint8[256*256];
1134  }
1135  else
1136  {
1137  m_uncompressedBuffer = new ossim_uint8[256*256*3];
1138  }
1139 
1141  m_tile->initialize();
1142 }
1143 
1145 {
1146  theOverview = 0;
1147 }
1148 
1150  const char* prefix)const
1151 {
1152  bool result = ossimImageHandler::saveState(kwl, prefix);
1153 
1154  return result;
1155 }
1156 
1158  const char* prefix)
1159 {
1160  const char* MODULE = "ossimRpfCacheTileSource::loadState";
1161 
1162  if(traceDebug())
1163  {
1164  CLOG << "Entering..." << endl;
1165  }
1166  bool result = ossimImageHandler::loadState(kwl, prefix);
1167 
1168  if(!result)
1169  {
1170  if(traceDebug())
1171  {
1172  CLOG << "Leaving..." << endl;
1173  }
1174  return false;
1175  }
1176  const char* lookup = 0;
1177  lookup = kwl.find(ossimString(prefix), "entry");
1178  ossim_int32 entry = ossimString(lookup).toInt32();
1179 
1180  // if an entry is specified then
1181  // call the open with an entry number
1182  if(lookup)
1183  {
1184  if(traceDebug())
1185  {
1186  CLOG << "Leaving..." << endl;
1187  }
1189  setCurrentEntry(entry);
1190  return result;
1191  }
1192 
1194 
1195  return result;
1196 }
1197 
1199 {
1200  return 256;
1201 }
1202 
1204 {
1205  return 256;
1206 }
1207 
1209 {
1211 }
1212 
1214 {
1216 }
1217 
1219 {
1220  if(name == "file_type")
1221  {
1223  {
1224  return new ossimStringProperty("file_type", "CIB");
1225  }
1227  {
1228  return new ossimStringProperty("file_type", "CADRG");
1229  }
1230  return 0;
1231  }
1232  return ossimImageHandler::getProperty(name);
1233 }
1234 
1236 {
1237  theLut = 0;
1238  if(m_fileNames.size() > 0)
1239  {
1240  // bool found = false;
1241  ossimRpfFrameEntry tempEntry;
1242  ossimRpfFrame aFrame;
1243  ossimFilename fileName = m_fileNames[0].split("|")[0];
1244  // if (fileName.exists())
1245  // {
1246  // found = true;
1247  // }
1248 
1249  if(aFrame.parseFile(fileName)
1251  {
1252  const vector<ossimRpfColorGrayscaleTable>& colorTable =
1253  aFrame.getColorGrayscaleTable();
1254 
1255  // ESH 03/2009 -- Partial fix for ticket #646.
1256  // Crash fix on reading RPFs: Make sure the colorTable vector
1257  // has entries before trying to make use of them.
1258  int numTables = (int)colorTable.size();
1259 
1260  ossim_uint32 numElements = (numTables > 0) ? colorTable[0].getNumberOfElements() : 0;
1261  if(numElements > 0)
1262  {
1265  {
1266  theLut = new ossimNBandLutDataObject(numElements,
1267  3,
1268  OSSIM_UINT8);
1269  }
1270  else
1271  {
1272  theLut = 0;
1273  return;
1274  }
1275  ossim_uint32 idx = 0;
1276 
1277  for(idx = 0; idx < numElements;++idx)
1278  {
1279  const ossim_uint8* startOfData = colorTable[0].getStartOfData(idx);
1280  switch(m_productType)
1281  {
1283  {
1284  (*theLut)[idx][0] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(startOfData[0]);
1285  (*theLut)[idx][1] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(startOfData[0]);
1286  (*theLut)[idx][2] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(startOfData[0]);
1287  break;
1288  }
1290  {
1291  (*theLut)[idx][0] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(startOfData[0]);
1292  (*theLut)[idx][1] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(startOfData[1]);
1293  (*theLut)[idx][2] = (ossimNBandLutDataObject::LUT_ENTRY_TYPE)(startOfData[2]);
1294  break;
1295  }
1296  default:
1297  {
1298  break;
1299  }
1300  }
1301  }
1302  }
1303  }
1304  }
1305 }
1306 
1308 {
1309  theDecimationFactors.clear();
1310 
1311  // Just needed to set the first R level here, the base class can do the rest:
1313 }
1314 
virtual bool open()=0
Pure virtual open.
void clear()
Erases the entire container.
Definition: ossimString.h:432
std::vector< ossimString > m_fileNames
The size of the input frames.
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
Protected structure that is only used internally by this class.
virtual ossim_uint32 getTileWidth() const
Returns the width of the output tile.
void fillSubTileCib(const ossimRpfFrame &aFrame, const ossimIrect &tileRect, const ossimFrameEntryData &frameEntryData, ossimImageData *tile)
Will uncompress the CIB file using a VQ decompression algorithm.
ossimRefPtr< ossimImageGeometry > theGeometry
virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level=0) const
Satisfies pure virtual requirement from ImageHandler class.
virtual ossimScalarType getOutputScalarType() const
This method allows you to query the scalar type of the output data.
ossimIrect m_actualImageRect
This holds the image bounds for the current entry.
static const char * DECIMAL_DEGREES_PER_PIXEL_LAT
virtual bool setCurrentEntry(ossim_uint32 entryIdx)
virtual ossim_uint32 getNumberOfBands() const
static const char * DATUM_KW
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
Gets a property for matching name.
#define CLOG
Definition: ossimTrace.h:23
ossimFilename theImageFile
virtual void setImageRectangle(const ossimIrect &rect)
const std::vector< ossimRpfCompressionOffsetTableData > & getTable() const
double lond() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:97
static const char * CENTRAL_MERIDIAN_KW
void allocateForProduct()
Will allocate an internal buffer for the given product.
Represents serializable keyword/value map.
static const char * UL_LAT_KW
virtual void getEntryList(std::vector< ossim_uint32 > &entryList) const
static const ossimErrorCode OSSIM_OK
std::basic_ifstream< char > ifstream
Class for char input file streams.
Definition: ossimIosFwd.h:44
bool valid() const
Definition: ossimRefPtr.h:75
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Attempts to initialize a transform and a projection given the KWL.
const char * find(const char *key) const
std::vector< ossimDpt > theDecimationFactors
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
bool almostEqual(T x, T y, T tolerance=FLT_EPSILON)
Definition: ossimCommon.h:53
virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel=0) const =0
Pure virtual, derived classes must implement.
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &rect, ossim_uint32 resLevel=0)
Returns a pointer to an ossimImageDataObject given a rectangluar region of interest.
ossim_uint32 height() const
Definition: ossimIrect.h:487
virtual ossimString getShortName() const
This method is defined in the base class ossimObject.
static const char * NUMBER_LINES_KW
static const char * TIE_POINT_LON_KW
static const char * NUMBER_INPUT_BANDS_KW
const ossimIpt & ul() const
Definition: ossimIrect.h:274
static const char * LR_LON_KW
void split(std::vector< ossimString > &result, const ossimString &separatorList, bool skipBlankFields=false) const
Splits this string into a vector of strings (fields) using the delimiter list specified.
virtual ossimDataObjectStatus getDataObjectStatus() const
std::istream & getline(std::istream &is, ossimString &str, char delim)
Definition: ossimString.h:916
bool intersects(const ossimIrect &rect) const
Definition: ossimIrect.cpp:183
unsigned short ossim_uint16
double latd() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:87
static const char * TYPE_KW
virtual void initialize()
Initialize the data buffer.
virtual bool isValidRLevel(ossim_uint32 resLevel) const
Determines if the passed in reslution level is valid.
ossim_int32 toInt32() const
const vector< ossimRpfColorGrayscaleTable > & getColorGrayscaleTable() const
Definition: ossimRpfFrame.h:80
double ossim_float64
ossimRefPtr< ossimImageData > m_tile
This is the actual data returned from a getTile request.
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
virtual void loadTile(const void *src, const ossimIrect &src_rect, ossimInterleaveType il_type)
virtual ossim_uint32 getNumberOfOutputBands() const
This method allows one to query the number of output bands.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
vector< ossimFrameEntryData > getIntersectingEntries(const ossimIrect &rect)
It is important to note that each frame is organized into an easting northing type orientation...
virtual bool getOverviewTile(ossim_uint32 resLevel, ossimImageData *result)
Method to get an overview tile.
static ossimImageDataFactory * instance()
static const char * LR_LAT_KW
double lat
Definition: ossimDpt.h:165
virtual bool setEntryToRender(ossim_uint32 index)
Sets the entry to render.
bool fillSubFrameBuffer(ossim_uint8 *buffer, ossim_uint32 spectralGroup, ossim_uint32 row, ossim_uint32 col) const
static const ossim_uint32 CIBCADRG_FRAME_HEIGHT
CONSTANT representing the height of a Frame.
virtual ~ossimRpfCacheTileSource()
Destructor.
virtual ossimDataObjectStatus validate() const
static const char * TIE_POINT_XY_KW
virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level=0) const
virtual ossimString getLongName() const
This method is defined in the base class ossimObject.
bool buildFrameEntryArray(ossimFilename imageFile)
static const char * LL_LON_KW
virtual ossim_uint32 getImageTileHeight() const
Returns the tile width of the image or 0 if the image is not tiled.
ossimRpfCacheProductType m_productType
Holds the enumeration specifying the product type.
unsigned int ossim_uint32
bool isValidRLevel(ossim_uint32 reduced_res_level) const
static const char * NUMBER_OUTPUT_BANDS_KW
void setEntry(const ossimFilename &rootDirectory, const ossimFilename &pathToFrameFileFromRoot)
virtual ossimIrect getImageRectangle() const
static const char * DECIMAL_DEGREES_PER_PIXEL_LON
unsigned char * m_compressedBuffer
This is for storage of a single compressed buffer.
virtual ossimRefPtr< ossimImageGeometry > getImageGeometry()
Populates the geometry object with image geometry information.
static const char * LL_LAT_KW
virtual bool open()
Pure virtual open.
const ossimIpt & lr() const
Definition: ossimIrect.h:276
static ossimString downcase(const ossimString &aString)
Definition: ossimString.cpp:48
virtual ossimRefPtr< ossimImageData > create(ossimSource *owner, ossimScalarType scalar, ossim_uint32 bands=1) const
ossim_uint32 width() const
Definition: ossimIrect.h:500
void initImageParameters(ossimImageGeometry *geom) const
Convenience method to set things needed in the image geometry from the image handler.
ossimIrect clipToRect(const ossimIrect &rect) const
Definition: ossimIrect.cpp:501
double lon
Definition: ossimDpt.h:164
virtual void establishDecimationFactors()
Virtual method determines the decimation factors at each resolution level.
Container class that holds both 2D transform and 3D projection information for an image Only one inst...
ossimScalarType
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to load the state of an object from a keyword list.
virtual ossim_uint32 getImageTileWidth() const
Returns the tile width of the image or 0 if the image is not tiled.
static const char * ORIGIN_LATITUDE_KW
return status
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
ossimErrorCode parseFile(const ossimFilename &filename, bool minimalParse=false)
virtual void makeBlank()
Initializes data to null pixel values.
ossimRpfCacheTileSource()
Default constructor.
virtual void completeOpen()
Will complete the opening process.
ossimIpt m_tileSize
The size of the output tile.
std::vector< std::vector< ossimRpfFrameEntry > > m_frameEntryArray
ossimString toString(ossim_uint32 precision=15) const
Definition: ossimDpt.cpp:160
ossimRefPtr< ossimImageHandler > theOverview
virtual void establishDecimationFactors()
Virtual method determines the decimation factors at each resolution level.
void setActualImageRect()
Will shift the rect and clamp it so not to go outside the -180 to 180 degree range.
This class defines an abstract Handler which all image handlers(loaders) should derive from...
static const ossim_uint32 CIBCADRG_FRAME_WIDTH
CONSTANT representing the width of a Frame.
unsigned char * m_uncompressedBuffer
This is used as a buffer to uncompress the data to.
ossim_int32 y
Definition: ossimIpt.h:142
void fillSubTileCadrg(const ossimRpfFrame &aFrame, const ossimIrect &tileRect, const ossimFrameEntryData &frameEntryData, ossimImageData *tile)
Will uncompress the CADRG file using a VQ decompression algorithm.
void makeNan()
Definition: ossimIrect.h:329
void checkLongitude(ossim_float64 &leftLon, const ossim_float64 &rightLon) const
Method to test for 180.0 <–> 180.00 and set leftLon to -180 if both left and right are 180...
virtual ossim_uint32 getNumberOfInputBands() const
This method allows you to query the number of input bands.
static const char * UL_LON_KW
static const char * UR_LAT_KW
static const char * UR_LON_KW
bool empty() const
Definition: ossimString.h:411
class ossimNBandLutDataObject
ossimFilename theOverviewFile
void fillTile(const ossimIrect &tileRect, const vector< ossimFrameEntryData > &framesInvolved, ossimImageData *tile)
This is a wrapper for the fill cib and fill cadrg.
ossimString ext() const
virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel=0) const =0
Pure virtual, derived classes must implement.
ossim_int32 x
Definition: ossimIpt.h:141
virtual ossim_uint32 getTileHeight() const
Returns the height of the output tile.
static const char * TIE_POINT_LAT_KW
ossimRefPtr< ossimNBandLutDataObject > theLut
8 bit unsigned integer
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
const ossimRpfCompressionSection * getCompressionSection() const
Definition: ossimRpfFrame.h:76
virtual void close()
Closes this image handler and deletes any allocated data.
bool isOpen() const
Determines if its open if there eists a table of contents object.
static const char * NUMBER_SAMPLES_KW
unsigned char ossim_uint8
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level=0) const
Satisfies pure virtual requirement from ImageHandler class.
ossim_uint32 m_numberOfSamples
This will be computed based on the frames organized within the directory.
8 bit unsigned iteger
ossim_uint32 m_numberOfLines
This will be computed based on the frames organized within the directory.
int ossim_int32