简体   繁体   English

CGContext-缩放,然后在点处裁剪图像

[英]CGContext - scale and then crop image at point

Similar to Instagram I have a square crop view (UIScrollView) that has a UIImageView inside it. 类似于Instagram,我有一个方形的裁剪视图(UIScrollView),其中有一个UIImageView。 So the user can drag a portrait or landscape image inside the square rect (equal to the width of the screen) and then the image should be cropped at the scroll offset. 因此,用户可以在方形矩形(等于屏幕的宽度)内拖动人像或风景图像,然后应在滚动偏移处裁剪图像。 The UIImageView is set to aspect fit. UIImageView设置为适合方面。 The UIScrollView content size is set to a scale factor for either landscape or portrait, so that it correctly renders with aspect fit ratio. 将UIScrollView内容大小设置为横向或纵向的比例因子,以便以纵横比正确显示。

When the user is done dragging I want to scale the image up based on a given size, let's say 1000x1000px square and then crop it at the scroll offset (using [UIImage drawAtPoint:CGPoint]. 当用户完成拖动后,我想根据给定的尺寸放大图像,假设为1000x1000px正方形,然后在滚动偏移处裁剪(使用[UIImage drawAtPoint:CGPoint]。

The problem is I can't get the math right to get the right offset point. 问题是我无法正确计算数学来获得正确的偏移点。 If I get it close on a 6+ it will be way off on a 4S. 如果我在6+上接近它,那在4S上将会遥遥无期。

Here's my code for the scale and crop: 这是我的缩放和裁剪代码:

(UIImage *)squareImageFromImage:(UIImage *)image scaledToSize:(CGFloat)newSize {
CGAffineTransform scaleTransform;
CGPoint origin;

if (image.size.width > image.size.height) {
    //landscape
    CGFloat scaleRatio = newSize / image.size.height;
    scaleTransform = CGAffineTransformMakeScale(scaleRatio, scaleRatio);
    origin = CGPointMake((int)(-self.scrollView.contentOffset.x*scaleRatio),0);
} else if (image.size.width < image.size.height) {
    //portrait
    CGFloat scaleRatio = newSize / image.size.width;
    scaleTransform = CGAffineTransformMakeScale(scaleRatio, scaleRatio);
    origin = CGPointMake(0, (int)(-self.scrollView.contentOffset.y*scaleRatio));
} else {
    //square
    CGFloat scaleRatio = newSize / image.size.width;
    scaleTransform = CGAffineTransformMakeScale(scaleRatio, scaleRatio);
    origin = CGPointMake(0, 0);
}

UIGraphicsBeginImageContextWithOptions(size, YES, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextConcatCTM(context, scaleTransform);
[image drawAtPoint:origin];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

return image;
}

So for example with landscape, if I drag the scroll left so that the image is cropped all the way to the right, my offset will be close on a 6+ but on a 4S it will be off by about 150-200 in terms of the CGPoint. 以风景为例,如果我向左拖动滚动条以使图像一直裁剪到最右边,那么我的偏移量在6+上将接近,但在4S上,其偏移量将为150-200 CGPoint。

Here is my code for setting up the scroll view and image view: 这是我用于设置滚动视图和图像视图的代码:

CGRect cropRect = CGRectMake(0.0f,0.0,SCREEN_WIDTH,SCREEN_WIDTH);
CGFloat ratio = (int)self.image.size.height/self.image.size.width;
CGRect r = CGRectMake(0.0,0.0,SCREEN_WIDTH,SCREEN_WIDTH);

if (ratio>1.00) {
    //portrait
    r = CGRectMake(0.0,0.0,SCREEN_WIDTH,(int)(SCREEN_WIDTH*ratio));
} else if (ratio<1.00) {
    //landscape
    CGFloat size = (int)self.image.size.width/self.image.size.height;
    cropOffset = (SCREEN_WIDTH*size)-SCREEN_WIDTH;
    r = CGRectMake(0.0,0.0,(int)(SCREEN_WIDTH*size),SCREEN_WIDTH);
}

NSLog(@"r.size.height == %.4f",r.size.height);
self.scrollView.frame = cropRect;
self.scrollView.contentSize = r.size;

self.imageView = [[UIImageView alloc] initWithFrame:r];
self.imageView.backgroundColor = [UIColor clearColor];
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
self.imageView.image = self.image;

[self.scrollView addSubview:self.imageView];

Cropping math can be tricky. 裁剪数学可能很棘手。 It's been a while since I've had to deal with this, so hopefully I'm pointing you in the right direction. 自从我不得不处理这个问题以来已经有一段时间了,所以希望我能为您指明正确的方向。 Here is a chunk of code from Pixology that grabs a scaled visible rect from a UIScrollView. 这是来自Pixology的大量代码,可从UIScrollView抓取缩放后的可见矩形。 I think the missing ingredient here might be zoomScale . 我认为这里缺少的成分可能是zoomScale

CGRect visibleRect;
visibleRect.origin = _scrollView.contentOffset;
visibleRect.size = _scrollView.bounds.size;
// figure in the scale
float theScale = 1.0 / _scrollView.zoomScale;
visibleRect.origin.x *= theScale;
visibleRect.origin.y *= theScale;
visibleRect.size.width *= theScale;
visibleRect.size.height *= theScale;

You may also need to figure in device screen scale: 您可能还需要计算设备屏幕比例:

CGFloat screenScale = [[UIScreen mainScreen] scale];

See how far you can get with this info, and let me know. 请参阅此信息,以了解您能得到多远的帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM