在Swift编程中,如何裁剪图像并将其放在中心之后?
这是我到目前为止所获得的...我已成功裁剪图像,但我想把它放在中心之后
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();
更新:
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)
我能够通过获取path.bound和size来中心它并更改我的ImageView的边界。 :)
答案 0 :(得分:61)
要获得裁剪的居中位置,可以将高度和宽度的差异减半。然后,您可以在检查图像的方向(哪个部分更长)后为新的宽度和高度指定边界
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
}
如果您想进一步阅读,我在此website找到了大部分此类信息。
针对 Swift 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
}
答案 1 :(得分:17)
接受的答案只对我做方格。我需要一个更灵活的裁剪机制,所以我写了一个扩展如下:
导入UIKit
extension UIImage {
func crop(to:CGSize) -> UIImage {
guard let cgimage = self.cgImage else { return self }
let contextImage: UIImage = UIImage(cgImage: cgimage)
guard let newCgImage = contextImage.cgImage else { return self }
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
guard let imageRef: CGImage = newCgImage.cropping(to: rect) else { return self}
// 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, false, self.scale)
cropped.draw(in: CGRect(x: 0, y: 0, width: to.width, height: to.height))
let resized = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resized ?? self
}
}
您可以这样使用:
let size = CGSize(width: 300, height: 200)
let image = UIImage(named: "my_great_photo")?.crop(size)
如果有人有想法如何使景观,肖像和广场处理更好,请告诉我。
答案 2 :(得分:13)
你可以尝试这个答案。 它是用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
}
}
答案 3 :(得分:6)
这是答案,归功于@awolf(Cropping an UIImage)。完美地处理比例和方向。只需在要裁剪的图像上调用此方法,然后传递裁剪cgImage
,而不必担心缩放或方向。请随意检查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
}
}
是否为零,而不是像我在这里那样用力展开它。
let x = (image.width - croppingFrame.width) / 2
如果您希望裁剪矩形居中,只需进行简单的数学计算即可。
imageView
另一个注意事项:如果您使用scrollView
中嵌入的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)
的边界作为裁剪框,则可以获得裁剪后的图像
from pynput.keyboard import Key,Controller import time
keyboard = Controller()
time.sleep(60)
# 1
keyboard.press(Key.enter)
keyboard.release(Key.enter)
# 2
i = 0
while i < 4:
keyboard.press(Key.tab)
keyboard.release(Key.tab)
i = i + 1;
# 3
i= 0
while i < 3:
keyboard.press(Key.enter)
keyboard.release(Key.enter)
i = i + 1;
# 4
i = 0
while i < 4:
with keyboard.pressed(Key.shift):
keyboard.press(Key.tab)
keyboard.release(Key.tab)
i = i + 1;
答案 4 :(得分:3)
Swift 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
}
答案 5 :(得分: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)
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!
}
}
答案 6 :(得分:2)
您可以使用以下方式裁剪:
let croppedImage = yourImage.cgImage.cropping(to:rect)
答案 7 :(得分:1)
改变这个:
masklayer.frame = ImgView.frame
对此:
masklayer.frame = ImgView.bounds
答案 8 :(得分:1)
您也可以非常简单地从Storyboard中将相关的ImageView置于“Aspect Fill”模式中,并在代码中添加:
Test
答案 9 :(得分:1)
接受的答案对我不起作用,所以我试着写了我自己的答案。这是我工作的结果:
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)
}
}
此功能将图像裁剪为给定比例。它保持图像规模。裁剪后的图像始终是原始图像的中心。
答案 10 :(得分:1)
或进行UImage扩展
extension UIImage {
func cropped(boundingBox: CGRect) -> UIImage? {
guard let cgImage = self.cgImage?.cropping(to: boundingBox) else {
return nil
}
return UIImage(cgImage: cgImage)
}
}
答案 11 :(得分:0)
您还可以使用Alamofire和AlamofireImage裁剪图像。
https://github.com/Alamofire/AlamofireImage
使用CocoaPods安装
pod 'AlamofireImage'
用法:
let image = UIImage(named: "unicorn")!
let size = CGSize(width: 100.0, height: 100.0)
// Scale image to size disregarding aspect ratio
let scaledImage = image.af_imageScaled(to: size)
let aspectScaledToFitImage = image.af_imageAspectScaled(toFit: size)
// Scale image to fill specified size while maintaining aspect ratio
let aspectScaledToFillImage = image.af_imageAspectScaled(toFill: size)
答案 12 :(得分:0)
在Swift 4.1中,我会简单地做:
imageView.clipsToBounds = true
imageView.contentMode = .scaleAspectFill
imageView.layer.cornerRadius = 20
答案 13 :(得分:0)
我想出了一个代码,不管原始视频帧的大小如何,该代码都可以提供理想的裁剪长宽比(改编自@Cole的答案):
func cropImage(uncroppedImage: UIImage, cropWidth: CGFloat, cropHeight: CGFloat) -> UIImage {
let contextImage: UIImage = UIImage(cgImage: uncroppedImage.cgImage!)
let contextSize: CGSize = contextImage.size
var cropX: CGFloat = 0.0
var cropY: CGFloat = 0.0
var cropRatio: CGFloat = CGFloat(cropWidth/cropHeight)
var originalRatio: CGFloat = contextSize.width/contextSize.height
var scaledCropHeight: CGFloat = 0.0
var scaledCropWidth: CGFloat = 0.0
// See what size is longer and set crop rect parameters
if originalRatio > cropRatio {
scaledCropHeight = contextSize.height
scaledCropWidth = (contextSize.height/cropHeight) * cropWidth
cropX = (contextSize.width - scaledCropWidth) / 2
cropY = 0
} else {
scaledCropWidth = contextSize.width
scaledCropHeight = (contextSize.width/cropWidth) * cropHeight
cropY = (contextSize.height / scaledCropHeight) / 2
cropX = 0
}
let rect: CGRect = CGRect(x: cropX, y: cropY, width: scaledCropWidth, height: scaledCropHeight)
// 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 croppedImage: UIImage = UIImage(cgImage: imageRef, scale: uncroppedImage.scale, orientation: uncroppedImage.imageOrientation)
return croppedImage
}
希望有帮助!