vspline 1.1.0
Generic C++11 Code for Uniform B-Splines
slice2.cc
Go to the documentation of this file.
1/************************************************************************/
2/* */
3/* vspline - a set of generic tools for creation and evaluation */
4/* of uniform b-splines */
5/* */
6/* Copyright 2015 - 2023 by Kay F. Jahnke */
7/* */
8/* Permission is hereby granted, free of charge, to any person */
9/* obtaining a copy of this software and associated documentation */
10/* files (the "Software"), to deal in the Software without */
11/* restriction, including without limitation the rights to use, */
12/* copy, modify, merge, publish, distribute, sublicense, and/or */
13/* sell copies of the Software, and to permit persons to whom the */
14/* Software is furnished to do so, subject to the following */
15/* conditions: */
16/* */
17/* The above copyright notice and this permission notice shall be */
18/* included in all copies or substantial portions of the */
19/* Software. */
20/* */
21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
23/* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
24/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
25/* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
26/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
27/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
28/* OTHER DEALINGS IN THE SOFTWARE. */
29/* */
30/************************************************************************/
31
32/// \file slice2.cc
33///
34/// \brief create 2D image data from a 3D spline
35///
36/// build a 3D volume from samples of the RGB colour colour_space
37/// build a spline over it and extract a 2D slice, using vspline::transform()
38///
39/// while the result is just about the same as the one we get from slice.cc,
40/// here we use additional functors to create the colour gradient and do the
41/// coordinate transformation.
42///
43/// compile with:
44/// clang++ -std=c++11 -march=native -o slice2 -O3 -pthread -DUSE_VC=1 slice2.cc -lvigraimpex -lVc
45/// or: clang++ -std=c++11 -march=native -o slice2 -O3 -pthread slice2.cc -lvigraimpex
46/// g++ also works.
47
48#include <iostream>
49
50#include <vspline/vspline.h>
51
52#include <vigra/stdimage.hxx>
53#include <vigra/imageinfo.hxx>
54#include <vigra/impex.hxx>
55
56// pixel_type is the result type, an RGB float pixel
57
58typedef vigra::RGBValue < unsigned char , 0 , 1 , 2 > pixel_type ;
59
60// voxel_type is the source data type, here we're using double precision
61
62typedef vigra::TinyVector < double , 3 > voxel_type ;
63
64// coordinate2_type has a 2D coordinate
65
66typedef vigra::TinyVector < float , 2 > coordinate2_type ;
67
68// coordinate3_type has a 3D coordinate
69
70typedef vigra::TinyVector < float , 3 > coordinate3_type ;
71
72// target_type is a 2D array of pixels
73
74typedef vigra::MultiArray < 2 , pixel_type > target_type ;
75
76// we'll use a common vectorization width of 8 throughout
77
78enum { VSIZE = 8 } ;
79
80// we'll use a functor to create the gradient in the b-spline
81
83: public vspline::unary_functor < coordinate3_type , voxel_type , VSIZE >
84{
85 // this method generates a voxel from a 3D coordinate.
86
87 template < class IN , class OUT >
88 void eval ( const IN & c , OUT & result ) const
89 {
90 // assign input to output and scale
91
92 result = c ;
93 result *= 25.5 ;
94
95 // because we don't have the relevant vigra numeric and promote traits,
96 // we *can't* write the obvious
97
98 // result = 25.5 * c ;
99 } ;
100} ;
101
102// type of b-spline evaluator producing pixels from 3D coordinates
103// here we pass all template arguments an evaluator can take:
104// - coordinate3_type for the type of incoming 3D coordinates
105// - pixel_type for the data type we want to receive as result
106// - VSIZE for the vectorization width
107// - -1 indicates we want unspecialized b-spline evaluation
108// - double: we want internal calculations done in double precision
109// - voxel_type will be the type of coefficients held in the spline
110
112 pixel_type ,
113 VSIZE ,
114 -1 ,
115 double ,
118
119// this functor is used for the coordinate transformation. It receives
120// 2D coordinates (discrete target coordinates) and produces 3D
121// coordinates which will be used to evaluate the spline. We pass
122// the vectorization width explicitly to make sure it's the same
123// as that used by the evaluator; if this weren't the case we could
124// not 'chain' them further down
125
127: public vspline::unary_functor < coordinate2_type , coordinate3_type , VSIZE >
128{
129 // this method transforms incoming discrete 2D coordinates - coordinates
130 // pertaining to pixels in the target image - into 3D 'pick-up' coordinates
131 // at which to evaluate the spline. Note how it's written as a template,
132 // since the code for unvectorized and vectorized evaluation is just
133 // the same. Note how we have coded coordinate2_type as consisting of
134 // two floats, rather than two ints, which would have been just as well,
135 // but which would have required transforming 'c' to it's floating point
136 // equivalent before doing the maths. The 'index-based' version of
137 // vspline::transform will feed the functor with the type it expects as
138 // it's incoming type, so coordinate2_type in this case - or it's
139 // vectorized equivalent.
140
141 template < class IN , class OUT >
142 void eval ( const IN & c , OUT & result ) const
143 {
144 result[0] = c[0] / 192.0f ;
145 result[1] = 10.0f - result[0] ;
146 result[2] = c[1] / 108.0f ;
147 } ;
148} ;
149
150int main ( int argc , char * argv[] )
151{
152 // we want a b-spline with natural boundary conditions
153
154 vigra::TinyVector < vspline::bc_code , 3 > bcv ( vspline::NATURAL ) ;
155
156 // create quintic 3D b-spline object containing voxels
157 // note the shape of the spline: it's ten units wide in each direction.
158 // this explains the factor 25.5 used to calculate the voxels it holds:
159 // the voxel's values will go from 0 to 255 for each channel
160
162 colour_space ( vigra::Shape3 ( 10 , 10 , 10 ) , 5 , bcv ) ;
163
164 // this functor will calculate the colour cube's content:
165
166 calculate_gradient_type gradient ;
167
168 // we could instead use vspline's 'amplify_type' to the same effect:
169
170// vspline::amplify_type < voxel_type , voxel_type , voxel_type , VSIZE >
171// gradient ( voxel_type ( 25.5 ) ) ;
172
173 // now we run an index-based transform on the spline's 'core'. This will
174 // feed successive 3D coordinates to 'gradient', which will calculate
175 // voxel values from them
176
177 vspline::transform ( gradient , colour_space.core ) ;
178
179 // prefilter the b-spline
180
181 colour_space.prefilter() ;
182
183 // create the coordinate transformation functor
184
186
187 // get an evaluator for the b-spline
188
189 ev_type ev ( colour_space ) ;
190
191 // 'chain' the coordinate transformation functor and the evaluator
192
193 auto combined = vspline::chain ( pick , ev ) ;
194
195 // this is where the result should go:
196
197 target_type target ( vigra::Shape2 ( 1920 , 1080 ) ) ;
198
199 // now we perform the transform, yielding the result
200 // note how we use a 'index-based' transform feeding the functor
201 // (combined) with discrete target coordinates. Inside 'combined',
202 // the incoming discrete coordinate is first transformed to the
203 // 'pick-up' coordinate, which is in turn used to evaluate the
204 // spline, yielding the result, which is stored in 'target'.
205
206 vspline::transform ( combined , target ) ;
207
208 // store the result with vigra impex
209
210 vigra::ImageExportInfo imageInfo ( "slice.tif" );
211
212 vigra::exportImage ( target ,
213 imageInfo
214 .setPixelType("UINT8")
215 .setCompression("100")
216 .setForcedRangeMapping ( 0 , 255 , 0 , 255 ) ) ;
217
218 std::cout << "result was written to slice.tif" << std::endl ;
219 exit ( 0 ) ;
220}
vigra::MultiArray< 2, pixel_type > target_type
Definition: ca_correct.cc:115
class evaluator encodes evaluation of a spline-like object. This is a generalization of b-spline eval...
Definition: eval.h:1718
void transform(const unary_functor_type &functor, const vigra::MultiArrayView< dimension, typename unary_functor_type::in_type > &input, vigra::MultiArrayView< dimension, typename unary_functor_type::out_type > &output, int njobs=vspline::default_njobs, vspline::atomic< bool > *p_cancel=0)
implementation of two-array transform using wielding::coupled_wield.
Definition: transform.h:211
vspline::chain_type< T1, T2 > chain(const T1 &t1, const T2 &t2)
chain is a factory function yielding the result of chaining two unary_functors.
@ NATURAL
Definition: common.h:75
int main(int argc, char *argv[])
Definition: slice2.cc:150
@ VSIZE
Definition: slice2.cc:78
vigra::RGBValue< unsigned char, 0, 1, 2 > pixel_type
Definition: slice2.cc:58
vspline::evaluator< coordinate3_type, pixel_type, VSIZE, -1, double, voxel_type > ev_type
Definition: slice2.cc:117
vigra::TinyVector< double, 3 > voxel_type
Definition: slice2.cc:62
vigra::TinyVector< float, 3 > coordinate3_type
Definition: slice2.cc:70
vigra::TinyVector< float, 2 > coordinate2_type
Definition: slice2.cc:66
vigra::MultiArray< 2, pixel_type > target_type
Definition: slice2.cc:74
void eval(const IN &c, OUT &result) const
Definition: slice2.cc:88
void eval(const IN &c, OUT &result) const
Definition: slice2.cc:142
class bspline now builds on class bspline_base, adding coefficient storage, while bspline_base provid...
Definition: bspline.h:499
view_type core
Definition: bspline.h:566
void prefilter(vspline::xlf_type boost=vspline::xlf_type(1), int njobs=vspline::default_njobs)
prefilter converts the knot point data in the 'core' area into b-spline coefficients....
Definition: bspline.h:815
class unary_functor provides a functor object which offers a system of types for concrete unary funct...
includes all headers from vspline (most of them indirectly)