Skip to content
Snippets Groups Projects
Commit 0f86b84c authored by David E DeMarle's avatar David E DeMarle Committed by Kitware Robot
Browse files

Merge topic 'dev/openslide-reader'


c3e6bc07 ADD: Readme
9084b08f FIX: for openslide v3.4.0-1 in ubuntu
455ce318 FIX: Image streaming
c0615a90 ADD: CanReadFile implementation with tests
1bf26eb6 FIX: Header errors and data alignment
883f6531 ENH: Working tests for Update
0e647a2d ENH: Find openslide on fedora
d36c7e53 ADD: New Microscopy domain and vtkOpenSlideReader

Acked-by: default avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !1235
parents c4872568 c3e6bc07
No related branches found
No related tags found
No related merge requests found
Showing
with 514 additions and 0 deletions
# OpenSlide required
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
find_package(OpenSlide REQUIRED)
mark_as_advanced(OPENSLIDE_INCLUDE_DIR OPENSLIDE_LIBRARY)
set(OPENSLIDE_SRCS vtkOpenSlideReader.cxx)
include_directories(${OPENSLIDE_INCLUDE_DIRS})
set(${vtk-module}_SYSTEM_INCLUDE_DIRS
${OPENSLIDE_INCLUDE_DIRS})
vtk_module_library(vtkDomainsMicroscopy ${OPENSLIDE_SRCS})
vtk_module_link_libraries(vtkDomainsMicroscopy LINK_PRIVATE ${OPENSLIDE_LIBRARY})
# A CMake find module for the OpenSlide microscopy file reader library.
#
# http://openslide.org
#
# Once done, this module will define
# OPENSLIDE_FOUND - system has OpenSlide
# OPENSLIDE_INCLUDE_DIRS - the OpenSlide include directory
# OPENSLIDE_LIBRARIES - link to these to use OpenSlide
# Look for the header.
find_path( OPENSLIDE_INCLUDE_DIR NAMES openslide.h PATHS
/usr/local/include/openslide
/usr/include/openslide)
mark_as_advanced( OPENSLIDE_INCLUDE_DIR )
# Look for the library.
find_library( OPENSLIDE_LIBRARY NAMES openslide )
mark_as_advanced( OPENSLIDE_LIBRARY )
# Handle the QUIETLY and REQUIRED arguments and set OPENSLIDE_FOUND true if all
# the listed variables are TRUE.
find_package( PackageHandleStandardArgs )
FIND_PACKAGE_HANDLE_STANDARD_ARGS( OPENSLIDE DEFAULT_MSG OPENSLIDE_LIBRARY OPENSLIDE_INCLUDE_DIR )
if( OPENSLIDE_FOUND )
set( OPENSLIDE_LIBRARIES ${OPENSLIDE_LIBRARY} )
set( OPENSLIDE_INCLUDE_DIRS ${OPENSLIDE_INCLUDE_DIR} )
endif()
# OpenSlideReader Tests
vtk_add_test_cxx(${vtk-module}CxxTests tests
TestOpenSlideReader.cxx
"DATA{${VTK_TEST_INPUT_DIR}/Microscopy/small2.ndpi}"
)
vtk_add_test_cxx(${vtk-module}CxxTests tests
TestOpenSlideReaderPartialTIF,TestOpenSlideReaderPartial.cxx
"DATA{${VTK_TEST_INPUT_DIR}/Microscopy/pathology.tif}"
)
vtk_test_cxx_executable(${vtk-module}CxxTests tests RENDERING_FACTORY)
/*=========================================================================
Program: Visualization Toolkit
Module: TestOpenSlideReader.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include <vtkNew.h>
#include <vtkOpenSlideReader.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkImageViewer2.h>
#include <vtkImageData.h>
#include <vtkPNGWriter.h>
// VTK includes
#include <vtkTestUtilities.h>
// C++ includes
#include <sstream>
// Main program
int TestOpenSlideReader(int argc, char** argv)
{
// This test is known to fail with openslide library libopenslide-dev shipped
// with ubuntu 14.04 as of March 31'2016. It does pass on fedora23, or if the
// openslide library is built from source
const char* rasterFileName = vtkTestUtilities::ExpandDataFileName(argc, argv,
"Data/Microscopy/small2.ndpi");
//std::cout << "Got Filename: " << rasterFileName << std::endl;
// Create reader to read shape file.
vtkNew<vtkOpenSlideReader> reader;
reader->SetFileName(rasterFileName);
reader->UpdateInformation();
delete [] rasterFileName;
// For debug
// reader->SetUpdateExtent(extent);
// vtkNew<vtkPNGWriter> writer;
// writer->SetInputConnection(reader->GetOutputPort());
// writer->SetFileName("this.png");
// writer->SetUpdateExtent(extent);
// writer->Update();
// writer->Write();
// Visualize
vtkNew<vtkRenderer> renderer;
vtkNew<vtkRenderWindow> window;
window->AddRenderer(renderer.GetPointer());
vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
renderWindowInteractor->SetRenderWindow(window.GetPointer());
vtkNew<vtkImageViewer2> imageViewer;
imageViewer->SetInputConnection(reader->GetOutputPort());
//imageViewer->SetExtent(1000,1500,1000,1500,0,0);
imageViewer->SetupInteractor(renderWindowInteractor.GetPointer());
//imageViewer->SetSlice(0);
imageViewer->Render();
imageViewer->GetRenderer()->ResetCamera();
renderWindowInteractor->Initialize();
imageViewer->Render();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
/*=========================================================================
Program: Visualization Toolkit
Module: TestOpenSlideReader.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include <vtkNew.h>
#include <vtkOpenSlideReader.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkImageViewer2.h>
#include <vtkImageData.h>
#include <vtkPNGWriter.h>
// VTK includes
#include <vtkTestUtilities.h>
// C++ includes
#include <sstream>
// Main program
int TestOpenSlideReaderPartial(int argc, char** argv)
{
if ( argc <= 1 )
{
std::cout << "Usage: " << argv[0] << " <image file>" << endl;
return EXIT_FAILURE;
}
std::cout << "Got Filename: " << argv[1] << std::endl;
// Create reader to read shape file.
vtkNew<vtkOpenSlideReader> reader;
reader->SetFileName(argv[1]);
reader->UpdateInformation();
int extent[6] = {100,299,100,299,0,0};
reader->UpdateExtent(extent);
vtkNew<vtkImageData> data;
data->ShallowCopy(reader->GetOutput());
// // For debug
// vtkNew<vtkPNGWriter> writer;
// writer->SetInputData(data.GetPointer());
// writer->SetFileName("this.png");
// writer->SetUpdateExtent(extent);
// writer->Update();
// writer->Write();
// Visualize
vtkNew<vtkRenderer> renderer;
vtkNew<vtkRenderWindow> window;
window->AddRenderer(renderer.GetPointer());
vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
renderWindowInteractor->SetRenderWindow(window.GetPointer());
vtkNew<vtkImageViewer2> imageViewer;
imageViewer->SetInputData(data.GetPointer());
//imageViewer->SetExtent(1000,1500,1000,1500,0,0);
imageViewer->SetupInteractor(renderWindowInteractor.GetPointer());
//imageViewer->SetSlice(0);
imageViewer->Render();
imageViewer->GetRenderer()->ResetCamera();
renderWindowInteractor->Initialize();
imageViewer->Render();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
c89273d8e9e3160cd1ac9d1f3a31bbf7
4b2972c7011281baa9a0fb3c883ffb7a
2513faaa18fd17a568b47e0bf0c10531
vtk_add_test_python(
testOpenSlideReader.py,NO_OUTPUT,NO_RT,NO_VALID)
#!/usr/bin/env python
import vtk
from vtk.test import Testing
from vtk.util.misc import vtkGetDataRoot
VTK_DATA_ROOT = vtkGetDataRoot()
import sys
class TestOpenSlideReader(Testing.vtkTest):
def testCanReadFile(self):
reader = vtk.vtkOpenSlideReader()
self.assertEqual(reader.CanReadFile(VTK_DATA_ROOT + "/Data/RectGrid2.vtk"), 0)
def testCanNotReadFile(self):
reader = vtk.vtkOpenSlideReader()
self.assertEqual(reader.CanReadFile(VTK_DATA_ROOT + "/Data/Microscopy/small2.ndpi"), 2)
if __name__ == "__main__":
Testing.main([(TestOpenSlideReader, 'test')])
vtk_module(vtkDomainsMicroscopy
DESCRIPTION "Readers and writers supporting whole slide images for microscopy domain"
DEPENDS
vtkCommonDataModel
vtkCommonExecutionModel
vtkIOImage
PRIVATE_DEPENDS
vtkIOXML
vtkFiltersSources
TEST_DEPENDS
vtkTestingCore
vtkTestingRendering
vtkInteractionImage
vtkRenderingContext${VTK_RENDERING_BACKEND}
EXCLUDE_FROM_ALL
)
# vtkOpenSlideReader
- A new image reader for vtk
- Wraps open source [openslide library](https://github.com/openslide/openslide "openslide") which implements read support for many whole slide image formats
- Mainly from microscopy domain
- Requires openslide libraries for building
# Known issues
- Ubuntu 14.04 contains incorrectly patched version of openjpeg (dependency of openslide), and thus openslide is unable to decode certain .svs files. This issue is not present in later versions of ubuntu or fedora 23.
/*=========================================================================
Program: Visualization Toolkit
Module: vtkOpenSlideReader.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkOpenSlideReader.h"
#include "vtkDataArray.h"
#include "vtkImageData.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkToolkits.h"
#include "vtkStreamingDemandDrivenPipeline.h"
vtkStandardNewMacro(vtkOpenSlideReader);
void vtkOpenSlideReader::ExecuteInformation()
{
//std::cout << this->GetFileName() << std::endl;
this->openslide_handle = openslide_open(this->GetFileName());
if(this->openslide_handle == NULL || openslide_get_error(this->openslide_handle) != NULL)
{
vtkErrorWithObjectMacro(this,
"File could not be opened by openslide"
);
return;
}
int64_t w, h;
openslide_get_level0_dimensions(this->openslide_handle, &w, &h);
// cout << "OpenSlideInfDims: " << w << ", " << h << endl;
this->vtkImageReader2::ExecuteInformation();
this->DataExtent[0] = 0;
this->DataExtent[1] = w-1;
this->DataExtent[2] = 0;
this->DataExtent[3] = h-1;
this->DataExtent[4] = 0;
this->DataExtent[5] = 0;
this->SetNumberOfScalarComponents(3);
this->SetDataScalarTypeToUnsignedChar();
}
//----------------------------------------------------------------------------
// This function reads a data from a file. The datas extent/axes
// are assumed to be the same as the file extent/order.
void vtkOpenSlideReader::ExecuteDataWithInformation(vtkDataObject *output,
vtkInformation *outInfo)
{
int inExtent[6];
vtkStreamingDemandDrivenPipeline::GetUpdateExtent(
outInfo,
inExtent);
vtkImageData *data = this->AllocateOutputData(output, outInfo);
if(this->openslide_handle == NULL)
{
vtkErrorWithObjectMacro(this,
"File could not be read by openslide"
);
return;
}
//std::cout << "OpenSlideReader Extents: " << data->GetExtent() << std::endl;
this->ComputeDataIncrements();
data->GetPointData()->GetScalars()->SetName("OpenSlideImage");
//// Leverage openslide to read the region
// VTK extents have origin at top left and y axis looking downwards
// openslide needs to convert
int w = inExtent[1] - inExtent[0] + 1;
int h = inExtent[3]- inExtent[2] + 1;
unsigned char * buffer = new unsigned char[w * h * 4];
openslide_read_region(this->openslide_handle, (unsigned int *) buffer,
inExtent[0],
this->DataExtent[3]-inExtent[3],
0, // level
w,
h
);
if(openslide_get_error(this->openslide_handle) != NULL)
{
// Buffer is deleted by the openslide in case the error occurs
// delete[] buffer;
vtkErrorWithObjectMacro(this,
"File could not be read by openslide"
);
return;
}
unsigned char* outputPtr = (unsigned char*)(data->GetScalarPointer());
unsigned char* bufPtr = (unsigned char*) buffer;
// Order = RGBA
for (long y=0; y < h; y++)
{
for(long x=0; x < w; x++)
{
unsigned char* rgba = &bufPtr[((h-1-y)*w + x) * 4];
unsigned char* rgb = &outputPtr[(y*w + x) * 3];
// Convert from BGRA to RGB
rgb[2] = rgba[0];
rgb[1] = rgba[1];
rgb[0] = rgba[2];
}
}
delete[] buffer;
// openslide_close(this->openslide_handle);
}
//----------------------------------------------------------------------------
int vtkOpenSlideReader::CanReadFile(const char* fname)
{
// 1 - I think I can read the file but I cannot prove it
// 2 - I definitely can read the file
// 3 - I can read the file and I have validated that I am the correct reader for this file
this->openslide_handle = openslide_open(fname);
if(this->openslide_handle == NULL || openslide_get_error(this->openslide_handle) != NULL)
{
// Unable to open
return 0;
}
else
{
// Pretty sure
if(this->openslide_handle != NULL)
{
openslide_close(this->openslide_handle);
this->openslide_handle = NULL;
}
return 2;
}
}
vtkOpenSlideReader::~vtkOpenSlideReader()
{
// Release openslide_handle if being used
if(this->openslide_handle != NULL)
{
openslide_close(this->openslide_handle);
}
}
//----------------------------------------------------------------------------
void vtkOpenSlideReader::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkOpenSlideReader.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
// .NAME vtkOpenSlideReader - read digital whole slide images supported by
// openslide library
// .SECTION Description
// vtkOpenSlideReader is a source object that uses openslide library to
// read multiple supported image formats used for whole slide images in
// microscopy community.
//
// .SECTION See Also
// vtkPTIFWriter
#ifndef vtkOpenSlideReader_h
#define vtkOpenSlideReader_h
#include "vtkDomainsMicroscopyModule.h" // For export macro
#include "vtkImageReader2.h"
extern "C" {
#include "openslide/openslide.h" // For openslide support
}
class VTKDOMAINSMICROSCOPY_EXPORT vtkOpenSlideReader : public vtkImageReader2
{
public:
static vtkOpenSlideReader *New();
vtkTypeMacro(vtkOpenSlideReader,vtkImageReader2);
virtual void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Is the given file supported ?
int CanReadFile(const char* fname);
// Description:
// Get the file extensions for this format.
// Returns a string with a space separated list of extensions in
// the format .extension
virtual const char* GetFileExtensions()
{
return ".ndpi .svs"; // TODO: Get exaustive list of formats
}
// Description:
// Return a descriptive name for the file format that might be useful in a GUI.
virtual const char* GetDescriptiveName()
{
return "Openslide::WholeSlideImage";
}
protected:
vtkOpenSlideReader() {}
~vtkOpenSlideReader();
virtual void ExecuteInformation();
virtual void ExecuteDataWithInformation(vtkDataObject *out, vtkInformation *outInfo);
private:
openslide_t *openslide_handle;
vtkOpenSlideReader(const vtkOpenSlideReader&); // Not implemented.
void operator=(const vtkOpenSlideReader&); // Not implemented.
};
#endif
f90e3de39f83b7b86cac190d4c9091f4
6a89389966723771bc54d12bbcba1a0b
7a3a6d1db332aba39a61ee62414a5298
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment