- put back wmksize(), wmkrange() and wmkpoint() as functions instead of macros
[wmaker-crm.git] / wrlib / rotate.c
blob9f493d03ae6f6c2b722666c958696c050f8fb3a4
1 /* rotate.c - image rotation
2 *
3 * Raster graphics library
4 *
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.
22 #include <config.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <X11/Xlib.h>
28 #include "wraster.h"
30 #include <math.h>
32 #ifndef PI
33 #define PI 3.14159265358979323846
34 #endif
37 static RImage *rotateImage(RImage *image, float angle);
40 RImage *RRotateImage(RImage *image, float angle)
42 RImage *img;
43 int nwidth, nheight;
44 int x, y;
45 int bpp = image->format == RRGBAFormat ? 4 : 3;
47 angle = ((int)angle % 360) + (angle - (int)angle);
49 if (angle == 0.0) {
50 return RCloneImage(image);
52 } else if (angle == 90.0) {
53 nwidth = image->height;
54 nheight = image->width;
56 img = RCreateImage(nwidth, nheight, True);
57 if (!img) {
58 return NULL;
61 if (bpp == 3) {
62 unsigned char *optr, *nptr;
63 unsigned offs;
66 offs = nwidth * 4;
68 optr = image->data;
69 nptr = img->data;
71 for (x = 0; x < nwidth; x++) {
72 nptr = img->data + x*4;
73 for (y = nheight; y; y--) {
74 nptr[0] = *optr++;
75 nptr[1] = *optr++;
76 nptr[2] = *optr++;
77 nptr[3] = 255;
79 nptr += offs;
82 } else {
83 unsigned *optr, *nptr;
84 unsigned *p;
86 optr = (unsigned*)image->data;
87 p = (unsigned*)img->data;
88 for (x = 0; x < nwidth; x++) {
89 nptr = p++;
90 for (y = nheight; y; y--) {
91 *nptr = *optr++;
92 nptr += nwidth;
96 } else if (angle == 180.0) {
98 nwidth = image->width;
99 nheight = image->height;
100 img = RCreateImage(nwidth, nheight, True);
101 if (!img) {
102 return NULL;
105 if (bpp == 3) {
106 unsigned char *optr, *nptr;
108 optr = image->data;
109 nptr = img->data + nwidth * nheight * 4 - 4;
111 for (y = 0; y < nheight; y++) {
112 for (x = 0; x < nwidth; x++) {
113 nptr[0] = optr[0];
114 nptr[1] = optr[1];
115 nptr[2] = optr[2];
116 nptr[3] = 255;
118 optr += 3;
119 nptr -= 4;
122 } else {
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--) {
129 *nptr = *optr;
130 optr++;
131 nptr--;
134 } else if (angle == 270.0) {
135 nwidth = image->height;
136 nheight = image->width;
138 img = RCreateImage(nwidth, nheight, True);
139 if (!img) {
140 return NULL;
143 if (bpp == 3) {
144 unsigned char *optr, *nptr;
145 unsigned offs;
148 offs = nwidth * 4;
150 optr = image->data;
151 nptr = img->data;
153 for (x = 0; x < nwidth; x++) {
154 nptr = img->data + x*4;
155 for (y = nheight; y; y--) {
156 nptr[0] = *optr++;
157 nptr[1] = *optr++;
158 nptr[2] = *optr++;
159 nptr[3] = 255;
161 nptr += offs;
164 } else {
165 unsigned *optr, *nptr;
166 unsigned *p;
168 optr = (unsigned*)image->data;
169 p = (unsigned*)img->data + nwidth*nheight;
170 for (x = 0; x < nwidth; x++) {
171 nptr = p--;
172 for (y = nheight; y; y--) {
173 *nptr = *optr++;
174 nptr -= nwidth;
178 } else {
179 img = rotateImage(image, angle);
182 return img;
189 * Image rotation through Bresenham's line algorithm:
191 * If a square must be rotate by angle a, like in:
192 * _______
193 * | B |
194 * | /4\ |
195 * | /3 8\|
196 * | /2 7 /|
197 * |A1 6 / | A_______B
198 * | \5 / a| <--- |1 2 3 4|
199 * |__C/_)_| |5 6 7 8|
200 * C-------
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;
214 int dx, dy;
215 int xi, yi;
216 int offset;
217 int dpr, dpru, p;
219 dx = abs(x2 - x1);
220 dy = abs(y2 - y1);
222 if (x1 > x2) xi = -1; else xi = 1;
223 if (y1 > y2) yi = -1; else yi = 1;
225 if (dx >= dy) {
227 dpr = dy << 1;
228 dpru = dpr - (dx << 1);
229 p = dpr - dx;
231 while (dx-- >= 0) {
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++;
239 else
240 dst[offset++] = 255;
242 /* calc next step */
243 if (p > 0) {
244 x1 += xi;
245 y1 += yi;
246 p += dpru;
247 } else {
248 x1 += xi;
249 p += dpr;
252 } else {
254 dpr = dx << 1;
255 dpru = dpr - (dy << 1);
256 p = dpr - dy;
258 while (dy-- >= 0) {
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++;
266 else
267 dst[offset++] = 255;
269 /* calc next step */
270 if (p > 0) {
271 x1 += xi;
272 y1 += yi;
273 p += dpru;
274 } else {
275 y1 += yi;
276 p += dpr;
282 *src = s;
286 static RImage *rotateImage(RImage *image, float angle)
288 RImage *img;
289 int nwidth, nheight;
290 int x1, y1;
291 int x2, y2;
292 int dx, dy;
293 int xi, yi;
294 int xx, yy;
295 unsigned char *src, *dst;
296 int dpr, dpru, p;
298 /* only 180o for now */
299 if (angle > 180.0)
300 angle -= 180.0;
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);
312 if (!img)
313 return NULL;
315 src = image->data;
316 dst = img->data;
318 x1 = floor(abs(cos(PI/2 - angle)*image->width));
319 y1 = 0;
321 x2 = 0;
322 y2 = floor(abs(sin(PI/2 - angle)*image->width));
324 xx = floor(abs(cos(angle)*image->height)) - 1;
325 yy = nheight - 1;
327 printf("%ix%i, %i %i %i %i %i\n",
328 nwidth, nheight, x1, y1, x2, y2, (int)((angle*180.0)/PI));
330 dx = abs(x2 - x1);
331 dy = abs(y2 - y1);
333 if (x1 > x2) xi = -1; else xi = 1;
334 if (y1 > y2) yi = -1; else yi = 1;
336 if (dx >= dy) {
337 dpr = dy << 1;
338 dpru = dpr - (dx << 1);
339 p = dpr - dx;
341 while (dx-- >= 0) {
343 copyLine(x1, y1, xx, yy, nwidth, image->format, dst, &src);
345 /* calc next step */
347 if (p > 0) {
348 x1 += xi;
349 y1 += yi;
350 xx += xi;
351 yy += yi;
352 p += dpru;
353 } else {
354 x1 += xi;
355 xx += xi;
356 p += dpr;
359 } else {
360 puts("NOT IMPLEMTENED");
361 return img;
362 dpr = dx << 1;
363 dpru = dpr - (dy << 1);
364 p = dpr - dy;
366 while (dy-- >= 0) {
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);
372 /* calc next step*/
373 if (p > 0) {
374 x1 += xi;
375 y1 += yi;
376 p += dpru;
377 } else {
378 y1 += yi;
379 p += dpr;
384 return img;