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 luminance->SetInput(img);
117 vtkSmartPointer< vtkImageAppendComponents > append = vtkSmartPointer< vtkImageAppendComponents >::New();
118 append->SetInput(0, img);
119 append->SetInput(1, luminance->GetOutput());
124 VolumeRendererManagerData* data = new VolumeRendererManagerData(append->GetOutput(), true);
125 data->SetIndependentComponents(independentcomponents);
128 prop3Dvect.push_back(data);
130 data->setId(_idCount);
138 vector< vtkImageData* > vectimg;
139 GetImages(img, vectimg);
140 vtkBoxWidget* boxw = 0;
141 for(unsigned i = 0; i < vectimg.size(); i++){
142 VolumeRendererManagerData* data = new VolumeRendererManagerData(vectimg[i], "");
144 vtkColorTransferFunction* colorf = data->GetColorFunction();
145 colorf->RemoveAllPoints();
146 double r = 0, g = 0, b = 0;
147 for(unsigned j = 0; j < 255; j++){
163 colorf->AddRGBPoint(j, r, g, b);
166 prop3Dvect.push_back(data);
168 data->setId(_idCount);
172 EnableBoundingBox(interactor, data->getId());
173 DisableBoundingBox(data->getId());
174 boxw = data->GetBoxWidget();
176 data->SetBoxWidget(boxw);
180 boxw->RemoveAllObservers();
182 vtkBoxWidgetCallback *callback = vtkBoxWidgetCallback::New();
184 for(unsigned i = 0; i < prop3Dvect.size(); i++){
185 VolumeRendererManagerData* data = prop3Dvect[i];
186 callback->AddMapper(data->GetVolumeMapper());
189 boxw->AddObserver(vtkCommand::InteractionEvent, callback);
194 /*vtkImageData* imgshort = 0;
195 imgshort = vtkImageData::New();
196 imgshort->SetNumberOfScalarComponents(1);
197 imgshort->SetExtent(img->GetExtent());
198 imgshort->SetSpacing(img->GetSpacing());
199 imgshort->SetOrigin(img->GetOrigin());
200 imgshort->SetScalarTypeToUnsignedShort();
201 imgshort->AllocateScalars();
202 GetImageDouble(img, imgshort);
204 VolumeRendererManagerData* data = new VolumeRendererManagerData(imgshort, "");
206 vtkColorTransferFunction* colorf = data->GetColorFunction();
207 colorf->RemoveAllPoints();
209 map< unsigned short, vector< double > > colormap;
211 int *extent = img->GetExtent();
213 for(unsigned i = extent[0]; i < extent[1]; i++){
214 for(unsigned j = extent[2]; j < extent[3]; j++){
215 for(unsigned k = extent[4]; k < extent[5]; k++){
217 unsigned char *imgpoint = ((unsigned char*)img->GetScalarPointer(i, j, k));
218 double temp = (double)(0.299*imgpoint[0] + 0.587*imgpoint[1] + 0.114*imgpoint[2]);
219 unsigned short val = temp*255.0;
221 vector< double > rgb;
222 rgb.push_back(0.299*imgpoint[0]);
223 rgb.push_back(0.587*imgpoint[1]);
224 rgb.push_back(0.114*imgpoint[2]);
233 map< unsigned short, vector< double > >::iterator it;
234 for(it = colormap.begin(); it != colormap.end(); ++it){
236 colorf->AddRGBPoint((*it).first, (*it).second[0] / 255.0, (*it).second[1] / 255.0, (*it).second[2] / 255.0);
239 prop3Dvect.push_back(data);
241 data->setId(_idCount);
242 EnableBoundingBox(interactor, data->getId());
243 DisableBoundingBox(data->getId());
250 VolumeRendererManagerData* data = new VolumeRendererManagerData(img, "");
251 prop3Dvect.push_back(data);
254 data->setId(_idCount);
257 EnableBoundingBox(interactor, data->getId());
258 DisableBoundingBox(data->getId());
262 return data->getId();
268 * @pre the image is not null and has more than one scalar component
269 * @post Each component in the image is put in a single image
270 * @param vtkImageData* img, multiple component image i.e. an image of vectors like an rgb
271 * @return vtkImageData* double type image
273 void VolumeRendererManager::GetImageDouble(vtkImageData* img, vtkImageData* imgushort){
276 int *extent = img->GetExtent();
278 for(unsigned i = extent[0]; i < extent[1]; i++){
279 for(unsigned j = extent[2]; j < extent[3]; j++){
280 for(unsigned k = extent[4]; k < extent[5]; k++){
281 if(img->GetScalarType() == VTK_UNSIGNED_CHAR){
282 unsigned char *imgpoint = ((unsigned char*)img->GetScalarPointer(i, j, k));
284 unsigned short *vectimgpoint = (unsigned short*)imgushort->GetScalarPointer(i, j, k);
285 double temp = (double)(0.299*imgpoint[0] + 0.587*imgpoint[1] + 0.114*imgpoint[2]);
286 *vectimgpoint = temp*255.0;
295 * @pre the image is not null and has more than one scalar component
296 * @post Each component in the image is separated to form a different image
297 * @param vtkImageData* img, multiple component image i.e. an image of vectors like an rgb
298 * @return vector<vtkImageData* > a vector of images, one for each component
300 void VolumeRendererManager::GetImages(vtkImageData* img, vector<vtkImageData* >& vectimg){
302 for(unsigned i = 0; i < img->GetNumberOfScalarComponents(); i++){
303 vectimg.push_back(vtkImageData::New());
304 vectimg[i]->SetNumberOfScalarComponents(1);
305 vectimg[i]->SetExtent(img->GetExtent());
306 vectimg[i]->SetSpacing(img->GetSpacing());
307 vectimg[i]->SetOrigin(img->GetOrigin());
308 vectimg[i]->SetScalarType(img->GetScalarType());
309 vectimg[i]->AllocateScalars();
312 int *extent = img->GetExtent();
314 for(unsigned i = extent[0]; i < extent[1]; i++){
315 for(unsigned j = extent[2]; j < extent[3]; j++){
316 for(unsigned k = extent[4]; k < extent[5]; k++){
317 if(img->GetScalarType() == VTK_UNSIGNED_CHAR){
318 unsigned char *imgpoint = ((unsigned char*)img->GetScalarPointer(i, j, k));
320 for(unsigned l = 0; l < vectimg.size(); l++){
321 unsigned char *vectimgpoint = (unsigned char*)vectimg[l]->GetScalarPointer(i, j, k);
322 *vectimgpoint = imgpoint[l];
324 }else if(img->GetScalarType() == VTK_CHAR){
325 char *imgpoint = ((char*)img->GetScalarPointer(i, j, k));
327 for(unsigned l = 0; l < vectimg.size(); l++){
328 char *vectimgpoint = ( char*)vectimg[l]->GetScalarPointer(i, j, k);
329 *vectimgpoint = imgpoint[l];
331 }else if(img->GetScalarType() == VTK_UNSIGNED_SHORT){
332 unsigned short *imgpoint = ((unsigned short*)img->GetScalarPointer(i, j, k));
334 for(unsigned l = 0; l < vectimg.size(); l++){
335 unsigned short *vectimgpoint = (unsigned short*)vectimg[l]->GetScalarPointer(i, j, k);
336 *vectimgpoint = imgpoint[l];
338 }else if(img->GetScalarType() == VTK_SHORT){
339 short *imgpoint = ((short*)img->GetScalarPointer(i, j, k));
341 for(unsigned l = 0; l < vectimg.size(); l++){
342 short *vectimgpoint = ( short*)vectimg[l]->GetScalarPointer(i, j, k);
343 *vectimgpoint = imgpoint[l];
352 ** Adds a prop3D to the manager and returns the identifier
354 int VolumeRendererManager::addVolume(int idTP, vtkImageData* vol, std::string dataname) throw(char*){
358 VolumeRendererManagerData* data = new VolumeRendererManagerData(vol, dataname);
359 prop3Dvect.push_back(data);
360 _renderer->AddActor(data->getProp3D());
363 data->setId(_idCount);
370 printf("VolumeRendererManager::addVolume->idVolumeRenderer: %i\n", data->getId());
371 return data->getId();
373 throw "Check mhd imagefile file or input";
378 ** adds or removes an actor depending of the bool value
381 void VolumeRendererManager::addRemoveActor(int propid, bool addremove) throw(char*){
384 VolumeRendererManagerData* data = this->getViewData(propid);
385 if(data->getProp3D()!=NULL){
387 _renderer->AddViewProp(data->getProp3D());
389 _renderer->RemoveViewProp(data->getProp3D());
396 ** Changes the opacity in a prop3D
398 void VolumeRendererManager::setVolumeOpacity(int propid, std::vector<double> greylevel,std::vector<double> value) throw(char*){
401 printf("EED VolumeRendererManager::setVolumeOpacity %d\n",propid);
403 VolumeRendererManagerData* volrenman = this->getViewData(propid);
406 volrenman->setVolumeOpacity(greylevel, value);
408 printf("EED VolumeRendererManager::setVolumeOpacity Warning volrenman NULL\n");
419 void VolumeRendererManager::setVolumeColor(int volid, std::vector<double> greylevel,
420 std::vector<double> red,
421 std::vector<double> green,
422 std::vector<double> blue)throw(char*){
423 printf("EED VolumeRendererManager::setVolumeColor start \n");
426 printf("EED VolumeRendererManager::setVolumeColor %d\n",volid);
428 VolumeRendererManagerData* volrenman = this->getViewData(volid);
431 this->getViewData(volid)->setVolumeColor(greylevel, red, green, blue);
433 printf("EED VolumeRendererManager::setVolumeColor Warning volrenman NULL\n");
437 printf("EED VolumeRendererManager::setVolumeColor end \n");
440 vtkImageData* VolumeRendererManager::getImageData(std::string filename){
441 if(filename.compare("")!= 0){
443 vtkMetaImageReader* reader = vtkMetaImageReader::New();
444 reader->SetFileName(filename.c_str());
446 vtkImageData* img = reader->GetOutput();
448 vtkImageCast* cast = vtkImageCast::New();
450 cast->SetOutputScalarTypeToUnsignedShort();
454 return cast->GetOutput();
460 vtkImageData* VolumeRendererManager::getImageData(){
464 void VolumeRendererManager::checkInvariant() throw(char*){
465 printf("EED VolumeRendererManager::checkInvariant start\n");
466 if(this->_renderer==NULL){
467 throw "Renderer not set";
469 printf("EED VolumeRendererManager::checkInvariant end \n");
472 VolumeRendererManagerData* VolumeRendererManager::getViewData(int id) throw(char*){
474 for(i = 0; i < (int)(prop3Dvect.size());i++){
475 if(prop3Dvect[i]->getId() == id){
476 return prop3Dvect[i];
479 throw "id not found in the data";
484 void VolumeRendererManager::deleteActor(int propid) throw (char *){
487 this->addRemoveActor(propid, false);
491 for(i = 0; i < (int)(prop3Dvect.size())&&!exit;i++){
492 if(prop3Dvect[i]->getId() == propid){
498 VolumeRendererManagerData* data = prop3Dvect[n];
500 for(j = i; j < (int)(prop3Dvect.size())-1;j++){
501 prop3Dvect[j] = prop3Dvect[j+1];
504 prop3Dvect.pop_back();
506 throw "id not found in the data";
511 vtkPiecewiseFunction* VolumeRendererManager::GetTransferFunction(int volumeid){
512 return getViewData(volumeid)->GetTransferFunction();
514 vtkColorTransferFunction* VolumeRendererManager::GetColorFunction(int volumeid){
516 return getViewData(volumeid)->GetColorFunction();
519 void VolumeRendererManager::changeCompositeMIPFunction(int id, int function) throw (char *){
521 for(unsigned i = 0; i < prop3Dvect.size(); i++)
522 prop3Dvect[i]->changeCompositeMIPFunction(function);
524 getViewData(id)->changeCompositeMIPFunction(function);
529 Changes the interpolation of the volume rendering.
530 type == 0 for linear interpolation
531 type == 1 for nearest interpolation
533 void VolumeRendererManager::changeInterpolationType(int type, int propid){
535 for(unsigned i = 0; i < prop3Dvect.size(); i++)
536 prop3Dvect[i]->changeInterpolationType(type);
538 getViewData(propid)->changeInterpolationType(type);
543 * Set the lookuptable to the volumes in memory
544 * if the id is set then it only changes the lookup table for a specific volume
546 void VolumeRendererManager::SetLookupTable(vtkLookupTable* lookup, int id){
548 for(unsigned i = 0; i < prop3Dvect.size(); i++)
549 prop3Dvect[i]->SetLookupTable(lookup);
551 getViewData(id)->SetLookupTable(lookup);
557 * @returns all the props3D in this manager
559 vector< vtkProp3D* > VolumeRendererManager::getProps3D(){
561 vector< vtkProp3D* > propvects;
562 for(unsigned i = 0; i < prop3Dvect.size(); i++){
563 propvects.push_back(prop3Dvect[i]->getProp3D());
569 * @param std::vector<double> greylevel, the corresponding greylevel in the image
570 * @param std::vector<double> value, the corresponding value for the opacity
571 * @param int propid, the correspoding id, by default it applies the changes to the first volume in the array
573 void VolumeRendererManager::setVolumeOpacity(std::vector<double> greylevel, std::vector<double> value, int propid){
575 for(unsigned i = 0; i < prop3Dvect.size(); i++)
576 prop3Dvect[i]->setVolumeOpacity(greylevel, value);
578 getViewData(propid)->setVolumeOpacity(greylevel, value);
582 void VolumeRendererManager::EnableBoundingBox(vtkRenderWindowInteractor* interactor, int propid){
584 for(unsigned i = 0; i < prop3Dvect.size(); i++)
585 prop3Dvect[i]->EnableBoundingBox(interactor);
587 getViewData(propid)->EnableBoundingBox(interactor);
591 void VolumeRendererManager::DisableBoundingBox(int propid){
594 for(unsigned i = 0; i < prop3Dvect.size(); i++)
595 prop3Dvect[i]->DisableBoundingBox();
597 getViewData(propid)->DisableBoundingBox();