1 /* rotate.c - image rotation
3 * Raster graphics library
5 * Copyright (c) 2000-2003 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
);
41 RRotateImage(RImage
*image
, float angle
)
46 int bpp
= image
->format
== RRGBAFormat
? 4 : 3;
48 angle
= ((int)angle
% 360) + (angle
- (int)angle
);
51 return RCloneImage(image
);
53 } else if (angle
== 90.0) {
54 nwidth
= image
->height
;
55 nheight
= image
->width
;
57 img
= RCreateImage(nwidth
, nheight
, True
);
63 unsigned char *optr
, *nptr
;
72 for (x
= 0; x
< nwidth
; x
++) {
73 nptr
= img
->data
+ x
*4;
74 for (y
= nheight
; y
; y
--) {
84 unsigned *optr
, *nptr
;
87 optr
= (unsigned*)image
->data
;
88 p
= (unsigned*)img
->data
;
89 for (x
= 0; x
< nwidth
; x
++) {
91 for (y
= nheight
; y
; y
--) {
97 } else if (angle
== 180.0) {
99 nwidth
= image
->width
;
100 nheight
= image
->height
;
101 img
= RCreateImage(nwidth
, nheight
, True
);
107 unsigned char *optr
, *nptr
;
110 nptr
= img
->data
+ nwidth
* nheight
* 4 - 4;
112 for (y
= 0; y
< nheight
; y
++) {
113 for (x
= 0; x
< nwidth
; x
++) {
124 unsigned *optr
, *nptr
;
126 optr
= (unsigned*)image
->data
;
127 nptr
= (unsigned*)img
->data
+ nwidth
* nheight
- 1;
129 for (y
= nheight
*nwidth
-1; y
>= 0; y
--) {
135 } else if (angle
== 270.0) {
136 nwidth
= image
->height
;
137 nheight
= image
->width
;
139 img
= RCreateImage(nwidth
, nheight
, True
);
145 unsigned char *optr
, *nptr
;
154 for (x
= 0; x
< nwidth
; x
++) {
155 nptr
= img
->data
+ x
*4;
156 for (y
= nheight
; y
; y
--) {
166 unsigned *optr
, *nptr
;
169 optr
= (unsigned*)image
->data
;
170 p
= (unsigned*)img
->data
+ nwidth
*nheight
;
171 for (x
= 0; x
< nwidth
; x
++) {
173 for (y
= nheight
; y
; y
--) {
180 img
= rotateImage(image
, angle
);
190 * Image rotation through Bresenham's line algorithm:
192 * If a square must be rotate by angle a, like in:
198 * |A1 6 / | A_______B
199 * | \5 / a| <--- |1 2 3 4|
200 * |__C/_)_| |5 6 7 8|
203 * for each point P1 in the line from C to A
204 * for each point P2 in the perpendicular line starting at P1
205 * get pixel from the source and plot at P2
206 * increment pixel location from source
212 copyLine(int x1
, int y1
, int x2
, int y2
, int nwidth
, int format
,
213 unsigned char *dst
, unsigned char **src
)
215 unsigned char *s
= *src
;
224 if (x1
> x2
) xi
= -1; else xi
= 1;
225 if (y1
> y2
) yi
= -1; else yi
= 1;
230 dpru
= dpr
- (dx
<< 1);
234 /* fetch and draw the pixel */
235 offset
= (x1
+ y1
* nwidth
) << 2;
236 dst
[offset
++] = *s
++;
237 dst
[offset
++] = *s
++;
238 dst
[offset
++] = *s
++;
239 if (format
== RRGBAFormat
)
240 dst
[offset
++] = *s
++;
257 dpru
= dpr
- (dy
<< 1);
261 /* fetch and draw the pixel */
262 offset
= (x1
+ y1
* nwidth
) << 2;
263 dst
[offset
++] = *s
++;
264 dst
[offset
++] = *s
++;
265 dst
[offset
++] = *s
++;
266 if (format
== RRGBAFormat
)
267 dst
[offset
++] = *s
++;
289 rotateImage(RImage
*image
, float angle
)
298 unsigned char *src
, *dst
;
301 /* only 180o for now */
306 angle
= (angle
* PI
) / 180.0;
308 nwidth
= ceil(abs(cos(angle
) * image
->width
))
309 + ceil(abs(cos(PI
/2 - angle
) * image
->width
));
311 nheight
= ceil(abs(sin(angle
) * image
->height
))
312 + ceil(abs(cos(PI
/2 - angle
) * image
->height
));
314 img
= RCreateImage(nwidth
, nheight
, True
);
321 x1
= floor(abs(cos(PI
/2 - angle
)*image
->width
));
325 y2
= floor(abs(sin(PI
/2 - angle
)*image
->width
));
327 xx
= floor(abs(cos(angle
)*image
->height
)) - 1;
330 printf("%ix%i, %i %i %i %i %i\n",
331 nwidth
, nheight
, x1
, y1
, x2
, y2
, (int)((angle
*180.0)/PI
));
336 if (x1
> x2
) xi
= -1; else xi
= 1;
337 if (y1
> y2
) yi
= -1; else yi
= 1;
341 dpru
= dpr
- (dx
<< 1);
346 copyLine(x1
, y1
, xx
, yy
, nwidth
, image
->format
, dst
, &src
);
363 puts("NOT IMPLEMTENED");
366 dpru
= dpr
- (dy
<< 1);
370 xx
= abs(x1
*sin(angle
*PI
/180.0));
371 yy
= abs(y1
*cos(angle
*PI
/180.0));
373 copyLine(x1
, y1
, xx
, yy
, nwidth
, image
->format
, dst
, &src
);