Closed kdbanman closed 8 years ago
#define C_PI 3.141592653589793238462643383279502884197169399375 void CImageProcessor::Swirl(Bitmap * pBitmap, double factor) { // This function effectively swirls an image int width = pBitmap->GetWidth(); int height = pBitmap->GetHeight(); double cX = (double)width/2.0f; double cY = (double)height/2.0f; BitmapData bitmapData; pBitmap->LockBits(&Rect(0,0,pBitmap->GetWidth(), pBitmap->GetHeight()), ImageLockModeWrite, PixelFormat32bppARGB, &bitmapData); unsigned int *pRawBitmapOrig = (unsigned int*)bitmapData.Scan0; // for easy access and indexing unsigned int *pBitmapCopy = new unsigned int[bitmapData.Stride*height/4]; memcpy(pBitmapCopy, pRawBitmapOrig, (bitmapData.Stride*height/4) * sizeof(unsigned int)); int nPixels = height*bitmapData.Stride/4; #pragma omp parallel for for (int i=0; i < height; i++) { double relY = cY-i; for (int j=0; j < width; j++) { double relX = j-cX; // relX and relY are points in our UV space // Calculate the angle our points are relative to UV origin. Everything is in radians. double originalAngle; if (relX != 0) { originalAngle = atan(abs(relY)/abs(relX)); if ( relX > 0 && relY < 0) originalAngle = 2.0f*C_PI - originalAngle; else if (relX <= 0 && relY >=0) originalAngle = C_PI-originalAngle; else if (relX <=0 && relY <0) originalAngle += C_PI; } else { // Take care of rare special case if (relY >= 0) originalAngle = 0.5f * C_PI; else originalAngle = 1.5f * C_PI; } // Calculate the distance from the center of the UV using pythagorean distance double radius = sqrt(relX*relX + relY*relY); // Use any equation we want to determine how much to rotate image by //double newAngle = originalAngle + factor*radius; // a progressive twist double newAngle = originalAngle + 1/(factor*radius+(4.0f/C_PI)); // Transform source UV coordinates back into bitmap coordinates int srcX = (int)(floor(radius * cos(newAngle)+0.5f)); int srcY = (int)(floor(radius * sin(newAngle)+0.5f)); srcX += cX; srcY += cY; srcY = height - srcY; // Clamp the source to legal image pixel if (srcX < 0) srcX = 0; else if (srcX >= width) srcX = width-1; if (srcY < 0) srcY = 0; else if (srcY >= height) srcY = height-1; // Set the pixel color pRawBitmapOrig[i*bitmapData.Stride/4 + j] = pBitmapCopy[srcY*bitmapData.Stride/4 + srcX]; } } delete[] pBitmapCopy; pBitmap->UnlockBits(&bitmapData); }
public class RotationGestureDetector { private static final int INVALID_POINTER_ID = -1; private float fX, fY, sX, sY; private int ptrID1, ptrID2; private float mAngle; private OnRotationGestureListener mListener; public float getAngle() { return mAngle; } public RotationGestureDetector(OnRotationGestureListener listener){ mListener = listener; ptrID1 = INVALID_POINTER_ID; ptrID2 = INVALID_POINTER_ID; } public boolean onTouchEvent(MotionEvent event){ switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: ptrID1 = event.getPointerId(event.getActionIndex()); break; case MotionEvent.ACTION_POINTER_DOWN: ptrID2 = event.getPointerId(event.getActionIndex()); sX = event.getX(event.findPointerIndex(ptrID1)); sY = event.getY(event.findPointerIndex(ptrID1)); fX = event.getX(event.findPointerIndex(ptrID2)); fY = event.getY(event.findPointerIndex(ptrID2)); break; case MotionEvent.ACTION_MOVE: if(ptrID1 != INVALID_POINTER_ID && ptrID2 != INVALID_POINTER_ID){ float nfX, nfY, nsX, nsY; nsX = event.getX(event.findPointerIndex(ptrID1)); nsY = event.getY(event.findPointerIndex(ptrID1)); nfX = event.getX(event.findPointerIndex(ptrID2)); nfY = event.getY(event.findPointerIndex(ptrID2)); mAngle = angleBetweenLines(fX, fY, sX, sY, nfX, nfY, nsX, nsY); if (mListener != null) { mListener.OnRotation(this); } } break; case MotionEvent.ACTION_UP: ptrID1 = INVALID_POINTER_ID; break; case MotionEvent.ACTION_POINTER_UP: ptrID2 = INVALID_POINTER_ID; break; case MotionEvent.ACTION_CANCEL: ptrID1 = INVALID_POINTER_ID; ptrID2 = INVALID_POINTER_ID; break; } return true; } private float angleBetweenLines (float fX, float fY, float sX, float sY, float nfX, float nfY, float nsX, float nsY) { float angle1 = (float) Math.atan2( (fY - sY), (fX - sX) ); float angle2 = (float) Math.atan2( (nfY - nsY), (nfX - nsX) ); float angle = ((float)Math.toDegrees(angle1 - angle2)) % 360; if (angle < -180.f) angle += 360.0f; if (angle > 180.f) angle -= 360.0f; return angle; } public static interface OnRotationGestureListener { public void OnRotation(RotationGestureDetector rotationDetector); } }
dissecting other's code is hard.. I'm doing the rotation myself.
Swirl code
Finger rotation code