Warp \ Bend Effect on a Uiview

Warp \ bend effect on a UIView?

Sha,

What I did was to lay out a rectangular grid of points in my OpenGL coordinates. (I used a 50x50 grid). I then define one or more control points in that same coordinate space. I have a general pinch-stretch algorithm that I wrote. It takes a control point, a radius, and a signed integer for the amount to attract/repel grid points, and applies it to the coordinates of my grid. For a pinch, it pulls the grid points closer to the control point, and for a stretch, it pushes the control points away. The change is greatest at the control point and goes down as the distance from the control point increases up to the radius value.

Once I've changed the coordinates of my mesh, I then define a set of triangle strips that draws the entire (warped) rectangular area of my image. I can render my entire texture onto the warped mesh with one OpenGL drawing call. OpenGL takes care of stretching the image pixels to fit the distorted triangles in my mesh of control points. Here is a sample before/after image that uses several control points to create a fat-face look. It shows the mesh grid so you can see what it's doing. It's my ugly mug, so apologies in advance:

Sample Image

And the stretched image:

Sample Image

In my case I wanted the control points along the perimeter of the image to stay in place and only the interior of the image to be distorted, so I added extra code logic to lock the perimeter control points into place. That's why the frame of the image is not pushed in like in your image. That required extra code however.

The code ends up using the distance formula to figure out how far each grid-point is from a control point, and then trig to figure out the angle, multiplication to change the distance, and then more trig to calculate the new location for each grid-point. Since I'm only transforming a 50x50 grid of control points, though, its fast enough to keep up.

Our app, Face Dancer, is free on the app store. (Download it at this link: Face Dancer in the App store You might want to download it and try it out. (It includes a number of free morphs, and then offers additional morphs as in-app purchases) There is also a paid "Plus" version that has all the morphs included.

When you're running Face Dancer if you two finger double-tap on the image, it displays the grid of control points it's using to create the morph so you can see what it's doing.

There is an OpenGL sample app called GLCameraRipple that is included with Xcode and linked from the documentation. I would suggest taking a look at that as a starting point. It takes a video feed from the camera and draws it to the screen. If you touch the screen it distorts the image as if the screen were a pool of water and your finger was causing ripples in it. It uses a mesh warp technique like what I described.

Unfortunately I don't think the app uses GLKit, which is a much easier way to use OpenGL ES 2.0. GLKit offers a number of features that make it much easier to use, including GLKViews and GLKViewControllers.

iOS drag on UIView, cloth effect

There is an open source reimplementation of this already.

Sample Image

This blog post: Mesh Transforms covers the private CAMeshTransform. Rather than treating a CALayer as a simple quad, it allows CALayers to be turned into a mesh of connected faces. This class is how Apple has been able to implement the page curl and iBooks page turning effects.

Sample Image

However, the API doesn't tolerate malformed input at all well and Apple has kept it a private API.

If you keep reading that blog post though you'll come to this section just after the bit about it being private API.

In the spirit of CAMeshTransform I created a BCMeshTransform which copies almost every feature of the original class.

...

Without direct, public access to Core Animation render server I was forced to use OpenGL for my implementation. This is not a perfect solution as it introduces some drawbacks the original class didn’t have, but it seems to be the only currently available option.

In effect he renders the content view into an OpenGL texture and then displays that. This lets him mess around with it however he likes.

Including like this...

I encourage you to check out the demo app I made for BCMeshTransformView. It contains a few ideas of how a mesh transform can be used to enrich interaction, like my very simple, but functional take on that famous Dribbble.

What famous Dribbble? This one:

Sample Image

Here is what the example looks like:

Sample Image

Open source project: https://github.com/Ciechan/BCMeshTransformView

Example Implementation of the curtain effect: BCCurtainDemoViewController.m


How does it work?

It sets the BCMeshTransformView up with some lighting and perspective.

// From: https://github.com/Ciechan/BCMeshTransformView/blob/master/Demo/BCMeshTransformViewDemo/BCCurtainDemoViewController.m#L59
self.transformView.diffuseLightFactor = 0.5;

CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = -1.0/2000.0;
self.transformView.supplementaryTransform = perspective;

Then using a UIPanGestureRecognizer it tracks the touches and uses this method to build a new mesh transform every time the users finger moves.

// From: https://github.com/Ciechan/BCMeshTransformView/blob/master/Demo/BCMeshTransformViewDemo/BCCurtainDemoViewController.m#L91
self.transformView.meshTransform = [BCMutableMeshTransform curtainMeshTransformAtPoint:CGPointMake(point.x + self.surplus, point.y) boundsSize:self.transformView.bounds.size];

// From: https://github.com/Ciechan/BCMeshTransformView/blob/master/Demo/BCMeshTransformViewDemo/BCMeshTransform%2BDemoTransforms.m#L14
+ (instancetype)curtainMeshTransformAtPoint:(CGPoint)point boundsSize:(CGSize)boundsSize
{
const float Frills = 3;

point.x = MIN(point.x, boundsSize.width);

BCMutableMeshTransform *transform = [BCMutableMeshTransform identityMeshTransformWithNumberOfRows:20 numberOfColumns:50];

CGPoint np = CGPointMake(point.x/boundsSize.width, point.y/boundsSize.height);

[transform mapVerticesUsingBlock:^BCMeshVertex(BCMeshVertex vertex, NSUInteger vertexIndex) {
float dy = vertex.to.y - np.y;
float bend = 0.25f * (1.0f - expf(-dy * dy * 10.0f));

float x = vertex.to.x;

vertex.to.z = 0.1 + 0.1f * sin(-1.4f * cos(x * x * Frills * 2.0 * M_PI)) * (1.0 - np.x);
vertex.to.x = (vertex.to.x) * np.x + vertex.to.x * bend * (1.0 - np.x);

return vertex;
}];

return transform;
}

Image Bending transform in ios

Finally I've came to an end in this. Instead of going for Open GLES , I used the ImageMagick Library which was very helpful.

Also I found a bash script to warp the images in cylindrical shapes using ImageMagick C APIs.

Refer Cylinderize Script. Just thought that it might be usefull to someone. Cheers.

Make a see-through layer

All views have a "Backing layer", including UILabel views.

As such, you can install a mask layer on the view's layer. You can make that mask layer a CAShapeLayer, or a regular layer with a CGImage as it's contents.

Don't mess with blend modes. Just add a mask layer to any layer that you want to be able to erase/un-erase, including a UILabel's layer

The mask layer will show/hide the contents of the layer it masks. (Opaque pixels in the mask reveal the layer underneath, but clear pixels hide it.)

If you want to be able to do freehand erasing/revealing of things like labels, I would suggest using a layer with an image in it as your mask. Draw opaque pixels into the masks image to "un-erase" the masked image, and draw with clear pixels to erase the masked image. Because you're just changing the mask, the masked image is left untouched.

@IBOutlet label: UILabel
var labelMask = CALayer()

...

func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
// Set up the mask to be the same size as the label view
labelMask.frame = label.bounds
label.layer.mask = labelMask
labelMask.contents = // install a UIImage's CGImage as the contents
// The rest of your viewDidAppear code goes here...
}

Edit:

I posted a demo app on Github it that illustrates how to mask ANY view using a CALayer. This demo app uses a CGImage to create a raster mask. You can also use a CAShapeLayer as a vector mask.

Here is the readme from that project:



MaskableImageView

This project demonstrates how to use a CALayer to mask a UIView.

It defines a custom subclass of UIImageView, MaskableView.

The MaskableView class has a property maskLayer that contains a CALayer.

MaskableView defines a didSet method on its bounds property so that when the view's bounds change, it resizes the mask layer to match the size of the image view.

The MaskableView has a method installSampleMask which builds an image the same size as the image view, mostly filled with opaque black, but with a small rectangle in the center filled with black at an alpha of 0.7. The translucent center rectangle causes the image view to become partly transparent and show the view underneath.

The demo app installs a couple of subviews into the MaskableView, a sample image of Scampers, one of my dogs, and a UILabel. It also installs an image of a checkerboard under the MaskableView so that you can see the translucent parts more easily.

The MaskableView has properties circleRadius, maskDrawingAlpha, and drawingAction that it uses to let the user erase/un-erase the image by tapping on the view to update the mask.

The MaskableView attaches a UIPanGestureRecognizer and a UITapGestureRecognizer to itself, with an action of gestureRecognizerUpdate. The gestureRecognizerUpdate method takes the tap/drag location from the gesture recognizer and uses it to draw a circle onto the image mask that either decreases the image mask's alpha (to partly erase pixels) or increase the image mask's alpha (to make those pixels more opaque.)

The MaskableView's mask drawing is crude, and only meant for demonstration purposes. It draws a series of discrete circles intstead of rendering a path into the mask based on the user's drag gesture. A better solution would be to connect the points from the gesture recognizer and use them to render a smoothed curve into the mask.

The app's screen looks like this:

Sample Image



Related Topics



Leave a reply



Submit