/** * $Id:$ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * The contents of this file may be used under the terms of either the GNU * General Public License Version 2 or later (the "GPL", see * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or * later (the "BL", see http://www.blender.org/BL/ ) which has to be * bought from the Blender Foundation to become active, in which case the * above mentioned GPL option does not apply. * * The Original Code is Copyright (C) 2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ #include "imbuf.h" #define OBJECTBLOK "rotate" short _rot_crop = TRUE; void rotcrop(int val) { _rot_crop = val; } void flip270(struct ImBuf * ibuf) { struct ImBuf * tbuf; int x, y; uint * rect, *frect; int skip; if (ibuf == 0) return; if (ibuf->rect == 0) return; tbuf = allocImBuf(ibuf->y, ibuf->x, 32, 1, 0); if (tbuf == 0) return; rect = ibuf->rect; skip = ibuf->y; for (y = ibuf->y - 1; y >= 0; y--){ frect = tbuf->rect + y; for (x = ibuf->x; x > 0; x--){ *frect = *rect++; frect += skip; } } memcpy(ibuf->rect, tbuf->rect, ibuf->x * ibuf->y * sizeof(uint)); x = ibuf->x; ibuf->x = ibuf->y; ibuf->y = x; freeImBuf(tbuf); } void flip90(struct ImBuf * ibuf) { struct ImBuf * tbuf; int x, y; uint * rect, *frect; int skip; if (ibuf == 0) return; if (ibuf->rect == 0) return; tbuf = allocImBuf(ibuf->y, ibuf->x, 32, 1, 0); if (tbuf == 0) return; frect = tbuf->rect; skip = tbuf->y; for (y = tbuf->y - 1; y >= 0; y--){ rect = ibuf->rect + y; for (x = tbuf->x; x > 0; x--){ *frect++ = *rect; rect += skip; } } memcpy(ibuf->rect, tbuf->rect, ibuf->x * ibuf->y * sizeof(uint)); x = ibuf->x; ibuf->x = ibuf->y; ibuf->y = x; freeImBuf(tbuf); } void flipy(struct ImBuf * ibuf) { short x,y,backx; uint *top,*bottom,temp; if (ibuf == 0) return; if (ibuf->rect == 0) return; x = ibuf->x; y = ibuf->y; backx = x<<1; top = ibuf->rect; bottom = top + ((y-1) * x); y >>= 1; for(;y>0;y--){ for(x = ibuf->x; x > 0; x--){ temp = *top; *(top++) = *bottom; *(bottom++) = temp; } bottom -= backx; } } void flipx(struct ImBuf * ibuf) { short x, y, halfx; uint *left, *right, temp, leftadd, rightadd; if (ibuf == 0) return; if (ibuf->rect == 0) return; halfx = ibuf->x >> 1; left = ibuf->rect; right = left + ibuf->x - 1; leftadd = ibuf->x - halfx; rightadd = ibuf->x + halfx; for(y = ibuf->y; y > 0; y--){ for(x = halfx; x > 0; x--){ temp = *left; *(left++) = *right; *(right--) = temp; } left += leftadd; right += rightadd; } } void scroll(ibuf,offs,dir) struct ImBuf *ibuf; short offs,dir; { uchar *point; int size; size = (ibuf->x*ibuf->y)-1; point = (uchar *)ibuf->rect; point += offs; if (dir>0){ point += size<<2; for(;size>0;size--){ point[4] = point[0]; point -= 4; } } else{ for(;size>0;size--){ point[0] = point[4]; point += 4; } } } void cropibuf(struct ImBuf * ibuf) { int x, y, found, step, and; short x1, y1, x2, y2; uint *rect; struct ImBuf tbuf; extern void rectcpy(); if (ibuf == 0) return; if (ibuf->rect == 0) return; rect = ibuf->rect; found = FALSE; for (y = 0; yy ; y++){ for (x = ibuf->x; x>0; x--){ if (*rect++) { found = TRUE; break; } } if (found) break; } if (found == FALSE){ ibuf->x = 1; ibuf->y = 1; return; } y1 = y; rect = ibuf->rect; rect += ibuf->x * ibuf->y - 1; found = FALSE; for (y = ibuf->y - 1; y >= 0 ; y--){ for (x = ibuf->x; x>0; x--){ if (*rect--) { found = TRUE; break; } } if (found) break; } y2 = y; step = ibuf->x; found = FALSE; for (x = 0; x < ibuf->x ; x++){ rect = ibuf->rect + x; for (y = ibuf->y; y > 0; y--){ if (*rect) { found = TRUE; break; } rect += step; } if (found) break; } x1 = x; step = ibuf->x; found = FALSE; for (x = ibuf->x - 1; x > 0; x--){ rect = ibuf->rect + x; for (y = ibuf->y; y > 0; y--){ if (*rect) { found = TRUE; break; } rect += step; } if (found) break; } x2 = x; /* dit moet veilig gaan */ tbuf = *ibuf; tbuf.x = x2 - x1 + 1; tbuf.y = y2 - y1 + 1; rectop(&tbuf, ibuf, 0, 0, x1, y1, 32767, 32767, rectcpy); ibuf->x = tbuf.x; ibuf->y = tbuf.y; ibuf->xorig += x1; ibuf->yorig += y1; } #define MINSHDIST 0.001 void shearx(struct ImBuf *ibuf, float dist) { struct ImBuf *tbuf; uchar *srect, *drect; int x, y; float w1, w2, tdist; float a, b, g, r, la, lb, lg, lr; extern void rectfill(); if (ibuf == 0) return; if (ibuf->rect == 0) return; tdist = fabsf(dist * ibuf->y); if (tdist < MINSHDIST) return; tbuf = allocImBuf(ibuf->x + 1 + tdist, ibuf->y, 32, 1, 0); rectoptot(tbuf, 0, rectfill, 0); if (tbuf == 0) return; if (dist > 0) tdist = 0.0; for (y = 0; y < ibuf->y; y++){ srect = (uchar *) (ibuf->rect + y * ibuf->x); drect = (uchar *) (tbuf->rect + y * tbuf->x); drect += ((int) tdist) * sizeof(uint); w1 = tdist - floorf(tdist); tdist += dist; if (w1 <= MINSHDIST) { memcpy(drect, srect, ibuf->x * sizeof(uint)); } else if ( w1 >= 1.0 - MINSHDIST) { memcpy(drect + sizeof(uint), srect, ibuf->x * sizeof(uint)); } else { w2 = 1.0 - w1; la = lb = lg = lr = 0.0; for (x = ibuf->x; x > 0; x--){ a = srect[0]; b = srect[1]; g = srect[2]; r = srect[3]; drect[0] = (w1 * la) + (w2 * a) + 0.5; drect[1] = (w1 * lb) + (w2 * b) + 0.5; drect[2] = (w1 * lg) + (w2 * g) + 0.5; drect[3] = (w1 * lr) + (w2 * r) + 0.5; srect += 4; drect += 4; la = a; lb = b; lg = g; lr = r; } drect[0] = (w1 * la) + 0.5; drect[1] = (w1 * lb) + 0.5; drect[2] = (w1 * lg) + 0.5; drect[3] = (w1 * lr) + 0.5; } } freerectImBuf(ibuf); ibuf->mall |= IB_rect; ibuf->rect = tbuf->rect; tbuf->rect = 0; ibuf->x = tbuf->x; freeImBuf(tbuf); } void rotibuf(struct ImBuf *ibuf, double angle) { angle = fmodf(angle, 360.0); if (angle < 0) angle = 360.0 + angle; if (angle < 45.0) { /* do nothing */ } else if (angle < 135.0) { flip90(ibuf); angle -= 90; } else if (angle < 225.0) { flipx(ibuf); flipy(ibuf); angle -= 180; } else if (angle < 315.0) { flip270(ibuf); angle -= 270; } else angle = angle - 360; angle = angle * M_PI / 180.0; shearx(ibuf, -tan(angle / 2.0)); flip270(ibuf); shearx(ibuf, -sin(angle)); flip90(ibuf); shearx(ibuf, -tan(angle / 2.0)); if (_rot_crop) cropibuf(ibuf); }