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()
65 VolumeRendererManager::~VolumeRendererManager()
70 for(unsigned i = 0; i < prop3Dvect.size();i++){
71 prop3Dvect[i]->Delete();
77 ** Sets the renderer to manage the prop3D from the view
79 void VolumeRendererManager::setRenderer(vtkRenderer* renderer)
85 ** Gets the renderer which manage the prop3D from the view
87 vtkRenderer* VolumeRendererManager::getRenderer(){
94 void VolumeRendererManager::Update(int ppid)
96 VolumeRendererManagerData* data = this->getViewData(ppid);
102 * @pre The image can have one or multiple components per voxel, and volume rendering is performed seprately over the
103 three of them. If the image has multiple components and the separate components flag is set to false, then
104 the vtkImageAppendComponents is used to create a single image.
105 * @post The volume rendering is performed over the image vol
106 * @param vtkImageData* the image volume
107 * @param bool separatecomponents, if the image has multiple components, then a mapper is used for each of the channels
108 if this flag is set to false and the volume has multiple components, vtkImageAppendComponents is used to create
109 a single representation of the image.
111 int VolumeRendererManager::addVolume(vtkImageData* img, vtkRenderWindowInteractor* interactor, bool independentcomponents)
113 if(img->GetNumberOfScalarComponents() > 1 && !independentcomponents)
117 vtkSmartPointer< vtkImageLuminance > luminance = vtkSmartPointer< vtkImageLuminance >::New();
118 //EED 2017-01-01 Migration VTK7
119 #if VTK_MAJOR_VERSION <= 5
120 luminance->SetInput(img);
122 luminance->SetInputData(img);
127 vtkSmartPointer< vtkImageAppendComponents > append = vtkSmartPointer< vtkImageAppendComponents >::New();
129 //EED 2017-01-01 Migration VTK7
130 #if VTK_MAJOR_VERSION <= 5
131 append->SetInput(0, img);
132 append->SetInput(1, luminance->GetOutput());
134 append->SetInputData(0, img);
135 append->SetInputData(1, luminance->GetOutput());
142 VolumeRendererManagerData* data = new VolumeRendererManagerData(append->GetOutput(), true);
143 data->SetIndependentComponents(independentcomponents);
146 prop3Dvect.push_back(data);
148 data->setId(_idCount);
156 vector< vtkImageData* > vectimg;
157 GetImages(img, vectimg);
158 vtkBoxWidget* boxw = 0;
159 for(unsigned i = 0; i < vectimg.size(); i++){
160 VolumeRendererManagerData* data = new VolumeRendererManagerData(vectimg[i], "");
162 vtkColorTransferFunction* colorf = data->GetColorFunction();
163 colorf->RemoveAllPoints();
164 double r = 0, g = 0, b = 0;
165 for(unsigned j = 0; j < 255; j++){
181 colorf->AddRGBPoint(j, r, g, b);
184 prop3Dvect.push_back(data);
186 data->setId(_idCount);
190 EnableBoundingBox(interactor, data->getId());
191 DisableBoundingBox(data->getId());
192 boxw = data->GetBoxWidget();
194 data->SetBoxWidget(boxw);
198 boxw->RemoveAllObservers();
200 vtkBoxWidgetCallback *callback = vtkBoxWidgetCallback::New();
202 for(unsigned i = 0; i < prop3Dvect.size(); i++){
203 VolumeRendererManagerData* data = prop3Dvect[i];
204 callback->AddMapper(data->GetVolumeMapper());
207 boxw->AddObserver(vtkCommand::InteractionEvent, callback);
212 /*vtkImageData* imgshort = 0;
213 imgshort = vtkImageData::New();
214 imgshort->SetNumberOfScalarComponents(1);
215 imgshort->SetExtent(img->GetExtent());
216 imgshort->SetSpacing(img->GetSpacing());
217 imgshort->SetOrigin(img->GetOrigin());
218 imgshort->SetScalarTypeToUnsignedShort();
219 imgshort->AllocateScalars();
220 GetImageDouble(img, imgshort);
222 VolumeRendererManagerData* data = new VolumeRendererManagerData(imgshort, "");
224 vtkColorTransferFunction* colorf = data->GetColorFunction();
225 colorf->RemoveAllPoints();
227 map< unsigned short, vector< double > > colormap;
229 int *extent = img->GetExtent();
231 for(unsigned i = extent[0]; i < extent[1]; i++){
232 for(unsigned j = extent[2]; j < extent[3]; j++){
233 for(unsigned k = extent[4]; k < extent[5]; k++){
235 unsigned char *imgpoint = ((unsigned char*)img->GetScalarPointer(i, j, k));
236 double temp = (double)(0.299*imgpoint[0] + 0.587*imgpoint[1] + 0.114*imgpoint[2]);
237 unsigned short val = temp*255.0;
239 vector< double > rgb;
240 rgb.push_back(0.299*imgpoint[0]);
241 rgb.push_back(0.587*imgpoint[1]);
242 rgb.push_back(0.114*imgpoint[2]);
251 map< unsigned short, vector< double > >::iterator it;
252 for(it = colormap.begin(); it != colormap.end(); ++it){
254 colorf->AddRGBPoint((*it).first, (*it).second[0] / 255.0, (*it).second[1] / 255.0, (*it).second[2] / 255.0);
257 prop3Dvect.push_back(data);
259 data->setId(_idCount);
260 EnableBoundingBox(interactor, data->getId());
261 DisableBoundingBox(data->getId());
268 VolumeRendererManagerData* data = new VolumeRendererManagerData(img, "");
269 prop3Dvect.push_back(data);
272 data->setId(_idCount);
275 EnableBoundingBox(interactor, data->getId());
276 DisableBoundingBox(data->getId());
280 return data->getId();
286 * @pre the image is not null and has more than one scalar component
287 * @post Each component in the image is put in a single image
288 * @param vtkImageData* img, multiple component image i.e. an image of vectors like an rgb
289 * @return vtkImageData* double type image
291 void VolumeRendererManager::GetImageDouble(vtkImageData* img, vtkImageData* imgushort){
294 int *extent = img->GetExtent();
296 for(unsigned i = extent[0]; i < extent[1]; i++){
297 for(unsigned j = extent[2]; j < extent[3]; j++){
298 for(unsigned k = extent[4]; k < extent[5]; k++){
299 if(img->GetScalarType() == VTK_UNSIGNED_CHAR){
300 unsigned char *imgpoint = ((unsigned char*)img->GetScalarPointer(i, j, k));
302 unsigned short *vectimgpoint = (unsigned short*)imgushort->GetScalarPointer(i, j, k);
303 double temp = (double)(0.299*imgpoint[0] + 0.587*imgpoint[1] + 0.114*imgpoint[2]);
304 *vectimgpoint = temp*255.0;
313 * @pre the image is not null and has more than one scalar component
314 * @post Each component in the image is separated to form a different image
315 * @param vtkImageData* img, multiple component image i.e. an image of vectors like an rgb
316 * @return vector<vtkImageData* > a vector of images, one for each component
318 void VolumeRendererManager::GetImages(vtkImageData* img, vector<vtkImageData* >& vectimg){
320 for(unsigned i = 0; i < img->GetNumberOfScalarComponents(); i++){
321 vectimg.push_back(vtkImageData::New());
322 vectimg[i]->SetExtent(img->GetExtent());
323 vectimg[i]->SetSpacing(img->GetSpacing());
324 vectimg[i]->SetOrigin(img->GetOrigin());
326 //EED 2017-01-01 Migration VTK7
327 #if VTK_MAJOR_VERSION <= 5
328 vectimg[i]->SetNumberOfScalarComponents(1);
329 vectimg[i]->SetScalarType(img->GetScalarType());
330 vectimg[i]->AllocateScalars();
332 vectimg[i]->AllocateScalars(img->GetScalarType(),1);
337 int *extent = img->GetExtent();
339 for(unsigned i = extent[0]; i < extent[1]; i++){
340 for(unsigned j = extent[2]; j < extent[3]; j++){
341 for(unsigned k = extent[4]; k < extent[5]; k++){
342 if(img->GetScalarType() == VTK_UNSIGNED_CHAR){
343 unsigned char *imgpoint = ((unsigned char*)img->GetScalarPointer(i, j, k));
345 for(unsigned l = 0; l < vectimg.size(); l++){
346 unsigned char *vectimgpoint = (unsigned char*)vectimg[l]->GetScalarPointer(i, j, k);
347 *vectimgpoint = imgpoint[l];
349 }else if(img->GetScalarType() == VTK_CHAR){
350 char *imgpoint = ((char*)img->GetScalarPointer(i, j, k));
352 for(unsigned l = 0; l < vectimg.size(); l++){
353 char *vectimgpoint = ( char*)vectimg[l]->GetScalarPointer(i, j, k);
354 *vectimgpoint = imgpoint[l];
356 }else if(img->GetScalarType() == VTK_UNSIGNED_SHORT){
357 unsigned short *imgpoint = ((unsigned short*)img->GetScalarPointer(i, j, k));
359 for(unsigned l = 0; l < vectimg.size(); l++){
360 unsigned short *vectimgpoint = (unsigned short*)vectimg[l]->GetScalarPointer(i, j, k);
361 *vectimgpoint = imgpoint[l];
363 }else if(img->GetScalarType() == VTK_SHORT){
364 short *imgpoint = ((short*)img->GetScalarPointer(i, j, k));
366 for(unsigned l = 0; l < vectimg.size(); l++){
367 short *vectimgpoint = ( short*)vectimg[l]->GetScalarPointer(i, j, k);
368 *vectimgpoint = imgpoint[l];
377 ** Adds a prop3D to the manager and returns the identifier
379 int VolumeRendererManager::addVolume(int idTP, vtkImageData* vol, std::string dataname) throw(char*){
383 VolumeRendererManagerData* data = new VolumeRendererManagerData(vol, dataname);
384 prop3Dvect.push_back(data);
385 _renderer->AddActor(data->getProp3D());
388 data->setId(_idCount);
395 printf("VolumeRendererManager::addVolume->idVolumeRenderer: %i\n", data->getId());
396 return data->getId();
398 throw "Check mhd imagefile file or input";
403 ** adds or removes an actor depending of the bool value
406 void VolumeRendererManager::addRemoveActor(int propid, bool addremove) throw(char*){
409 VolumeRendererManagerData* data = this->getViewData(propid);
410 if(data->getProp3D()!=NULL){
412 _renderer->AddViewProp(data->getProp3D());
414 _renderer->RemoveViewProp(data->getProp3D());
421 ** Changes the opacity in a prop3D
423 void VolumeRendererManager::setVolumeOpacity(int propid, std::vector<double> greylevel,std::vector<double> value) throw(char*){
426 printf("EED VolumeRendererManager::setVolumeOpacity %d\n",propid);
428 VolumeRendererManagerData* volrenman = this->getViewData(propid);
431 volrenman->setVolumeOpacity(greylevel, value);
433 printf("EED VolumeRendererManager::setVolumeOpacity Warning volrenman NULL\n");
444 void VolumeRendererManager::setVolumeColor(int volid, std::vector<double> greylevel,
445 std::vector<double> red,
446 std::vector<double> green,
447 std::vector<double> blue)throw(char*){
448 printf("EED VolumeRendererManager::setVolumeColor start \n");
451 printf("EED VolumeRendererManager::setVolumeColor %d\n",volid);
453 VolumeRendererManagerData* volrenman = this->getViewData(volid);
456 this->getViewData(volid)->setVolumeColor(greylevel, red, green, blue);
458 printf("EED VolumeRendererManager::setVolumeColor Warning volrenman NULL\n");
462 printf("EED VolumeRendererManager::setVolumeColor end \n");
465 vtkImageData* VolumeRendererManager::getImageData(std::string filename){
466 if(filename.compare("")!= 0){
468 vtkMetaImageReader* reader = vtkMetaImageReader::New();
469 reader->SetFileName(filename.c_str());
471 vtkImageData* img = reader->GetOutput();
473 vtkImageCast* cast = vtkImageCast::New();
474 //EED 2017-01-01 Migration VTK7
475 #if VTK_MAJOR_VERSION <= 5
478 cast->SetInputData(img);
481 cast->SetOutputScalarTypeToUnsignedShort();
485 return cast->GetOutput();
491 vtkImageData* VolumeRendererManager::getImageData(){
495 void VolumeRendererManager::checkInvariant() throw(char*){
496 printf("EED VolumeRendererManager::checkInvariant start\n");
497 if(this->_renderer==NULL){
498 throw "Renderer not set";
500 printf("EED VolumeRendererManager::checkInvariant end \n");
503 VolumeRendererManagerData* VolumeRendererManager::getViewData(int id) throw(char*){
505 for(i = 0; i < (int)(prop3Dvect.size());i++){
506 if(prop3Dvect[i]->getId() == id){
507 return prop3Dvect[i];
510 throw "id not found in the data";
515 void VolumeRendererManager::deleteActor(int propid) throw (char *){
518 this->addRemoveActor(propid, false);
522 for(i = 0; i < (int)(prop3Dvect.size())&&!exit;i++){
523 if(prop3Dvect[i]->getId() == propid){
529 VolumeRendererManagerData* data = prop3Dvect[n];
531 for(j = i; j < (int)(prop3Dvect.size())-1;j++){
532 prop3Dvect[j] = prop3Dvect[j+1];
535 prop3Dvect.pop_back();
537 throw "id not found in the data";
542 vtkPiecewiseFunction* VolumeRendererManager::GetTransferFunction(int volumeid){
543 return getViewData(volumeid)->GetTransferFunction();
545 vtkColorTransferFunction* VolumeRendererManager::GetColorFunction(int volumeid){
547 return getViewData(volumeid)->GetColorFunction();
550 void VolumeRendererManager::changeCompositeMIPFunction(int id, int function) throw (char *){
552 for(unsigned i = 0; i < prop3Dvect.size(); i++)
553 prop3Dvect[i]->changeCompositeMIPFunction(function);
555 getViewData(id)->changeCompositeMIPFunction(function);
560 Changes the interpolation of the volume rendering.
561 type == 0 for linear interpolation
562 type == 1 for nearest interpolation
564 void VolumeRendererManager::changeInterpolationType(int type, int propid){
566 for(unsigned i = 0; i < prop3Dvect.size(); i++)
567 prop3Dvect[i]->changeInterpolationType(type);
569 getViewData(propid)->changeInterpolationType(type);
574 * Set the lookuptable to the volumes in memory
575 * if the id is set then it only changes the lookup table for a specific volume
577 void VolumeRendererManager::SetLookupTable(vtkLookupTable* lookup, int id){
579 for(unsigned i = 0; i < prop3Dvect.size(); i++)
580 prop3Dvect[i]->SetLookupTable(lookup);
582 getViewData(id)->SetLookupTable(lookup);
588 * @returns all the props3D in this manager
590 vector< vtkProp3D* > VolumeRendererManager::getProps3D(){
592 vector< vtkProp3D* > propvects;
593 for(unsigned i = 0; i < prop3Dvect.size(); i++){
594 propvects.push_back(prop3Dvect[i]->getProp3D());
600 * @param std::vector<double> greylevel, the corresponding greylevel in the image
601 * @param std::vector<double> value, the corresponding value for the opacity
602 * @param int propid, the correspoding id, by default it applies the changes to the first volume in the array
604 void VolumeRendererManager::setVolumeOpacity(std::vector<double> greylevel, std::vector<double> value, int propid){
606 for(unsigned i = 0; i < prop3Dvect.size(); i++)
607 prop3Dvect[i]->setVolumeOpacity(greylevel, value);
609 getViewData(propid)->setVolumeOpacity(greylevel, value);
613 void VolumeRendererManager::EnableBoundingBox(vtkRenderWindowInteractor* interactor, int propid){
615 for(unsigned i = 0; i < prop3Dvect.size(); i++)
616 prop3Dvect[i]->EnableBoundingBox(interactor);
618 getViewData(propid)->EnableBoundingBox(interactor);
622 void VolumeRendererManager::DisableBoundingBox(int propid){
625 for(unsigned i = 0; i < prop3Dvect.size(); i++)
626 prop3Dvect[i]->DisableBoundingBox();
628 getViewData(propid)->DisableBoundingBox();