In Swift programming , how do you crop an image and put it on the center afterwards?
在Swift编程中,如何裁剪一个图像,然后将其放在中间?
This is what I've got so far ... I've successfully crop the image but I want to put it on the center after
这是我目前为止所得到的…我已经成功地裁剪了图像,但是我想把它放在后面的中间
ImgView.image = OrigImage
var masklayer = CAShapeLayer()
masklayer.frame = ImgView.frame
masklayer.path = path.CGPath
masklayer.fillColor = UIColor.whiteColor().CGColor
masklayer.backgroundColor = UIColor.clearColor().CGColor
ImgView.layer.mask = masklayer
UIGraphicsBeginImageContext(ImgView.bounds.size);
ImgView.layer.renderInContext(UIGraphicsGetCurrentContext())
var image = UIGraphicsGetImageFromCurrentImageContext()
ImgView.image = image
UIGraphicsEndImageContext();
UPDATE :
更新:
let rect: CGRect = CGRectMake(path.bounds.minX, path.bounds.minY, path.bounds.width, path.bounds.height)
// Create bitmap image from context using the rect
let imageRef: CGImageRef = CGImageCreateWithImageInRect(image.CGImage, rect)
ImgView.bounds = rect
ImgView.image = UIImage(CGImage: imageRef)
I was able to center it by getting the path.bound and size and change the bounds of my ImageView. :)
我可以通过路径把它居中。绑定和大小并更改我的ImageView的边界。:)
10 个解决方案
#1
50
To get a centered position for your crop, you can halve the difference of the height and width. Then you can assign the bounds for the new width and height after checking the orientation of the image (which part is longer)
为了使你的作物处于中心位置,你可以将高度和宽度的差减半。然后,您可以在检查图像的方向(哪个部分更长)之后,为新的宽度和高度分配界限
func cropToBounds(image: UIImage, width: Double, height: Double) -> UIImage {
let contextImage: UIImage = UIImage(CGImage: image.CGImage)!
let contextSize: CGSize = contextImage.size
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
var cgwidth: CGFloat = CGFloat(width)
var cgheight: CGFloat = CGFloat(height)
// See what size is longer and create the center off of that
if contextSize.width > contextSize.height {
posX = ((contextSize.width - contextSize.height) / 2)
posY = 0
cgwidth = contextSize.height
cgheight = contextSize.height
} else {
posX = 0
posY = ((contextSize.height - contextSize.width) / 2)
cgwidth = contextSize.width
cgheight = contextSize.width
}
let rect: CGRect = CGRectMake(posX, posY, cgwidth, cgheight)
// Create bitmap image from context using the rect
let imageRef: CGImageRef = CGImageCreateWithImageInRect(contextImage.CGImage, rect)
// Create a new image based on the imageRef and rotate back to the original orientation
let image: UIImage = UIImage(CGImage: imageRef, scale: image.scale, orientation: image.imageOrientation)!
return image
}
I found most of this info over at this website in case you wanted to read further.
我在这个网站上找到了这些信息,以备你进一步阅读。
Updated for Swift 4
更新迅速4
func cropToBounds(image: UIImage, width: Double, height: Double) -> UIImage {
let cgimage = image.cgImage!
let contextImage: UIImage = UIImage(cgImage: cgimage)
let contextSize: CGSize = contextImage.size
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
var cgwidth: CGFloat = CGFloat(width)
var cgheight: CGFloat = CGFloat(height)
// See what size is longer and create the center off of that
if contextSize.width > contextSize.height {
posX = ((contextSize.width - contextSize.height) / 2)
posY = 0
cgwidth = contextSize.height
cgheight = contextSize.height
} else {
posX = 0
posY = ((contextSize.height - contextSize.width) / 2)
cgwidth = contextSize.width
cgheight = contextSize.width
}
let rect: CGRect = CGRect(x: posX, y: posY, width: cgwidth, height: cgheight)
// Create bitmap image from context using the rect
let imageRef: CGImage = cgimage.cropping(to: rect)!
// Create a new image based on the imageRef and rotate back to the original orientation
let image: UIImage = UIImage(cgImage: imageRef, scale: image.scale, orientation: image.imageOrientation)
return image
}
#2
13
The accepted answer only does squares for me. I needed a bit more flexible cropping mechanism so I wrote an extension as follows:
公认的答案只对我有好处。我需要更灵活的裁剪机制,所以我写了一个扩展如下:
import UIKit
extension UIImage {
func crop(to:CGSize) -> UIImage {
guard let cgimage = self.CGImage else { return self }
let contextImage: UIImage = UIImage(CGImage: cgimage)
let contextSize: CGSize = contextImage.size
//Set to square
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
let cropAspect: CGFloat = to.width / to.height
var cropWidth: CGFloat = to.width
var cropHeight: CGFloat = to.height
if to.width > to.height { //Landscape
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
posY = (contextSize.height - cropHeight) / 2
} else if to.width < to.height { //Portrait
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
posX = (contextSize.width - cropWidth) / 2
} else { //Square
if contextSize.width >= contextSize.height { //Square on landscape (or square)
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
posX = (contextSize.width - cropWidth) / 2
}else{ //Square on portrait
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
posY = (contextSize.height - cropHeight) / 2
}
}
let rect: CGRect = CGRectMake(posX, posY, cropWidth, cropHeight)
// Create bitmap image from context using the rect
let imageRef: CGImageRef = CGImageCreateWithImageInRect(contextImage.CGImage, rect)!
// Create a new image based on the imageRef and rotate back to the original orientation
let cropped: UIImage = UIImage(CGImage: imageRef, scale: self.scale, orientation: self.imageOrientation)
UIGraphicsBeginImageContextWithOptions(to, true, self.scale)
cropped.drawInRect(CGRectMake(0, 0, to.width, to.height))
let resized = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resized
}
}
You can use it so:
你可以这样使用:
let size = CGSize(width: 300, height: 200)
let image = UIImage(named: "my_great_photo")?.crop(size)
If anyone has ideas how to make the landscape, portrait and square handling a bit better let me know.
如果有人知道如何制作风景,肖像和广场的处理,最好让我知道。
#3
10
You can try this answer. It is written in swift 3.
你可以试试这个答案。它是用swift 3写的。
extension UIImage {
func crop(to:CGSize) -> UIImage {
guard let cgimage = self.cgImage else { return self }
let contextImage: UIImage = UIImage(cgImage: cgimage)
let contextSize: CGSize = contextImage.size
//Set to square
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
let cropAspect: CGFloat = to.width / to.height
var cropWidth: CGFloat = to.width
var cropHeight: CGFloat = to.height
if to.width > to.height { //Landscape
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
posY = (contextSize.height - cropHeight) / 2
} else if to.width < to.height { //Portrait
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
posX = (contextSize.width - cropWidth) / 2
} else { //Square
if contextSize.width >= contextSize.height { //Square on landscape (or square)
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
posX = (contextSize.width - cropWidth) / 2
}else{ //Square on portrait
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
posY = (contextSize.height - cropHeight) / 2
}
}
let rect: CGRect = CGRect(x : posX, y : posY, width : cropWidth, height : cropHeight)
// Create bitmap image from context using the rect
let imageRef: CGImage = contextImage.cgImage!.cropping(to: rect)!
// Create a new image based on the imageRef and rotate back to the original orientation
let cropped: UIImage = UIImage(cgImage: imageRef, scale: self.scale, orientation: self.imageOrientation)
cropped.draw(in: CGRect(x : 0, y : 0, width : to.width, height : to.height))
return cropped
}
}
#4
3
Working Swift 3 example
工作迅速3例
extension UIImage {
func crop(to:CGSize) -> UIImage {
guard let cgimage = self.cgImage else { return self }
let contextImage: UIImage = UIImage(cgImage: cgimage)
let contextSize: CGSize = contextImage.size
//Set to square
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
let cropAspect: CGFloat = to.width / to.height
var cropWidth: CGFloat = to.width
var cropHeight: CGFloat = to.height
if to.width > to.height { //Landscape
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
posY = (contextSize.height - cropHeight) / 2
} else if to.width < to.height { //Portrait
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
posX = (contextSize.width - cropWidth) / 2
} else { //Square
if contextSize.width >= contextSize.height { //Square on landscape (or square)
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
posX = (contextSize.width - cropWidth) / 2
}else{ //Square on portrait
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
posY = (contextSize.height - cropHeight) / 2
}
}
let rect: CGRect = CGRect(x: posX, y: posY, width: cropWidth, height: cropHeight)
// Create bitmap image from context using the rect
let imageRef: CGImage = contextImage.cgImage!.cropping(to: rect)!
// Create a new image based on the imageRef and rotate back to the original orientation
let cropped: UIImage = UIImage(cgImage: imageRef, scale: self.scale, orientation: self.imageOrientation)
UIGraphicsBeginImageContextWithOptions(to, true, self.scale)
cropped.draw(in: CGRect(x: 0, y: 0, width: to.width, height: to.height))
let resized = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resized!
}
}
#5
3
This is THE answer, credit to @awolf (Cropping an UIImage). Handles scale and orientation perfectly. Just call this method on the image you want to crop, and pass in the cropping CGRect
without worrying about scale or orientation. Feel free to check whether cgImage
is nil instead of force unwrapping it like I did here.
这就是答案,归功于@awolf(剪切一个UIImage)。完美地处理比例和方向。只需在想要裁剪的图像上调用此方法,并传入裁剪CGRect,而不必担心规模或方向。请随意检查cgImage是否为nil,而不是像我在这里那样展开。
extension UIImage {
func croppedInRect(rect: CGRect) -> UIImage {
func rad(_ degree: Double) -> CGFloat {
return CGFloat(degree / 180.0 * .pi)
}
var rectTransform: CGAffineTransform
switch imageOrientation {
case .left:
rectTransform = CGAffineTransform(rotationAngle: rad(90)).translatedBy(x: 0, y: -self.size.height)
case .right:
rectTransform = CGAffineTransform(rotationAngle: rad(-90)).translatedBy(x: -self.size.width, y: 0)
case .down:
rectTransform = CGAffineTransform(rotationAngle: rad(-180)).translatedBy(x: -self.size.width, y: -self.size.height)
default:
rectTransform = .identity
}
rectTransform = rectTransform.scaledBy(x: self.scale, y: self.scale)
let imageRef = self.cgImage!.cropping(to: rect.applying(rectTransform))
let result = UIImage(cgImage: imageRef!, scale: self.scale, orientation: self.imageOrientation)
return result
}
}
If you want the cropping rect to be centered, just do simple math. Along the lines of
如果你想让裁剪矩形居中,只需做简单的计算。的
let x = (image.width - croppingFrame.width) / 2
Another note: if you are working with imageView
embedded in a scrollView
, there is one additional step, you have to take the zoom factor into account. Assuming your imageView
spans the entire content view of the scrollView
, and you use the bounds of the scrollView
as the cropping frame, the cropped image can be obtained as
另一个注意事项:如果您正在使用嵌入在scrollView中的imageView,那么还有一个额外的步骤,您必须考虑缩放因子。假设您的imageView跨越了scrollView的整个内容视图,并且使用scrollView的边界作为裁剪框架,那么裁剪后的图像可以作为
let ratio = imageView.image!.size.height / scrollView.contentSize.height
let origin = CGPoint(x: scrollView.contentOffset.x * ratio, y: scrollView.contentOffset.y * ratio)
let size = CGSize(width: scrollView.bounds.size.width * ratio, let height: scrollView.bounds.size.height * ratio)
let cropFrame = CGRect(origin: origin, size: size)
let croppedImage = imageView.image!.croppedInRect(rect: cropFrame)
#6
2
Props to Cole
Swift 3
斯威夫特3
func crop(image: UIImage, withWidth width: Double, andHeight height: Double) -> UIImage? {
if let cgImage = image.cgImage {
let contextImage: UIImage = UIImage(cgImage: cgImage)
let contextSize: CGSize = contextImage.size
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
var cgwidth: CGFloat = CGFloat(width)
var cgheight: CGFloat = CGFloat(height)
// See what size is longer and create the center off of that
if contextSize.width > contextSize.height {
posX = ((contextSize.width - contextSize.height) / 2)
posY = 0
cgwidth = contextSize.height
cgheight = contextSize.height
} else {
posX = 0
posY = ((contextSize.height - contextSize.width) / 2)
cgwidth = contextSize.width
cgheight = contextSize.width
}
let rect: CGRect = CGRect(x: posX, y: posY, width: cgwidth, height: cgheight)
// Create bitmap image from context using the rect
var croppedContextImage: CGImage? = nil
if let contextImage = contextImage.cgImage {
if let croppedImage = contextImage.cropping(to: rect) {
croppedContextImage = croppedImage
}
}
// Create a new image based on the imageRef and rotate back to the original orientation
if let croppedImage:CGImage = croppedContextImage {
let image: UIImage = UIImage(cgImage: croppedImage, scale: image.scale, orientation: image.imageOrientation)
return image
}
}
return nil
}
#7
1
Accepted answer did not work for me, so I tried wrote my own. Here is an effect of my work:
接受的回答对我不起作用,所以我尝试自己写。这是我工作的一个效果:
import UIKit
extension UIImage {
func cropedToRatio(ratio: CGFloat) -> UIImage? {
let newImageWidth = size.height * ratio
let cropRect = CGRect(x: ((size.width - newImageWidth) / 2.0) * scale,
y: 0.0,
width: newImageWidth * scale,
height: size.height * scale)
guard let cgImage = cgImage else {
return nil
}
guard let newCgImage = cgImage.cropping(to: cropRect) else {
return nil
}
return UIImage(cgImage: newCgImage, scale: scale, orientation: imageOrientation)
}
}
This function crop image to given ratio. It keeps image scale. Cropped image is always center of original image.
这个函数裁剪图像到给定的比例。它使图像比例尺。裁剪图像始终是原始图像的中心。
#8
1
You can also, very simply, put the concerned ImageView in "Aspect Fill" mode from the Storyboard, and add this in the code :
您还可以非常简单地将相关的ImageView放在故事板的“Aspect Fill”模式中,并将其添加到代码中:
imageView.layer.masksToBounds = true
imageView.clipsToBounds = true
#9
0
Change this:
改变:
masklayer.frame = ImgView.frame
To this:
:
masklayer.frame = ImgView.bounds
#10
0
You can just crop using:
你可以用:
let croppedImage = yourImage.cgImage.cropping(to:rect)
#1
50
To get a centered position for your crop, you can halve the difference of the height and width. Then you can assign the bounds for the new width and height after checking the orientation of the image (which part is longer)
为了使你的作物处于中心位置,你可以将高度和宽度的差减半。然后,您可以在检查图像的方向(哪个部分更长)之后,为新的宽度和高度分配界限
func cropToBounds(image: UIImage, width: Double, height: Double) -> UIImage {
let contextImage: UIImage = UIImage(CGImage: image.CGImage)!
let contextSize: CGSize = contextImage.size
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
var cgwidth: CGFloat = CGFloat(width)
var cgheight: CGFloat = CGFloat(height)
// See what size is longer and create the center off of that
if contextSize.width > contextSize.height {
posX = ((contextSize.width - contextSize.height) / 2)
posY = 0
cgwidth = contextSize.height
cgheight = contextSize.height
} else {
posX = 0
posY = ((contextSize.height - contextSize.width) / 2)
cgwidth = contextSize.width
cgheight = contextSize.width
}
let rect: CGRect = CGRectMake(posX, posY, cgwidth, cgheight)
// Create bitmap image from context using the rect
let imageRef: CGImageRef = CGImageCreateWithImageInRect(contextImage.CGImage, rect)
// Create a new image based on the imageRef and rotate back to the original orientation
let image: UIImage = UIImage(CGImage: imageRef, scale: image.scale, orientation: image.imageOrientation)!
return image
}
I found most of this info over at this website in case you wanted to read further.
我在这个网站上找到了这些信息,以备你进一步阅读。
Updated for Swift 4
更新迅速4
func cropToBounds(image: UIImage, width: Double, height: Double) -> UIImage {
let cgimage = image.cgImage!
let contextImage: UIImage = UIImage(cgImage: cgimage)
let contextSize: CGSize = contextImage.size
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
var cgwidth: CGFloat = CGFloat(width)
var cgheight: CGFloat = CGFloat(height)
// See what size is longer and create the center off of that
if contextSize.width > contextSize.height {
posX = ((contextSize.width - contextSize.height) / 2)
posY = 0
cgwidth = contextSize.height
cgheight = contextSize.height
} else {
posX = 0
posY = ((contextSize.height - contextSize.width) / 2)
cgwidth = contextSize.width
cgheight = contextSize.width
}
let rect: CGRect = CGRect(x: posX, y: posY, width: cgwidth, height: cgheight)
// Create bitmap image from context using the rect
let imageRef: CGImage = cgimage.cropping(to: rect)!
// Create a new image based on the imageRef and rotate back to the original orientation
let image: UIImage = UIImage(cgImage: imageRef, scale: image.scale, orientation: image.imageOrientation)
return image
}
#2
13
The accepted answer only does squares for me. I needed a bit more flexible cropping mechanism so I wrote an extension as follows:
公认的答案只对我有好处。我需要更灵活的裁剪机制,所以我写了一个扩展如下:
import UIKit
extension UIImage {
func crop(to:CGSize) -> UIImage {
guard let cgimage = self.CGImage else { return self }
let contextImage: UIImage = UIImage(CGImage: cgimage)
let contextSize: CGSize = contextImage.size
//Set to square
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
let cropAspect: CGFloat = to.width / to.height
var cropWidth: CGFloat = to.width
var cropHeight: CGFloat = to.height
if to.width > to.height { //Landscape
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
posY = (contextSize.height - cropHeight) / 2
} else if to.width < to.height { //Portrait
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
posX = (contextSize.width - cropWidth) / 2
} else { //Square
if contextSize.width >= contextSize.height { //Square on landscape (or square)
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
posX = (contextSize.width - cropWidth) / 2
}else{ //Square on portrait
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
posY = (contextSize.height - cropHeight) / 2
}
}
let rect: CGRect = CGRectMake(posX, posY, cropWidth, cropHeight)
// Create bitmap image from context using the rect
let imageRef: CGImageRef = CGImageCreateWithImageInRect(contextImage.CGImage, rect)!
// Create a new image based on the imageRef and rotate back to the original orientation
let cropped: UIImage = UIImage(CGImage: imageRef, scale: self.scale, orientation: self.imageOrientation)
UIGraphicsBeginImageContextWithOptions(to, true, self.scale)
cropped.drawInRect(CGRectMake(0, 0, to.width, to.height))
let resized = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resized
}
}
You can use it so:
你可以这样使用:
let size = CGSize(width: 300, height: 200)
let image = UIImage(named: "my_great_photo")?.crop(size)
If anyone has ideas how to make the landscape, portrait and square handling a bit better let me know.
如果有人知道如何制作风景,肖像和广场的处理,最好让我知道。
#3
10
You can try this answer. It is written in swift 3.
你可以试试这个答案。它是用swift 3写的。
extension UIImage {
func crop(to:CGSize) -> UIImage {
guard let cgimage = self.cgImage else { return self }
let contextImage: UIImage = UIImage(cgImage: cgimage)
let contextSize: CGSize = contextImage.size
//Set to square
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
let cropAspect: CGFloat = to.width / to.height
var cropWidth: CGFloat = to.width
var cropHeight: CGFloat = to.height
if to.width > to.height { //Landscape
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
posY = (contextSize.height - cropHeight) / 2
} else if to.width < to.height { //Portrait
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
posX = (contextSize.width - cropWidth) / 2
} else { //Square
if contextSize.width >= contextSize.height { //Square on landscape (or square)
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
posX = (contextSize.width - cropWidth) / 2
}else{ //Square on portrait
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
posY = (contextSize.height - cropHeight) / 2
}
}
let rect: CGRect = CGRect(x : posX, y : posY, width : cropWidth, height : cropHeight)
// Create bitmap image from context using the rect
let imageRef: CGImage = contextImage.cgImage!.cropping(to: rect)!
// Create a new image based on the imageRef and rotate back to the original orientation
let cropped: UIImage = UIImage(cgImage: imageRef, scale: self.scale, orientation: self.imageOrientation)
cropped.draw(in: CGRect(x : 0, y : 0, width : to.width, height : to.height))
return cropped
}
}
#4
3
Working Swift 3 example
工作迅速3例
extension UIImage {
func crop(to:CGSize) -> UIImage {
guard let cgimage = self.cgImage else { return self }
let contextImage: UIImage = UIImage(cgImage: cgimage)
let contextSize: CGSize = contextImage.size
//Set to square
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
let cropAspect: CGFloat = to.width / to.height
var cropWidth: CGFloat = to.width
var cropHeight: CGFloat = to.height
if to.width > to.height { //Landscape
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
posY = (contextSize.height - cropHeight) / 2
} else if to.width < to.height { //Portrait
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
posX = (contextSize.width - cropWidth) / 2
} else { //Square
if contextSize.width >= contextSize.height { //Square on landscape (or square)
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
posX = (contextSize.width - cropWidth) / 2
}else{ //Square on portrait
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
posY = (contextSize.height - cropHeight) / 2
}
}
let rect: CGRect = CGRect(x: posX, y: posY, width: cropWidth, height: cropHeight)
// Create bitmap image from context using the rect
let imageRef: CGImage = contextImage.cgImage!.cropping(to: rect)!
// Create a new image based on the imageRef and rotate back to the original orientation
let cropped: UIImage = UIImage(cgImage: imageRef, scale: self.scale, orientation: self.imageOrientation)
UIGraphicsBeginImageContextWithOptions(to, true, self.scale)
cropped.draw(in: CGRect(x: 0, y: 0, width: to.width, height: to.height))
let resized = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resized!
}
}
#5
3
This is THE answer, credit to @awolf (Cropping an UIImage). Handles scale and orientation perfectly. Just call this method on the image you want to crop, and pass in the cropping CGRect
without worrying about scale or orientation. Feel free to check whether cgImage
is nil instead of force unwrapping it like I did here.
这就是答案,归功于@awolf(剪切一个UIImage)。完美地处理比例和方向。只需在想要裁剪的图像上调用此方法,并传入裁剪CGRect,而不必担心规模或方向。请随意检查cgImage是否为nil,而不是像我在这里那样展开。
extension UIImage {
func croppedInRect(rect: CGRect) -> UIImage {
func rad(_ degree: Double) -> CGFloat {
return CGFloat(degree / 180.0 * .pi)
}
var rectTransform: CGAffineTransform
switch imageOrientation {
case .left:
rectTransform = CGAffineTransform(rotationAngle: rad(90)).translatedBy(x: 0, y: -self.size.height)
case .right:
rectTransform = CGAffineTransform(rotationAngle: rad(-90)).translatedBy(x: -self.size.width, y: 0)
case .down:
rectTransform = CGAffineTransform(rotationAngle: rad(-180)).translatedBy(x: -self.size.width, y: -self.size.height)
default:
rectTransform = .identity
}
rectTransform = rectTransform.scaledBy(x: self.scale, y: self.scale)
let imageRef = self.cgImage!.cropping(to: rect.applying(rectTransform))
let result = UIImage(cgImage: imageRef!, scale: self.scale, orientation: self.imageOrientation)
return result
}
}
If you want the cropping rect to be centered, just do simple math. Along the lines of
如果你想让裁剪矩形居中,只需做简单的计算。的
let x = (image.width - croppingFrame.width) / 2
Another note: if you are working with imageView
embedded in a scrollView
, there is one additional step, you have to take the zoom factor into account. Assuming your imageView
spans the entire content view of the scrollView
, and you use the bounds of the scrollView
as the cropping frame, the cropped image can be obtained as
另一个注意事项:如果您正在使用嵌入在scrollView中的imageView,那么还有一个额外的步骤,您必须考虑缩放因子。假设您的imageView跨越了scrollView的整个内容视图,并且使用scrollView的边界作为裁剪框架,那么裁剪后的图像可以作为
let ratio = imageView.image!.size.height / scrollView.contentSize.height
let origin = CGPoint(x: scrollView.contentOffset.x * ratio, y: scrollView.contentOffset.y * ratio)
let size = CGSize(width: scrollView.bounds.size.width * ratio, let height: scrollView.bounds.size.height * ratio)
let cropFrame = CGRect(origin: origin, size: size)
let croppedImage = imageView.image!.croppedInRect(rect: cropFrame)
#6
2
Props to Cole
Swift 3
斯威夫特3
func crop(image: UIImage, withWidth width: Double, andHeight height: Double) -> UIImage? {
if let cgImage = image.cgImage {
let contextImage: UIImage = UIImage(cgImage: cgImage)
let contextSize: CGSize = contextImage.size
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
var cgwidth: CGFloat = CGFloat(width)
var cgheight: CGFloat = CGFloat(height)
// See what size is longer and create the center off of that
if contextSize.width > contextSize.height {
posX = ((contextSize.width - contextSize.height) / 2)
posY = 0
cgwidth = contextSize.height
cgheight = contextSize.height
} else {
posX = 0
posY = ((contextSize.height - contextSize.width) / 2)
cgwidth = contextSize.width
cgheight = contextSize.width
}
let rect: CGRect = CGRect(x: posX, y: posY, width: cgwidth, height: cgheight)
// Create bitmap image from context using the rect
var croppedContextImage: CGImage? = nil
if let contextImage = contextImage.cgImage {
if let croppedImage = contextImage.cropping(to: rect) {
croppedContextImage = croppedImage
}
}
// Create a new image based on the imageRef and rotate back to the original orientation
if let croppedImage:CGImage = croppedContextImage {
let image: UIImage = UIImage(cgImage: croppedImage, scale: image.scale, orientation: image.imageOrientation)
return image
}
}
return nil
}
#7
1
Accepted answer did not work for me, so I tried wrote my own. Here is an effect of my work:
接受的回答对我不起作用,所以我尝试自己写。这是我工作的一个效果:
import UIKit
extension UIImage {
func cropedToRatio(ratio: CGFloat) -> UIImage? {
let newImageWidth = size.height * ratio
let cropRect = CGRect(x: ((size.width - newImageWidth) / 2.0) * scale,
y: 0.0,
width: newImageWidth * scale,
height: size.height * scale)
guard let cgImage = cgImage else {
return nil
}
guard let newCgImage = cgImage.cropping(to: cropRect) else {
return nil
}
return UIImage(cgImage: newCgImage, scale: scale, orientation: imageOrientation)
}
}
This function crop image to given ratio. It keeps image scale. Cropped image is always center of original image.
这个函数裁剪图像到给定的比例。它使图像比例尺。裁剪图像始终是原始图像的中心。
#8
1
You can also, very simply, put the concerned ImageView in "Aspect Fill" mode from the Storyboard, and add this in the code :
您还可以非常简单地将相关的ImageView放在故事板的“Aspect Fill”模式中,并将其添加到代码中:
imageView.layer.masksToBounds = true
imageView.clipsToBounds = true
#9
0
Change this:
改变:
masklayer.frame = ImgView.frame
To this:
:
masklayer.frame = ImgView.bounds
#10
0
You can just crop using:
你可以用:
let croppedImage = yourImage.cgImage.cropping(to:rect)