我有一些代码来调整图像的大小,这样我就可以得到图像中心的缩放块-我用这个来获取一个UIImage,并返回一个小的,正方形的图像表示,类似于在照片应用程序的相册视图中看到的。(我知道我可以使用UIImageView和调整裁剪模式来实现相同的结果,但这些图像有时显示在UIWebViews中)。
我已经开始注意到这段代码中的一些崩溃,我有点难住了。我有两种不同的理论,不知道哪一种是正确的。
理论1)我通过绘制到目标尺寸的屏幕外图像上下文来实现裁剪。因为我想要图像的中心部分,所以我将传递给drawwinrect的CGRect参数设置为比图像上下文的边界更大的值。我希望这是符合规定的,但我是不是在试图掩盖其他我不应该触及的记忆?
理论2)我在后台线程中做所有这些。我知道UIKit的某些部分被限制在主线程中。我假设/希望绘制到屏幕外的视图不是其中之一。我错了吗?
(哦,我真怀念NSImage的drawwinrect:fromRect:operation:fraction:方法。)
在Swift中裁剪UIImage的最佳解决方案,在精度方面,像素缩放…:
private func squareCropImageToSideLength(let sourceImage: UIImage,
let sideLength: CGFloat) -> UIImage {
// input size comes from image
let inputSize: CGSize = sourceImage.size
// round up side length to avoid fractional output size
let sideLength: CGFloat = ceil(sideLength)
// output size has sideLength for both dimensions
let outputSize: CGSize = CGSizeMake(sideLength, sideLength)
// calculate scale so that smaller dimension fits sideLength
let scale: CGFloat = max(sideLength / inputSize.width,
sideLength / inputSize.height)
// scaling the image with this scale results in this output size
let scaledInputSize: CGSize = CGSizeMake(inputSize.width * scale,
inputSize.height * scale)
// determine point in center of "canvas"
let center: CGPoint = CGPointMake(outputSize.width/2.0,
outputSize.height/2.0)
// calculate drawing rect relative to output Size
let outputRect: CGRect = CGRectMake(center.x - scaledInputSize.width/2.0,
center.y - scaledInputSize.height/2.0,
scaledInputSize.width,
scaledInputSize.height)
// begin a new bitmap context, scale 0 takes display scale
UIGraphicsBeginImageContextWithOptions(outputSize, true, 0)
// optional: set the interpolation quality.
// For this you need to grab the underlying CGContext
let ctx: CGContextRef = UIGraphicsGetCurrentContext()
CGContextSetInterpolationQuality(ctx, kCGInterpolationHigh)
// draw the source image into the calculated rect
sourceImage.drawInRect(outputRect)
// create new image from bitmap context
let outImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
// clean up
UIGraphicsEndImageContext()
// pass back new image
return outImage
}
调用此函数的指令:
let image: UIImage = UIImage(named: "Image.jpg")!
let squareImage: UIImage = self.squareCropImageToSideLength(image, sideLength: 320)
self.myUIImageView.image = squareImage
注意:最初的源代码灵感是用Objective-C写的,可以在Cocoanetics博客上找到。
要裁剪视网膜图像,同时保持相同的比例和方向,在UIImage类别中使用以下方法(iOS 4.0及以上):
- (UIImage *)crop:(CGRect)rect {
if (self.scale > 1.0f) {
rect = CGRectMake(rect.origin.x * self.scale,
rect.origin.y * self.scale,
rect.size.width * self.scale,
rect.size.height * self.scale);
}
CGImageRef imageRef = CGImageCreateWithImageInRect(self.CGImage, rect);
UIImage *result = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation];
CGImageRelease(imageRef);
return result;
}
更新2014-05-28:我写这篇文章的时候,iOS 3左右还是热门的新事物,我相信现在有更好的方法来做到这一点,可能是内置的。正如很多人提到的,这种方法没有考虑到轮换;阅读一些额外的答案,并散布一些点赞的爱,让这个问题的回答对每个人都有帮助。
最初的反应:
我将把我对相同问题的回答复制/粘贴到其他地方:
没有一个简单的类方法可以做到这一点,但有一个函数可以使用来获得所需的结果:CGImageCreateWithImageInRect(CGImageRef, CGRect)将帮助您解决这个问题。
下面是一个简短的例子:
CGImageRef imageRef = CGImageCreateWithImageInRect([largeImage CGImage], cropRect);
// or use the UIImage wherever you like
[UIImageView setImage:[UIImage imageWithCGImage:imageRef]];
CGImageRelease(imageRef);
斯威夫特5:
extension UIImage {
func cropped(rect: CGRect) -> UIImage? {
guard let cgImage = cgImage else { return nil }
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
let context = UIGraphicsGetCurrentContext()
context?.translateBy(x: 0.0, y: self.size.height)
context?.scaleBy(x: 1.0, y: -1.0)
context?.draw(cgImage, in: CGRect(x: rect.minX, y: rect.minY, width: self.size.width, height: self.size.height), byTiling: false)
let croppedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return croppedImage
}
}