X-Git-Url: https://repo.or.cz/w/wmaker-crm.git/blobdiff_plain/59fc927dc9f183802621138534fa6eaafe5593ba..688a56e8ab67b56550e2874d9d7423f0d435bfd9:/wrlib/rotate.c diff --git a/wrlib/rotate.c b/wrlib/rotate.c dissimilarity index 81% index f69c8c98..472c51a4 100644 --- a/wrlib/rotate.c +++ b/wrlib/rotate.c @@ -1,389 +1,385 @@ -/* rotate.c - image rotation - * - * Raster graphics library - * - * Copyright (c) 2000-2003 Alfredo K. Kojima - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include - -#include -#include -#include -#include -#include "wraster.h" - -#include - -#ifndef PI -#define PI 3.14159265358979323846 -#endif - - -static RImage *rotateImage(RImage *image, float angle); - - -RImage* -RRotateImage(RImage *image, float angle) -{ - RImage *img; - int nwidth, nheight; - int x, y; - int bpp = image->format == RRGBAFormat ? 4 : 3; - - angle = ((int)angle % 360) + (angle - (int)angle); - - if (angle == 0.0) { - return RCloneImage(image); - - } else if (angle == 90.0) { - nwidth = image->height; - nheight = image->width; - - img = RCreateImage(nwidth, nheight, True); - if (!img) { - return NULL; - } - - if (bpp == 3) { - unsigned char *optr, *nptr; - unsigned offs; - - - offs = nwidth * 4; - - optr = image->data; - nptr = img->data; - - for (x = 0; x < nwidth; x++) { - nptr = img->data + x*4; - for (y = nheight; y; y--) { - nptr[0] = *optr++; - nptr[1] = *optr++; - nptr[2] = *optr++; - nptr[3] = 255; - - nptr += offs; - } - } - } else { - unsigned *optr, *nptr; - unsigned *p; - - optr = (unsigned*)image->data; - p = (unsigned*)img->data; - for (x = 0; x < nwidth; x++) { - nptr = p++; - for (y = nheight; y; y--) { - *nptr = *optr++; - nptr += nwidth; - } - } - } - } else if (angle == 180.0) { - - nwidth = image->width; - nheight = image->height; - img = RCreateImage(nwidth, nheight, True); - if (!img) { - return NULL; - } - - if (bpp == 3) { - unsigned char *optr, *nptr; - - optr = image->data; - nptr = img->data + nwidth * nheight * 4 - 4; - - for (y = 0; y < nheight; y++) { - for (x = 0; x < nwidth; x++) { - nptr[0] = optr[0]; - nptr[1] = optr[1]; - nptr[2] = optr[2]; - nptr[3] = 255; - - optr += 3; - nptr -= 4; - } - } - } else { - unsigned *optr, *nptr; - - optr = (unsigned*)image->data; - nptr = (unsigned*)img->data + nwidth * nheight - 1; - - for (y = nheight*nwidth-1; y >= 0; y--) { - *nptr = *optr; - optr++; - nptr--; - } - } - } else if (angle == 270.0) { - nwidth = image->height; - nheight = image->width; - - img = RCreateImage(nwidth, nheight, True); - if (!img) { - return NULL; - } - - if (bpp == 3) { - unsigned char *optr, *nptr; - unsigned offs; - - - offs = nwidth * 4; - - optr = image->data; - nptr = img->data; - - for (x = 0; x < nwidth; x++) { - nptr = img->data + x*4; - for (y = nheight; y; y--) { - nptr[0] = *optr++; - nptr[1] = *optr++; - nptr[2] = *optr++; - nptr[3] = 255; - - nptr += offs; - } - } - } else { - unsigned *optr, *nptr; - unsigned *p; - - optr = (unsigned*)image->data; - p = (unsigned*)img->data + nwidth*nheight; - for (x = 0; x < nwidth; x++) { - nptr = p--; - for (y = nheight; y; y--) { - *nptr = *optr++; - nptr -= nwidth; - } - } - } - } else { - img = rotateImage(image, angle); - } - - return img; -} - - - - -/* - * Image rotation through Bresenham's line algorithm: - * - * If a square must be rotate by angle a, like in: - * _______ - * | B | - * | /4\ | - * | /3 8\| - * | /2 7 /| - * |A1 6 / | A_______B - * | \5 / a| <--- |1 2 3 4| - * |__C/_)_| |5 6 7 8| - * C------- - * - * for each point P1 in the line from C to A - * for each point P2 in the perpendicular line starting at P1 - * get pixel from the source and plot at P2 - * increment pixel location from source - * - */ - - -static void -copyLine(int x1, int y1, int x2, int y2, int nwidth, int format, - unsigned char *dst, unsigned char **src) -{ - unsigned char *s = *src; - int dx, dy; - int xi, yi; - int offset; - int dpr, dpru, p; - - dx = abs(x2 - x1); - dy = abs(y2 - y1); - - if (x1 > x2) xi = -1; else xi = 1; - if (y1 > y2) yi = -1; else yi = 1; - - if (dx >= dy) { - - dpr = dy << 1; - dpru = dpr - (dx << 1); - p = dpr - dx; - - while (dx-- >= 0) { - /* fetch and draw the pixel */ - offset = (x1 + y1 * nwidth) << 2; - dst[offset++] = *s++; - dst[offset++] = *s++; - dst[offset++] = *s++; - if (format == RRGBAFormat) - dst[offset++] = *s++; - else - dst[offset++] = 255; - - /* calc next step */ - if (p > 0) { - x1 += xi; - y1 += yi; - p += dpru; - } else { - x1 += xi; - p += dpr; - } - } - } else { - - dpr = dx << 1; - dpru = dpr - (dy << 1); - p = dpr - dy; - - while (dy-- >= 0) { - /* fetch and draw the pixel */ - offset = (x1 + y1 * nwidth) << 2; - dst[offset++] = *s++; - dst[offset++] = *s++; - dst[offset++] = *s++; - if (format == RRGBAFormat) - dst[offset++] = *s++; - else - dst[offset++] = 255; - - /* calc next step */ - if (p > 0) { - x1 += xi; - y1 += yi; - p += dpru; - } else { - y1 += yi; - p += dpr; - } - } - } - - - *src = s; -} - - -static RImage* -rotateImage(RImage *image, float angle) -{ - RImage *img; - int nwidth, nheight; - int x1, y1; - int x2, y2; - int dx, dy; - int xi, yi; - int xx, yy; - unsigned char *src, *dst; - int dpr, dpru, p; - - /* only 180o for now */ - if (angle > 180.0) - angle -= 180.0; - - - angle = (angle * PI) / 180.0; - - nwidth = ceil(abs(cos(angle) * image->width)) - + ceil(abs(cos(PI/2 - angle) * image->width)); - - nheight = ceil(abs(sin(angle) * image->height)) - + ceil(abs(cos(PI/2 - angle) * image->height)); - - img = RCreateImage(nwidth, nheight, True); - if (!img) - return NULL; - - src = image->data; - dst = img->data; - - x1 = floor(abs(cos(PI/2 - angle)*image->width)); - y1 = 0; - - x2 = 0; - y2 = floor(abs(sin(PI/2 - angle)*image->width)); - - xx = floor(abs(cos(angle)*image->height)) - 1; - yy = nheight - 1; - - printf("%ix%i, %i %i %i %i %i\n", - nwidth, nheight, x1, y1, x2, y2, (int)((angle*180.0)/PI)); - - dx = abs(x2 - x1); - dy = abs(y2 - y1); - - if (x1 > x2) xi = -1; else xi = 1; - if (y1 > y2) yi = -1; else yi = 1; - - if (dx >= dy) { - dpr = dy << 1; - dpru = dpr - (dx << 1); - p = dpr - dx; - - while (dx-- >= 0) { - - copyLine(x1, y1, xx, yy, nwidth, image->format, dst, &src); - - /* calc next step */ - - if (p > 0) { - x1 += xi; - y1 += yi; - xx += xi; - yy += yi; - p += dpru; - } else { - x1 += xi; - xx += xi; - p += dpr; - } - } - } else { - puts("NOT IMPLEMTENED"); - return img; - dpr = dx << 1; - dpru = dpr - (dy << 1); - p = dpr - dy; - - while (dy-- >= 0) { - xx = abs(x1*sin(angle*PI/180.0)); - yy = abs(y1*cos(angle*PI/180.0)); - - copyLine(x1, y1, xx, yy, nwidth, image->format, dst, &src); - - /* calc next step*/ - if (p > 0) { - x1 += xi; - y1 += yi; - p += dpru; - } else { - y1 += yi; - p += dpr; - } - } - } - - return img; -} - +/* rotate.c - image rotation + * + * Raster graphics library + * + * Copyright (c) 2000-2003 Alfredo K. Kojima + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include +#include +#include +#include +#include "wraster.h" + +#include + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + +static RImage *rotateImage(RImage * image, float angle); + +RImage *RRotateImage(RImage * image, float angle) +{ + RImage *img; + int nwidth, nheight; + int x, y; + int bpp = image->format == RRGBAFormat ? 4 : 3; + + angle = ((int)angle % 360) + (angle - (int)angle); + + if (angle == 0.0) { + return RCloneImage(image); + + } else if (angle == 90.0) { + nwidth = image->height; + nheight = image->width; + + img = RCreateImage(nwidth, nheight, True); + if (!img) { + return NULL; + } + + if (bpp == 3) { + unsigned char *optr, *nptr; + unsigned offs; + + offs = nwidth * 4; + + optr = image->data; + nptr = img->data; + + for (x = 0; x < nwidth; x++) { + nptr = img->data + x * 4; + for (y = nheight; y; y--) { + nptr[0] = *optr++; + nptr[1] = *optr++; + nptr[2] = *optr++; + nptr[3] = 255; + + nptr += offs; + } + } + } else { + unsigned *optr, *nptr; + unsigned *p; + + optr = (unsigned *)image->data; + p = (unsigned *)img->data; + for (x = 0; x < nwidth; x++) { + nptr = p++; + for (y = nheight; y; y--) { + *nptr = *optr++; + nptr += nwidth; + } + } + } + } else if (angle == 180.0) { + + nwidth = image->width; + nheight = image->height; + img = RCreateImage(nwidth, nheight, True); + if (!img) { + return NULL; + } + + if (bpp == 3) { + unsigned char *optr, *nptr; + + optr = image->data; + nptr = img->data + nwidth * nheight * 4 - 4; + + for (y = 0; y < nheight; y++) { + for (x = 0; x < nwidth; x++) { + nptr[0] = optr[0]; + nptr[1] = optr[1]; + nptr[2] = optr[2]; + nptr[3] = 255; + + optr += 3; + nptr -= 4; + } + } + } else { + unsigned *optr, *nptr; + + optr = (unsigned *)image->data; + nptr = (unsigned *)img->data + nwidth * nheight - 1; + + for (y = nheight * nwidth - 1; y >= 0; y--) { + *nptr = *optr; + optr++; + nptr--; + } + } + } else if (angle == 270.0) { + nwidth = image->height; + nheight = image->width; + + img = RCreateImage(nwidth, nheight, True); + if (!img) { + return NULL; + } + + if (bpp == 3) { + unsigned char *optr, *nptr; + unsigned offs; + + offs = nwidth * 4; + + optr = image->data; + nptr = img->data; + + for (x = 0; x < nwidth; x++) { + nptr = img->data + x * 4; + for (y = nheight; y; y--) { + nptr[0] = *optr++; + nptr[1] = *optr++; + nptr[2] = *optr++; + nptr[3] = 255; + + nptr += offs; + } + } + } else { + unsigned *optr, *nptr; + unsigned *p; + + optr = (unsigned *)image->data; + p = (unsigned *)img->data + nwidth * nheight; + for (x = 0; x < nwidth; x++) { + nptr = p--; + for (y = nheight; y; y--) { + *nptr = *optr++; + nptr -= nwidth; + } + } + } + } else { + img = rotateImage(image, angle); + } + + return img; +} + +/* + * Image rotation through Bresenham's line algorithm: + * + * If a square must be rotate by angle a, like in: + * _______ + * | B | + * | /4\ | + * | /3 8\| + * | /2 7 /| + * |A1 6 / | A_______B + * | \5 / a| <--- |1 2 3 4| + * |__C/_)_| |5 6 7 8| + * C------- + * + * for each point P1 in the line from C to A + * for each point P2 in the perpendicular line starting at P1 + * get pixel from the source and plot at P2 + * increment pixel location from source + * + */ + +static void +copyLine(int x1, int y1, int x2, int y2, int nwidth, int format, unsigned char *dst, unsigned char **src) +{ + unsigned char *s = *src; + int dx, dy; + int xi, yi; + int offset; + int dpr, dpru, p; + + dx = abs(x2 - x1); + dy = abs(y2 - y1); + + if (x1 > x2) + xi = -1; + else + xi = 1; + if (y1 > y2) + yi = -1; + else + yi = 1; + + if (dx >= dy) { + + dpr = dy << 1; + dpru = dpr - (dx << 1); + p = dpr - dx; + + while (dx-- >= 0) { + /* fetch and draw the pixel */ + offset = (x1 + y1 * nwidth) << 2; + dst[offset++] = *s++; + dst[offset++] = *s++; + dst[offset++] = *s++; + if (format == RRGBAFormat) + dst[offset++] = *s++; + else + dst[offset++] = 255; + + /* calc next step */ + if (p > 0) { + x1 += xi; + y1 += yi; + p += dpru; + } else { + x1 += xi; + p += dpr; + } + } + } else { + + dpr = dx << 1; + dpru = dpr - (dy << 1); + p = dpr - dy; + + while (dy-- >= 0) { + /* fetch and draw the pixel */ + offset = (x1 + y1 * nwidth) << 2; + dst[offset++] = *s++; + dst[offset++] = *s++; + dst[offset++] = *s++; + if (format == RRGBAFormat) + dst[offset++] = *s++; + else + dst[offset++] = 255; + + /* calc next step */ + if (p > 0) { + x1 += xi; + y1 += yi; + p += dpru; + } else { + y1 += yi; + p += dpr; + } + } + } + + *src = s; +} + +static RImage *rotateImage(RImage * image, float angle) +{ + RImage *img; + int nwidth, nheight; + int x1, y1; + int x2, y2; + int dx, dy; + int xi, yi; + int xx, yy; + unsigned char *src, *dst; + int dpr, dpru, p; + + /* only 180o for now */ + if (angle > 180.0) + angle -= 180.0; + + angle = (angle * PI) / 180.0; + + nwidth = ceil(abs(cos(angle) * image->width)) + + ceil(abs(cos(PI / 2 - angle) * image->width)); + + nheight = ceil(abs(sin(angle) * image->height)) + + ceil(abs(cos(PI / 2 - angle) * image->height)); + + img = RCreateImage(nwidth, nheight, True); + if (!img) + return NULL; + + src = image->data; + dst = img->data; + + x1 = floor(abs(cos(PI / 2 - angle) * image->width)); + y1 = 0; + + x2 = 0; + y2 = floor(abs(sin(PI / 2 - angle) * image->width)); + + xx = floor(abs(cos(angle) * image->height)) - 1; + yy = nheight - 1; + + printf("%ix%i, %i %i %i %i %i\n", nwidth, nheight, x1, y1, x2, y2, (int)((angle * 180.0) / PI)); + + dx = abs(x2 - x1); + dy = abs(y2 - y1); + + if (x1 > x2) + xi = -1; + else + xi = 1; + if (y1 > y2) + yi = -1; + else + yi = 1; + + if (dx >= dy) { + dpr = dy << 1; + dpru = dpr - (dx << 1); + p = dpr - dx; + + while (dx-- >= 0) { + + copyLine(x1, y1, xx, yy, nwidth, image->format, dst, &src); + + /* calc next step */ + + if (p > 0) { + x1 += xi; + y1 += yi; + xx += xi; + yy += yi; + p += dpru; + } else { + x1 += xi; + xx += xi; + p += dpr; + } + } + } else { + puts("NOT IMPLEMTENED"); + return img; + dpr = dx << 1; + dpru = dpr - (dy << 1); + p = dpr - dy; + + while (dy-- >= 0) { + xx = abs(x1 * sin(angle * PI / 180.0)); + yy = abs(y1 * cos(angle * PI / 180.0)); + + copyLine(x1, y1, xx, yy, nwidth, image->format, dst, &src); + + /* calc next step */ + if (p > 0) { + x1 += xi; + y1 += yi; + p += dpru; + } else { + y1 += yi; + p += dpr; + } + } + } + + return img; +}