Robert Bob Gumptingham wrote: >But I have been doing further testing. While the FN CubicBSpline does >result in some overhead, the primary cycle wasters are the checks I am >doing to make sure I don't go peeking and poking out of bounds. Comment >these out, and the thing flies along. Threadsters: I combined the three channels into a onetime pass, computation wise.. don't know why I didn't see it earlier, probably fixated on the original port's approach before I changed that. Still slow, but now lots faster compared to the original. Wiped out two out of bounds checks for the G and B channels. I think I can apply an RP special byte computer for the pixel addresses and whack some more slothness. One cool thing...my bilinear is near identical to Photoshop quality >:) They seem to be using some half-pixel offset of the pixel centers though. I will write Adobe for the source code of their bicubic rotation, to save time. Surely they will respond. <g> But I stomp the venerable Graphic Converter's rotation routines for speed with no discernable difference in quality there either, at least for v3.8.2. Might have changed since. We talking 18 seconds for GC, 2.5 for me on test image. :) Wahooo, its another grand graphics day. Below is altered current incarnation of the slothly bicubic. Robert Covington // FB 3 LOCAL FN CubicBSpline#(x as double) DIM && DIM as single y, y2, y3, result result=0 LONG IF x < 0 y = -x Xelse y = x END IF y2=y*y y3=y2*y Long if y <= 1.0 result = ( 2.0/3.0 + 0.5 * y3 - y2) Xelse LONG IF y <= 2.0 result=1.0/6.0*(2-y)*(2-y)*(2-y) END IF END IF END FN = result LOCAL FN ArbitraryBicubisaurus(angle as double) DIM && DIM as double a,b,xsize,ysize DIM as double newfX, newfY DIM as double sinTheta, cosTheta, rads,Xmid, Ymid DIM as double cubsum, sumR, sumG, sumB DIM as long newIndex,val1, val2, val3, val4,index,imageval DIM @tmpWorld as long, @tmpDevice as long DIM as int yy,xx,newX,newY,m,n', Xmid, Ymid DIM as int rr,gg,bb DIM tX as int DIM tY as int DIm as int offsetX, offsetY angle = -angle FN Make_Progress_Wnd(_bicubic,"") Cursor _watchCursor rads = 3.141592/180*angle sinTheta = sin(rads) cosTheta = cos(rads) xsize = gRect.right-gRect.left ysize = gRect.bottom-gRect.top Xmid = .5*xsize Ymid = .5*ysize tX = gRect.right-1 tY = gRect.bottom-1 FOR yy = 0 TO tY FOR xx = 0 TO tX newfX = (xx-Xmid)*cosTheta - (yy-Ymid)*sinTheta +Xmid newX = newfX newfY = (xx-Xmid)*sinTheta + (yy-Ymid)*cosTheta +Ymid newY = newfY LONG IF newX <= tX AND newX >= 0 LONG IF newY <= tY AND newY >= 0 a = newfX-newX b = newfY-newY newIndex = gBaseAddr + (yy * gRowBytes) + (xx*4) a = abs(a) b = Abs(b) sumR = 0 sumG = 0 sumB = 0 FOR m = -1 TO 2 FOR n = -1 TO 2 LONG IF ((newx+m >= 0) AND (newx+m <= xsize-1)) LONG IF ((newy+n >=0) AND (newy+n <= ysize-1)) imageval = gCopyAddr + ((newy+n) * gCopyBytes) + ((newx+m)*4) XElse imageval = gCopyAddr + (newy * gCopyBytes) + (newx*4) END IF XElse imageval = gCopyAddr + ((newy+m) * gCopyBytes) + (newx*4) END IF cubsum = FN CubicBSpline#(-a+m)*FN CubicBSpline#(-b+n) sumR = sumR + (PEEK(imageval+1))*cubsum sumG = sumG + (PEEK(imageval+2))*cubsum sumB = sumB + (PEEK(imageval+3))*cubsum Next n NEXT m rr = INT(sumR) gg = INT(sumG) bb = INT(sumB) Poke newIndex + 1, rr Poke newIndex + 2, gg Poke newIndex + 3, bb END IF END IF NEXT xx FN Update_Progress_Wnd( yy/tY) NEXT yy FN Close_Progress_Wnd Cursor _arrowCursor END FN