1 /*# ---------------------------------------------------------------------
3 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
5 # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
6 # Previous Authors : Laurent Guigues, Jean-Pierre Roux
7 # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
9 # This software is governed by the CeCILL-B license under French law and
10 # abiding by the rules of distribution of free software. You can use,
11 # modify and/ or redistribute the software under the terms of the CeCILL-B
12 # license as circulated by CEA, CNRS and INRIA at the following URL
13 # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
14 # or in the file LICENSE.txt.
16 # As a counterpart to the access to the source code and rights to copy,
17 # modify and redistribute granted by the license, users are provided only
18 # with a limited warranty and the software's author, the holder of the
19 # economic rights, and the successive licensors have only limited
22 # The fact that you are presently reading this means that you have had
23 # knowledge of the CeCILL-B license and that you accept its terms.
24 # ------------------------------------------------------------------------ */
26 #include "volumerenderermanager.h"
28 /*=========================================================================
31 Module: $RCSfile: volumerenderermanager.cxx,v $
33 Date: $Date: 2012/11/15 14:16:37 $
34 Version: $Revision: 1.4 $
36 Copyright: (c) 2002, 2003
39 This software is distributed WITHOUT ANY WARRANTY; without even
40 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
41 PURPOSE. See the above copyright notice for more information.
43 =========================================================================*/
45 #include <vtkMetaImageReader.h>
46 #include <vtkImageCast.h>
48 #include "vtkImageLuminance.h"
49 #include "vtkImageAppendComponents.h"
50 #include "vtkSmartPointer.h"
57 ** Start of the manager class
59 VolumeRendererManager::VolumeRendererManager(){
63 VolumeRendererManager::~VolumeRendererManager(){
67 for(unsigned i = 0; i < prop3Dvect.size();i++){
68 prop3Dvect[i]->Delete();
74 ** Sets the renderer to manage the prop3D from the view
76 void VolumeRendererManager::setRenderer(vtkRenderer* renderer){
81 ** Gets the renderer which manage the prop3D from the view
83 vtkRenderer* VolumeRendererManager::getRenderer(){
90 void VolumeRendererManager::Update(int ppid){
91 VolumeRendererManagerData* data = this->getViewData(ppid);
97 * @pre The image can have one or multiple components per voxel, and volume rendering is performed seprately over the
98 three of them. If the image has multiple components and the separate components flag is set to false, then
99 the vtkImageAppendComponents is used to create a single image.
100 * @post The volume rendering is performed over the image vol
101 * @param vtkImageData* the image volume
102 * @param bool separatecomponents, if the image has multiple components, then a mapper is used for each of the channels
103 if this flag is set to false and the volume has multiple components, vtkImageAppendComponents is used to create
104 a single representation of the image.
106 int VolumeRendererManager::addVolume(vtkImageData* img, vtkRenderWindowInteractor* interactor, bool independentcomponents){
107 if(img->GetNumberOfScalarComponents() > 1 && !independentcomponents){
113 vtkSmartPointer< vtkImageLuminance > luminance = vtkSmartPointer< vtkImageLuminance >::New();
114 //EED 2017-01-01 Migration VTK7
115 #if VTK_MAJOR_VERSION <= 5
116 luminance->SetInput(img);
118 luminance->SetInputData(img);
123 vtkSmartPointer< vtkImageAppendComponents > append = vtkSmartPointer< vtkImageAppendComponents >::New();
125 //EED 2017-01-01 Migration VTK7
126 #if VTK_MAJOR_VERSION <= 5
127 append->SetInput(0, img);
128 append->SetInput(1, luminance->GetOutput());
130 append->SetInputData(0, img);
131 append->SetInputData(1, luminance->GetOutput());
138 VolumeRendererManagerData* data = new VolumeRendererManagerData(append->GetOutput(), true);
139 data->SetIndependentComponents(independentcomponents);
142 prop3Dvect.push_back(data);
144 data->setId(_idCount);
152 vector< vtkImageData* > vectimg;
153 GetImages(img, vectimg);
154 vtkBoxWidget* boxw = 0;
155 for(unsigned i = 0; i < vectimg.size(); i++){
156 VolumeRendererManagerData* data = new VolumeRendererManagerData(vectimg[i], "");
158 vtkColorTransferFunction* colorf = data->GetColorFunction();
159 colorf->RemoveAllPoints();
160 double r = 0, g = 0, b = 0;
161 for(unsigned j = 0; j < 255; j++){
177 colorf->AddRGBPoint(j, r, g, b);
180 prop3Dvect.push_back(data);
182 data->setId(_idCount);
186 EnableBoundingBox(interactor, data->getId());
187 DisableBoundingBox(data->getId());
188 boxw = data->GetBoxWidget();
190 data->SetBoxWidget(boxw);
194 boxw->RemoveAllObservers();
196 vtkBoxWidgetCallback *callback = vtkBoxWidgetCallback::New();
198 for(unsigned i = 0; i < prop3Dvect.size(); i++){
199 VolumeRendererManagerData* data = prop3Dvect[i];
200 callback->AddMapper(data->GetVolumeMapper());
203 boxw->AddObserver(vtkCommand::InteractionEvent, callback);
208 /*vtkImageData* imgshort = 0;
209 imgshort = vtkImageData::New();
210 imgshort->SetNumberOfScalarComponents(1);
211 imgshort->SetExtent(img->GetExtent());
212 imgshort->SetSpacing(img->GetSpacing());
213 imgshort->SetOrigin(img->GetOrigin());
214 imgshort->SetScalarTypeToUnsignedShort();
215 imgshort->AllocateScalars();
216 GetImageDouble(img, imgshort);
218 VolumeRendererManagerData* data = new VolumeRendererManagerData(imgshort, "");
220 vtkColorTransferFunction* colorf = data->GetColorFunction();
221 colorf->RemoveAllPoints();
223 map< unsigned short, vector< double > > colormap;
225 int *extent = img->GetExtent();
227 for(unsigned i = extent[0]; i < extent[1]; i++){
228 for(unsigned j = extent[2]; j < extent[3]; j++){
229 for(unsigned k = extent[4]; k < extent[5]; k++){
231 unsigned char *imgpoint = ((unsigned char*)img->GetScalarPointer(i, j, k));
232 double temp = (double)(0.299*imgpoint[0] + 0.587*imgpoint[1] + 0.114*imgpoint[2]);
233 unsigned short val = temp*255.0;
235 vector< double > rgb;
236 rgb.push_back(0.299*imgpoint[0]);
237 rgb.push_back(0.587*imgpoint[1]);
238 rgb.push_back(0.114*imgpoint[2]);
247 map< unsigned short, vector< double > >::iterator it;
248 for(it = colormap.begin(); it != colormap.end(); ++it){
250 colorf->AddRGBPoint((*it).first, (*it).second[0] / 255.0, (*it).second[1] / 255.0, (*it).second[2] / 255.0);
253 prop3Dvect.push_back(data);
255 data->setId(_idCount);
256 EnableBoundingBox(interactor, data->getId());
257 DisableBoundingBox(data->getId());
264 VolumeRendererManagerData* data = new VolumeRendererManagerData(img, "");
265 prop3Dvect.push_back(data);
268 data->setId(_idCount);
271 EnableBoundingBox(interactor, data->getId());
272 DisableBoundingBox(data->getId());
276 return data->getId();
282 * @pre the image is not null and has more than one scalar component
283 * @post Each component in the image is put in a single image
284 * @param vtkImageData* img, multiple component image i.e. an image of vectors like an rgb
285 * @return vtkImageData* double type image
287 void VolumeRendererManager::GetImageDouble(vtkImageData* img, vtkImageData* imgushort){
290 int *extent = img->GetExtent();
292 for(unsigned i = extent[0]; i < extent[1]; i++){
293 for(unsigned j = extent[2]; j < extent[3]; j++){
294 for(unsigned k = extent[4]; k < extent[5]; k++){
295 if(img->GetScalarType() == VTK_UNSIGNED_CHAR){
296 unsigned char *imgpoint = ((unsigned char*)img->GetScalarPointer(i, j, k));
298 unsigned short *vectimgpoint = (unsigned short*)imgushort->GetScalarPointer(i, j, k);
299 double temp = (double)(0.299*imgpoint[0] + 0.587*imgpoint[1] + 0.114*imgpoint[2]);
300 *vectimgpoint = temp*255.0;
309 * @pre the image is not null and has more than one scalar component
310 * @post Each component in the image is separated to form a different image
311 * @param vtkImageData* img, multiple component image i.e. an image of vectors like an rgb
312 * @return vector<vtkImageData* > a vector of images, one for each component
314 void VolumeRendererManager::GetImages(vtkImageData* img, vector<vtkImageData* >& vectimg){
316 for(unsigned i = 0; i < img->GetNumberOfScalarComponents(); i++){
317 vectimg.push_back(vtkImageData::New());
318 vectimg[i]->SetExtent(img->GetExtent());
319 vectimg[i]->SetSpacing(img->GetSpacing());
320 vectimg[i]->SetOrigin(img->GetOrigin());
322 //EED 2017-01-01 Migration VTK7
323 #if VTK_MAJOR_VERSION <= 5
324 vectimg[i]->SetNumberOfScalarComponents(1);
325 vectimg[i]->SetScalarType(img->GetScalarType());
326 vectimg[i]->AllocateScalars();
328 vectimg[i]->AllocateScalars(img->GetScalarType(),1);
333 int *extent = img->GetExtent();
335 for(unsigned i = extent[0]; i < extent[1]; i++){
336 for(unsigned j = extent[2]; j < extent[3]; j++){
337 for(unsigned k = extent[4]; k < extent[5]; k++){
338 if(img->GetScalarType() == VTK_UNSIGNED_CHAR){
339 unsigned char *imgpoint = ((unsigned char*)img->GetScalarPointer(i, j, k));
341 for(unsigned l = 0; l < vectimg.size(); l++){
342 unsigned char *vectimgpoint = (unsigned char*)vectimg[l]->GetScalarPointer(i, j, k);
343 *vectimgpoint = imgpoint[l];
345 }else if(img->GetScalarType() == VTK_CHAR){
346 char *imgpoint = ((char*)img->GetScalarPointer(i, j, k));
348 for(unsigned l = 0; l < vectimg.size(); l++){
349 char *vectimgpoint = ( char*)vectimg[l]->GetScalarPointer(i, j, k);
350 *vectimgpoint = imgpoint[l];
352 }else if(img->GetScalarType() == VTK_UNSIGNED_SHORT){
353 unsigned short *imgpoint = ((unsigned short*)img->GetScalarPointer(i, j, k));
355 for(unsigned l = 0; l < vectimg.size(); l++){
356 unsigned short *vectimgpoint = (unsigned short*)vectimg[l]->GetScalarPointer(i, j, k);
357 *vectimgpoint = imgpoint[l];
359 }else if(img->GetScalarType() == VTK_SHORT){
360 short *imgpoint = ((short*)img->GetScalarPointer(i, j, k));
362 for(unsigned l = 0; l < vectimg.size(); l++){
363 short *vectimgpoint = ( short*)vectimg[l]->GetScalarPointer(i, j, k);
364 *vectimgpoint = imgpoint[l];
373 ** Adds a prop3D to the manager and returns the identifier
375 int VolumeRendererManager::addVolume(int idTP, vtkImageData* vol, std::string dataname) throw(char*){
379 VolumeRendererManagerData* data = new VolumeRendererManagerData(vol, dataname);
380 prop3Dvect.push_back(data);
381 _renderer->AddActor(data->getProp3D());
384 data->setId(_idCount);
391 printf("VolumeRendererManager::addVolume->idVolumeRenderer: %i\n", data->getId());
392 return data->getId();
394 throw "Check mhd imagefile file or input";
399 ** adds or removes an actor depending of the bool value
402 void VolumeRendererManager::addRemoveActor(int propid, bool addremove) throw(char*){
405 VolumeRendererManagerData* data = this->getViewData(propid);
406 if(data->getProp3D()!=NULL){
408 _renderer->AddViewProp(data->getProp3D());
410 _renderer->RemoveViewProp(data->getProp3D());
417 ** Changes the opacity in a prop3D
419 void VolumeRendererManager::setVolumeOpacity(int propid, std::vector<double> greylevel,std::vector<double> value) throw(char*){
422 printf("EED VolumeRendererManager::setVolumeOpacity %d\n",propid);
424 VolumeRendererManagerData* volrenman = this->getViewData(propid);
427 volrenman->setVolumeOpacity(greylevel, value);
429 printf("EED VolumeRendererManager::setVolumeOpacity Warning volrenman NULL\n");
440 void VolumeRendererManager::setVolumeColor(int volid, std::vector<double> greylevel,
441 std::vector<double> red,
442 std::vector<double> green,
443 std::vector<double> blue)throw(char*){
444 printf("EED VolumeRendererManager::setVolumeColor start \n");
447 printf("EED VolumeRendererManager::setVolumeColor %d\n",volid);
449 VolumeRendererManagerData* volrenman = this->getViewData(volid);
452 this->getViewData(volid)->setVolumeColor(greylevel, red, green, blue);
454 printf("EED VolumeRendererManager::setVolumeColor Warning volrenman NULL\n");
458 printf("EED VolumeRendererManager::setVolumeColor end \n");
461 vtkImageData* VolumeRendererManager::getImageData(std::string filename){
462 if(filename.compare("")!= 0){
464 vtkMetaImageReader* reader = vtkMetaImageReader::New();
465 reader->SetFileName(filename.c_str());
467 vtkImageData* img = reader->GetOutput();
469 vtkImageCast* cast = vtkImageCast::New();
470 //EED 2017-01-01 Migration VTK7
471 #if VTK_MAJOR_VERSION <= 5
474 cast->SetInputData(img);
477 cast->SetOutputScalarTypeToUnsignedShort();
481 return cast->GetOutput();
487 vtkImageData* VolumeRendererManager::getImageData(){
491 void VolumeRendererManager::checkInvariant() throw(char*){
492 printf("EED VolumeRendererManager::checkInvariant start\n");
493 if(this->_renderer==NULL){
494 throw "Renderer not set";
496 printf("EED VolumeRendererManager::checkInvariant end \n");
499 VolumeRendererManagerData* VolumeRendererManager::getViewData(int id) throw(char*){
501 for(i = 0; i < (int)(prop3Dvect.size());i++){
502 if(prop3Dvect[i]->getId() == id){
503 return prop3Dvect[i];
506 throw "id not found in the data";
511 void VolumeRendererManager::deleteActor(int propid) throw (char *){
514 this->addRemoveActor(propid, false);
518 for(i = 0; i < (int)(prop3Dvect.size())&&!exit;i++){
519 if(prop3Dvect[i]->getId() == propid){
525 VolumeRendererManagerData* data = prop3Dvect[n];
527 for(j = i; j < (int)(prop3Dvect.size())-1;j++){
528 prop3Dvect[j] = prop3Dvect[j+1];
531 prop3Dvect.pop_back();
533 throw "id not found in the data";
538 vtkPiecewiseFunction* VolumeRendererManager::GetTransferFunction(int volumeid){
539 return getViewData(volumeid)->GetTransferFunction();
541 vtkColorTransferFunction* VolumeRendererManager::GetColorFunction(int volumeid){
543 return getViewData(volumeid)->GetColorFunction();
546 void VolumeRendererManager::changeCompositeMIPFunction(int id, int function) throw (char *){
548 for(unsigned i = 0; i < prop3Dvect.size(); i++)
549 prop3Dvect[i]->changeCompositeMIPFunction(function);
551 getViewData(id)->changeCompositeMIPFunction(function);
556 Changes the interpolation of the volume rendering.
557 type == 0 for linear interpolation
558 type == 1 for nearest interpolation
560 void VolumeRendererManager::changeInterpolationType(int type, int propid){
562 for(unsigned i = 0; i < prop3Dvect.size(); i++)
563 prop3Dvect[i]->changeInterpolationType(type);
565 getViewData(propid)->changeInterpolationType(type);
570 * Set the lookuptable to the volumes in memory
571 * if the id is set then it only changes the lookup table for a specific volume
573 void VolumeRendererManager::SetLookupTable(vtkLookupTable* lookup, int id){
575 for(unsigned i = 0; i < prop3Dvect.size(); i++)
576 prop3Dvect[i]->SetLookupTable(lookup);
578 getViewData(id)->SetLookupTable(lookup);
584 * @returns all the props3D in this manager
586 vector< vtkProp3D* > VolumeRendererManager::getProps3D(){
588 vector< vtkProp3D* > propvects;
589 for(unsigned i = 0; i < prop3Dvect.size(); i++){
590 propvects.push_back(prop3Dvect[i]->getProp3D());
596 * @param std::vector<double> greylevel, the corresponding greylevel in the image
597 * @param std::vector<double> value, the corresponding value for the opacity
598 * @param int propid, the correspoding id, by default it applies the changes to the first volume in the array
600 void VolumeRendererManager::setVolumeOpacity(std::vector<double> greylevel, std::vector<double> value, int propid){
602 for(unsigned i = 0; i < prop3Dvect.size(); i++)
603 prop3Dvect[i]->setVolumeOpacity(greylevel, value);
605 getViewData(propid)->setVolumeOpacity(greylevel, value);
609 void VolumeRendererManager::EnableBoundingBox(vtkRenderWindowInteractor* interactor, int propid){
611 for(unsigned i = 0; i < prop3Dvect.size(); i++)
612 prop3Dvect[i]->EnableBoundingBox(interactor);
614 getViewData(propid)->EnableBoundingBox(interactor);
618 void VolumeRendererManager::DisableBoundingBox(int propid){
621 for(unsigned i = 0; i < prop3Dvect.size(); i++)
622 prop3Dvect[i]->DisableBoundingBox();
624 getViewData(propid)->DisableBoundingBox();