wrlib: add explicit type definition in API to allow compiler Type Checks (1/3)
[wmaker-crm.git] / wrlib / rotate.c
blobf2f92b998c41ff1647cf49dae4c9e6f09d37e7cd
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;
47 * Angle steps below this value would represent a rotation
48 * of less than 1 pixel for a 4k wide image, so not worth
49 * bothering the difference. That makes it a perfect
50 * candidate for an Epsilon when trying to compare angle
51 * to known values
53 static const float min_usable_angle = 0.00699;
55 angle = fmod(angle, 360.0);
56 if (angle < 0.0)
57 angle += 360.0;
59 if (angle < min_usable_angle) {
60 /* Rotate by 0 degree */
61 return RCloneImage(image);
63 } else if ((angle > 90.0 - min_usable_angle) &&
64 (angle < 90.0 + min_usable_angle)) {
65 nwidth = image->height;
66 nheight = image->width;
68 img = RCreateImage(nwidth, nheight, True);
69 if (!img)
70 return NULL;
72 if (bpp == 3) {
73 unsigned char *optr, *nptr;
75 optr = image->data;
76 nptr = img->data;
78 for (x = nwidth; x; x--) {
79 nptr = img->data + 4 * (x - 1);
80 for (y = nheight; y; y--) {
81 nptr[0] = *optr++;
82 nptr[1] = *optr++;
83 nptr[2] = *optr++;
84 nptr[3] = 255;
86 nptr += 4 * nwidth;
89 } else {
90 unsigned char *optr, *nptr;
92 optr = image->data;
93 nptr = img->data;
95 for (x = nwidth; x; x--) {
96 nptr = img->data + 4 * (x - 1);
97 for (y = nheight; y; y--) {
98 nptr[0] = *optr++;
99 nptr[1] = *optr++;
100 nptr[2] = *optr++;
101 nptr[3] = *optr++;
103 nptr += 4 * nwidth;
107 } else if ((angle > 180.0 - min_usable_angle) &&
108 (angle < 180.0 + min_usable_angle)) {
110 nwidth = image->width;
111 nheight = image->height;
112 img = RCreateImage(nwidth, nheight, True);
113 if (!img)
114 return NULL;
116 if (bpp == 3) {
117 unsigned char *optr, *nptr;
119 optr = image->data;
120 nptr = img->data + nwidth * nheight * 4 - 4;
122 for (y = 0; y < nheight; y++) {
123 for (x = 0; x < nwidth; x++) {
124 nptr[0] = optr[0];
125 nptr[1] = optr[1];
126 nptr[2] = optr[2];
127 nptr[3] = 255;
129 optr += 3;
130 nptr -= 4;
133 } else {
134 unsigned *optr, *nptr;
136 optr = (unsigned *)image->data;
137 nptr = (unsigned *)img->data + nwidth * nheight - 1;
139 for (y = nheight * nwidth - 1; y >= 0; y--) {
140 *nptr = *optr;
141 optr++;
142 nptr--;
145 } else if ((angle > 270.0 - min_usable_angle) &&
146 (angle < 270.0 + min_usable_angle)) {
147 nwidth = image->height;
148 nheight = image->width;
150 img = RCreateImage(nwidth, nheight, True);
151 if (!img)
152 return NULL;
154 if (bpp == 3) {
155 unsigned char *optr, *nptr;
157 optr = image->data;
159 for (x = nwidth; x; x--) {
160 nptr = img->data + 4 * nwidth * nheight - x * 4;
161 for (y = nheight; y; y--) {
162 nptr[0] = *optr++;
163 nptr[1] = *optr++;
164 nptr[2] = *optr++;
165 nptr[3] = 255;
167 nptr -= 4 * nwidth;
170 } else {
171 unsigned char *optr, *nptr;
173 optr = image->data;
175 for (x = nwidth; x; x--) {
176 nptr = img->data + 4 * nwidth * nheight - x * 4;
177 for (y = nheight; y; y--) {
178 nptr[0] = *optr++;
179 nptr[1] = *optr++;
180 nptr[2] = *optr++;
181 nptr[3] = *optr++;
183 nptr -= 4 * nwidth;
187 } else {
188 img = rotateImage(image, angle);
191 return img;
195 * Image rotation through Bresenham's line algorithm:
197 * If a square must be rotate by angle a, like in:
198 * _______
199 * | B |
200 * | /4\ |
201 * | /3 8\|
202 * | /2 7 /|
203 * |A1 6 / | A_______B
204 * | \5 / a| <--- |1 2 3 4|
205 * |__C/_)_| |5 6 7 8|
206 * C-------
208 * for each point P1 in the line from C to A
209 * for each point P2 in the perpendicular line starting at P1
210 * get pixel from the source and plot at P2
211 * increment pixel location from source
215 #if 0
216 static void
217 copyLine(int x1, int y1, int x2, int y2, int nwidth, int format, unsigned char *dst, unsigned char **src)
219 unsigned char *s = *src;
220 int dx, dy;
221 int xi, yi;
222 int offset;
223 int dpr, dpru, p;
225 dx = abs(x2 - x1);
226 dy = abs(y2 - y1);
228 if (x1 > x2)
229 xi = -1;
230 else
231 xi = 1;
232 if (y1 > y2)
233 yi = -1;
234 else
235 yi = 1;
237 if (dx >= dy) {
239 dpr = dy << 1;
240 dpru = dpr - (dx << 1);
241 p = dpr - dx;
243 while (dx-- >= 0) {
244 /* fetch and draw the pixel */
245 offset = (x1 + y1 * nwidth) << 2;
246 dst[offset++] = *s++;
247 dst[offset++] = *s++;
248 dst[offset++] = *s++;
249 if (format == RRGBAFormat)
250 dst[offset++] = *s++;
251 else
252 dst[offset++] = 255;
254 /* calc next step */
255 if (p > 0) {
256 x1 += xi;
257 y1 += yi;
258 p += dpru;
259 } else {
260 x1 += xi;
261 p += dpr;
264 } else {
266 dpr = dx << 1;
267 dpru = dpr - (dy << 1);
268 p = dpr - dy;
270 while (dy-- >= 0) {
271 /* fetch and draw the pixel */
272 offset = (x1 + y1 * nwidth) << 2;
273 dst[offset++] = *s++;
274 dst[offset++] = *s++;
275 dst[offset++] = *s++;
276 if (format == RRGBAFormat)
277 dst[offset++] = *s++;
278 else
279 dst[offset++] = 255;
281 /* calc next step */
282 if (p > 0) {
283 x1 += xi;
284 y1 += yi;
285 p += dpru;
286 } else {
287 y1 += yi;
288 p += dpr;
293 *src = s;
295 #endif
297 static RImage *rotateImage(RImage *image, float angle)
299 (void) angle;
300 puts("NOT FULLY IMPLEMENTED");
301 return RCloneImage(image);
302 #if 0
303 RImage *img;
304 int nwidth, nheight;
305 int x1, y1;
306 int x2, y2;
307 int dx, dy;
308 int xi, yi;
309 int xx, yy;
310 unsigned char *src, *dst;
311 int dpr, dpru, p;
313 /* only 180o for now */
314 if (angle > 180.0)
315 angle -= 180.0;
317 angle = (angle * PI) / 180.0;
319 nwidth = ceil(abs(cos(angle) * image->width))
320 + ceil(abs(cos(PI / 2 - angle) * image->width));
322 nheight = ceil(abs(sin(angle) * image->height))
323 + ceil(abs(cos(PI / 2 - angle) * image->height));
325 img = RCreateImage(nwidth, nheight, True);
326 if (!img)
327 return NULL;
329 src = image->data;
330 dst = img->data;
332 x1 = floor(abs(cos(PI / 2 - angle) * image->width));
333 y1 = 0;
335 x2 = 0;
336 y2 = floor(abs(sin(PI / 2 - angle) * image->width));
338 xx = floor(abs(cos(angle) * image->height)) - 1;
339 yy = nheight - 1;
341 printf("%ix%i, %i %i %i %i %i\n", nwidth, nheight, x1, y1, x2, y2, (int)((angle * 180.0) / PI));
343 dx = abs(x2 - x1);
344 dy = abs(y2 - y1);
346 if (x1 > x2)
347 xi = -1;
348 else
349 xi = 1;
350 if (y1 > y2)
351 yi = -1;
352 else
353 yi = 1;
355 if (dx >= dy) {
356 dpr = dy << 1;
357 dpru = dpr - (dx << 1);
358 p = dpr - dx;
360 while (dx-- >= 0) {
362 copyLine(x1, y1, xx, yy, nwidth, image->format, dst, &src);
364 /* calc next step */
366 if (p > 0) {
367 x1 += xi;
368 y1 += yi;
369 xx += xi;
370 yy += yi;
371 p += dpru;
372 } else {
373 x1 += xi;
374 xx += xi;
375 p += dpr;
378 } else {
379 dpr = dx << 1;
380 dpru = dpr - (dy << 1);
381 p = dpr - dy;
383 while (dy-- >= 0) {
384 xx = abs(x1 * sin(angle * PI / 180.0));
385 yy = abs(y1 * cos(angle * PI / 180.0));
387 copyLine(x1, y1, xx, yy, nwidth, image->format, dst, &src);
389 /* calc next step */
390 if (p > 0) {
391 x1 += xi;
392 y1 += yi;
393 p += dpru;
394 } else {
395 y1 += yi;
396 p += dpr;
401 return img;
402 #endif