1 /* rotate.c - image rotation
3 * Raster graphics library
5 * Copyright (c) 2000 Alfredo K. Kojima
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 #define PI 3.14159265358979323846
37 static RImage
*rotateImage(RImage
*image
, float angle
);
40 RImage
*RRotateImage(RImage
*image
, float angle
)
45 int bpp
= image
->format
== RRGBAFormat
? 4 : 3;
47 angle
= ((int)angle
% 360) + (angle
- (int)angle
);
50 return RCloneImage(image
);
52 } else if (angle
== 90.0) {
53 nwidth
= image
->height
;
54 nheight
= image
->width
;
56 img
= RCreateImage(nwidth
, nheight
, True
);
62 unsigned char *optr
, *nptr
;
71 for (x
= 0; x
< nwidth
; x
++) {
72 nptr
= img
->data
+ x
*4;
73 for (y
= nheight
; y
; y
--) {
83 unsigned *optr
, *nptr
;
86 optr
= (unsigned*)image
->data
;
87 p
= (unsigned*)img
->data
;
88 for (x
= 0; x
< nwidth
; x
++) {
90 for (y
= nheight
; y
; y
--) {
96 } else if (angle
== 180.0) {
98 nwidth
= image
->width
;
99 nheight
= image
->height
;
100 img
= RCreateImage(nwidth
, nheight
, True
);
106 unsigned char *optr
, *nptr
;
109 nptr
= img
->data
+ nwidth
* nheight
* 4 - 4;
111 for (y
= 0; y
< nheight
; y
++) {
112 for (x
= 0; x
< nwidth
; x
++) {
123 unsigned *optr
, *nptr
;
125 optr
= (unsigned*)image
->data
;
126 nptr
= (unsigned*)img
->data
+ nwidth
* nheight
- 1;
128 for (y
= nheight
*nwidth
-1; y
>= 0; y
--) {
134 } else if (angle
== 270.0) {
135 nwidth
= image
->height
;
136 nheight
= image
->width
;
138 img
= RCreateImage(nwidth
, nheight
, True
);
144 unsigned char *optr
, *nptr
;
153 for (x
= 0; x
< nwidth
; x
++) {
154 nptr
= img
->data
+ x
*4;
155 for (y
= nheight
; y
; y
--) {
165 unsigned *optr
, *nptr
;
168 optr
= (unsigned*)image
->data
;
169 p
= (unsigned*)img
->data
+ nwidth
*nheight
;
170 for (x
= 0; x
< nwidth
; x
++) {
172 for (y
= nheight
; y
; y
--) {
179 img
= rotateImage(image
, angle
);
189 * Image rotation through Bresenham's line algorithm:
191 * If a square must be rotate by angle a, like in:
197 * |A1 6 / | A_______B
198 * | \5 / a| <--- |1 2 3 4|
199 * |__C/_)_| |5 6 7 8|
202 * for each point P1 in the line from C to A
203 * for each point P2 in the perpendicular line starting at P1
204 * get pixel from the source and plot at P2
205 * increment pixel location from source
210 static void copyLine(int x1
, int y1
, int x2
, int y2
, int nwidth
, int format
,
211 unsigned char *dst
, unsigned char **src
)
213 unsigned char *s
= *src
;
222 if (x1
> x2
) xi
= -1; else xi
= 1;
223 if (y1
> y2
) yi
= -1; else yi
= 1;
228 dpru
= dpr
- (dx
<< 1);
232 /* fetch and draw the pixel */
233 offset
= (x1
+ y1
* nwidth
) << 2;
234 dst
[offset
++] = *s
++;
235 dst
[offset
++] = *s
++;
236 dst
[offset
++] = *s
++;
237 if (format
== RRGBAFormat
)
238 dst
[offset
++] = *s
++;
255 dpru
= dpr
- (dy
<< 1);
259 /* fetch and draw the pixel */
260 offset
= (x1
+ y1
* nwidth
) << 2;
261 dst
[offset
++] = *s
++;
262 dst
[offset
++] = *s
++;
263 dst
[offset
++] = *s
++;
264 if (format
== RRGBAFormat
)
265 dst
[offset
++] = *s
++;
286 static RImage
*rotateImage(RImage
*image
, float angle
)
295 unsigned char *src
, *dst
;
298 /* only 180o for now */
303 angle
= (angle
* PI
) / 180.0;
305 nwidth
= ceil(abs(cos(angle
) * image
->width
))
306 + ceil(abs(cos(PI
/2 - angle
) * image
->width
));
308 nheight
= ceil(abs(sin(angle
) * image
->height
))
309 + ceil(abs(cos(PI
/2 - angle
) * image
->height
));
311 img
= RCreateImage(nwidth
, nheight
, True
);
318 x1
= floor(abs(cos(PI
/2 - angle
)*image
->width
));
322 y2
= floor(abs(sin(PI
/2 - angle
)*image
->width
));
324 xx
= floor(abs(cos(angle
)*image
->height
)) - 1;
327 printf("%ix%i, %i %i %i %i %i\n",
328 nwidth
, nheight
, x1
, y1
, x2
, y2
, (int)((angle
*180.0)/PI
));
333 if (x1
> x2
) xi
= -1; else xi
= 1;
334 if (y1
> y2
) yi
= -1; else yi
= 1;
338 dpru
= dpr
- (dx
<< 1);
343 copyLine(x1
, y1
, xx
, yy
, nwidth
, image
->format
, dst
, &src
);
360 puts("NOT IMPLEMTENED");
363 dpru
= dpr
- (dy
<< 1);
367 xx
= abs(x1
*sin(angle
*PI
/180.0));
368 yy
= abs(y1
*cos(angle
*PI
/180.0));
370 copyLine(x1
, y1
, xx
, yy
, nwidth
, image
->format
, dst
, &src
);