CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxViewCollectionImageWriter.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
12 
13 #include <QPixmap>
14 #include "cxPatientModelService.h"
15 #include <QtConcurrent>
16 #include <QDesktopWidget>
17 #include <QApplication>
18 #include "cxReporter.h"
19 #include "boost/bind.hpp"
20 #include <QScreen>
21 #include <QVBoxLayout>
22 #include "cxViewService.h"
23 //#include "cxSecondaryViewLayoutWindow.h"
24 #include "cxViewCollectionWidget.h"
25 #include "vtkRenderer.h"
26 #include "vtkWindowToImageFilter.h"
27 #include "vtkRenderWindow.h"
28 #include "vtkPNGWriter.h"
29 #include "vtkUnsignedCharArray.h"
30 #include <QPainter>
31 #include "cxVolumeHelpers.h"
32 #include "vtkImageImport.h"
33 #include <QTime>
34 
35 namespace cx
36 {
37 
38 
40 {
41 
42 }
43 
45 {
46  std::vector<ViewPtr> views = mWidget->getViews();
47  Eigen::Array3i target_size(mWidget->width(), mWidget->height(), 1);
48  vtkImageDataPtr target = generateVtkImageData(target_size, Vector3D(1,1,1), 150, 3);
49 
50  for (unsigned i=0; i<views.size(); ++i)
51  {
52  vtkImageDataPtr vtkImage = this->view2vtkImageData(views[i]);
53  QPoint vtkpos = this->getVtkPositionOfView(views[i]);
54  this->drawImageAtPos(target, vtkImage, vtkpos);
55  }
56 
57  return target;
58 }
59 
60 QPoint ViewCollectionImageWriter::getVtkPositionOfView(ViewPtr view)
61 {
62  QPoint qpos_ul = mWidget->getPosition(view); // UL position in qt-space of mWidget
63 // CX_LOG_CHANNEL_DEBUG("CA") << " qpos_ul " << qpos_ul.x() << " " << qpos_ul.y();
64  Eigen::Array2i size_view(view->getRenderer()->GetSize());
65 // CX_LOG_CHANNEL_DEBUG("CA") << " size " << size;
66  QPoint qpos_ll = qpos_ul + QPoint(0, size_view[1]-1); // LL position in qt-space of mWidget
67 // CX_LOG_CHANNEL_DEBUG("CA") << " qpos_ll " << qpos_ll.x() << " " << qpos_ll.y();
68  QPoint vtkpos_ll = this->qt2vtk(qpos_ll);
69 // CX_LOG_CHANNEL_DEBUG("CA") << " vtkpos_ll " << vtkpos_ll.x() << " " << vtkpos_ll.y();
70  return vtkpos_ll;
71 }
72 
73 QPoint ViewCollectionImageWriter::qt2vtk(QPoint qpos)
74 {
75  int H = mWidget->height();
76  QPoint vtkpos(qpos.x(), H-1-qpos.y());
77  return vtkpos;
78 }
79 
80 
81 void ViewCollectionImageWriter::drawImageAtPos(vtkImageDataPtr target, vtkImageDataPtr image, QPoint pos)
82 {
83  unsigned char* src = reinterpret_cast<unsigned char*>(image->GetScalarPointer());
84  unsigned char* dst = reinterpret_cast<unsigned char*>(target->GetScalarPointer());
85  Eigen::Array3i dim_src(image->GetDimensions());
86  int depth = 3;
87  CX_ASSERT(target->GetNumberOfScalarComponents()==depth);
88  CX_ASSERT(image->GetNumberOfScalarComponents()==depth);
89 
90  for (int y=0; y<dim_src[1]; ++y)
91  {
92  unsigned char* src = reinterpret_cast<unsigned char*>(image->GetScalarPointer(0,y,0));
93  unsigned char* dst = reinterpret_cast<unsigned char*>(target->GetScalarPointer(pos.x(),pos.y()+y,0));
94  memcpy(dst, src, dim_src[0]*depth);
95  }
96 }
97 
98 // the vtk canonical way
99 //vtkImageDataPtr ViewCollectionImageWriter::view2vtkImageData(ViewPtr view)
100 //{
101 // Eigen::Array4d vp(view->getRenderer()->GetViewport());
102 // vtkWindowToImageFilterPtr w2i = vtkWindowToImageFilterPtr::New();
103 // w2i->ShouldRerenderOff();
104 // w2i->SetInput(view->getRenderWindow());
105 // w2i->SetViewport(vp.data());
106 // w2i->SetReadFrontBuffer(false);
107 // CX_LOG_CHANNEL_DEBUG("CA") << " - 2";
108 // w2i->Update();
109 // CX_LOG_CHANNEL_DEBUG("CA") << " - 3 -upd";
110 // vtkImageDataPtr image = w2i->GetOutput();
111 // return image;
112 //}
113 
114 // alternative to vtkWindowToImageFilter, effectively reimplementing parts of that filter (for debugging speed)
115 vtkImageDataPtr ViewCollectionImageWriter::view2vtkImageData(ViewPtr view)
116 {
117  vtkRenderWindowPtr renderWindow = view->getRenderWindow();
118  vtkRendererPtr renderer = view->getRenderer();
119  Eigen::Array4d vp(renderer->GetViewport()); // need the viewport in pixels
120 
121  Eigen::Array2i origin(renderer->GetOrigin());
122  Eigen::Array2i size(renderer->GetSize());
123  Eigen::Array<int,6,1> extent;
124  extent[0] = 0;
125  extent[1] = size[0]-1;
126  extent[2] = 0;
127  extent[3] = size[1]-1;
128  extent[4] = 0;
129  extent[5] = 0;
130  int frontBuffer = false;
131 
132  unsigned char *pixels;
133 // QTime qtimer = QTime::currentTime();
134 
135 // CX_LOG_CHANNEL_DEBUG("CA") << " renderWindow->GetPixelData0";
136  renderWindow->MakeCurrent();
137 // CX_LOG_CHANNEL_DEBUG("CA") << " after makecurrent";
138  pixels = renderWindow->GetPixelData(origin[0], origin[1], origin[0]+size[0]-1, origin[1]+size[1]-1, frontBuffer);
139 // CX_LOG_CHANNEL_DEBUG("CA") << " renderWindow->GetPixelData2";
140 
141 // std::cout << "ViewCollectionImageWriter::view2vtkImageData qtimer ms=" << qtimer.msecsTo(QTime::currentTime()) << std::endl;
142 
143  typedef vtkSmartPointer<vtkImageImport> vtkImageImportPtr;
144  vtkImageImportPtr import = vtkImageImportPtr::New();
145  import->SetDataScalarTypeToUnsignedChar();
146  import->SetNumberOfScalarComponents(3);
147  import->SetDataExtent(extent.data());
148  import->SetWholeExtent(extent.data());
149  bool takeOwnership = true;
150  import->SetImportVoidPointer(pixels, !takeOwnership);
151  import->Update();
152  return import->GetOutput();
153 }
154 
155 
157 {
158  CX_ASSERT(input->GetNumberOfScalarComponents()==3);
159  CX_ASSERT(input->GetScalarType() == VTK_UNSIGNED_CHAR);
160 
161  unsigned char* ptr = reinterpret_cast<unsigned char*>(input->GetScalarPointer());
162  Eigen::Array3i dim(input->GetDimensions());
163 
164  // important: input the line length. This will not copy the buffer.
165  QImage retval(ptr, dim[0], dim[1], dim[0]*3, QImage::Format_RGB888);
166  // copy contents into image, then flip according to conventions vtk<->qt.
167  return retval.copy().mirrored(false, true);
168 }
169 
170 
171 } // namespace cx
#define CX_ASSERT(statement)
Definition: cxLogger.h:116
virtual std::vector< ViewPtr > getViews()=0
ViewCollectionImageWriter(ViewCollectionWidget *widget)
vtkSmartPointer< class vtkRenderWindow > vtkRenderWindowPtr
boost::shared_ptr< class View > ViewPtr
static QImage vtkImageData2QImage(vtkImageDataPtr input)
vtkSmartPointer< class vtkRenderer > vtkRendererPtr
vtkImageDataPtr generateVtkImageData(Eigen::Array3i dim, Vector3D spacing, const unsigned char initValue, int components)
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
vtkSmartPointer< class vtkImageImport > vtkImageImportPtr
virtual QPoint getPosition(ViewPtr view)=0
vtkSmartPointer< class vtkImageData > vtkImageDataPtr
Namespace for all CustusX production code.