Fraxinus  17.12-rc1
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) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
33 
34 #include <QPixmap>
35 #include "cxPatientModelService.h"
36 #include <QtConcurrent>
37 #include <QDesktopWidget>
38 #include <QApplication>
39 #include "cxReporter.h"
40 #include "boost/bind.hpp"
41 #include <QScreen>
42 #include <QVBoxLayout>
43 #include "cxViewService.h"
44 //#include "cxSecondaryViewLayoutWindow.h"
45 #include "cxViewCollectionWidget.h"
46 #include "vtkRenderer.h"
47 #include "vtkWindowToImageFilter.h"
48 #include "vtkRenderWindow.h"
49 #include "vtkPNGWriter.h"
50 #include "vtkUnsignedCharArray.h"
51 #include <QPainter>
52 #include "cxVolumeHelpers.h"
53 #include "vtkImageImport.h"
54 #include <QTime>
55 
56 namespace cx
57 {
58 
59 
61 {
62 
63 }
64 
66 {
67  std::vector<ViewPtr> views = mWidget->getViews();
68  Eigen::Array3i target_size(mWidget->width(), mWidget->height(), 1);
69  vtkImageDataPtr target = generateVtkImageData(target_size, Vector3D(1,1,1), 150, 3);
70 
71  for (unsigned i=0; i<views.size(); ++i)
72  {
73  vtkImageDataPtr vtkImage = this->view2vtkImageData(views[i]);
74  QPoint vtkpos = this->getVtkPositionOfView(views[i]);
75  this->drawImageAtPos(target, vtkImage, vtkpos);
76  }
77 
78  return target;
79 }
80 
81 QPoint ViewCollectionImageWriter::getVtkPositionOfView(ViewPtr view)
82 {
83  QPoint qpos_ul = mWidget->getPosition(view); // UL position in qt-space of mWidget
84 // CX_LOG_CHANNEL_DEBUG("CA") << " qpos_ul " << qpos_ul.x() << " " << qpos_ul.y();
85  Eigen::Array2i size_view(view->getRenderer()->GetSize());
86 // CX_LOG_CHANNEL_DEBUG("CA") << " size " << size;
87  QPoint qpos_ll = qpos_ul + QPoint(0, size_view[1]-1); // LL position in qt-space of mWidget
88 // CX_LOG_CHANNEL_DEBUG("CA") << " qpos_ll " << qpos_ll.x() << " " << qpos_ll.y();
89  QPoint vtkpos_ll = this->qt2vtk(qpos_ll);
90 // CX_LOG_CHANNEL_DEBUG("CA") << " vtkpos_ll " << vtkpos_ll.x() << " " << vtkpos_ll.y();
91  return vtkpos_ll;
92 }
93 
94 QPoint ViewCollectionImageWriter::qt2vtk(QPoint qpos)
95 {
96  int H = mWidget->height();
97  QPoint vtkpos(qpos.x(), H-1-qpos.y());
98  return vtkpos;
99 }
100 
101 
102 void ViewCollectionImageWriter::drawImageAtPos(vtkImageDataPtr target, vtkImageDataPtr image, QPoint pos)
103 {
104  unsigned char* src = reinterpret_cast<unsigned char*>(image->GetScalarPointer());
105  unsigned char* dst = reinterpret_cast<unsigned char*>(target->GetScalarPointer());
106  Eigen::Array3i dim_src(image->GetDimensions());
107  int depth = 3;
108  CX_ASSERT(target->GetNumberOfScalarComponents()==depth);
109  CX_ASSERT(image->GetNumberOfScalarComponents()==depth);
110 
111  for (int y=0; y<dim_src[1]; ++y)
112  {
113  unsigned char* src = reinterpret_cast<unsigned char*>(image->GetScalarPointer(0,y,0));
114  unsigned char* dst = reinterpret_cast<unsigned char*>(target->GetScalarPointer(pos.x(),pos.y()+y,0));
115  memcpy(dst, src, dim_src[0]*depth);
116  }
117 }
118 
119 // the vtk canonical way
120 //vtkImageDataPtr ViewCollectionImageWriter::view2vtkImageData(ViewPtr view)
121 //{
122 // Eigen::Array4d vp(view->getRenderer()->GetViewport());
123 // vtkWindowToImageFilterPtr w2i = vtkWindowToImageFilterPtr::New();
124 // w2i->ShouldRerenderOff();
125 // w2i->SetInput(view->getRenderWindow());
126 // w2i->SetViewport(vp.data());
127 // w2i->SetReadFrontBuffer(false);
128 // CX_LOG_CHANNEL_DEBUG("CA") << " - 2";
129 // w2i->Update();
130 // CX_LOG_CHANNEL_DEBUG("CA") << " - 3 -upd";
131 // vtkImageDataPtr image = w2i->GetOutput();
132 // return image;
133 //}
134 
135 // alternative to vtkWindowToImageFilter, effectively reimplementing parts of that filter (for debugging speed)
136 vtkImageDataPtr ViewCollectionImageWriter::view2vtkImageData(ViewPtr view)
137 {
138  vtkRenderWindowPtr renderWindow = view->getRenderWindow();
139  vtkRendererPtr renderer = view->getRenderer();
140  Eigen::Array4d vp(renderer->GetViewport()); // need the viewport in pixels
141 
142  Eigen::Array2i origin(renderer->GetOrigin());
143  Eigen::Array2i size(renderer->GetSize());
144  Eigen::Array<int,6,1> extent;
145  extent[0] = 0;
146  extent[1] = size[0]-1;
147  extent[2] = 0;
148  extent[3] = size[1]-1;
149  extent[4] = 0;
150  extent[5] = 0;
151  int frontBuffer = false;
152 
153  unsigned char *pixels;
154 // QTime qtimer = QTime::currentTime();
155 
156 // CX_LOG_CHANNEL_DEBUG("CA") << " renderWindow->GetPixelData0";
157  renderWindow->MakeCurrent();
158 // CX_LOG_CHANNEL_DEBUG("CA") << " after makecurrent";
159  pixels = renderWindow->GetPixelData(origin[0], origin[1], origin[0]+size[0]-1, origin[1]+size[1]-1, frontBuffer);
160 // CX_LOG_CHANNEL_DEBUG("CA") << " renderWindow->GetPixelData2";
161 
162 // std::cout << "ViewCollectionImageWriter::view2vtkImageData qtimer ms=" << qtimer.msecsTo(QTime::currentTime()) << std::endl;
163 
164  typedef vtkSmartPointer<vtkImageImport> vtkImageImportPtr;
165  vtkImageImportPtr import = vtkImageImportPtr::New();
166  import->SetDataScalarTypeToUnsignedChar();
167  import->SetNumberOfScalarComponents(3);
168  import->SetDataExtent(extent.data());
169  import->SetWholeExtent(extent.data());
170  bool takeOwnership = true;
171  import->SetImportVoidPointer(pixels, !takeOwnership);
172  import->Update();
173  return import->GetOutput();
174 }
175 
176 
178 {
179  CX_ASSERT(input->GetNumberOfScalarComponents()==3);
180  CX_ASSERT(input->GetScalarType() == VTK_UNSIGNED_CHAR);
181 
182  unsigned char* ptr = reinterpret_cast<unsigned char*>(input->GetScalarPointer());
183  Eigen::Array3i dim(input->GetDimensions());
184 
185  // important: input the line length. This will not copy the buffer.
186  QImage retval(ptr, dim[0], dim[1], dim[0]*3, QImage::Format_RGB888);
187  // copy contents into image, then flip according to conventions vtk<->qt.
188  return retval.copy().mirrored(false, true);
189 }
190 
191 
192 } // namespace cx
#define CX_ASSERT(statement)
Definition: cxLogger.h:137
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:63
vtkSmartPointer< class vtkImageImport > vtkImageImportPtr
virtual QPoint getPosition(ViewPtr view)=0
vtkSmartPointer< class vtkImageData > vtkImageDataPtr
Namespace for all CustusX production code.