diff --git a/pipi/Makefile.am b/pipi/Makefile.am index 0d06c2c..8945743 100644 --- a/pipi/Makefile.am +++ b/pipi/Makefile.am @@ -70,6 +70,7 @@ filter_sources = \ filter/blur.c \ filter/convolution.c \ filter/color.c \ + filter/rotate.c \ filter/transform.c \ filter/median.c \ filter/dilate.c \ diff --git a/pipi/context.c b/pipi/context.c index 9b3996c..b31b683 100644 --- a/pipi/context.c +++ b/pipi/context.c @@ -71,6 +71,7 @@ pipi_command_t const *pipi_get_command_list(void) { "rotate90", 0 }, { "rotate180", 0 }, { "rotate270", 0 }, + { "rotate", 1 }, { "invert", 0 }, { "threshold", 1 }, { "dilate", 0 }, @@ -350,7 +351,7 @@ int pipi_command(pipi_context_t *ctx, char const *cmd, ...) pipi_free(tmp); } else if(!strcmp(cmd, "brightness") || !strcmp(cmd, "contrast") - || !strcmp(cmd, "threshold")) + || !strcmp(cmd, "threshold") || !strcmp(cmd, "rotate")) { pipi_image_t *src, *dst = NULL; char const *arg; @@ -368,6 +369,7 @@ int pipi_command(pipi_context_t *ctx, char const *cmd, ...) { case 'b': dst = pipi_brightness(src, val); break; case 'c': dst = pipi_contrast(src, val); break; + case 'r': dst = pipi_rotate(src, val); break; case 't': dst = pipi_threshold(src, val); break; } if(dst == NULL) diff --git a/pipi/filter/rotate.c b/pipi/filter/rotate.c new file mode 100644 index 0000000..af1d23a --- /dev/null +++ b/pipi/filter/rotate.c @@ -0,0 +1,100 @@ +/* + * libpipi Pathetic image processing interface library + * Copyright (c) 2004-2008 Sam Hocevar + * All Rights Reserved + * + * $Id$ + * + * This library is free software. It comes without any warranty, to + * the extent permitted by applicable law. You can redistribute it + * and/or modify it under the terms of the Do What The Fuck You Want + * To Public License, Version 2, as published by Sam Hocevar. See + * http://sam.zoy.org/wtfpl/COPYING for more details. + */ + +/* + * wave.c: wave and other warping effects + */ + +#include "config.h" + +#include +#include +#include +#include +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif + +#include "pipi.h" +#include "pipi_internals.h" + +pipi_image_t *pipi_rotate(pipi_image_t *src, double a) +{ + pipi_image_t *dst; + pipi_pixels_t *srcp, *dstp; + float *srcdata, *dstdata; + double sina, cosa, cx, cy; + int x, y, w, h, i, gray; + + w = src->w; + h = src->h; + + gray = (src->last_modified == PIPI_PIXELS_Y_F32); + + srcp = gray ? pipi_get_pixels(src, PIPI_PIXELS_Y_F32) + : pipi_get_pixels(src, PIPI_PIXELS_RGBA_F32); + srcdata = (float *)srcp->pixels; + + dst = pipi_new(w, h); + dstp = gray ? pipi_get_pixels(dst, PIPI_PIXELS_Y_F32) + : pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32); + dstdata = (float *)dstp->pixels; + + sina = sin(a * M_PI / 180.0); + cosa = cos(a * M_PI / 180.0); + + cx = (double)w / 2.0; + cy = (double)h / 2.0; + + for(y = 0; y < h; y++) + { + for(x = 0; x < w; x++) + { + double dx, dy; + int x2, y2; + + dx = ((double)x - cx) * cosa - ((double)y - cy) * sina; + dy = ((double)y - cy) * cosa + ((double)x - cx) * sina; + + x2 = (int)(cx + dx + 0.5); + y2 = (int)(cy + dy + 0.5); + + if(gray) + { + if(x2 < 0 || y2 < 0 || x2 >= w || y2 >= h) + ; + else + dstdata[y * w + x] = srcdata[y2 * w + x2]; + } + else + { + if(x2 < 0 || y2 < 0 || x2 >= w || y2 >= h) + { + dstdata[4 * (y * w + x) + 3] = 0.0f; + } + else + { + for(i = 0; i < 4; i++) + { + dstdata[4 * (y * w + x) + i] + = srcdata[4 * (y2 * w + x2) + i]; + } + } + } + } + } + + return dst; +} + diff --git a/pipi/pipi.h b/pipi/pipi.h index 16ce6f9..f2cb306 100644 --- a/pipi/pipi.h +++ b/pipi/pipi.h @@ -192,6 +192,7 @@ __extern pipi_image_t *pipi_invert(pipi_image_t *); __extern pipi_image_t *pipi_threshold(pipi_image_t *, double); __extern pipi_image_t *pipi_hflip(pipi_image_t *); __extern pipi_image_t *pipi_vflip(pipi_image_t *); +__extern pipi_image_t *pipi_rotate(pipi_image_t *, double); __extern pipi_image_t *pipi_rotate90(pipi_image_t *); __extern pipi_image_t *pipi_rotate180(pipi_image_t *); __extern pipi_image_t *pipi_rotate270(pipi_image_t *);