1## Copyright (C) 2002 Jeff Orchard <jjo@sfu.ca> 2## 3## This program is free software; you can redistribute it and/or modify it under 4## the terms of the GNU General Public License as published by the Free Software 5## Foundation; either version 3 of the License, or (at your option) any later 6## version. 7## 8## This program is distributed in the hope that it will be useful, but WITHOUT 9## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 11## details. 12## 13## You should have received a copy of the GNU General Public License along with 14## this program; if not, see <http://www.gnu.org/licenses/>. 15 16## -*- texinfo -*- 17## @deftypefn {Function File} {} imshear (@var{M}, @var{axis}, @var{alpha}, @var{bbox}) 18## Applies a shear to the image @var{M}. 19## 20## The argument @var{M} is either a matrix or an RGB image. 21## 22## @var{axis} is the axis along which the shear is to be applied, and can 23## be either 'x' or 'y'. 24## For example, to shear sideways is to shear along the 'x' axis. Choosing 25## 'y' causes an up/down shearing. 26## 27## @var{alpha} is the slope of the shear. For an 'x' shear, it is the 28## horizontal shift (in pixels) applied to the pixel above the 29## center. For a 'y' shear, it is the vertical shift (in pixels) 30## applied to the pixel just to the right of the center pixel. 31## 32## NOTE: @var{alpha} does NOT need to be an integer. 33## 34## @var{bbox} can be one of 'loose', 'crop' or 'wrap'. 35## 'loose' allows the image to grow to accommodate the new transformed image. 36## 'crop' keeps the same size as the original, clipping any part of the image 37## that is moved outside the bounding box. 38## 'wrap' keeps the same size as the original, but does not clip the part 39## of the image that is outside the bounding box. Instead, it wraps it back 40## into the image. 41## 42## If called with only 3 arguments, @var{bbox} is set to 'loose' by default. 43## @end deftypefn 44 45function g = imshear(m, axis, alpha, bbox, noshift) 46 47 # The code below only does y-shearing. This is because of 48 # the implementation of fft (operates on columns, but not rows). 49 # So, transpose first for x-shearing. 50 if ( strcmp(axis, "x")==1 ) 51 m = m'; 52 endif 53 54 if ( nargin < 4 ) 55 bbox = "loose"; 56 noshift = 0; 57 elseif ( nargin < 5 ) 58 noshift = 0; 59 endif 60 61 [ydim_orig xdim_orig] = size(m); 62 if ( strcmp(bbox, "wrap") == 0 ) 63 ypad = ceil( (xdim_orig+1)/2 * abs(alpha) ); 64 m = padarray (m, ypad); 65 endif 66 67 [ydim_new xdim_new] = size(m); 68 xcentre = ( xdim_new + 1 ) / 2; 69 ycentre = ( ydim_new + 1 ) / 2; 70 71 # This applies FFT to columns of m (x-axis remains a spatial axis). 72 # Because the way that fft and fftshift are implemented, the origin 73 # will move by 1/2 pixel, depending on the polarity of the image 74 # dimensions. 75 # 76 # If dim is even (=2n), then the origin of the fft below is located 77 # at the centre of pixel (n+1). ie. if dim=16, then centre is at 9. 78 # 79 # If dim is odd (=2n+1), then the origin of the fft below is located 80 # at the centre of pixel (n). ie. if dim=15, then centre is at 8. 81 if ( noshift==1 ) 82 M = fft(m); 83 else 84 #M = imtranslate(fft(imtranslate(m, -xcentre, ycentre, "wrap")), xcentre, -ycentre, "wrap"); 85 M = fftshift(fft(fftshift(m))); 86 endif 87 88 [ydim xdim] = size(m); 89 x = zeros(ydim, xdim); 90 91 # Find coords of the origin of the image. 92 if ( noshift==1 ) 93 xc_coord = 1; 94 yc_coord = 1; 95 l = (1:ydim)' - yc_coord; 96 r = (1:xdim) - xc_coord; 97 if ( strcmp(bbox, "wrap")==1 ) 98 l((ydim/2):ydim) = l((ydim/2):ydim) - ydim; 99 r((xdim/2):xdim) = r((xdim/2):xdim) - xdim; 100 endif 101 else 102 xc_coord = (xdim+1)/2; 103 yc_coord = (ydim+1)/2; 104 l = (1:ydim)' - yc_coord; 105 r = (1:xdim) - xc_coord; 106 endif 107 x = l * r; 108 109 Ms = M.* exp(2*pi*I*alpha/ydim * x); 110 111 if ( noshift==1 ) 112 g = abs(ifft(Ms)); 113 else 114 #g = abs(imtranslate( ifft( imtranslate(Ms, -xcentre, ycentre, "wrap") ), xcentre, -ycentre, "wrap")); 115 g = abs( fftshift(ifft(ifftshift(Ms))) ); 116 endif 117 118 if ( strcmp(bbox, "crop")==1 ) 119 g = g(ypad+1:ydim_orig+ypad, :); 120 endif 121 122 # Un-transpose if x-shearing was wanted 123 if ( strcmp(axis, "x")==1 ) 124 g = g'; 125 endif 126endfunction 127