Skip to content

Commit

Permalink
- Added special case for YCbCr TIFF files that are read upside down b…
Browse files Browse the repository at this point in the history
…y libtiff's readRGBATile

- Added WSIMaxValues to Patch to be able to get the extremes of an entire slide given a patch.
- Fixed correct disabling of VSI via macros
  • Loading branch information
GeertLitjens committed Jul 25, 2017
1 parent 711a150 commit 8979086
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 8 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ PROJECT(DIAGPathology)

SET(CURRENT_MAJOR_VERSION 1)
SET(CURRENT_MINOR_VERSION 7)
SET(CURRENT_PATCH_VERSION 1)
SET(CURRENT_PATCH_VERSION 3)
set(ASAP_VERSION ${CURRENT_MAJOR_VERSION}.${CURRENT_MINOR_VERSION}.${CURRENT_PATCH_VERSION})

include (GenerateExportHeader)
Expand Down
9 changes: 8 additions & 1 deletion core/Patch.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class Patch : public ImageSource {
bool _ownData;
std::vector<unsigned long long> _dimensions;
std::vector<unsigned long long> _strides;
std::vector<double> _wsiMinValues;
std::vector<double> _wsiMaxValues;
void calculateStrides();

void swap(Patch<T>& first, Patch<T>& second);
Expand All @@ -24,7 +26,7 @@ public :
~Patch();
Patch(const Patch& rhs);
Patch& operator=(const Patch rhs);
Patch(const std::vector<unsigned long long>& dimensions, const pathology::ColorType& ctype = pathology::Monochrome, T* data = NULL, bool ownData = true);
Patch(const std::vector<unsigned long long>& dimensions, const pathology::ColorType& ctype = pathology::Monochrome, T* data = NULL, bool ownData = true, std::vector<double> wsiMinValues = std::vector<double>(), std::vector<double> wsiMaxValues = std::vector<double>());

// Arithmetic operators
Patch<T> operator*(const T& val);
Expand All @@ -41,8 +43,13 @@ public :

std::vector<unsigned long long> getStrides();

double getWSIMinValue(int channel = -1) const;
double getWSIMaxValue(int channel = -1) const;

double getMinValue(int channel = -1);
double getMaxValue(int channel = -1);
double getMinValue(int channel = -1) const;
double getMaxValue(int channel = -1) const;

T getValue(const std::vector<unsigned long long>& index) const;
void setValue(const std::vector<unsigned long long>& index, const T& value);
Expand Down
62 changes: 60 additions & 2 deletions core/Patch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,32 @@ Patch<T>::~Patch()
}
}

template<typename T>
double Patch<T>::getWSIMinValue(int channel) const {
if (channel < 0) {
return *std::max_element(_wsiMinValues.begin(), _wsiMinValues.end());
}
else if (channel < _wsiMinValues.size()) {
return _wsiMinValues[channel];
}
else{
return std::numeric_limits<double>::max();
}
}

template<typename T>
double Patch<T>::getWSIMaxValue(int channel) const {
if (channel < 0) {
return *std::max_element(_wsiMaxValues.begin(), _wsiMaxValues.end());
}
else if (channel < _wsiMaxValues.size()) {
return _wsiMaxValues[channel];
}
else{
return std::numeric_limits<double>::min();
}
}

template<typename T>
double Patch<T>::getMinValue(int channel) {
double min = std::numeric_limits<double>::max();
Expand All @@ -85,6 +111,32 @@ double Patch<T>::getMaxValue(int channel) {
return max;
}

template<typename T>
double Patch<T>::getMinValue(int channel) const {
double min = std::numeric_limits<double>::max();
if (_buffer) {
for (int i = 0; i < _bufferSize; ++i) {
if (_buffer[i] < min) {
min = _buffer[i];
}
}
}
return min;
}

template<typename T>
double Patch<T>::getMaxValue(int channel) const {
double max = std::numeric_limits<double>::min();
if (_buffer) {
for (int i = 0; i < _bufferSize; ++i) {
if (_buffer[i] > max) {
max = _buffer[i];
}
}
}
return max;
}


template<typename T>
const int Patch<T>::getSamplesPerPixel() const {
Expand All @@ -102,7 +154,7 @@ const unsigned long long Patch<T>::getBufferSize() const {
}

template<typename T>
Patch<T>::Patch(const std::vector<unsigned long long>& dimensions, const pathology::ColorType& colorType, T* data, bool ownData) :
Patch<T>::Patch(const std::vector<unsigned long long>& dimensions, const pathology::ColorType& colorType, T* data, bool ownData, std::vector<double> wsiMinValues, std::vector<double> wsiMaxValues) :
ImageSource(),
_dimensions(dimensions),
_buffer(data),
Expand All @@ -128,6 +180,8 @@ Patch<T>::Patch(const std::vector<unsigned long long>& dimensions, const patholo
_colorType = pathology::Indexed;
}
}
this->_wsiMaxValues = wsiMaxValues;
this->_wsiMinValues = wsiMinValues;
calculateStrides();
_isValid = true;
}
Expand All @@ -139,7 +193,9 @@ Patch<T>::Patch(const Patch<T>& rhs) :
_dimensions(rhs._dimensions),
_ownData(true),
_strides(rhs._strides),
_buffer(NULL)
_buffer(NULL),
_wsiMinValues(rhs._wsiMinValues),
_wsiMaxValues(rhs._wsiMaxValues)
{
_buffer = new T[_bufferSize];
std::copy(rhs._buffer, rhs._buffer + rhs._bufferSize, _buffer);
Expand All @@ -153,6 +209,8 @@ void Patch<T>::swap(Patch<T>& first, Patch<T>& second) {
std::swap(first._buffer, second._buffer);
std::swap(first._bufferSize, second._bufferSize);
std::swap(first._ownData, second._ownData);
std::swap(first._wsiMinValues, second._wsiMinValues);
std::swap(first._wsiMaxValues, second._wsiMaxValues);
std::swap(first._strides, second._strides);
}

Expand Down
1 change: 1 addition & 0 deletions io/multiresolutionimageinterface/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ IF(BUILD_MULTIRESOLUTIONIMAGEINTERFACE_VSI_SUPPORT)
FIND_PACKAGE(DCMTKJPEG REQUIRED)
ADD_LIBRARY(multiresolutionimageinterface SHARED ${MULTIRESOLUTIONIMAGEINTERFACE_SRCS} ${MULTIRESOLUTIONIMAGEINTERFACE_HS} ${VSI_SOURCE_HS} ${VSI_SOURCE_SRCS})
TARGET_LINK_LIBRARIES(multiresolutionimageinterface PRIVATE ${DCMTKJPEG_LIBRARY} libtiff core libjasper libjpeg zlib pugixml Boost::disable_autolinking Boost::thread)
TARGET_COMPILE_DEFINITIONS(multiresolutionimageinterface PRIVATE HAS_MULTIRESOLUTIONIMAGEINTERFACE_VSI_SUPPORT)
ELSE(BUILD_MULTIRESOLUTIONIMAGEINTERFACE_VSI_SUPPORT)
ADD_LIBRARY(multiresolutionimageinterface SHARED ${MULTIRESOLUTIONIMAGEINTERFACE_SRCS} ${MULTIRESOLUTIONIMAGEINTERFACE_HS})
TARGET_LINK_LIBRARIES(multiresolutionimageinterface PRIVATE libtiff core libjasper libjpeg zlib pugixml Boost::disable_autolinking Boost::thread)
Expand Down
7 changes: 6 additions & 1 deletion io/multiresolutionimageinterface/MultiResolutionImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,12 @@ public :
for (unsigned int i = 0; i < _spacing.size(); ++i) {
patchSpacing[i] = _spacing[i] * levelDownsample;
}
Patch<T> patch = Patch<T>(dims, this->getColorType(), data, true);
std::vector<double> minValues, maxValues;
for (unsigned int i = 0; i < this->getSamplesPerPixel(); ++i) {
minValues.push_back(this->getMinValue(i));
maxValues.push_back(this->getMaxValue(i));
}
Patch<T> patch = Patch<T>(dims, this->getColorType(), data, true, minValues, maxValues);
patch.setSpacing(patchSpacing);
return patch;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#include "MultiResolutionImageFactory.h"
#include "MultiResolutionImage.h"
#include "VSIImage.h"
#include "core/filetools.h"
#include "core/stringconversion.h"

#ifdef HAS_MULTIRESOLUTIONIMAGEINTERFACE_VSI_SUPPORT
#include "VSIImage.h"
#endif

#ifdef _WIN32
#include <windows.h>
#else
Expand All @@ -30,7 +33,12 @@ MultiResolutionImage* MultiResolutionImageFactory::openImage(const std::string&
if (std::find(factoryExtensions.begin(), factoryExtensions.end(), extension) != factoryExtensions.end()) {
MultiResolutionImage* img = it->second->readImage(fileName);
if (img) {

#ifdef HAS_MULTIRESOLUTIONIMAGEINTERFACE_VSI_SUPPORT
if ((img->getNumberOfLevels() > 1 || dynamic_cast<VSIImage*>(img) != NULL) || (img->getNumberOfLevels() == 1 && img->getLevelDimensions(0)[0] < 4096)) {
#else
if ((img->getNumberOfLevels() > 1) || (img->getNumberOfLevels() == 1 && img->getLevelDimensions(0)[0] < 4096)) {
#endif
return img;
}
else {
Expand Down
21 changes: 19 additions & 2 deletions io/multiresolutionimageinterface/TIFFImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,8 @@ template <typename T> T* TIFFImage::FillRequestedRegionFromTIFF(const long long&
std::fill(temp,temp+width*height*nrSamples,static_cast<T>(0));
unsigned int tileW=_tileSizesPerLevel[level][0], tileH=_tileSizesPerLevel[level][1], levelH=_levelDimensions[level][1], levelW=_levelDimensions[level][0];

long long levelStartX = startX / getLevelDownsample(level);
long long levelStartY = startY / getLevelDownsample(level);
long long levelStartX = std::floor(startX / getLevelDownsample(level) + 0.5);
long long levelStartY = std::floor(startY / getLevelDownsample(level) + 0.5);
long long startTileY = levelStartY-(levelStartY-((levelStartY/tileH)*tileH));
long long startTileX = levelStartX-(levelStartX-((levelStartX/tileW)*tileW));
long long finalX = levelStartX + width >= levelW ? levelW : levelStartX + width;
Expand Down Expand Up @@ -316,6 +316,23 @@ template <typename T> T* TIFFImage::FillRequestedRegionFromTIFF(const long long&
TIFFGetField(_tiff, TIFFTAG_PHOTOMETRIC, &ycbcr);
if (ycbcr == PHOTOMETRIC_YCBCR) {
TIFFReadRGBATile(_tiff, ix, iy, (uint32*)tile);
unsigned char* tmp_row = new unsigned char[tileW*nrSamples];
for (unsigned int rev_y = 0; rev_y < tileH / 2; ++rev_y) {
std::copy(tile + rev_y*tileW*nrSamples, tile + (rev_y + 1)*tileW*nrSamples, tmp_row);
std::copy(tile + (tileH*tileW*nrSamples) - (rev_y + 1)*tileW*nrSamples, tile + (tileH*tileW*nrSamples) - rev_y*tileW*nrSamples, tile + rev_y*tileW*nrSamples);
std::copy(tmp_row, tmp_row + tileW*nrSamples, tile + (tileH*tileW*nrSamples) - (rev_y + 1)*tileW*nrSamples);
}
delete[] tmp_row;
for (unsigned int pos = 0; pos < tileW*tileH*nrSamples; pos += 4) {
unsigned char r = tile[pos + 0];
unsigned char g = tile[pos + 1];
unsigned char b = tile[pos + 2];
unsigned char a = tile[pos + 3];
tile[pos + 0] = b;
tile[pos + 1] = g;
tile[pos + 2] = r;
tile[pos + 3] = a;
}
}
else {
TIFFReadTile(_tiff, tile, ix, iy, 0, 0);
Expand Down

0 comments on commit 8979086

Please sign in to comment.