configure: Add detection of library kvm that is used under OpenBSD
[wmaker-crm.git] / wrlib / rotate.c
blobb1379ba38e23c24042dc4d0bbec87904740620b4
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,
20 * MA 02110-1301, USA.
23 #include <config.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <X11/Xlib.h>
29 #include "wraster.h"
31 #include <math.h>
33 #ifndef PI
34 #define PI 3.14159265358979323846
35 #endif
37 static RImage *rotateImage(RImage * image, float angle);
39 RImage *RRotateImage(RImage * image, float angle)
41 RImage *img;
42 int nwidth, nheight;
43 int x, y;
44 int bpp = image->format == RRGBAFormat ? 4 : 3;
46 angle = ((int)angle % 360) + (angle - (int)angle);
48 if (angle == 0.0) {
49 return RCloneImage(image);
51 } else if (angle == 90.0) {
52 nwidth = image->height;
53 nheight = image->width;
55 img = RCreateImage(nwidth, nheight, True);
56 if (!img) {
57 return NULL;
60 if (bpp == 3) {
61 unsigned char *optr, *nptr;
62 unsigned offs;
64 offs = nwidth * 4;
66 optr = image->data;
67 nptr = img->data;
69 for (x = 0; x < nwidth; x++) {
70 nptr = img->data + x * 4;
71 for (y = nheight; y; y--) {
72 nptr[0] = *optr++;
73 nptr[1] = *optr++;
74 nptr[2] = *optr++;
75 nptr[3] = 255;
77 nptr += offs;
80 } else {
81 unsigned *optr, *nptr;
82 unsigned *p;
84 optr = (unsigned *)image->data;
85 p = (unsigned *)img->data;
86 for (x = 0; x < nwidth; x++) {
87 nptr = p++;
88 for (y = nheight; y; y--) {
89 *nptr = *optr++;
90 nptr += nwidth;
94 } else if (angle == 180.0) {
96 nwidth = image->width;
97 nheight = image->height;
98 img = RCreateImage(nwidth, nheight, True);
99 if (!img) {
100 return NULL;
103 if (bpp == 3) {
104 unsigned char *optr, *nptr;
106 optr = image->data;
107 nptr = img->data + nwidth * nheight * 4 - 4;
109 for (y = 0; y < nheight; y++) {
110 for (x = 0; x < nwidth; x++) {
111 nptr[0] = optr[0];
112 nptr[1] = optr[1];
113 nptr[2] = optr[2];
114 nptr[3] = 255;
116 optr += 3;
117 nptr -= 4;
120 } else {
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--) {
127 *nptr = *optr;
128 optr++;
129 nptr--;
132 } else if (angle == 270.0) {
133 nwidth = image->height;
134 nheight = image->width;
136 img = RCreateImage(nwidth, nheight, True);
137 if (!img) {
138 return NULL;
141 if (bpp == 3) {
142 unsigned char *optr, *nptr;
143 unsigned offs;
145 offs = nwidth * 4;
147 optr = image->data;
148 nptr = img->data;
150 for (x = 0; x < nwidth; x++) {
151 nptr = img->data + x * 4;
152 for (y = nheight; y; y--) {
153 nptr[0] = *optr++;
154 nptr[1] = *optr++;
155 nptr[2] = *optr++;
156 nptr[3] = 255;
158 nptr += offs;
161 } else {
162 unsigned *optr, *nptr;
163 unsigned *p;
165 optr = (unsigned *)image->data;
166 p = (unsigned *)img->data + nwidth * nheight;
167 for (x = 0; x < nwidth; x++) {
168 nptr = p--;
169 for (y = nheight; y; y--) {
170 *nptr = *optr++;
171 nptr -= nwidth;
175 } else {
176 img = rotateImage(image, angle);
179 return img;
183 * Image rotation through Bresenham's line algorithm:
185 * If a square must be rotate by angle a, like in:
186 * _______
187 * | B |
188 * | /4\ |
189 * | /3 8\|
190 * | /2 7 /|
191 * |A1 6 / | A_______B
192 * | \5 / a| <--- |1 2 3 4|
193 * |__C/_)_| |5 6 7 8|
194 * C-------
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
203 static void
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;
207 int dx, dy;
208 int xi, yi;
209 int offset;
210 int dpr, dpru, p;
212 dx = abs(x2 - x1);
213 dy = abs(y2 - y1);
215 if (x1 > x2)
216 xi = -1;
217 else
218 xi = 1;
219 if (y1 > y2)
220 yi = -1;
221 else
222 yi = 1;
224 if (dx >= dy) {
226 dpr = dy << 1;
227 dpru = dpr - (dx << 1);
228 p = dpr - dx;
230 while (dx-- >= 0) {
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++;
238 else
239 dst[offset++] = 255;
241 /* calc next step */
242 if (p > 0) {
243 x1 += xi;
244 y1 += yi;
245 p += dpru;
246 } else {
247 x1 += xi;
248 p += dpr;
251 } else {
253 dpr = dx << 1;
254 dpru = dpr - (dy << 1);
255 p = dpr - dy;
257 while (dy-- >= 0) {
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++;
265 else
266 dst[offset++] = 255;
268 /* calc next step */
269 if (p > 0) {
270 x1 += xi;
271 y1 += yi;
272 p += dpru;
273 } else {
274 y1 += yi;
275 p += dpr;
280 *src = s;
283 static RImage *rotateImage(RImage * image, float angle)
285 RImage *img;
286 int nwidth, nheight;
287 int x1, y1;
288 int x2, y2;
289 int dx, dy;
290 int xi, yi;
291 int xx, yy;
292 unsigned char *src, *dst;
293 int dpr, dpru, p;
295 /* only 180o for now */
296 if (angle > 180.0)
297 angle -= 180.0;
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);
308 if (!img)
309 return NULL;
311 src = image->data;
312 dst = img->data;
314 x1 = floor(abs(cos(PI / 2 - angle) * image->width));
315 y1 = 0;
317 x2 = 0;
318 y2 = floor(abs(sin(PI / 2 - angle) * image->width));
320 xx = floor(abs(cos(angle) * image->height)) - 1;
321 yy = nheight - 1;
323 printf("%ix%i, %i %i %i %i %i\n", nwidth, nheight, x1, y1, x2, y2, (int)((angle * 180.0) / PI));
325 dx = abs(x2 - x1);
326 dy = abs(y2 - y1);
328 if (x1 > x2)
329 xi = -1;
330 else
331 xi = 1;
332 if (y1 > y2)
333 yi = -1;
334 else
335 yi = 1;
337 if (dx >= dy) {
338 dpr = dy << 1;
339 dpru = dpr - (dx << 1);
340 p = dpr - dx;
342 while (dx-- >= 0) {
344 copyLine(x1, y1, xx, yy, nwidth, image->format, dst, &src);
346 /* calc next step */
348 if (p > 0) {
349 x1 += xi;
350 y1 += yi;
351 xx += xi;
352 yy += yi;
353 p += dpru;
354 } else {
355 x1 += xi;
356 xx += xi;
357 p += dpr;
360 } else {
361 puts("NOT IMPLEMTENED");
362 return img;
363 dpr = dx << 1;
364 dpru = dpr - (dy << 1);
365 p = dpr - dy;
367 while (dy-- >= 0) {
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);
373 /* calc next step */
374 if (p > 0) {
375 x1 += xi;
376 y1 += yi;
377 p += dpru;
378 } else {
379 y1 += yi;
380 p += dpr;
385 return img;