How to convert a point to a device point with GPUImageView? - ios

I want to use the instance method "-captureDevicePointOfInterestForPoint:" of AVCaptureVideoPreviewLayer, but the project uses GPUImageView instead of AVCaptureVideoPreviewLayer.
Is there any way to convert a point to a device point with GPUImageView?

You can achieve it with two steps:
Convert coordinates from OpenGL to GPUImageView.
Convert coordinates from GPUImageView to other UIView or to a device by using UIView's methods.
OpenGL in GPUImage has next coordinate system: X: [-1.0, 1.0] (from left to right), Y: [-1.0, 1.0] (from bottom, to top).
We can get next affine transform to convert point from OpenGL to GPUImageView:
//self is GPUImageView
CGAffineTransform moveToPositive = CGAffineTransformMakeTranslation(1.0, 1.0);
CGAffineTransform normolizeTransform = CGAffineTransformMakeScale(1.0 / 2.0, 1.0 / 2.0);
CGAffineTransform invertion = CGAffineTransformConcat(CGAffineTransformMakeScale(1.0, -1.0), CGAffineTransformMakeTranslation(0.0, 1.0));
CGAffineTransform scaleToSelfBounds = CGAffineTransformMakeScale(CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds));
CGAffineTransform resultTransform = CGAffineTransformConcat(CGAffineTransformConcat(CGAffineTransformConcat(moveToPositive, normolizeTransform), invertion), scaleToSelfBounds);
You can use this transformation to convert points from OpenGL to GPUImageView.

Related

Changing the CALayer anchor point

Changing the anchor point of a CALayer after a CATransform3dRotate gives weird results. I think the problem is, anchorPoint property is set on the previous state (no transform) of layer not the current state (after transform) of the layer.
Is there a way to change the anchorPoint of a CALayer's current state??
Code for Transform:
CATransform3D transform = CATransform3DIdentity;
transform.m34 = -(1.0/800.0);
videoPlayerView.layer.zPosition = 100;
videoPlayerView.layer.transform = CATransform3DRotate(transform, (30*M_PI)/180, 1.0f, 0.0f, 0.0f);
Code to change the anchor Point
if(videoPlayerView.layer.anchorPoint.x != 0.0)
{
videoPlayerView.layer.anchorPoint = CGPointMake(0.0, 0.5);
videoPlayerView.layer.position = CGPointMake(videoPlayerView.layer.frame.origin.x - videoPlayerView.layer.frame.size.width/2,videoPlayerView.layer.position.y);
}
Basically, I have to rotate the Layer like a book flip. I have already done this without using the 30 degree transofrm, but I want it to look more 3D so applied the 30 degree transform along the x axis. So that it looks like the book is placed on a table.
And in order to rotate, setting the anchor point is necessary. If not, please advice otherwise...
instead of changing anchorPoint use
CATransform3DTranslate(transform, 50.0000f, 0.0000f, 0.0000f);
Translate along X by 50.00 points
Apply 0.40 percent of perspective or you can use the same code you are using right now
rotate the CAlayer using Y .
CATransform3D transform = CATransform3DIdentity;
CATransform3D tmp = CATransform3DIdentity;
transform = CATransform3DRotate(transform, 0.0146f, 0, 1, 0);
transform = CATransform3DTranslate(transform, 50.0000f, 0.0000f, 0.0000f);
tmp = CATransform3DIdentity;
tmp.m34 = 0.0040f;
transform = CATransform3DConcat(transform, tmp);
check the link for more reference.
let me know if it works.

CGAffineTransform MakeScale resulting in black screen?

Trying to flip a UIImageView with scaling it to -1.0 but it results in a black screen. Scaling with 1.0, 1.0 shows results as expected.
Here's my code:
UIImageView *vImg = [[UIImageView alloc] initWithImage:finalImg];
CGAffineTransform transform = CGAffineTransformMakeScale(-1.0, 1.0);
[vImg setTransform:transform];
What am I missing?
A quick all-in-one solution exists in UIImage:
- (id)initWithCGImage:(CGImageRef)imageRef scale:(CGFloat)scale orientation:(UIImageOrientation)orientation;
with one of the UIImageOrientation*Mirrored orientations.
EDIT: IIRC the prepended translation is only required for low-level drawRect due to the different coordinates system, so the scale transform alone should be fine. Are you sure the bug doesn't lie elsewhere?

Combining a UIView perspective transform with other CATranform3Ds

I'm writing an app such that sprites (subclasses of UIImageView) can be rotated, resized, and panned across the screen using gestures. I also would like to be able to apply a 3D perspective transformation to the sprites.
I have the rotate/resize/pan functionality working correctly, as well as the perspective transform. However, they don't seem to work together correctly. If I rotate an unmodified sprite, then try to skew it, the sprite 'resets' it's rotation, then applies the perspective. The opposite works though; if I skew first, I can apply any 2D transformation after without it resetting.
Here is the code I'm using: (rotate, resize, and pan are done using UIGestureRecognizers, whereas the skew uses a UISlider).
Rotate:
- (void)didRotateSprite:(UIRotationGestureRecognizer *)rotate
{
CGFloat angle = rotate.rotation;
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DRotate(spriteView.layer.transform, angle, 0, 0, 1);
spriteView.layer.transform = transform;
rotate.rotation = 0.0;
}
Resize:
- (void)didPinchSprite:(UIPinchGestureRecognizer *)pinch
{
CGFloat scale = pinch.scale;
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DScale(spriteView.layer.transform, scale, scale, 1);
view.layer.transform = transform;
pinch.scale = 1.0;
}
Perspective:
- (IBAction)perspectiveChanged:(UISlider *)slider
{
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0 / -100;
transform = CATransform3DRotate(transform, (1 - (slider.value * 2)) * M_PI_2, 1, 0, 0);
spriteView.layer.transform = transform;
}
Thank you!
Found the answer with a lot of debugging and the help of this question. The trick was to transform the view's perspective using:
spriteView.superview.layer.sublayerTransform = transform;
This recursively applies the transformation to the view's superview and any subviews contained in it. For more information about this, check out the documentation and Apple's Layer Style Properties guide too.

How to rotate a CAShapeLayer at its center point

I have made a CAShapeLayer with few points by setting its stroke color to red . Then i have filled the color with a pattern of an UIImage. I want to rotate that CAShapeLayer along with its filled pattern using UIRotationGestureRecognizer.
I have used CATransform3DRotate but it is not working properly.
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DRotate(transform, recognizer.rotation, 0.0, 0.0, 1.0);
shapeLayer.transform = transform;
Thanks in advance
You'll want to call:
shapeLayer.anchorPoint = (CGPoint){0.5, 0.5};
You're also starting with the identity transform, which throws away any transformations you've done before, like positioning the layer. What you want to do is:
shapeLayer.transform = CATransform3DRotate(shapeLayer.transform, recognizer.rotation, 0.0, 0.0, 1.0);

Transform of UIImageView.layer affects UIScrollView zoomScale

I have a UIImageView that is in a UIScrollView. I load images into the UIImageView's CALayer with the following code:
UIImage *image = [UIImage imageNamed: fileToDisplay];
NSLog(#"If I don't flip image imageScrollView.zoomScale: %f", imageScrollView.zoomScale);
[[imageView layer] setContents: (id)image.CGImage];
if (flipped)
{
[[imageView layer] setTransform: CATransform3DMakeRotation(180.0 / 180.0 * M_PI, 0.0, 1.0, 0.0)];
NSLog(#"If image flipped imageScrollView.zoomScale: %f", imageScrollView.zoomScale);
}
I am 'flipping' the image about the y axis. The unexpected event is that the transformation of the imageView.layer is changing the imageScrollView.zoomScale as shown in the following output:
If I don't flip image imageScrollView.zoomScale: 0.465455
If image flipped imageScrollView.zoomScale: 1.000000
My question is how do I make this not happen? If there is no way to do defeat this behavior, what do I have to do to achieve the image framing that is performed on images I do not flip. In other words just setting the zoomScale to what it was prior to the transform does not work. Something else has changed in the UIScrollView (not the contentSize or the contentOffset).
Thanks for the help.
Because you're using a CATransform3DMake... method, you're creating a new transform and replacing the current transform. You need to use CATransform3DRotate instead, to add the rotation to the current transform (which is used for the scale).
imageView.layer.transform = CATransform3DRotate(imageView.layer.transform , 180.0 / 180.0 * M_PI, 0.0, 1.0, 0.0);

Resources