File Coverage

lib/PDL/Image2D/rotate.c
Criterion Covered Total %
statement 0 135 0.0
branch 0 90 0.0
condition n/a
subroutine n/a
pod n/a
total 0 225 0.0


line stmt bran cond sub pod time code
1             /* rotate.c - code modified from pnmrotate.c which included the following
2             copyright notice
3             */
4              
5             /* pnmrotate.c - read a portable anymap and rotate it by some angle
6             **
7             ** Copyright (C) 1989, 1991 by Jef Poskanzer.
8             **
9             ** Permission to use, copy, modify, and distribute this software and its
10             ** documentation for any purpose and without fee is hereby granted, provided
11             ** that the above copyright notice appear in all copies and that both that
12             ** copyright notice and this permission notice appear in supporting
13             ** documentation. This software is provided "as is" without express or
14             ** implied warranty.
15             */
16              
17             #include
18             #include
19             #include "EXTERN.h"
20             #include "perl.h"
21             #include "pdl.h"
22              
23             #ifndef M_PI
24             #define M_PI 3.14159265358979323846
25             #endif /*M_PI*/
26              
27             #define SCALE 4096
28             #define HALFSCALE 2048
29              
30             typedef unsigned char imT; /* image type */
31              
32 0           static imT* my_allocarray(int cols, int rows)
33             {
34 0           imT *arr = NULL;
35 0 0         if ((arr = malloc(sizeof(imT)*cols*rows)) == NULL)
36 0           croak("error getting memory for temporary array");
37 0           return arr;
38             }
39              
40 0           int getnewsize(PDL_Indx cols, PDL_Indx rows, float fangle, PDL_Indx *newcols, PDL_Indx *newrows)
41             {
42             float xshearfac, yshearfac;
43             PDL_Indx tempcols, yshearjunk, x2shearjunk;
44              
45 0 0         if ( fangle < -90.0 || fangle > 90.0 )
    0          
46             /* error( "angle must be between -90 and 90 degrees" ); */
47 0           return -1;
48 0           fangle = fangle * M_PI / 180.0; /* convert to radians */
49              
50 0           xshearfac = tan( fangle / 2.0 );
51 0 0         if ( xshearfac < 0.0 )
52 0           xshearfac = -xshearfac;
53 0           yshearfac = sin( fangle );
54 0 0         if ( yshearfac < 0.0 )
55 0           yshearfac = -yshearfac;
56              
57 0           tempcols = rows * xshearfac + cols + 0.999999;
58 0           yshearjunk = ( tempcols - cols ) * yshearfac;
59 0           *newrows = tempcols * yshearfac + rows + 0.999999;
60 0           x2shearjunk = ( *newrows - rows - yshearjunk ) * xshearfac;
61 0           *newrows -= 2 * yshearjunk;
62 0           *newcols = *newrows * xshearfac + tempcols + 0.999999 - 2 * x2shearjunk;
63             /* printf("oldrows: %d, oldcols: %d\n",rows,cols);
64             printf("newrows: %d, newcols: %d\n",*newrows,*newcols);
65             */
66 0           return 0; /* OK */
67             }
68              
69 0           int rotate(imT *im, imT *out, int cols, int rows, int nc, int nr,
70             float fangle, imT bgval, int antialias)
71             {
72             float xshearfac, yshearfac, new0;
73             int intnew0;
74             imT *xelrow, *newxelrow, *temp1xels, *temp2xels, *nxP, *xP, prevxel, x;
75             int tempcols, newcols, yshearjunk, x2shearjunk, row, col, new, newrows;
76             register long fracnew0, omfracnew0;
77              
78             /* other angles should do a simple multiple of 90 degrees rotate before
79             calling this one */
80 0 0         if ( fangle < -90.0 || fangle > 90.0 )
    0          
81             /* error( "angle must be between -90 and 90 degrees" ); */
82 0           return -1;
83 0           fangle = fangle * M_PI / 180.0; /* convert to radians */
84              
85 0           xshearfac = tan( fangle / 2.0 );
86 0 0         if ( xshearfac < 0.0 )
87 0           xshearfac = -xshearfac;
88 0           yshearfac = sin( fangle );
89 0 0         if ( yshearfac < 0.0 )
90 0           yshearfac = -yshearfac;
91              
92 0           tempcols = rows * xshearfac + cols + 0.999999;
93 0           yshearjunk = ( tempcols - cols ) * yshearfac;
94 0           newrows = tempcols * yshearfac + rows + 0.999999;
95 0           x2shearjunk = ( newrows - rows - yshearjunk ) * xshearfac;
96 0           newrows -= 2 * yshearjunk;
97 0           newcols = newrows * xshearfac + tempcols + 0.999999 - 2 * x2shearjunk;
98            
99             /* check that the output has the right size */
100 0 0         if (nc != newcols || nr != newrows)
    0          
101 0           return -2;
102              
103             /* First shear X into temp1xels. */
104 0           temp1xels = my_allocarray( tempcols, rows );
105 0 0         for ( row = 0; row < rows; ++row )
106             {
107 0           xelrow = im + row * cols; /* current row to process */
108 0 0         if ( fangle > 0 )
109 0           new0 = row * xshearfac;
110             else
111 0           new0 = ( rows - row ) * xshearfac;
112 0           intnew0 = (int) new0;
113              
114 0 0         if ( antialias )
115             {
116 0           fracnew0 = ( new0 - intnew0 ) * SCALE;
117 0           omfracnew0 = SCALE - fracnew0;
118              
119 0           for ( col = 0, nxP = temp1xels+row*tempcols;
120 0 0         col < tempcols; ++col, ++nxP )
121 0           *nxP = bgval;
122              
123 0           prevxel = bgval;
124 0           for ( col = 0, nxP = temp1xels+row*tempcols+intnew0, xP = xelrow;
125 0 0         col < cols; ++col, ++nxP, ++xP )
126             {
127 0           *nxP = (fracnew0 * prevxel + omfracnew0 * *xP + HALFSCALE )
128 0           / SCALE;
129 0           prevxel = *xP;
130             }
131 0 0         if ( fracnew0 > 0 && intnew0 + cols < tempcols )
    0          
132             {
133 0           *nxP =
134 0           ( fracnew0 * prevxel + omfracnew0 * bgval + HALFSCALE )
135 0           / SCALE;
136             }
137             }
138             else
139             {
140 0           for ( col = 0, nxP = temp1xels+row*tempcols;
141 0 0         col < intnew0; ++col, ++nxP )
142 0           *nxP = bgval;
143 0 0         for ( col = 0, xP = xelrow; col < cols; ++col, ++nxP, ++xP )
144 0           *nxP = *xP;
145 0 0         for ( col = intnew0 + cols; col < tempcols; ++col, ++nxP )
146 0           *nxP = bgval;
147             }
148             }
149             /* Now inverse shear Y from temp1 into temp2. */
150 0           temp2xels = my_allocarray( tempcols, newrows );
151 0 0         for ( col = 0; col < tempcols; ++col )
152             {
153 0 0         if ( fangle > 0 )
154 0           new0 = ( tempcols - col ) * yshearfac;
155             else
156 0           new0 = col * yshearfac;
157 0           intnew0 = (int) new0;
158 0           fracnew0 = ( new0 - intnew0 ) * SCALE;
159 0           omfracnew0 = SCALE - fracnew0;
160 0           intnew0 -= yshearjunk;
161              
162 0 0         for ( row = 0; row < newrows; ++row )
163 0           temp2xels[row*tempcols+col] = bgval;
164              
165 0 0         if ( antialias )
166             {
167 0           prevxel = bgval;
168 0 0         for ( row = 0; row < rows; ++row )
169             {
170 0           new = row + intnew0;
171 0 0         if ( new >= 0 && new < newrows )
    0          
172             {
173 0           nxP = temp2xels+new*tempcols+col;
174 0           x = temp1xels[row*tempcols+col];
175 0           *nxP =
176 0           ( fracnew0 * prevxel + omfracnew0 * x + HALFSCALE )
177 0           / SCALE;
178 0           prevxel = x;
179             }
180             }
181 0 0         if ( fracnew0 > 0 && intnew0 + rows < newrows )
    0          
182             {
183 0           nxP = temp2xels+(intnew0 + rows)*tempcols+col;
184 0           *nxP = ( fracnew0 * prevxel + omfracnew0 * bgval + HALFSCALE )
185 0           / SCALE ;
186             }
187             }
188             else
189             {
190 0 0         for ( row = 0; row < rows; ++row )
191             {
192 0           new = row + intnew0;
193 0 0         if ( new >= 0 && new < newrows )
    0          
194 0           temp2xels[new*tempcols+col] = temp1xels[row*tempcols+col];
195             }
196             }
197             }
198 0           free(temp1xels);
199              
200 0 0         for ( row = 0; row < newrows; ++row )
201             {
202 0           newxelrow = out + row*newcols;;
203 0 0         if ( fangle > 0 )
204 0           new0 = row * xshearfac;
205             else
206 0           new0 = ( newrows - row ) * xshearfac;
207 0           intnew0 = (int) new0;
208 0           fracnew0 = ( new0 - intnew0 ) * SCALE;
209 0           omfracnew0 = SCALE - fracnew0;
210 0           intnew0 -= x2shearjunk;
211              
212 0 0         for ( col = 0, nxP = newxelrow; col < newcols; ++col, ++nxP )
213 0           *nxP = bgval;
214              
215 0 0         if ( antialias )
216             {
217 0           prevxel = bgval;
218 0           for ( col = 0, xP = temp2xels+row*tempcols;
219 0 0         col < tempcols; ++col, ++xP )
220             {
221 0           new = intnew0 + col;
222 0 0         if ( new >= 0 && new < newcols )
    0          
223             {
224 0           nxP = &(newxelrow[new]);
225 0           *nxP =
226 0           ( fracnew0 * prevxel + omfracnew0 * *xP + HALFSCALE )
227 0           / SCALE;
228 0           prevxel = *xP;
229             }
230             }
231 0 0         if ( fracnew0 > 0 && intnew0 + tempcols < newcols )
    0          
232             {
233 0           nxP = &(newxelrow[intnew0 + tempcols]);
234 0           *nxP =
235 0           ( fracnew0 * prevxel + omfracnew0 * bgval + HALFSCALE )
236 0           / SCALE;
237             }
238             }
239             else
240             {
241 0           for ( col = 0, xP = temp2xels+row*tempcols;
242 0 0         col < tempcols; ++col, ++xP )
243             {
244 0           new = intnew0 + col;
245 0 0         if ( new >= 0 && new < newcols )
    0          
246 0           newxelrow[new] = *xP;
247             }
248             }
249              
250             }
251 0           free(temp2xels);
252 0           return 0; /* OK */
253             }