Skip to content

Commit

Permalink
Support M3 compressed data.
Browse files Browse the repository at this point in the history
M3 data is the same as C3 (jpeg compression) with the addition of
a block mask.  This block mask indicates which blocks are empty
and not included in the file.

Remove faulty assumption that M3 data must have a pad pixel mask
even if the header says the pad pixel mask does not exist.

Remap the block offsets/sizes from masked to absolute so the normal
block lookup procedure works.

Tested on the AFRL Greene 07 dataset.
  • Loading branch information
Kris Jurka committed Jun 30, 2022
1 parent 975a149 commit 43b74e8
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 9 deletions.
38 changes: 34 additions & 4 deletions src/imaging/ossimNitfTileSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,7 @@ bool ossimNitfTileSource::canUncompress(const ossimNitfImageHeader* hdr) const
{
ossimString code = hdr->getCompressionCode();

if (code == "C3") // jpeg
if (code == "C3" || code == "M3") // jpeg
{
if (hdr->getBitsPerPixelPerBand() == 8)
{
Expand All @@ -708,7 +708,7 @@ bool ossimNitfTileSource::canUncompress(const ossimNitfImageHeader* hdr) const
if(traceDebug())
{
ossimNotify(ossimNotifyLevel_DEBUG)
<< "Entry with jpeg compression (C3) has an unsupported "
<< "Entry with jpeg compression (C3 or M3) has an unsupported "
<< "JPEG data precision: " << hdr->getBitsPerPixelPerBand()
<< std::endl;
}
Expand Down Expand Up @@ -744,7 +744,7 @@ void ossimNitfTileSource::initializeReadMode()
ossimString imode = hdr->getIMode();
ossimString compressionCode = hdr->getCompressionCode();

if ( (compressionCode == "C3") && ((imode == "B")||(imode == "P")) )
if ( (compressionCode == "C3" || compressionCode == "M3") && ((imode == "B")||(imode == "P")) )
{
theReadMode = READ_JPEG_BLOCK;
}
Expand Down Expand Up @@ -1144,7 +1144,7 @@ bool ossimNitfTileSource::initializeBlockSize()
{
theBlockSizeInBytes *= theNumberOfInputBands;
ossimString code = hdr->getCompressionCode();
if (code == "C3") // jpeg
if (code == "C3" || code == "M3") // jpeg
{
m_jpegOffsetsDirty = true;
}
Expand Down Expand Up @@ -3374,6 +3374,30 @@ bool ossimNitfTileSource::scanForJpegBlockOffsets()
theFileStr->seekg(0, ios::beg);
theFileStr->clear();

// We've got a masked image and we need to remap the masked block
// details to absolute block numbers so we can use them.
if (hdr->hasBlockMaskRecords()) {
// copy the masked block details so we can replace them.
vector<std::streamoff> offsets = theNitfBlockOffset;
vector<ossim_uint32> sizes = theNitfBlockSize;
theNitfBlockOffset.clear();
theNitfBlockSize.clear();

ossim_uint32 masked_idx = 0;
for (ossim_uint32 block=0; block<total_blocks; block++) {
ossim_uint32 offset = hdr->getBlockMaskRecordOffset(block, 0);
ossim_uint32 size = 0;
if (offset != 0xffffffff) {
offset = offsets[masked_idx];
size = sizes[masked_idx];
masked_idx++;
}
theNitfBlockOffset.push_back(offset);
theNitfBlockSize.push_back(size);
}
allBlocksFound = true;
}

#if 0 /* Please leave for debug. (drb) */
std::streamoff startOfData = hdr->getDataLocation();
ossimNotify(ossimNotifyLevel_WARN) << "current entry: " << theCurrentEntry << "\n";
Expand Down Expand Up @@ -3445,6 +3469,12 @@ bool ossimNitfTileSource::uncompressJpegBlock(ossim_uint32 x, ossim_uint32 y)
<< "\nblock size: " << theNitfBlockSize[blockNumber]
<< std::endl;
}

// We have a masked image and this is an empty tile.
if (theNitfBlockOffset[blockNumber] == 0xffffffff) {
theCacheTile->makeBlank();
return true;
}

// Seek to the block.
theFileStr->seekg(theNitfBlockOffset[blockNumber], ios::beg);
Expand Down
4 changes: 1 addition & 3 deletions src/support_data/ossimNitfImageHeaderV2_0.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,7 @@ void ossimNitfImageHeaderV2_0::parseStream(ossim::istream& in)
}
delete [] blockRead;
}
if((thePadPixelMaskRecordLength > 0)||
(( (getCompressionCode().upcase() == "M3"))&&
(thePadPixelMaskRecordLength == 0)))
if(thePadPixelMaskRecordLength > 0)
{
ossim_uint32 totalNumber = 0;
if(theImageMode[0] == 'S')
Expand Down
3 changes: 1 addition & 2 deletions src/support_data/ossimNitfImageHeaderV2_1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,7 @@ void ossimNitfImageHeaderV2_1::parseStream(ossim::istream& in, const ossimNitfFi
}
delete [] blockRead;
}
if( (thePadPixelMaskRecordLength > 0) ||
( (getCompressionCode().upcase() == "M3") && (thePadPixelMaskRecordLength == 0) ) )
if(thePadPixelMaskRecordLength > 0)
{
ossim_uint32 totalNumber = 0;
if(theImageMode[0] == 'S')
Expand Down

0 comments on commit 43b74e8

Please sign in to comment.