]> Creatis software - CreaPhase.git/blob - octave_packages/image-1.0.15/imrotate_Fourier.m
Add a useful package (from Source forge) for octave
[CreaPhase.git] / octave_packages / image-1.0.15 / imrotate_Fourier.m
1 ## Copyright (C) 2002 Jeff Orchard <jorchard@cs.uwaterloo.ca>
2 ##
3 ## This program is free software; you can redistribute it and/or
4 ## modify it under the terms of the GNU General Public License
5 ## as published by the Free Software Foundation; either version 2
6 ## of the License, or (at your option) any later version.
7 ##
8 ## This program is distributed in the hope that it will be useful, but
9 ## WITHOUT ANY WARRANTY; without even the implied warranty of
10 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 ## General Public License for more details.
12 ##
13 ## You should have received a copy of the GNU General Public License
14 ## along with this program; If not, see <http://www.gnu.org/licenses/>.
15
16 ## -*- texinfo -*-
17 ## @deftypefn {Function File} {} imrotate(@var{M}, @var{theta}, @var{method}, @var{bbox})
18 ## Rotation of a 2D matrix.
19 ##
20 ## Applies a rotation of @var{THETA} degrees to matrix @var{M}.
21 ##
22 ## The @var{method} argument is not implemented, and is only included for compatibility with Matlab.
23 ## This function uses Fourier interpolation,
24 ## decomposing the rotation matrix into 3 shears.
25 ##
26 ## @var{bbox} can be either 'loose' or 'crop'.
27 ## 'loose' allows the image to grow to accomodate the rotated image.
28 ## 'crop' keeps the same size as the original, clipping any part of the image
29 ## that is moved outside the bounding box.
30 ## @end deftypefn
31
32 ## Author: Jeff Orchard <jorchard@cs.uwaterloo.ca>
33 ## Created: Oct. 14, 2002
34
35 function fs = imrotate_Fourier(f, theta, method="fourier", bbox="loose")
36
37     ## Input checking
38     if (nargin < 2)
39       error("imrotate_Fourier: not enough input arguments");
40     endif
41     [imrows, imcols, tmp] = size(f);
42     if (tmp != 1)
43       error("imrotate_Fourier: first input argument must be a gray-scale image");
44     endif
45     if (!isscalar(theta))
46       error("imrotate_Fourier: second input argument must be a real scalar");
47     endif
48
49         # Get original dimensions.
50         [ydim_orig, xdim_orig] = size(f);
51
52         # This finds the index coords of the centre of the image (indices are base-1)
53         #   eg. if xdim_orig=8, then xcentre_orig=4.5 (half-way between 1 and 8)
54         xcentre_orig = (xdim_orig+1) / 2;
55         ycentre_orig = (ydim_orig+1) / 2;
56
57         # Pre-process the angle ===========================================================
58         # Whichever 90 degree multiple theta is closest to, that multiple of 90 will
59         # be implemented by rot90. The remainder will be done by shears.
60
61         # This ensures that 0 <= theta < 360.
62         theta = rem( rem(theta,360) + 360, 360 );
63
64         # This is a flag to keep track of 90-degree rotations.
65         perp = 0;
66
67         if ( theta>=0 && theta<=45 )
68                 phi = theta;
69         elseif ( theta>45 && theta<=135 )
70                 phi = theta - 90;
71                 f = rot90(f,1);
72                 perp = 1;
73         elseif ( theta>135 && theta<=225 )
74                 phi = theta - 180;
75                 f = rot90(f,2);
76         elseif ( theta>225 && theta<=315 )
77                 phi = theta - 270;
78                 f = rot90(f,3);
79                 perp = 1;
80         else
81                 phi = theta;
82         endif
83
84
85
86         if ( phi == 0 )
87                 fs = f;
88                 if ( strcmp(bbox,"loose") == 1 )
89                         return;
90                 else
91                         xmax = xcentre_orig;
92                         ymax = ycentre_orig;
93                         if ( perp == 1 )
94                                 xmax = max([xmax ycentre_orig]);
95                                 ymax = max([ymax xcentre_orig]);
96                                 [ydim xdim] = size(fs);
97                                 xpad = ceil( xmax - (xdim+1)/2 );
98                                 ypad = ceil( ymax - (ydim+1)/2 );
99                                 fs = impad(fs, [xpad,xpad], [ypad,ypad], "zeros");
100                         endif
101                         xcentre_new = (size(fs,2)+1) / 2;
102                         ycentre_new = (size(fs,1)+1) / 2;
103                 endif
104         else
105
106                 # At this point, we can assume -45<theta<45 (degrees)
107
108                 phi = phi * pi / 180;
109                 theta = theta * pi / 180;
110                 R = [ cos(theta) -sin(theta) ; sin(theta) cos(theta) ];
111
112                 # Find max of each dimension... this will be expanded for "loose" and "crop"
113                 xmax = xcentre_orig;
114                 ymax = ycentre_orig;
115
116                 # If we don't want wrapping, we have to zeropad.
117                 # Cropping will be done later, if necessary.
118                 if ( strcmp(bbox, "wrap") == 0 )
119                         corners = ( [ xdim_orig xdim_orig -xdim_orig -xdim_orig ; ydim_orig -ydim_orig ydim_orig -ydim_orig ] + 1 )/ 2;
120                         rot_corners = R * corners;
121                         xmax = max([xmax rot_corners(1,:)]);
122                         ymax = max([ymax rot_corners(2,:)]);
123
124                         # If we are doing a 90-degree rotation first, we need to make sure our
125                         # image is large enough to hold the rot90 image as well.
126                         if ( perp == 1 )
127                                 xmax = max([xmax ycentre_orig]);
128                                 ymax = max([ymax xcentre_orig]);
129                         endif
130
131                         [ydim xdim] = size(f);
132                         xpad = ceil( xmax - xdim/2 );
133                         ypad = ceil( ymax - ydim/2 );
134                         %f = impad(f, [xpad,xpad], [ypad,ypad], "zeros");
135                         xcentre_new = (size(f,2)+1) / 2;
136                         ycentre_new = (size(f,1)+1) / 2;
137                 endif
138
139                 #size(f)
140                 [S1, S2] = MakeShears(phi);
141
142                 tic;
143                 f1 = imshear(f, 'x', S1(1,2), 'loose');
144                 f2 = imshear(f1, 'y', S2(2,1), 'loose');
145                 fs = real( imshear(f2, 'x', S1(1,2), 'loose') );
146                 %fs = f2;
147                 xcentre_new = (size(fs,2)+1) / 2;
148                 ycentre_new = (size(fs,1)+1) / 2;
149         endif
150
151         if ( strcmp(bbox, "crop") == 1 )
152
153                 # Crop to original dimensions
154                 x1 = ceil (xcentre_new - xdim_orig/2);
155                 y1 = ceil (ycentre_new - ydim_orig/2);
156                 fs = fs (y1:(y1+ydim_orig-1), x1:(x1+xdim_orig-1));
157
158         elseif ( strcmp(bbox, "loose") == 1 )
159
160                 # Find tight bounds on size of rotated image
161                 # These should all be positive, or 0.
162                 xmax_loose = ceil( xcentre_new + max(rot_corners(1,:)) );
163                 xmin_loose = floor( xcentre_new - max(rot_corners(1,:)) );
164                 ymax_loose = ceil( ycentre_new + max(rot_corners(2,:)) );
165                 ymin_loose = floor( ycentre_new - max(rot_corners(2,:)) );
166
167                 %fs = fs( (ymin_loose+1):(ymax_loose-1) , (xmin_loose+1):(xmax_loose-1) );
168                 fs = fs( (ymin_loose+1):(ymax_loose-1) , (xmin_loose+1):(xmax_loose-1) );
169
170         endif
171
172     ## Prevent overshooting
173     if (strcmp(class(f), "double"))
174       fs(fs>1) = 1;
175       fs(fs<0) = 0;
176     endif
177
178 endfunction
179
180 function [S1, S2] = MakeShears(theta)
181     S1 = eye(2);
182     S2 = eye(2);
183
184     S1(1,2) = -tan(theta/2);
185     S2(2,1) = sin(theta);
186 endfunction