Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed crash with cloud optimized geotiffs(COGs) accessing wrong image #276

Merged
merged 1 commit into from
Nov 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/ossim/imaging/ossimTiffTileSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,10 @@ class OSSIMDLLEXPORT ossimTiffTileSource : public ossimImageHandler
std::vector<ossim_uint16> thePlanarConfig;
std::vector<ossim_uint16> thePhotometric;
std::vector<ossim_uint32> theRowsPerStrip;

// Holds the image file directory(IFD) for each image/mask level.
std::vector<ossim_uint32> theImageDirectoryList;
std::vector<ossim_uint32> theMaskDirectoryList;

/** theInputTileSize reflects the most efficient tiling scheme for reading from disk. If the
* image is tiled, then the output tile size will match the tiling on disk. If it is stripped,
Expand Down
9 changes: 6 additions & 3 deletions include/ossim/support_data/TiffHandlerState.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,9 +401,12 @@ namespace ossim
bool getMinSampleValue(ossim_float64 &minSampleValue, ossim_int32 directory = 0) const;
bool getMaxSampleValue(ossim_float64 &maxSampleValue, ossim_int32 directory = 0) const;
bool hasColorMap(ossim_int32 dir)const;
bool isReduced(ossim_int32 directory = 0) const;
bool isPage(ossim_int32 directory = 0) const;
bool isMask(ossim_int32 directory = 0) const;

// Overloaded for int not called from baseline.
// bool isReduced(ossim_int32 directory = 0) const;
// bool isPage(ossim_int32 directory = 0) const;
// bool isMask(ossim_int32 directory = 0) const;

bool isDigitalGlobe()const;
ossim_int32 getSubFileType(ossim_int32 directory = 0) const;
ossim_uint32 getNumberOfDirectories()const;
Expand Down
85 changes: 63 additions & 22 deletions src/imaging/ossimTiffTileSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ ossimTiffTileSource::ossimTiffTileSource()
thePhotometric(0),
theRowsPerStrip(0),
theImageDirectoryList(0),
theMaskDirectoryList(0),
theCurrentTiffRlevel(0),
theCompressionType(0),
theOutputBandList(0)
Expand Down Expand Up @@ -206,7 +207,7 @@ bool ossimTiffTileSource::getTile(ossimImageData *result,
reallocateBuffer = true;
}

if (getCurrentTiffRLevel() != theImageDirectoryList[level])
if (theCurrentDirectory != theImageDirectoryList[level])
{
status = setTiffDirectory(theImageDirectoryList[level]);
if (status)
Expand Down Expand Up @@ -405,6 +406,7 @@ bool ossimTiffTileSource::open(std::shared_ptr<ossim::istream> &str,
}
theImageFile = ossimFilename(connectionString);
theImageDirectoryList.clear();
theMaskDirectoryList.clear();

//---
// Note: The 'm' in "rm" is to tell TIFFOpen to not memory map the file.
Expand Down Expand Up @@ -556,29 +558,42 @@ bool ossimTiffTileSource::open(std::shared_ptr<ossim::istream> &str,
<< endl;
}

if (state->isReduced(dir))
if (dir != 0)
{
//---
// Check for a thumbnail image. If present don't use as it will mess with
// overviews. Currently only checking if it's a two directory image, i.e. a full
// res and a thumbnail.
//
// Note this shuts off the thumbnail which someone may want to see. We could make
// this a reader prop if it becomes an issue. drb - 09 Jan. 2012.
//---
if (dir != 0)
if (state->isReduced(dir))
{
//---
// Check for a thumbnail image. If present don't use as it will mess with
// overviews. Currently only checking if it's a two directory image, i.e. a full
// res and a thumbnail.
//
// Note this shuts off the thumbnail which someone may want to see. We could make
// this a reader prop if it becomes an issue. drb - 09 Jan. 2012.
//---
bool acceptAsRrdsLayer = true;
if ((theNumberOfDirectories == 2) && (dir == 1))
{
acceptAsRrdsLayer = isPowerOfTwoDecimation(dir);
}

if (acceptAsRrdsLayer)
{
theImageDirectoryList.push_back(dir);
}
}
else if ( (state->getSubFileType(dir) == FILETYPE_MASK) ||
(state->getSubFileType(dir) == 5) )
{
// sub_file_type of 5(bit mask) is not in tiff.h yet.
theMaskDirectoryList.push_back(dir);
}
else
{
ossimNotify(ossimNotifyLevel_WARN)
<< MODULE << " WARNING:\nUnhandled sub file type value!"
<< "IFD: " << dir << " sub file type: " << state->getSubFileType(dir)
<< std::endl;
}
}

thePlanarConfig[dir] = state->getPlanarConfig(dir);
Expand Down Expand Up @@ -1030,7 +1045,8 @@ bool ossimTiffTileSource::loadFromScanLine(const ossimIrect &clip_rect,
ossimInterleaveType type =
(thePlanarConfig[theCurrentDirectory] == PLANARCONFIG_CONTIG) ? OSSIM_BIP : OSSIM_BIL;

if (theBufferRLevel != getCurrentTiffRLevel() || !clip_rect.completely_within(theBufferRect))
if (theBufferRLevel != getCurrentTiffRLevel() ||
!clip_rect.completely_within(theBufferRect))
{
//***
// Must reload the buffer. Grab enough lines to fill the depth of the
Expand Down Expand Up @@ -1318,7 +1334,7 @@ bool ossimTiffTileSource::loadFromRgbaU8Tile(const ossimIrect &tile_rect,
ulTilePt.y +
theInputTileSize[theCurrentDirectory].y - 1);

if (getCurrentTiffRLevel() != theBufferRLevel ||
if (theBufferRLevel != getCurrentTiffRLevel() ||
tiff_tile_rect != theBufferRect)
{
// Need to grab a new tile.
Expand Down Expand Up @@ -1466,8 +1482,8 @@ bool ossimTiffTileSource::loadFromRgbaU8Strip(const ossimIrect &tile_rect,
// Loop through strips...
for (ossim_uint32 strip = starting_strip; strip <= ending_strip; strip++)
{
if ((theBufferRLevel != theCurrentDirectory) ||
(clip_rect.completely_within(theBufferRect) == false))
if (theBufferRLevel != getCurrentTiffRLevel() ||
!clip_rect.completely_within(theBufferRect))
{
if (TIFFReadRGBAStrip(theTiffPtr,
(strip * theRowsPerStrip[theCurrentDirectory]),
Expand All @@ -1480,7 +1496,7 @@ bool ossimTiffTileSource::loadFromRgbaU8Strip(const ossimIrect &tile_rect,
}

// Capture rect and rlevel of buffer:
theBufferRLevel = theCurrentDirectory;
theBufferRLevel = getCurrentTiffRLevel();
theBufferRect = ossimIrect(
0,
starting_strip,
Expand Down Expand Up @@ -1730,7 +1746,7 @@ bool ossimTiffTileSource::loadFromU16Strip(const ossimIrect &clip_rect, ossimIma
// Loop through strips....
for (ossim_uint32 strip = starting_strip; strip <= ending_strip; ++strip)
{
if ((theBufferRLevel != theCurrentDirectory) ||
if (theBufferRLevel != getCurrentTiffRLevel() ||
!clip_rect.completely_within(theBufferRect))
{
// Fill buffer block:
Expand Down Expand Up @@ -1788,7 +1804,7 @@ bool ossimTiffTileSource::loadFromU16Strip(const ossimIrect &clip_rect, ossimIma
if (status)
{
// Capture rect and rlevel of buffer:
theBufferRLevel = theCurrentDirectory;
theBufferRLevel = getCurrentTiffRLevel();
theBufferRect = ossimIrect(0,
startY,
theImageWidth[theCurrentDirectory] - 1,
Expand Down Expand Up @@ -2059,9 +2075,10 @@ std::ostream &ossimTiffTileSource::print(std::ostream &os) const
<< "\nmin_sample_value: " << theMinSampleValue
<< "\nmax_sample_value: " << theMaxSampleValue
<< "\nnull_sample_value: " << theNullSampleValue
<< "\nr0_is_full_res: " << theR0isFullRes
<< "\ntheNumberOfDirectories: " << theNumberOfDirectories
<< "\nr0_is_full_res: " << theR0isFullRes;

<< "\nimage_dirs: " << theImageDirectoryList.size();
for (ossim_uint32 i = 0; i < theNumberOfDirectories; ++i)
{
os << "\ndirectory[" << i << "]"
Expand All @@ -2085,6 +2102,30 @@ std::ostream &ossimTiffTileSource::print(std::ostream &os) const
os << endl;
}

os << "\nmask_dirs: " << theMaskDirectoryList.size();
for (ossim_uint32 i=0; i<(ossim_uint32)theMaskDirectoryList.size(); ++i )
{
ossim_uint32 ifdIndex = theMaskDirectoryList[i];
os << "\nmask_ifd_index: " << ifdIndex
<< "\nmask_width: " << theImageWidth[ifdIndex]
<< "\nmask_length: " << theImageLength[ifdIndex]
<< "\nmask_read method: " << getReadMethod(ifdIndex).c_str()
<< "\nmask_planar: " << thePlanarConfig[ifdIndex]
<< "\nmask_photometric: " << thePhotometric[ifdIndex];
if (theRowsPerStrip[ifdIndex])
{
os << "\nmask_rows_per_strip: " << theRowsPerStrip[ifdIndex];
}
if (theInputTileSize[i].x)
{
os << "\nmask_tile_width: " << theInputTileSize[i].x;
}
if (theInputTileSize[i].y)
{
os << "\nmask_tile_length: " << theInputTileSize[i].y;
}
}

if (theTile.valid())
{
os << "\nOutput tile dump:\n"
Expand Down Expand Up @@ -2665,7 +2706,7 @@ bool ossimTiffTileSource::allocateBuffer()
}

theBufferRect.makeNan();
theBufferRLevel = theCurrentDirectory;
theBufferRLevel = getCurrentTiffRLevel();

if (bSuccess && (buffer_size != theBufferSize))
{
Expand Down
28 changes: 20 additions & 8 deletions src/support_data/TiffHandlerState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ void ossim::TiffHandlerState::loadDefaults(std::shared_ptr<ossim::istream> &str,
m_tags.getSortedList(prefixValues, "tiff.image");
nValues = prefixValues.size();
addValue("tiff.number_of_directories", ossimString::toString(nValues));
ossim_uint32 idx = 0;
// ossim_uint32 idx = 0;
//ossim_int64 h = getImageLength(0);
//ossim_int64 w = getImageWidth(0);
ossim_int64 tw = getTileWidth(0);
Expand Down Expand Up @@ -222,13 +222,13 @@ void ossim::TiffHandlerState::loadDirectory(TIFF* tiffPtr,
{
ossim_uint32 imageWidth=0;
ossim_uint32 imageLength=0;
ossim_int32 readMethod=0;
// ossim_int32 readMethod=0;
ossim_uint16 planarConfig=0;
ossim_uint16 photometric=0;
ossim_uint32 rowsPerStrip=0;
ossim_uint32 imageTileWidth=0;
ossim_uint32 imageTileLength=0;
ossim_uint32 imageDirectoryList=0;
// ossim_uint32 imageDirectoryList=0;
ossim_int32 compressionType=0;
ossim_uint32 subFileType=0;
ossim_uint16 bitsPerSample=0;
Expand Down Expand Up @@ -435,7 +435,7 @@ void ossim::TiffHandlerState::loadGeotiffTags(TIFF* tiffPtr,
ossim_uint16 rasterType = 0;
ossim_uint16 pcsCode = 0;
ossim_uint16 coordTransGeoCode = 0;
ossim_uint32 idx = 0;
// ossim_uint32 idx = 0;
GTIF* gtif = GTIFNew(tiffPtr);
char citationStrPtr[CITATION_STRING_SIZE];
char* buf = 0;
Expand Down Expand Up @@ -693,17 +693,27 @@ bool ossim::TiffHandlerState::isDigitalGlobe() const

bool ossim::TiffHandlerState::isReduced(ossim_uint32 directory)const
{
return getSubFileType(directory)&FILETYPE_REDUCEDIMAGE;
// return getSubFileType(directory) & FILETYPE_REDUCEDIMAGE;
return getSubFileType(directory) == FILETYPE_REDUCEDIMAGE;
}

bool ossim::TiffHandlerState::isMask(ossim_uint32 directory)const
{
return getSubFileType(directory) & FILETYPE_MASK;
//---
// NOTE:
// sub_file_type of 5(bit mask) from cloud optimized geotiff(COG) sample
// is not in tiff.h yet. Not sure if it's standard yet. drb - 20211109
//---

// return getSubFileType(directory) & FILETYPE_MASK;
ossim_int32 sub_file_type = getSubFileType(directory);
return (sub_file_type == FILETYPE_MASK) || (sub_file_type == 5);
}

bool ossim::TiffHandlerState::isPage(ossim_uint32 directory)const
{
return getSubFileType(directory) & FILETYPE_PAGE;
// return getSubFileType(directory) & FILETYPE_PAGE;
return getSubFileType(directory) == FILETYPE_PAGE;
}

bool ossim::TiffHandlerState::isTiled(ossim_uint32 directory)const
Expand All @@ -717,7 +727,7 @@ void ossim::TiffHandlerState::convertArrayToStringList(ossimString& result, doub
result = "";
if(doubleArray && (doubleArraySize > 0))
{
ossim_int32 precision = 20;
// ossim_int32 precision = 20;
std::ostringstream doubleArrayStream;
doubleArrayStream << "(";
for(idx = 0; idx < doubleArraySize-1;++idx)
Expand Down Expand Up @@ -950,6 +960,7 @@ bool ossim::TiffHandlerState::hasColorMap(ossim_int32 directory)const
return exists(directory, "colormap");
}

#if 0 /* Overloaded methods for int32 dir not called in core. */
bool ossim::TiffHandlerState::isReduced(ossim_int32 directory) const
{

Expand All @@ -965,6 +976,7 @@ bool ossim::TiffHandlerState::isMask(ossim_int32 directory) const
{
return getSubFileType(directory) == FILETYPE_MASK;
}
#endif

ossim_int32 ossim::TiffHandlerState::getSubFileType(ossim_int32 directory) const
{
Expand Down