diff --git a/Core/Code/Algorithms/mitkPlaneClipping.h b/Core/Code/Algorithms/mitkPlaneClipping.h index 1d7da8505b..f685f5589a 100644 --- a/Core/Code/Algorithms/mitkPlaneClipping.h +++ b/Core/Code/Algorithms/mitkPlaneClipping.h @@ -1,141 +1,141 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKPLANECLIPPING_H_HEADER_INCLUDED #define MITKPLANECLIPPING_H_HEADER_INCLUDED #include #include #include #include namespace mitk { namespace PlaneClipping { /** \brief Internal helper method for intersection testing used only in CalculateClippedPlaneBounds() */ static bool LineIntersectZero( vtkPoints *points, int p1, int p2, vtkFloatingPointType *bounds ) { vtkFloatingPointType point1[3]; vtkFloatingPointType point2[3]; points->GetPoint( p1, point1 ); points->GetPoint( p2, point2 ); if ( (point1[2] * point2[2] <= 0.0) && (point1[2] != point2[2]) ) { double x, y; x = ( point1[0] * point2[2] - point1[2] * point2[0] ) / ( point2[2] - point1[2] ); y = ( point1[1] * point2[2] - point1[2] * point2[1] ) / ( point2[2] - point1[2] ); if ( x < bounds[0] ) { bounds[0] = x; } if ( x > bounds[1] ) { bounds[1] = x; } if ( y < bounds[2] ) { bounds[2] = y; } if ( y > bounds[3] ) { bounds[3] = y; } bounds[4] = bounds[5] = 0.0; return true; } return false; } /** \brief Calculate the bounding box of the resliced image. This is necessary for arbitrarily rotated planes in an image volume. A rotated plane (e.g. in swivel mode) will have a new bounding box, which needs to be calculated. */ static bool CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry, const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ) { // Clip the plane with the bounding geometry. To do so, the corner points // of the bounding box are transformed by the inverse transformation // matrix, and the transformed bounding box edges derived therefrom are // clipped with the plane z=0. The resulting min/max values are taken as // bounds for the image reslicer. const mitk::BoundingBox *boundingBox = boundingGeometry->GetBoundingBox(); mitk::BoundingBox::PointType bbMin = boundingBox->GetMinimum(); mitk::BoundingBox::PointType bbMax = boundingBox->GetMaximum(); vtkSmartPointer points = vtkSmartPointer::New(); if(boundingGeometry->GetImageGeometry()) { points->InsertPoint( 0, bbMin[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); points->InsertPoint( 1, bbMin[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); points->InsertPoint( 2, bbMin[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); points->InsertPoint( 3, bbMin[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); points->InsertPoint( 4, bbMax[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); points->InsertPoint( 5, bbMax[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); points->InsertPoint( 6, bbMax[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); points->InsertPoint( 7, bbMax[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); } else { points->InsertPoint( 0, bbMin[0], bbMin[1], bbMin[2] ); points->InsertPoint( 1, bbMin[0], bbMin[1], bbMax[2] ); points->InsertPoint( 2, bbMin[0], bbMax[1], bbMax[2] ); points->InsertPoint( 3, bbMin[0], bbMax[1], bbMin[2] ); points->InsertPoint( 4, bbMax[0], bbMin[1], bbMin[2] ); points->InsertPoint( 5, bbMax[0], bbMin[1], bbMax[2] ); points->InsertPoint( 6, bbMax[0], bbMax[1], bbMax[2] ); points->InsertPoint( 7, bbMax[0], bbMax[1], bbMin[2] ); } vtkSmartPointer newPoints = vtkSmartPointer::New(); vtkSmartPointer transform = vtkSmartPointer::New(); transform->Identity(); transform->Concatenate( planeGeometry->GetVtkTransform()->GetLinearInverse() ); transform->Concatenate( boundingGeometry->GetVtkTransform() ); transform->TransformPoints( points, newPoints ); bounds[0] = bounds[2] = 10000000.0; bounds[1] = bounds[3] = -10000000.0; bounds[4] = bounds[5] = 0.0; LineIntersectZero( newPoints, 0, 1, bounds ); LineIntersectZero( newPoints, 1, 2, bounds ); LineIntersectZero( newPoints, 2, 3, bounds ); LineIntersectZero( newPoints, 3, 0, bounds ); LineIntersectZero( newPoints, 0, 4, bounds ); LineIntersectZero( newPoints, 1, 5, bounds ); LineIntersectZero( newPoints, 2, 6, bounds ); LineIntersectZero( newPoints, 3, 7, bounds ); LineIntersectZero( newPoints, 4, 5, bounds ); LineIntersectZero( newPoints, 5, 6, bounds ); LineIntersectZero( newPoints, 6, 7, bounds ); LineIntersectZero( newPoints, 7, 4, bounds ); if ( (bounds[0] > 9999999.0) || (bounds[2] > 9999999.0) || (bounds[1] < -9999999.0) || (bounds[3] < -9999999.0) ) { return false; } else { // The resulting bounds must be adjusted by the plane spacing, since we // we have so far dealt with index coordinates const float *planeSpacing = planeGeometry->GetFloatSpacing(); bounds[0] *= planeSpacing[0]; bounds[1] *= planeSpacing[0]; bounds[2] *= planeSpacing[1]; bounds[3] *= planeSpacing[1]; bounds[4] *= planeSpacing[2]; bounds[5] *= planeSpacing[2]; return true; } } } } -#endif \ No newline at end of file +#endif diff --git a/Core/Code/Rendering/mitkRenderingTestHelper.cpp b/Core/Code/Rendering/mitkRenderingTestHelper.cpp index 7f319a0130..cf646c1de3 100644 --- a/Core/Code/Rendering/mitkRenderingTestHelper.cpp +++ b/Core/Code/Rendering/mitkRenderingTestHelper.cpp @@ -1,191 +1,191 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //VTK #include #include #include #include //MITK #include #include #include #include #include #include #include // include gl to read out properties #include #include mitkRenderingTestHelper::mitkRenderingTestHelper(int width, int height, int argc, char* argv[]) { // Global interaction must(!) be initialized mitk::GlobalInteraction::GetInstance()->Initialize("global"); m_DataStorage = mitk::StandaloneDataStorage::New(); m_RenderWindow = mitk::RenderWindow::New(); m_RenderWindow->GetRenderer()->SetDataStorage(m_DataStorage); m_RenderWindow->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard2D); this->GetVtkRenderWindow()->SetSize( width, height ); m_RenderWindow->GetRenderer()->Resize( width, height); //this->GetVtkRenderWindow()->DoubleBufferOff( ); this->SetInputFileNames(argc, argv); // prints the glinfo after creation of the vtkrenderwindow this->PrintGLInfo(); } mitkRenderingTestHelper::~mitkRenderingTestHelper() { } void mitkRenderingTestHelper::PrintGLInfo() { GLint maxTextureSize; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);; MITK_INFO << "OpenGL Render Context Information: \n" << "- GL_VENDOR: "<< glGetString(GL_VENDOR) << "\n" << "- GL_RENDERER: "<< glGetString(GL_RENDERER) << "\n" << "- GL_VERSION: "<< glGetString(GL_VERSION) << "\n" << "- GL_MAX_TEXTURE_SIZE: "<< maxTextureSize << "\n" << "- GL_EXTENSIONS: "<< glGetString(GL_EXTENSIONS); } void mitkRenderingTestHelper::SetMapperID( mitk::BaseRenderer::StandardMapperSlot id) { m_RenderWindow->GetRenderer()->SetMapperID(id); } void mitkRenderingTestHelper::Render() { //if the datastorage is initialized and at least 1 image is loaded render it if(m_DataStorage.IsNotNull() || m_DataStorage->GetAll()->Size() >= 1 ) { //perform global reinit: m_RenderWindow->GetRenderer()->PrepareRender(); // mitk::RenderingManager::GetInstance()->RequestUpdate(m_RenderWindow->GetVtkRenderWindow()); //use this to actually show the iamge in a renderwindow this->GetVtkRenderWindow()->Render(); // this->GetVtkRenderWindow()->GetInteractor()->Start(); } else { MITK_ERROR << "No images loaded in data storage!"; } } void mitkRenderingTestHelper::PrepareRender() { //perform global reinit: m_RenderWindow->GetRenderer()->PrepareRender(); } mitk::DataStorage::Pointer mitkRenderingTestHelper::GetDataStorage() { return m_DataStorage; } void mitkRenderingTestHelper::SetInputFileNames(int argc, char* argv[]) { // parse parameters for (int i = 1; i < argc; ++i) { //add everything to a list but -T and -V std::string tmp = argv[i]; if((tmp.compare("-T")) && (tmp.compare("-V"))) { this->AddToStorage(tmp); } else { break; } } } void mitkRenderingTestHelper::SetViewDirection(mitk::SliceNavigationController::ViewDirection viewDirection) { mitk::BaseRenderer::GetInstance(m_RenderWindow->GetVtkRenderWindow())->GetSliceNavigationController()->SetDefaultViewDirection(viewDirection); mitk::RenderingManager::GetInstance()->InitializeViews( m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll()) ); } void mitkRenderingTestHelper::ReorientSlices(mitk::Point3D origin, mitk::Vector3D rotation) { mitk::SliceNavigationController::Pointer sliceNavigationController = mitk::BaseRenderer::GetInstance(m_RenderWindow->GetVtkRenderWindow())->GetSliceNavigationController(); sliceNavigationController->ReorientSlices(origin, rotation); } vtkRenderer* mitkRenderingTestHelper::GetVtkRenderer() { return m_RenderWindow->GetRenderer()->GetVtkRenderer(); } void mitkRenderingTestHelper::SetImageProperty(const char *propertyKey, mitk::BaseProperty* property ) { this->m_DataStorage->GetNode(mitk::NodePredicateDataType::New("Image"))->SetProperty(propertyKey, property); } vtkRenderWindow* mitkRenderingTestHelper::GetVtkRenderWindow() { return m_RenderWindow->GetVtkRenderWindow(); } //method to save a screenshot of the renderwindow (e.g. create a reference screenshot) void mitkRenderingTestHelper::SaveAsPNG(std::string fileName) { vtkSmartPointer renderer = this->GetVtkRenderer(); bool doubleBuffering( renderer->GetRenderWindow()->GetDoubleBuffer() ); renderer->GetRenderWindow()->DoubleBufferOff(); vtkSmartPointer magnifier = vtkSmartPointer::New(); magnifier->SetInput(renderer); - magnifier->SetMagnification(1.0); + magnifier->SetMagnification(1); vtkSmartPointer fileWriter = vtkSmartPointer::New(); fileWriter->SetInput(magnifier->GetOutput()); fileWriter->SetFileName(fileName.c_str()); fileWriter->Write(); renderer->GetRenderWindow()->SetDoubleBuffer(doubleBuffering); } void mitkRenderingTestHelper::AddToStorage(const std::string &filename) { try { mitk::DataNode::Pointer node = mitk::IOUtil::LoadDataNode(filename); this->AddNodeToStorage(node); } catch ( itk::ExceptionObject & e ) { MITK_ERROR << "Failed loading test data '" << filename << "': " << e.what(); } } void mitkRenderingTestHelper::AddNodeToStorage(mitk::DataNode::Pointer node) { this->m_DataStorage->Add(node); mitk::RenderingManager::GetInstance()->InitializeViews( m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll()) ); } diff --git a/Core/Code/Rendering/vtkMitkLevelWindowFilter.cpp b/Core/Code/Rendering/vtkMitkLevelWindowFilter.cpp index d53739f41a..d12d23b1c4 100644 --- a/Core/Code/Rendering/vtkMitkLevelWindowFilter.cpp +++ b/Core/Code/Rendering/vtkMitkLevelWindowFilter.cpp @@ -1,597 +1,597 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "vtkMitkLevelWindowFilter.h" #include #include #include #include //used for acos etc. #include //used for PI #include #include static const double PI = itk::Math::pi; vtkMitkLevelWindowFilter::vtkMitkLevelWindowFilter():m_MinOpacity(0.0),m_MaxOpacity(255.0) { //MITK_INFO << "mitk level/window filter uses " << GetNumberOfThreads() << " thread(s)"; } vtkMitkLevelWindowFilter::~vtkMitkLevelWindowFilter() { } unsigned long int vtkMitkLevelWindowFilter::GetMTime() { unsigned long mTime=this->vtkObject::GetMTime(); unsigned long time; if ( this->m_LookupTable != NULL ) { time = this->m_LookupTable->GetMTime(); mTime = ( time > mTime ? time : mTime ); } return mTime; } void vtkMitkLevelWindowFilter::SetLookupTable(vtkScalarsToColors *lookupTable) { if (m_LookupTable != lookupTable) { m_LookupTable = lookupTable; this->Modified(); } } vtkScalarsToColors* vtkMitkLevelWindowFilter::GetLookupTable() { return m_LookupTable; } //This code was copied from the iil. The template works only for float and double. //Internal method which should never be used anywhere else and should not be in th header. // Convert color pixels from (R,G,B) to (H,S,I). // Reference: "Digital Image Processing, 2nd. edition", R. Gonzalez and R. Woods. Prentice Hall, 2002. template void RGBtoHSI(T* RGB, T* HSI) { T R = RGB[0], G = RGB[1], B = RGB[2], nR = (R<0?0:(R>255?255:R))/255, nG = (G<0?0:(G>255?255:G))/255, nB = (B<0?0:(B>255?255:B))/255, m = nR0) H = (nB<=nG)?theta:360-theta; if (sum>0) S = 1 - 3/sum*m; I = sum/3; HSI[0] = (T)H; HSI[1] = (T)S; HSI[2] = (T)I; } //This code was copied from the iil. The template works only for float and double. //Internal method which should never be used anywhere else and should not be in th header. // Convert color pixels from (H,S,I) to (R,G,B). template void HSItoRGB(T* HSI, T* RGB) { T H = (T)HSI[0], S = (T)HSI[1], I = (T)HSI[2], a = I*(1-S), R = 0, G = 0, B = 0; if (H<120) { B = a; R = (T)(I*(1+S*std::cos(H*PI/180)/std::cos((60-H)*PI/180))); G = 3*I-(R+B); } else if (H<240) { H-=120; R = a; G = (T)(I*(1+S*std::cos(H*PI/180)/std::cos((60-H)*PI/180))); B = 3*I-(R+G); } else { H-=240; G = a; B = (T)(I*(1+S*std::cos(H*PI/180)/std::cos((60-H)*PI/180))); R = 3*I-(G+B); } R*=255; G*=255; B*=255; RGB[0] = (T)(R<0?0:(R>255?255:R)); RGB[1] = (T)(G<0?0:(G>255?255:G)); RGB[2] = (T)(B<0?0:(B>255?255:B)); } //Internal method which should never be used anywhere else and should not be in th header. //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkApplyLookupTableOnRGBA(vtkMitkLevelWindowFilter* self, vtkImageData* inData, vtkImageData* outData, int outExt[6], vtkFloatingPointType* clippingBounds, T*) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); vtkLookupTable* lookupTable; const int maxC = inData->GetNumberOfScalarComponents(); double tableRange[2]; lookupTable = dynamic_cast(self->GetLookupTable()); lookupTable->GetTableRange(tableRange); //parameters for RGB level window double scale = (tableRange[1] -tableRange[0] > 0 ? 255.0 / (tableRange[1] - tableRange[0]) : 0.0); double bias = tableRange[0] * scale; //parameters for opaque level window double scaleOpac = (self->GetMaxOpacity() -self->GetMinOpacity() > 0 ? 255.0 / (self->GetMaxOpacity() - self->GetMinOpacity()) : 0.0); double biasOpac = self->GetMinOpacity() * scaleOpac; int y = outExt[2]; // Loop through ouput pixels while (!outputIt.IsAtEnd()) { T* inputSI = inputIt.BeginSpan(); T* outputSI = outputIt.BeginSpan(); T* outputSIEnd = outputIt.EndSpan(); if( y >= clippingBounds[2] && y < clippingBounds[3] ) { int x = outExt[0]; while (outputSI != outputSIEnd) { if ( x >= clippingBounds[0] && x < clippingBounds[1]) { double rgb[3], alpha, hsi[3]; // level/window mechanism for intensity in HSI space rgb[0] = static_cast(*inputSI); inputSI++; rgb[1] = static_cast(*inputSI); inputSI++; rgb[2] = static_cast(*inputSI); inputSI++; RGBtoHSI(rgb,hsi); hsi[2] = hsi[2] * 255.0 * scale - bias; hsi[2] = (hsi[2] > 255.0 ? 255 : (hsi[2] < 0.0 ? 0 : hsi[2])); hsi[2] /= 255.0; HSItoRGB(hsi,rgb); *outputSI = static_cast(rgb[0]); outputSI++; *outputSI = static_cast(rgb[1]); outputSI++; *outputSI = static_cast(rgb[2]); outputSI++; unsigned char finalAlpha = 255; //RGBA case if(maxC >= 4) { // level/window mechanism for opacity alpha = static_cast(*inputSI); inputSI++; alpha = alpha * scaleOpac - biasOpac; if(alpha > 255.0) { alpha = 255.0; } else if(alpha < 0.0) { alpha = 0.0; } - finalAlpha = static_cast(alpha); + finalAlpha = static_cast(alpha); for( int c = 4; c < maxC; c++ ) inputSI++; } *outputSI = static_cast(finalAlpha); outputSI++; } else { inputSI+=maxC; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; } x++; } } else { while (outputSI != outputSIEnd) { *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; } } inputIt.NextSpan(); outputIt.NextSpan(); y++; } } //Internal method which should never be used anywhere else and should not be in th header. //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkApplyLookupTableOnScalarsFast(vtkMitkLevelWindowFilter *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], T *) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); double tableRange[2]; // access vtkLookupTable vtkLookupTable* lookupTable = dynamic_cast(self->GetLookupTable()); lookupTable->GetTableRange(tableRange); // access elements of the vtkLookupTable int * realLookupTable = reinterpret_cast(lookupTable->GetTable()->GetPointer(0)); int maxIndex = lookupTable->GetNumberOfColors() - 1; float scale = (tableRange[1] -tableRange[0] > 0 ? (maxIndex + 1) / (tableRange[1] - tableRange[0]) : 0.0); // ensuring that starting point is zero float bias = - tableRange[0] * scale; // due to later conversion to int for rounding bias += 0.5f; // Loop through ouput pixels while (!outputIt.IsAtEnd()) { unsigned char* outputSI = outputIt.BeginSpan(); unsigned char* outputSIEnd = outputIt.EndSpan(); T* inputSI = inputIt.BeginSpan(); while (outputSI != outputSIEnd) { // map to an index int idx = static_cast( *inputSI * scale + bias ); if (idx < 0) idx = 0; else if (idx > maxIndex) idx = maxIndex; * reinterpret_cast(outputSI) = realLookupTable[idx]; inputSI++; outputSI+=4; } inputIt.NextSpan(); outputIt.NextSpan(); } } //Internal method which should never be used anywhere else and should not be in th header. //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkApplyLookupTableOnScalars(vtkMitkLevelWindowFilter *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], vtkFloatingPointType* clippingBounds, T *) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); vtkScalarsToColors* lookupTable = self->GetLookupTable(); int y = outExt[2]; // Loop through ouput pixels while (!outputIt.IsAtEnd()) { unsigned char* outputSI = outputIt.BeginSpan(); unsigned char* outputSIEnd = outputIt.EndSpan(); // do we iterate over the inner vertical clipping bounds if( y >= clippingBounds[2] && y < clippingBounds[3] ) { T* inputSI = inputIt.BeginSpan(); int x= outExt[0]; while (outputSI != outputSIEnd) { // is this pixel within horizontal clipping bounds if ( x >= clippingBounds[0] && x < clippingBounds[1]) { // fetching original value double grayValue = static_cast(*inputSI); // applying lookuptable - copy the 4 (RGBA) chars as a single int *reinterpret_cast(outputSI) = *reinterpret_cast(lookupTable->MapValue( grayValue )); } else { // outer horizontal clipping bounds - write a transparent RGBA pixel as a single int *reinterpret_cast(outputSI) = 0; } inputSI++; outputSI+=4; x++; } } else { // outer vertical clipping bounds - write a transparent RGBA line as ints while (outputSI != outputSIEnd) { *reinterpret_cast(outputSI) = 0; outputSI+=4; } } inputIt.NextSpan(); outputIt.NextSpan(); y++; } } //Internal method which should never be used anywhere else and should not be in th header. //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkApplyLookupTableOnScalarsCTF(vtkMitkLevelWindowFilter *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], vtkFloatingPointType* clippingBounds, T *) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); vtkColorTransferFunction* lookupTable = dynamic_cast(self->GetLookupTable()); int y = outExt[2]; // Loop through ouput pixels while (!outputIt.IsAtEnd()) { unsigned char* outputSI = outputIt.BeginSpan(); unsigned char* outputSIEnd = outputIt.EndSpan(); // do we iterate over the inner vertical clipping bounds if( y >= clippingBounds[2] && y < clippingBounds[3] ) { T* inputSI = inputIt.BeginSpan(); int x= outExt[0]; while (outputSI != outputSIEnd) { // is this pixel within horizontal clipping bounds if ( x >= clippingBounds[0] && x < clippingBounds[1]) { // fetching original value double grayValue = static_cast(*inputSI); // applying directly colortransferfunction // because vtkColorTransferFunction::MapValue is not threadsafe double rgb[3]; lookupTable->GetColor( grayValue, rgb ); outputSI[0] = static_cast(255.0*rgb[0] + 0.5); outputSI[1] = static_cast(255.0*rgb[1] + 0.5); outputSI[2] = static_cast(255.0*rgb[2] + 0.5); outputSI[3] = 255; } else { // outer horizontal clipping bounds - write a transparent RGBA pixel as a single int *reinterpret_cast(outputSI) = 0; } inputSI++; outputSI+=4; x++; } } else { // outer vertical clipping bounds - write a transparent RGBA line as ints while (outputSI != outputSIEnd) { *reinterpret_cast(outputSI) = 0; outputSI+=4; } } inputIt.NextSpan(); outputIt.NextSpan(); y++; } } void vtkMitkLevelWindowFilter::ExecuteInformation() { vtkImageData *input = this->GetInput(); vtkImageData *output = this->GetOutput(); if (!input) { vtkErrorMacro(<< "Input not set."); return; } output->CopyTypeSpecificInformation( input ); // TODO make output RGBA output->SetScalarTypeToUnsignedChar(); output->SetNumberOfScalarComponents(4); int extent[6]; input->GetWholeExtent(extent); output->SetExtent(extent); output->SetWholeExtent(extent); output->SetUpdateExtent(extent); output->AllocateScalars(); } //Method to run the filter in different threads. void vtkMitkLevelWindowFilter::ThreadedExecute(vtkImageData *inData, vtkImageData *outData, int extent[6], int /*id*/) { if(inData->GetNumberOfScalarComponents() > 2) { switch (inData->GetScalarType()) { vtkTemplateMacro( vtkApplyLookupTableOnRGBA( this, inData, outData, extent, m_ClippingBounds, static_cast(0))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } else { bool dontClip = extent[2] >= m_ClippingBounds[2] && extent[3] <= m_ClippingBounds[3] && extent[0] >= m_ClippingBounds[0] && extent[1] <= m_ClippingBounds[1]; if(this->GetLookupTable()) this->GetLookupTable()->Build(); vtkLookupTable *vlt = dynamic_cast(this->GetLookupTable()); vtkColorTransferFunction *ctf = dynamic_cast(this->GetLookupTable()); bool linearLookupTable = vlt && vlt->GetScale() == VTK_SCALE_LINEAR; bool useFast = dontClip && linearLookupTable; if(ctf) { switch (inData->GetScalarType()) { vtkTemplateMacro( vtkApplyLookupTableOnScalarsCTF( this, inData, outData, extent, m_ClippingBounds, static_cast(0))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } else if(useFast) { switch (inData->GetScalarType()) { vtkTemplateMacro( vtkApplyLookupTableOnScalarsFast( this, inData, outData, extent, static_cast(0))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } else { switch (inData->GetScalarType()) { vtkTemplateMacro( vtkApplyLookupTableOnScalars( this, inData, outData, extent, m_ClippingBounds, static_cast(0))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } } } void vtkMitkLevelWindowFilter::ExecuteInformation( vtkImageData *vtkNotUsed(inData), vtkImageData *vtkNotUsed(outData)) { } void vtkMitkLevelWindowFilter::SetMinOpacity(double minOpacity) { m_MinOpacity = minOpacity; } inline double vtkMitkLevelWindowFilter::GetMinOpacity() const { return m_MinOpacity; } void vtkMitkLevelWindowFilter::SetMaxOpacity(double maxOpacity) { m_MaxOpacity = maxOpacity; } inline double vtkMitkLevelWindowFilter::GetMaxOpacity() const { return m_MaxOpacity; } void vtkMitkLevelWindowFilter::SetClippingBounds(vtkFloatingPointType* bounds) // TODO does vtkFloatingPointType[4] work?? { for (unsigned int i = 0 ; i < 4; ++i) m_ClippingBounds[i] = bounds[i]; }