Skip to content

Commit

Permalink
Implemented ImagePyramidAccess:setBlankPatch
Browse files Browse the repository at this point in the history
  • Loading branch information
smistad committed Nov 22, 2024
1 parent f447f9a commit 5d201e6
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 10 deletions.
37 changes: 28 additions & 9 deletions source/FAST/Data/Access/ImagePyramidAccess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,19 @@ void jpegErrorExit(j_common_ptr cinfo) {
}

int ImagePyramidAccess::readTileFromTIFF(void *data, int x, int y, int level) {
const auto tileWidth = m_image->getLevelTileWidth(level);
const auto tileHeight = m_image->getLevelTileHeight(level);
const auto channels = m_image->getNrOfChannels();
TIFFSetDirectory(m_tiffHandle, level);
uint32_t tile_id = TIFFComputeTile(m_tiffHandle, x, y, 0, 0);
if(TIFFGetStrileByteCount(m_tiffHandle, tile_id) == 1) { // Blank patch
if(channels == 1) {
std::memset(data, 0, tileWidth*tileHeight*channels);
} else {
std::memset(data, 255, tileWidth*tileHeight*channels);
}
return 0;
}
// Assumes level (directory is already set)
if(m_compressionFormat == ImageCompression::NEURAL_NETWORK) {
auto decompressionModel = m_image->getDecompressionModel();
Expand All @@ -531,7 +544,6 @@ int ImagePyramidAccess::readTileFromTIFF(void *data, int x, int y, int level) {
shape[0] = 1;
int64_t size = shape.getTotalSize()*4;
float* buffer = new float[shape.getTotalSize()];
uint32_t tile_id = TIFFComputeTile(m_tiffHandle, x, y, 0, 0);
int bytesRead = TIFFReadRawTile(m_tiffHandle, tile_id, buffer, size);
auto tensor = Tensor::create(buffer, shape);
decompressionModel->connect(tensor);
Expand All @@ -548,11 +560,7 @@ int ImagePyramidAccess::readTileFromTIFF(void *data, int x, int y, int level) {
int bytesRead = 0;
if(m_compressionFormat == ImageCompression::JPEG) {
// Use libjpeg for decompression, as ome-tiff files doesn't seem to like tiff's internal jpeg
auto tileWidth = m_image->getLevelTileWidth(level);
auto tileHeight = m_image->getLevelTileHeight(level);
const auto channels = m_image->getNrOfChannels();
auto buffer = make_uninitialized_unique<char[]>(tileWidth*tileHeight*channels);
uint32_t tile_id = TIFFComputeTile(m_tiffHandle, x, y, 0, 0);
bytesRead = TIFFReadRawTile(m_tiffHandle, tile_id, buffer.get(), tileWidth*tileHeight*channels);

jpeg_decompress_struct cinfo;
Expand Down Expand Up @@ -582,11 +590,7 @@ int ImagePyramidAccess::readTileFromTIFF(void *data, int x, int y, int level) {
throw Exception("JPEG error: " + std::string(e.what())); // or return an error code
}
} else if(m_compressionFormat == ImageCompression::JPEGXL) {
auto tileWidth = m_image->getLevelTileWidth(level);
auto tileHeight = m_image->getLevelTileHeight(level);
const auto channels = m_image->getNrOfChannels();
auto buffer = make_uninitialized_unique<char[]>(tileWidth*tileHeight*channels);
uint32_t tile_id = TIFFComputeTile(m_tiffHandle, x, y, 0, 0);
bytesRead = TIFFReadRawTile(m_tiffHandle, tile_id, buffer.get(), tileWidth*tileHeight*channels);

JPEGXLCompression jxl;
Expand All @@ -604,5 +608,20 @@ void ImagePyramidAccess::setTIFFDirectory(int level) {
TIFFSetDirectory(m_tiffHandle, level);
}

void ImagePyramidAccess::setBlankPatch(int level, int x, int y) {
if(m_tiffHandle == nullptr)
throw Exception("setBlankPatch only available for TIFF backend ImagePyramids");

std::lock_guard<std::mutex> lock(m_readMutex);
TIFFSetDirectory(m_tiffHandle, level);
uint32_t tile_id = TIFFComputeTile(m_tiffHandle, x, y, 0, 0);
TIFFSetWriteOffset(m_tiffHandle, 0); // Set write offset to 0, so that we dont appen data
// Writing zero bytes, will produce a warning, thus we write 1 byte
char data = 0;
TIFFWriteRawTile(m_tiffHandle, tile_id, &data, 1);
TIFFCheckpointDirectory(m_tiffHandle);
m_initializedPatchList.insert(std::to_string(level) + "-" + std::to_string(tile_id));
}


}
1 change: 1 addition & 0 deletions source/FAST/Data/Access/ImagePyramidAccess.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class FAST_EXPORT ImagePyramidAccess : Object {
typedef std::unique_ptr<ImagePyramidAccess> pointer;
ImagePyramidAccess(std::vector<ImagePyramidLevel> levels, openslide_t* fileHandle, TIFF* tiffHandle, std::shared_ptr<ImagePyramid> imagePyramid, bool writeAccess, std::unordered_set<std::string>& initializedPatchList, std::mutex& readMutex, ImageCompression compressionFormat);
void setPatch(int level, int x, int y, std::shared_ptr<Image> patch, bool propagate = true);
void setBlankPatch(int level, int x, int y);
bool isPatchInitialized(uint level, uint x, uint y);
template <class T>
std::unique_ptr<T[]> getPatchData(int level, int x, int y, int width, int height);
Expand Down
3 changes: 2 additions & 1 deletion source/FAST/Data/ImagePyramid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ ImagePyramid::ImagePyramid(int width, int height, int channels, int patchWidth,
// TODO need to initialize somehow?
// We need to write the first tile for some reason... or we will get an error saying it is missing required
// TileOffsets
TIFFCheckpointDirectory(m_tiffHandle); // Need to check in the tile width and length tags, before writing a tile
if(m_compressionFormat == ImageCompression::JPEGXL) {
auto data = std::make_unique<uchar[]>(samplesPerPixel); // Is initialized to zeros
auto tileID = TIFFComputeTile(tiff, 0, 0, 0, 0);
Expand All @@ -166,9 +167,9 @@ ImagePyramid::ImagePyramid(int width, int height, int channels, int patchWidth,
}*/
// END

TIFFWriteDirectory(m_tiffHandle);
reportInfo() << "Done creating level " << currentLevel << reportEnd();
++currentLevel;
TIFFWriteDirectory(m_tiffHandle);
}

mBoundingBox = DataBoundingBox(Vector3f(getFullWidth(), getFullHeight(), 0));
Expand Down

0 comments on commit 5d201e6

Please sign in to comment.