OpenWalnut  1.5.0dev
WTransferFunctionScene.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <vector>
26 
27 #include <QtCore/QMimeData>
28 #include <QtCore/QUrl>
29 #include <QGraphicsSceneDragDropEvent>
30 
31 #include "core/common/WTransferFunction.h"
32 #include "WTransferFunctionScene.h"
33 #include "WTransferFunctionWidget.h"
34 
36  : BaseClass( parent ),
37  myparent( dynamic_cast<WTransferFunctionWidget*>( parent ) )
38 {
39  setBackgroundBrush( QBrush( Qt::lightGray, Qt::CrossPattern ) ); //Qt::white );
40 }
41 
43 {
44 }
45 
46 void WTransferFunctionScene::dragMoveEvent( QGraphicsSceneDragDropEvent* event )
47 {
48  if( sceneRect().contains( event->scenePos() ) )
49  {
50  if( event->mimeData()->hasColor() )
51  {
52  if( myparent )
53  {
54  event->accept();
55  }
56  return;
57  }
58  if( event->mimeData()->hasImage() )
59  {
60  if( myparent )
61  {
62  event->accept();
63  }
64  return;
65  }
66  if( event->mimeData()->hasUrls() )
67  {
68  // this may be realtively slow but is the most-reliable way
69  // to find out whether we accept drags of images:
70  // Just load the image whenever it is offered and we hope that
71  // nobody offers a really large image!
72  QImage image( event->mimeData()->urls().first().toLocalFile() );
73  if( !image.isNull() )
74  {
75  event->accept();
76  return;
77  }
78  }
79  }
80  BaseClass::dragMoveEvent( event );
81 }
82 
83 namespace
84 {
85  inline QColor toQColor( const WColor &color )
86  {
87  QColor tmp;
88  tmp.setRgbF( color[0],
89  color[1],
90  color[2],
91  color[3] );
92 
93  return tmp;
94  }
95 }
96 
97 
98 void do_update( const WTransferFunction& tf, WTransferFunctionWidget* m_transferFunction )
99 {
100  // check whether the values changed. If they did, propagate to the GUI
101  {
102  m_transferFunction->clearTransferFunction();
103  //m_transferFunction->externalDataChange( tf );
104  m_transferFunction->setHistogram( tf.getHistogram() );
105 
106  // initialize the widget with the new transfer function
107  size_t nbColors = tf.numColors();
108  QColor c;
109  if( nbColors > 0 )
110  {
111  WColor cc = tf.getColor( 0 );
112  c = toQColor( cc );
113  double iso = tf.getColorIsovalue( 0 );
114  m_transferFunction->insertColorNormalized( QPointF( iso, 0 ), &c );
115  }
116  if( nbColors > 1 )
117  {
118  WColor cc = tf.getColor( nbColors-1 );
119  c = toQColor( cc );
120  double iso = tf.getColorIsovalue( nbColors-1 );
121  m_transferFunction->insertColorNormalized( QPointF( iso, 0 ), &c );
122  }
123  for( size_t i = 1; i< nbColors-1; ++i )
124  {
125  WColor cc = tf.getColor( i );
126  c = toQColor( cc );
127  double iso = tf.getColorIsovalue( i );
128  m_transferFunction->insertColorNormalized( QPointF( iso, 0 ), &c );
129  }
130  size_t nbAlphas = tf.numAlphas();
131 
132  // add first alpha first
133  if( nbAlphas > 0 )
134  {
135  double alpha = tf.getAlpha( 0 );
136  double iso = tf.getAlphaIsovalue( 0 );
137  m_transferFunction->insertPointNormalized( QPointF( iso, alpha ) );
138  }
139 
140  // add last alpha second to prevent the widget moving mid points to the right
141  if( nbAlphas > 1 )
142  {
143  double alpha = tf.getAlpha( nbAlphas-1 );
144  double iso = tf.getAlphaIsovalue( nbAlphas-1 );
145  m_transferFunction->insertPointNormalized( QPointF( iso, alpha ) );
146  }
147 
148  for( size_t i = 1; i< nbAlphas-1; ++i )
149  {
150  double alpha = tf.getAlpha( i );
151  double iso = tf.getAlphaIsovalue( i );
152  m_transferFunction->insertPointNormalized( QPointF( iso, alpha ) );
153  }
154  }
155 }
156 
157 
158 void WTransferFunctionScene::dropEvent( QGraphicsSceneDragDropEvent* event )
159 {
160  if( sceneRect().contains( event->scenePos() ) )
161  {
162  if( event->mimeData()->hasColor() )
163  {
164  if( myparent )
165  {
166  event->accept();
167  QColor color = qvariant_cast<QColor>( event->mimeData()->colorData() );
168  {
169  myparent->insertColor( event->scenePos(), &color );
170  }
171  }
172  }
173  QImage myImage;
174  if( event->mimeData()->hasImage() )
175  {
176  myImage = qvariant_cast < QImage > ( event->mimeData()->imageData() );
177  // std::cout << "found image" << std::endl;
178  }
179  if( event->mimeData()->hasUrls() )
180  {
181  QList < QUrl > urls = event->mimeData()->urls();
182  Q_ASSERT( !urls.empty() );
183  myImage = QImage( urls.first().toLocalFile() );
184  // std::cout << "found url" << std::endl;
185  }
186  if( !myImage.isNull() )
187  {
188  // std::cout << "work on image" << std::endl;
189  QImage image = myImage;
190  event->accept();
191  std::vector < unsigned char > data( 4*image.width() );
192  for( int i = 0; i < image.width( ); ++i )
193  {
194  QRgb pixel = image.pixel( i, 0 );
195  data[ 4*i+0 ] = qRed( pixel );
196  data[ 4*i+1 ] = qGreen( pixel );
197  data[ 4*i+2 ] = qBlue( pixel );
198  data[ 4*i+3 ] = qAlpha( pixel );
199  }
200 
201  WTransferFunction tf = WTransferFunction::createFromRGBA( &( data[ 0 ] ), image.width() );
202  do_update( tf, myparent );
203  }
204  return;
205  }
206  BaseClass::dropEvent( event );
207 }
208 
virtual ~WTransferFunctionScene()
Default destructor.
virtual void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
Checks whether the drag is inside the main rectangle of the scene and whether the dragged object is o...
virtual void dropEvent(QGraphicsSceneDragDropEvent *event)
Allows drop of QColor-alike objects and creates new color control points in the scene.
WTransferFunctionScene(QObject *parent=0)
Default constructor.
WTransferFunctionWidget * myparent
storage of the widget as this currently manages the data
A widget that holds a scene to display and modify the transfer function.
void insertColorNormalized(const QPointF &pos, QColor const *const color=0)
Same as insertColor but in normalized coordinates, i.e., [ 0...1 ] along x.
void insertColor(const QPointF &pos, QColor const *const color=0)
Insert a new color control point at scene position pos (only the x-value is relevant) If a color is p...
void setHistogram(const std::vector< double > &histogram)
Called from external to set histogram.
void insertPointNormalized(const QPointF &position)
Same as insertPoint but in normalized coordinates and not in screen space.
void clearTransferFunction()
Remove all points from the transfer function widget to be able to insert new points.
A class that stores a 1D transfer function which consists of a linear interpolation of alpha and colo...
double getColorIsovalue(size_t i) const
The isovalue of the color at a given index.
const std::vector< double > & getHistogram() const
Returns the histogram.
size_t numAlphas() const
Get the number of alphas.
double getAlphaIsovalue(size_t i) const
Get the isovalue at a given index in the alpha values.
size_t numColors() const
Get the number of colors.
double getAlpha(size_t i) const
Get alpha at given index.
const WColor & getColor(size_t i) const
Get color at given index.
static WTransferFunction createFromRGBA(unsigned char const *const rgba, size_t size)
Try to estimate a transfer function from an RGBA image.