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., 51 Franklin St, Fifth Floor, Boston,
34 #define PI 3.14159265358979323846
37 static RImage
*rotateImage(RImage
* image
, float angle
);
39 RImage
*RRotateImage(RImage
* image
, float angle
)
44 int bpp
= image
->format
== RRGBAFormat
? 4 : 3;
46 angle
= ((int)angle
% 360) + (angle
- (int)angle
);
49 return RCloneImage(image
);
51 } else if (angle
== 90.0) {
52 nwidth
= image
->height
;
53 nheight
= image
->width
;
55 img
= RCreateImage(nwidth
, nheight
, True
);
61 unsigned char *optr
, *nptr
;
69 for (x
= 0; x
< nwidth
; x
++) {
70 nptr
= img
->data
+ x
* 4;
71 for (y
= nheight
; y
; y
--) {
81 unsigned *optr
, *nptr
;
84 optr
= (unsigned *)image
->data
;
85 p
= (unsigned *)img
->data
;
86 for (x
= 0; x
< nwidth
; x
++) {
88 for (y
= nheight
; y
; y
--) {
94 } else if (angle
== 180.0) {
96 nwidth
= image
->width
;
97 nheight
= image
->height
;
98 img
= RCreateImage(nwidth
, nheight
, True
);
104 unsigned char *optr
, *nptr
;
107 nptr
= img
->data
+ nwidth
* nheight
* 4 - 4;
109 for (y
= 0; y
< nheight
; y
++) {
110 for (x
= 0; x
< nwidth
; x
++) {
121 unsigned *optr
, *nptr
;
123 optr
= (unsigned *)image
->data
;
124 nptr
= (unsigned *)img
->data
+ nwidth
* nheight
- 1;
126 for (y
= nheight
* nwidth
- 1; y
>= 0; y
--) {
132 } else if (angle
== 270.0) {
133 nwidth
= image
->height
;
134 nheight
= image
->width
;
136 img
= RCreateImage(nwidth
, nheight
, True
);
142 unsigned char *optr
, *nptr
;
150 for (x
= 0; x
< nwidth
; x
++) {
151 nptr
= img
->data
+ x
* 4;
152 for (y
= nheight
; y
; y
--) {
162 unsigned *optr
, *nptr
;
165 optr
= (unsigned *)image
->data
;
166 p
= (unsigned *)img
->data
+ nwidth
* nheight
;
167 for (x
= 0; x
< nwidth
; x
++) {
169 for (y
= nheight
; y
; y
--) {
176 img
= rotateImage(image
, angle
);
183 * Image rotation through Bresenham's line algorithm:
185 * If a square must be rotate by angle a, like in:
191 * |A1 6 / | A_______B
192 * | \5 / a| <--- |1 2 3 4|
193 * |__C/_)_| |5 6 7 8|
196 * for each point P1 in the line from C to A
197 * for each point P2 in the perpendicular line starting at P1
198 * get pixel from the source and plot at P2
199 * increment pixel location from source
204 copyLine(int x1
, int y1
, int x2
, int y2
, int nwidth
, int format
, unsigned char *dst
, unsigned char **src
)
206 unsigned char *s
= *src
;
227 dpru
= dpr
- (dx
<< 1);
231 /* fetch and draw the pixel */
232 offset
= (x1
+ y1
* nwidth
) << 2;
233 dst
[offset
++] = *s
++;
234 dst
[offset
++] = *s
++;
235 dst
[offset
++] = *s
++;
236 if (format
== RRGBAFormat
)
237 dst
[offset
++] = *s
++;
254 dpru
= dpr
- (dy
<< 1);
258 /* fetch and draw the pixel */
259 offset
= (x1
+ y1
* nwidth
) << 2;
260 dst
[offset
++] = *s
++;
261 dst
[offset
++] = *s
++;
262 dst
[offset
++] = *s
++;
263 if (format
== RRGBAFormat
)
264 dst
[offset
++] = *s
++;
283 static RImage
*rotateImage(RImage
* image
, float angle
)
292 unsigned char *src
, *dst
;
295 /* only 180o for now */
299 angle
= (angle
* PI
) / 180.0;
301 nwidth
= ceil(abs(cos(angle
) * image
->width
))
302 + ceil(abs(cos(PI
/ 2 - angle
) * image
->width
));
304 nheight
= ceil(abs(sin(angle
) * image
->height
))
305 + ceil(abs(cos(PI
/ 2 - angle
) * image
->height
));
307 img
= RCreateImage(nwidth
, nheight
, True
);
314 x1
= floor(abs(cos(PI
/ 2 - angle
) * image
->width
));
318 y2
= floor(abs(sin(PI
/ 2 - angle
) * image
->width
));
320 xx
= floor(abs(cos(angle
) * image
->height
)) - 1;
323 printf("%ix%i, %i %i %i %i %i\n", nwidth
, nheight
, x1
, y1
, x2
, y2
, (int)((angle
* 180.0) / PI
));
339 dpru
= dpr
- (dx
<< 1);
344 copyLine(x1
, y1
, xx
, yy
, nwidth
, image
->format
, dst
, &src
);
361 puts("NOT IMPLEMTENED");
364 dpru
= dpr
- (dy
<< 1);
368 xx
= abs(x1
* sin(angle
* PI
/ 180.0));
369 yy
= abs(y1
* cos(angle
* PI
/ 180.0));
371 copyLine(x1
, y1
, xx
, yy
, nwidth
, image
->format
, dst
, &src
);