"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "Libtmp/Image2D/image2d.pd" between
PDL-2.081.tar.gz and PDL-2.082.tar.gz

About: PDL (Perl Data Language) aims to turn perl into an efficient numerical language for scientific computing (similar to IDL and MatLab).

image2d.pd  (PDL-2.081):image2d.pd  (PDL-2.082)
skipping to change at line 28 skipping to change at line 28
=head1 SYNOPSIS =head1 SYNOPSIS
use PDL::Image2D; use PDL::Image2D;
=cut =cut
use PDL; # ensure qsort routine available use PDL; # ensure qsort routine available
use PDL::Math; use PDL::Math;
use Carp; use Carp;
my %boundary2value = (Reflect=>1, Truncate=>2, Replicate=>3);
EOD EOD
pp_addpm({At=>'Bot'},<<'EOD'); pp_addpm({At=>'Bot'},<<'EOD');
=head1 AUTHORS =head1 AUTHORS
Copyright (C) Karl Glazebrook 1997 with additions by Robin Williams Copyright (C) Karl Glazebrook 1997 with additions by Robin Williams
(rjrw@ast.leeds.ac.uk), Tim Jeness (timj@jach.hawaii.edu), (rjrw@ast.leeds.ac.uk), Tim Jenness (timj@jach.hawaii.edu),
and Doug Burke (burke@ifa.hawaii.edu). and Doug Burke (burke@ifa.hawaii.edu).
All rights reserved. There is no warranty. You are allowed All rights reserved. There is no warranty. You are allowed
to redistribute this software / documentation under certain to redistribute this software / documentation under certain
conditions. For details, see the file COPYING in the PDL conditions. For details, see the file COPYING in the PDL
distribution. If this file is separated from the PDL distribution, distribution. If this file is separated from the PDL distribution,
the copyright notice should be included in the file. the copyright notice should be included in the file.
=cut =cut
skipping to change at line 188 skipping to change at line 189
break; break;
default: default:
REALMOD($loop2,$size); REALMOD($loop2,$size);
} }
map${var}\[$loop] = $loop2; map${var}\[$loop] = $loop2;
}\n"; }\n";
} # sub: init_map() } # sub: init_map()
sub init_vars { sub init_vars {
my $href = shift || { };
my $sizevars = shift || [qw(m n p q)]; my $sizevars = shift || [qw(m n p q)];
my $compvars = shift || []; my $compvars = shift || [];
$href->{vars} = '' unless defined $href->{vars}; my $str = "int i,j, i1,j1, i2,j2, poff, qoff;";
$href->{malloc} = '' unless defined $href->{malloc};
$href->{check} = '' unless defined $href->{check};
my $str = $href->{vars};
$str .= "int i,j, i1,j1, i2,j2, poff, qoff;";
$str .= $str .=
'int opt = $COMP(opt); 'int opt = $COMP(opt);
' . join("\n", map "int ${_}_size = \$SIZE(${_});", @$sizevars) . ' ' . join("\n", map "int ${_}_size = \$SIZE(${_});", @$sizevars) . '
' . join("\n", map "int ${_}_size = \$COMP(__${_}_size);", @$compvars) . ' . join("\n", map "int ${_}_size = \$COMP(${_}_size);", @$compvars) . '
' PDL_Indx *mapi = $P(mapi), *mapj = $P(mapj);
int *mapi, *mapj; if ((mapi==NULL) || (mapj==NULL)) $CROAK("Out of Memory");
mapi = (int *) malloc((p_size+m_size)*sizeof(int));
mapj = (int *) malloc((q_size+n_size)*sizeof(int));
';
$str .= $href->{malloc} . "\n";
$str .= "if ($href->{check} (mapi==NULL) || (mapj==NULL))\n";
$str .= ' $CROAK("Out of Memory");
poff = p_size/2; mapi += p_size-1; poff = p_size/2; mapi += p_size-1;
qoff = q_size/2; mapj += q_size-1; qoff = q_size/2; mapj += q_size-1;
'; ';
return $str; return $str;
} # sub: init_vars() } # sub: init_vars()
pp_def('conv2d', Doc=><<'EOD', pp_def('conv2d', Doc=><<'EOD',
=for ref =for ref
2D convolution of an array with a kernel (smoothing) 2D convolution of an array with a kernel (smoothing)
For large kernels, using a FFT routine, For large kernels, using a FFT routine,
such as L<fftconvolve()|PDL::FFT/fftconvolve()> in C<PDL::FFT>, such as L<PDL::FFT/fftconvolve>,
will be quicker. will be quicker.
=for usage =for usage
$new = conv2d $old, $kernel, {OPTIONS} $new = conv2d $old, $kernel, {OPTIONS}
=for example =for example
$smoothed = conv2d $image, ones(3,3), {Boundary => Reflect} $smoothed = conv2d $image, ones(3,3), {Boundary => Reflect}
skipping to change at line 249 skipping to change at line 238
(i.e. wrap around axis) (i.e. wrap around axis)
=> Reflect - reflect at boundary => Reflect - reflect at boundary
=> Truncate - truncate at boundary => Truncate - truncate at boundary
=> Replicate - repeat boundary pixel values => Replicate - repeat boundary pixel values
=cut =cut
EOD EOD
BadDoc => BadDoc =>
'Unlike the FFT routines, conv2d is able to process bad values.', 'Unlike the FFT routines, conv2d is able to process bad values.',
HandleBad => 1, HandleBad => 1,
Pars => 'a(m,n); kern(p,q); [o]b(m,n);', Pars => 'a(m,n); kern(p,q); [o]b(m,n); indx [t]mapi(isize); indx [t]mapj
(jsize)',
RedoDimsCode => '
$SIZE(isize) = $SIZE(p) + $SIZE(m);
$SIZE(jsize) = $SIZE(q) + $SIZE(n);
',
OtherPars => 'int opt;', OtherPars => 'int opt;',
PMCode => ' PMCode => '
sub PDL::conv2d { sub PDL::conv2d {
my $opt; $opt = pop @_ if ref($_[$#_]) eq \'HASH\'; my $opt; $opt = pop @_ if ref($_[$#_]) eq \'HASH\';
die \'Usage: conv2d( a(m,n), kern(p,q), [o]b(m,n), {Options} )\' die \'Usage: conv2d( a(m,n), kern(p,q), [o]b(m,n), {Options} )\'
if $#_<1 || $#_>2; if $#_<1 || $#_>2;
my($x,$kern) = @_; my($x,$kern) = @_;
my $c = $#_ == 2 ? $_[2] : $x->nullcreate; my $c = $#_ == 2 ? $_[2] : $x->nullcreate;
PDL::_conv2d_int($x,$kern,$c, PDL::_conv2d_int($x,$kern,$c,
(!(defined $opt && exists $$opt{Boundary}))?0: (!($opt && exists $$opt{Boundary}))?0:$boundary2value{$$opt{Boundary}}
(($$opt{Boundary} eq "Reflect") + );
2*($$opt{Boundary} eq "Truncate") +
3*($$opt{Boundary} eq "Replicate")));
return $c; return $c;
} }
', ',
GenericTypes => $A, GenericTypes => $A,
Code => Code =>
init_vars( { vars => 'PDL_CLDouble tmp; int flag;' } ) . init_vars() .
init_map("i") . init_map("i") .
init_map("j") . init_map("j") .
' '
PDL_CLDouble tmp; int flag;
broadcastloop %{ broadcastloop %{
loop(n) %{ loop(n) %{
loop(m) %{ loop(m) %{
tmp = 0; tmp = 0;
for(j1=0; j1<q_size; j1++) { for(j1=0; j1<q_size; j1++) {
j2 = mapj[n-j1]; j2 = mapj[n-j1];
if (j2 >= 0) { if (j2 >= 0) {
for(i1=0; i1<p_size; i1++) { for(i1=0; i1<p_size; i1++) {
i2 = mapi[m-i1]; i2 = mapi[m-i1];
if (i2 >= 0) { if (i2 >= 0) {
skipping to change at line 295 skipping to change at line 287
} /* if: good */ } /* if: good */
} /* if: i2 >= 0 */ } /* if: i2 >= 0 */
} /* for: i1 */ } /* for: i1 */
} /* if: j2 >= 0 */ } /* if: j2 >= 0 */
} /* for: j1 */ } /* for: j1 */
PDL_IF_BAD(if ( !flag ) { $SETBAD(b()); } PDL_IF_BAD(if ( !flag ) { $SETBAD(b()); }
else,) { $b() = tmp; } else,) { $b() = tmp; }
%} %}
%} %}
%} %}
free(mapj+1-q_size); free(mapi+1-p_size);', ',
); # pp_def: conv2d ); # pp_def: conv2d
pp_addhdr(<<'EOF'); pp_addhdr(<<'EOF');
PDL_TYPELIST_REAL(PDL_QSORT) PDL_TYPELIST_REAL(PDL_QSORT)
EOF EOF
pp_def('med2d', Doc=> <<'EOD', pp_def('med2d', Doc=> <<'EOD',
=for ref =for ref
2D median-convolution of an array with a kernel (smoothing) 2D median-convolution of an array with a kernel (smoothing)
skipping to change at line 334 skipping to change at line 326
=> Reflect - reflect at boundary => Reflect - reflect at boundary
=> Truncate - truncate at boundary => Truncate - truncate at boundary
=> Replicate - repeat boundary pixel values => Replicate - repeat boundary pixel values
=cut =cut
EOD EOD
BadDoc => BadDoc =>
'Bad values are ignored in the calculation. If all elements within the 'Bad values are ignored in the calculation. If all elements within the
kernel are bad, the output is set bad.', kernel are bad, the output is set bad.',
HandleBad => 1, HandleBad => 1,
Pars => 'a(m,n); kern(p,q); [o]b(m,n); double+ [t]tmp(pq);', Pars => 'a(m,n); kern(p,q); [o]b(m,n); double+ [t]tmp(pq); indx [t]mapi( isize); indx [t]mapj(jsize)',
OtherPars => 'int opt;', OtherPars => 'int opt;',
PMCode => <<'EOF', PMCode => <<'EOF',
sub PDL::med2d { sub PDL::med2d {
my $opt; $opt = pop @_ if ref($_[$#_]) eq 'HASH'; my $opt; $opt = pop @_ if ref($_[$#_]) eq 'HASH';
die 'Usage: med2d( a(m,n), kern(p,q), [o]b(m,n), {Options} )' die 'Usage: med2d( a(m,n), kern(p,q), [o]b(m,n), {Options} )'
if $#_<1 || $#_>2; if $#_<1 || $#_>2;
my($x,$kern) = @_; my($x,$kern) = @_;
croak "med2d: kernel must contain some positive elements.\n" croak "med2d: kernel must contain some positive elements.\n"
if all( $kern <= 0 ); if all( $kern <= 0 );
my $c = $#_ == 2 ? $_[2] : $x->nullcreate; my $c = $#_ == 2 ? $_[2] : $x->nullcreate;
PDL::_med2d_int($x,$kern,$c, PDL::_med2d_int($x,$kern,$c,
(!(defined $opt && exists $$opt{Boundary}))?0: (!($opt && exists $$opt{Boundary}))?0:$boundary2value{$$opt{Boundary}}
(($$opt{Boundary} eq "Reflect") + );
2*($$opt{Boundary} eq "Truncate") +
3*($$opt{Boundary} eq "Replicate")));
return $c; return $c;
} }
EOF EOF
RedoDimsCode => '$SIZE(pq) = $SIZE(p)*$SIZE(q);', RedoDimsCode => '
$SIZE(pq) = $SIZE(p)*$SIZE(q);
$SIZE(isize) = $SIZE(p) + $SIZE(m);
$SIZE(jsize) = $SIZE(q) + $SIZE(n);
',
Code => Code =>
init_vars( { vars => 'int flag;' } ) . init_vars() .
init_map("i") . init_map("i") .
init_map("j") . init_map("j") .
' '
int flag;
PDL_LDouble kk, aa; PDL_LDouble kk, aa;
broadcastloop %{ broadcastloop %{
for(j=0; j<n_size; j++) { for(j=0; j<n_size; j++) {
for(i=0; i<m_size; i++) { for(i=0; i<m_size; i++) {
PDL_Indx count = 0; PDL_Indx count = 0;
flag = 0; flag = 0;
for(j1=0; j1<q_size; j1++) { for(j1=0; j1<q_size; j1++) {
j2 = mapj[j-j1]; j2 = mapj[j-j1];
if (j2 >= 0) if (j2 >= 0)
for(i1=0; i1<p_size; i1++) { for(i1=0; i1<p_size; i1++) {
skipping to change at line 385 skipping to change at line 380
if ( kk > 0 ) { if ( kk > 0 ) {
$tmp(pq=>count++) = aa * kk; $tmp(pq=>count++) = aa * kk;
} }
} }
} /* if: i2 >= 0 */ } /* if: i2 >= 0 */
} /* for: i1 */ } /* for: i1 */
} /* for: j1 */ } /* for: j1 */
PDL_IF_BAD(if ( flag == 0 ) { PDL_IF_BAD(if ( flag == 0 ) {
$SETBAD(b(m=>i,n=>j)); $SETBAD(b(m=>i,n=>j));
} else,) { } else,) {
qsort_D( $P(tmp), 0, count-1 ); qsort_$PPSYM(tmp)( $P(tmp), 0, count-1 );
$b(m=>i,n=>j) = $tmp(pq=>(count-1)/2); $b(m=>i,n=>j) = $tmp(pq=>(count-1)/2);
} }
} /* for: i */ } /* for: i */
} /* for: j */ } /* for: j */
%} %}
free(mapj+1-q_size); free(mapi+1-p_size);
' '
); # pp_def: med2d ); # pp_def: med2d
pp_def('med2df', Doc=> <<'EOD', pp_def('med2df', Doc=> <<'EOD',
=for ref =for ref
2D median-convolution of an array in a pxq window (smoothing) 2D median-convolution of an array in a pxq window (smoothing)
skipping to change at line 426 skipping to change at line 420
Boundary - controls what values are assumed for the image when kernel Boundary - controls what values are assumed for the image when kernel
crosses its edge: crosses its edge:
=> Default - periodic boundary conditions (i.e. wrap around axis) => Default - periodic boundary conditions (i.e. wrap around axis)
=> Reflect - reflect at boundary => Reflect - reflect at boundary
=> Truncate - truncate at boundary => Truncate - truncate at boundary
=> Replicate - repeat boundary pixel values => Replicate - repeat boundary pixel values
=cut =cut
EOD EOD
Pars => 'a(m,n); [o]b(m,n);', Pars => 'a(m,n); [o]b(m,n); indx [t]mapi(isize); indx [t]mapj(jsize)',
# funny parameter names to avoid special case in 'init_vars' OtherPars => 'int p_size=>p; int q_size=>q; int opt;',
OtherPars => 'int __p_size; int __q_size; int opt;', RedoDimsCode => '
$SIZE(isize) = $SIZE(p) + $SIZE(m);
$SIZE(jsize) = $SIZE(q) + $SIZE(n);
',
PMCode => <<'EOF', PMCode => <<'EOF',
sub PDL::med2df { sub PDL::med2df {
my $opt; $opt = pop @_ if ref($_[$#_]) eq 'HASH'; my $opt; $opt = pop @_ if ref($_[$#_]) eq 'HASH';
die 'Usage: med2df( a(m,n), [o]b(m,n), p, q, {Options} )' die 'Usage: med2df( a(m,n), [o]b(m,n), p, q, {Options} )'
if $#_<2 || $#_>3; if $#_<2 || $#_>3;
my($x,$p,$q) = @_; my($x,$p,$q) = @_;
croak "med2df: kernel must contain some positive elements.\n" croak "med2df: kernel must contain some positive elements.\n"
if $p == 0 && $q == 0; if $p == 0 && $q == 0;
my $c = $#_ == 3 ? $_[3] : $x->nullcreate; my $c = $#_ == 3 ? $_[3] : $x->nullcreate;
&PDL::_med2df_int($x,$c,$p,$q, &PDL::_med2df_int($x,$c,$p,$q,
(!(defined $opt && exists $$opt{Boundary}))?0: (!($opt && exists $$opt{Boundary}))?0:$boundary2value{$$opt{Boundary}}
(($$opt{Boundary} eq "Reflect") + );
2*($$opt{Boundary} eq "Truncate") +
3*($$opt{Boundary} eq "Replicate")));
return $c; return $c;
} }
EOF EOF
Code => Code =>
init_vars( { vars => '$GENERIC() kk; int count;' }, [qw(m n)], [qw(p q)] ) . init_vars() .
init_map("i") . init_map("i") .
init_map("j") . init_map("j") .
' '
$GENERIC() tmp[p_size*q_size]; int count;
$GENERIC() kk, tmp[p_size*q_size];
broadcastloop %{ broadcastloop %{
for(j=0; j<n_size; j++) { for(j=0; j<n_size; j++) {
for(i=0; i<m_size; i++) { for(i=0; i<m_size; i++) {
count = 0; count = 0;
for(j1=0; j1<q_size; j1++) { for(j1=0; j1<q_size; j1++) {
j2 = mapj[j-j1]; j2 = mapj[j-j1];
if (j2 >= 0) if (j2 >= 0)
for(i1=0; i1<p_size; i1++) { for(i1=0; i1<p_size; i1++) {
i2 = mapi[i-i1]; i2 = mapi[i-i1];
skipping to change at line 474 skipping to change at line 470
} /* if: i2 >= 0 */ } /* if: i2 >= 0 */
} /* for: i1 */ } /* for: i1 */
} /* for: j1 */ } /* for: j1 */
$b(m=>i,n=>j) = $b(m=>i,n=>j) =
quick_select_$PPSYM() (tmp, count ); quick_select_$PPSYM() (tmp, count );
} /* for: i */ } /* for: i */
} /* for: j */ } /* for: j */
%} %}
free(mapj+1-q_size); free(mapi+1-p_size);
', ',
); # pp_def: med2df ); # pp_def: med2df
pp_addhdr(<<'EOH'); pp_addhdr(<<'EOH');
#define EZ(x) ez ? 0 : (x) #define EZ(x) ez ? 0 : (x)
EOH EOH
pp_def('box2d', pp_def('box2d',
Pars => 'a(n,m); [o] b(n,m)', Pars => 'a(n,m); [o] b(n,m)',
OtherPars => 'int wx; int wy; int edgezero', OtherPars => 'int wx; int wy; int edgezero',
skipping to change at line 710 skipping to change at line 705
', ',
); );
pp_def('max2d_ind', pp_def('max2d_ind',
Doc=><<'EOD', Doc=><<'EOD',
=for ref =for ref
Return value/position of maximum value in 2D image Return value/position of maximum value in 2D image
Contributed by Tim Jeness Contributed by Tim Jenness
=cut =cut
EOD EOD
BadDoc=><<'EOD', BadDoc=><<'EOD',
Bad values are excluded from the search. If all pixels Bad values are excluded from the search. If all pixels
are bad then the output is set bad. are bad then the output is set bad.
skipping to change at line 1486 skipping to change at line 1481
C<$px> and C<$py> are C<np> by C<np> element ndarrays which describe C<$px> and C<$py> are C<np> by C<np> element ndarrays which describe
a polynomial mapping (of order C<np-1>) a polynomial mapping (of order C<np-1>)
from the I<output> C<(u,v)> image to the I<input> C<(x,y)> image: from the I<output> C<(u,v)> image to the I<input> C<(x,y)> image:
x = sum(j=0,np-1) sum(i=0,np-1) px(i,j) * u^i * v^j x = sum(j=0,np-1) sum(i=0,np-1) px(i,j) * u^i * v^j
y = sum(j=0,np-1) sum(i=0,np-1) py(i,j) * u^i * v^j y = sum(j=0,np-1) sum(i=0,np-1) py(i,j) * u^i * v^j
The transformation is returned for the reverse direction (ie The transformation is returned for the reverse direction (ie
output to input image) since that is what is required by the output to input image) since that is what is required by the
L<warp2d()|/warp2d> routine. The L<applywarp2d()|/applywarp2d> L</warp2d> routine. The L</applywarp2d>
routine can be used to convert a set of C<$u,$v> points given routine can be used to convert a set of C<$u,$v> points given
C<$px> and C<$py>. C<$px> and C<$py>.
Options: Options:
=for options =for options
FIT - which terms to fit? default ones(byte,$nf,$nf) FIT - which terms to fit? default ones(byte,$nf,$nf)
=begin comment =begin comment
skipping to change at line 1613 skipping to change at line 1608
=for ref =for ref
Transform a set of points using a 2-D polynomial mapping Transform a set of points using a 2-D polynomial mapping
=for usage =for usage
( $x, $y ) = applywarp2d( $px, $py, $u, $v ) ( $x, $y ) = applywarp2d( $px, $py, $u, $v )
Convert a set of points (stored in 1D ndarrays C<$u,$v>) Convert a set of points (stored in 1D ndarrays C<$u,$v>)
to C<$x,$y> using the 2-D polynomial with coefficients stored in C<$px> to C<$x,$y> using the 2-D polynomial with coefficients stored in C<$px>
and C<$py>. See L<fitwarp2d()|/fitwarp2d> and C<$py>. See L</fitwarp2d>
for more information on the format of C<$px> and C<$py>. for more information on the format of C<$px> and C<$py>.
=cut =cut
# use SVD to fit data. Assuming no errors. # use SVD to fit data. Assuming no errors.
=pod =pod
=begin comment =begin comment
skipping to change at line 1889 skipping to change at line 1884
*applywarp2d = \&PDL::applywarp2d; *applywarp2d = \&PDL::applywarp2d;
' ); ' );
## resampling routines taken from v3.6-0 of the Eclipse package ## resampling routines taken from v3.6-0 of the Eclipse package
## http://www.eso.org/eclipse by Nicolas Devillard ## http://www.eso.org/eclipse by Nicolas Devillard
## ##
pp_addhdr( '#include "resample.h"' . "\n" ); pp_addhdr( '#include "resample.h"' . "\n" );
# pod for warp2d pp_def(
# and support routine 'warp2d',
# Doc=> <<'EOD',
pp_addpm( <<'EOD');
=head2 warp2d
=for sig
Signature: (img(m,n); double px(np,np); double py(np,np); [o] warp(m,n); { opt
ions })
=for ref =for ref
Warp a 2D image given a polynomial describing the I<reverse> mapping. Warp a 2D image given a polynomial describing the I<reverse> mapping.
=for usage =for usage
$out = warp2d( $img, $px, $py, { options } ); $out = warp2d( $img, $px, $py, { options } );
Apply the polynomial transformation encoded in the C<$px> and Apply the polynomial transformation encoded in the C<$px> and
C<$py> ndarrays to warp the input image C<$img> into the output C<$py> ndarrays to warp the input image C<$img> into the output
image C<$out>. image C<$out>.
The format for the polynomial transformation is described in The format for the polynomial transformation is described in
the documentation for the L<fitwarp2d()|/fitwarp2d> routine. the documentation for the L</fitwarp2d> routine.
At each point C<x,y>, the closest 16 pixel values are combined At each point C<x,y>, the closest 16 pixel values are combined
with an interpolation kernel to calculate the value at C<u,v>. with an interpolation kernel to calculate the value at C<u,v>.
The interpolation is therefore done in the image, rather than The interpolation is therefore done in the image, rather than
Fourier, domain. Fourier, domain.
By default, a C<tanh> kernel is used, but this can be changed By default, a C<tanh> kernel is used, but this can be changed
using the C<KERNEL> option discussed below using the C<KERNEL> option discussed below
(the choice of kernel depends on the frequency content of the input image). (the choice of kernel depends on the frequency content of the input image).
The routine is based on the C<warping> command from The routine is based on the C<warping> command from
skipping to change at line 1958 skipping to change at line 1945
The options are: The options are:
=for options =for options
KERNEL - default value is tanh KERNEL - default value is tanh
NOVAL - default value is 0 NOVAL - default value is 0
C<KERNEL> is used to specify which interpolation kernel to use C<KERNEL> is used to specify which interpolation kernel to use
(to see what these kernels look like, use the (to see what these kernels look like, use the
L<warp2d_kernel()|/warp2d_kernel> routine). L</warp2d_kernel> routine).
The options are: The options are:
=over 4 =over 4
=item tanh =item tanh
Hyperbolic tangent: the approximation of an ideal box filter by the Hyperbolic tangent: the approximation of an ideal box filter by the
product of symmetric tanh functions. product of symmetric tanh functions.
=item sinc =item sinc
skipping to change at line 2007 skipping to change at line 1994
=item hamming =item hamming
This kernel uses the same C<H(x)> as the Hann filter, but with This kernel uses the same C<H(x)> as the Hann filter, but with
C<a = 0.54>. C<a = 0.54>.
=back =back
C<NOVAL> gives the value used to indicate that a pixel in the C<NOVAL> gives the value used to indicate that a pixel in the
output image does not map onto one in the input image. output image does not map onto one in the input image.
EOD
=cut HandleBad => 0,
Pars => 'img(m,n); ldouble px(np,np); ldouble py(np,np); [o] warp(m,n); ldou
ble [t] poly(np); ldouble [t] kernel(ns)',
OtherPars => 'char *kernel_type; double noval; int nsamples => ns',
GenericTypes => [ qw(F D E) ],
PMCode => <<'EOF',
# support routine # support routine
{ {
my %warp2d = map { ($_,1) } qw( tanh sinc sinc2 lanczos hamming hann ); my %warp2d = map { ($_,1) } qw( tanh sinc sinc2 lanczos hamming hann );
# note: convert to lower case # note: convert to lower case
sub _check_kernel ($$) { sub _check_kernel ($$) {
my $kernel = lc shift; my $kernel = lc shift;
my $code = shift; my $code = shift;
barf "Unknown kernel $kernel sent to $code\n" . barf "Unknown kernel $kernel sent to $code\n" .
"\tmust be one of [" . join(',',keys %warp2d) . "]\n" "\tmust be one of [" . join(',',keys %warp2d) . "]\n"
unless exists $warp2d{$kernel}; unless exists $warp2d{$kernel};
return $kernel; return $kernel;
} }
} }
EOD
pp_def(
'warp2d',
Doc=> undef,
HandleBad => 0,
Pars => 'img(m,n); ldouble px(np,np); ldouble py(np,np); [o] warp(m,n);',
OtherPars => 'char *kernel_type; double noval;',
GenericTypes => [ qw(F D E) ],
PMCode => '
sub PDL::warp2d { sub PDL::warp2d {
my $opts = PDL::Options->new( { KERNEL => "tanh", NOVAL => 0 } ); my $opts = PDL::Options->new( { KERNEL => "tanh", NOVAL => 0 } );
$opts->options( pop(@_) ) if ref($_[$#_]) eq "HASH"; $opts->options( pop(@_) ) if ref($_[$#_]) eq "HASH";
die "Usage: warp2d( in(m,n), px(np,np); py(np,np); [o] out(m,n), {Options} ) " die "Usage: warp2d( in(m,n), px(np,np); py(np,np); [o] out(m,n), {Options} ) "
if $#_<2 || $#_>3; if $#_<2 || $#_>3;
my $img = shift; my $img = shift;
my $px = shift; my $px = shift;
my $py = shift; my $py = shift;
my $out = $#_ == -1 ? PDL->null() : shift; my $out = $#_ == -1 ? PDL->null() : shift;
# safety checks # safety checks
my $copt = $opts->current(); my $copt = $opts->current();
my $kernel = _check_kernel( $$copt{KERNEL}, "warp2d" ); my $kernel = _check_kernel( $$copt{KERNEL}, "warp2d" );
&PDL::_warp2d_int( $img, $px, $py, $out, $kernel, $$copt{NOVAL}, _get_kernel
&PDL::_warp2d_int( $img, $px, $py, $out, $kernel, $$copt{NOVAL} ); _size() );
return $out; return $out;
} }
EOF
', Code => <<'EOF',
Code => '
PDL_Indx ncoeff, lx_out, ly_out, i, j, k, lx_3, ly_3, px, py, tabx, taby; PDL_Indx ncoeff, lx_out, ly_out, i, j, k, lx_3, ly_3, px, py, tabx, taby;
PDL_Indx da[16], db[16] ; PDL_Indx da[16], db[16] ;
PDL_LDouble cur, neighbors[16], rsc[8], sumrs, x, y, *kernel, *poly ; PDL_LDouble cur, neighbors[16], rsc[8], sumrs, x, y, *kernel = $P(kernel), * poly = $P(poly);
/* Generate default interpolation kernel */ /* Generate interpolation kernel */
kernel = generate_interpolation_kernel( $COMP(kernel_type) ) ; if (!generate_interpolation_kernel($COMP(kernel_type), $SIZE(ns), kernel))
if (kernel == NULL) { $CROAK("Invalid kernel type '%s'", $COMP(kernel_type));
$CROAK( "Ran out of memory building kernel\n" );
}
/* Compute sizes */ /* Compute sizes */
ncoeff = $SIZE(np); ncoeff = $SIZE(np);
lx_out = $SIZE(m); /* is this right? */ lx_out = $SIZE(m); /* is this right? */
ly_out = $SIZE(n); ly_out = $SIZE(n);
lx_3 = lx_out - 3; lx_3 = lx_out - 3;
ly_3 = ly_out - 3; ly_3 = ly_out - 3;
/* Pre compute leaps for 16 closest neighbors positions */ /* Pre compute leaps for 16 closest neighbors positions */
da[0] = -1; db[0] = -1; da[0] = -1; db[0] = -1;
skipping to change at line 2096 skipping to change at line 2067
da[8] = -1; db[8] = 1; da[8] = -1; db[8] = 1;
da[9] = 0; db[9] = 1; da[9] = 0; db[9] = 1;
da[10] = 1; db[10] = 1; da[10] = 1; db[10] = 1;
da[11] = 2; db[11] = 1; da[11] = 2; db[11] = 1;
da[12] = -1; db[12] = 2; da[12] = -1; db[12] = 2;
da[13] = 0; db[13] = 2; da[13] = 0; db[13] = 2;
da[14] = 1; db[14] = 2; da[14] = 1; db[14] = 2;
da[15] = 2; db[15] = 2; da[15] = 2; db[15] = 2;
/* allocate memory for polynomial */
poly = malloc( ncoeff * sizeof(PDL_LDouble) );
if ( poly == NULL ) {
$CROAK( "Ran out of memory\n" );
}
poly[0] = 1.0; poly[0] = 1.0;
/* Loop over the output image */ /* Loop over the output image */
broadcastloop %{ broadcastloop %{
loop(n) %{ loop(n) %{
/* fill in poly array */ /* fill in poly array */
for ( k = 1; k < ncoeff; k++ ) { for ( k = 1; k < ncoeff; k++ ) {
poly[k] = (PDL_LDouble) n * poly[k-1]; poly[k] = (PDL_LDouble) n * poly[k-1];
} }
skipping to change at line 2177 skipping to change at line 2143
rsc[3]*neighbors[15] ) ; rsc[3]*neighbors[15] ) ;
/* Copy the value to the output image */ /* Copy the value to the output image */
$warp() = ($GENERIC()) (cur/sumrs); $warp() = ($GENERIC()) (cur/sumrs);
} /* if: edge or interior */ } /* if: edge or interior */
%} /* loop(m) */ %} /* loop(m) */
%} /* loop(n) */ %} /* loop(n) */
%} /* broadcastloop */ %} /* broadcastloop */
EOF
free(poly);
kernel_free(kernel) ;
',
); # pp_def: warp2d ); # pp_def: warp2d
pp_addxs( ' pp_addxs( '
int int
_get_kernel_size() _get_kernel_size()
PROTOTYPE: PROTOTYPE:
CODE: CODE:
RETVAL = KERNEL_SAMPLES; RETVAL = KERNEL_SAMPLES;
OUTPUT: OUTPUT:
RETVAL RETVAL
'); ');
pp_add_exported('', 'warp2d_kernel'); pp_def( 'warp2d_kernel',
pp_addpm( ' Doc => <<'EOF',
=head2 warp2d_kernel
=for ref =for ref
Return the specified kernel, as used by L</warp2d> Return the specified kernel, as used by L</warp2d>
=for usage =for usage
( $x, $k ) = warp2d_kernel( $name ) ( $x, $k ) = warp2d_kernel( $name )
The valid values for C<$name> are the same as the C<KERNEL> option The valid values for C<$name> are the same as the C<KERNEL> option
of L<warp2d()|/warp2d>. of L</warp2d>.
=for example =for example
line warp2d_kernel( "hamming" ); line warp2d_kernel( "hamming" );
EOF
=cut
'); # pp_addpm
# this is not very clever, but it's a pain to create a valid
# ndarray in XS code
#
pp_def( 'warp2d_kernel',
Doc => undef,
HandleBad => 0, HandleBad => 0,
PMCode => ' PMCode => '
sub PDL::warp2d_kernel ($) { sub PDL::warp2d_kernel ($) {
my $kernel = _check_kernel( shift, "warp2d_kernel" ); my $kernel = _check_kernel( shift, "warp2d_kernel" );
&PDL::_warp2d_kernel_int( my $x=PDL->null, my $k=PDL->null, $kernel, _get_ke
my $nelem = _get_kernel_size(); rnel_size() );
my $x = zeroes( $nelem );
my $k = zeroes( $nelem );
&PDL::_warp2d_kernel_int( $x, $k, $kernel );
return ( $x, $k ); return ( $x, $k );
# return _get_kernel( $kernel );
} }
*warp2d_kernel = \&PDL::warp2d_kernel;
', ',
Pars => '[o] x(n); [o] k(n);', Pars => '[o] x(n); [o] k(n); ldouble [t] kernel(n)',
OtherPars => 'char *name;', OtherPars => 'char *name; PDL_Indx nsize => n',
GenericTypes => [ qw(F D E) ], GenericTypes => [ qw(F D E) ],
Code => ' Code => <<'EOF',
PDL_LDouble *kernel = $P(kernel);
PDL_LDouble *kernel, xx; if (!generate_interpolation_kernel($COMP(name), $SIZE(n), kernel))
$CROAK("Invalid kernel type '%s'", $COMP(name));
if ( $SIZE(n) != KERNEL_SAMPLES ) {
$CROAK( "Internal error in warp2d_kernel - mismatch in kernel size\n" );
}
kernel = generate_interpolation_kernel($COMP(name));
if ( kernel == NULL ) {
$CROAK( "unable to allocate memory for kernel" );
}
/* fill in ndarrays */ /* fill in ndarrays */
xx = 0.0; PDL_LDouble xx = 0.0;
broadcastloop %{ broadcastloop %{
loop (n) %{ loop (n) %{
$x() = xx; $x() = xx;
$k() = kernel[n]; $k() = kernel[n];
xx += 1.0 / (double) TABSPERPIX; xx += 1.0 / (double) TABSPERPIX;
%} %}
%} %}
EOF
/* free the kernel */ );
kernel_free( kernel );
');
pp_done(); pp_done();
 End of changes. 51 change blocks. 
149 lines changed or deleted 79 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)