SwiftUI - 缩放、缩放和裁剪图像



使用存储库链接进行编辑。

我正在使用 SwiftUI,因此无法访问"裁剪视图"。我使用手势而不是 ScrollView 来捕获图像的缩放级别和偏移量(x 和 y(。我无法返回基于这些因素正确裁剪的图像。

似乎SwiftUI本身可能是一个因素。也许在确定偏移和缩放级别时需要考虑视图中图像的偏移量?

我有图像,并且从视图上的手势中具有以下值来表示比例和 x/y 位置:

@State var scale: CGFloat = 1.0
@State var currentPosition: CGSize = CGSize.zero

当前尝试,最接近调用的函数:

func prepareImage( ) {
let imageToManipulate =  UIImage(named: "landscape")
let currentPositionWidth = self.currentPosition.width
let currentPositionHeight = self.currentPosition.height
let zoomScale = self.scale
let imsize = imageToManipulate!.size
var scale : CGFloat = self.frameSize.width / imsize.width
if imsize.height * scale < self.frameSize.height {
scale = self.frameSize.height / imsize.height
}
let croppedImsize = CGSize(width: (self.frameSize.width/scale) / zoomScale, height: (self.frameSize.height/scale) / zoomScale)
let xOffset = (( imsize.width - croppedImsize.width ) / 2.0) - (currentPositionWidth / zoomScale)
let yOffset = (( imsize.height - croppedImsize.height) / 2.0) - (currentPositionHeight / zoomScale)
let croppedImrect: CGRect = CGRect(x: xOffset, y: yOffset, width: croppedImsize.width, height: croppedImsize.height)
let r = UIGraphicsImageRenderer(size:croppedImsize)
let croppedIm = r.image { _ in
imageToManipulate!.draw(at: CGPoint(x:-croppedImrect.origin.x, y:-croppedImrect.origin.y))
}
self.croppedImage = croppedIm
self.photoIsFinished = true
}

但是,正如您将在存储库中看到的那样,当组合缩放/缩放和 x/y 偏移量时,它总是有点"关闭"。

同样,当您尝试裁剪为正方形图像时,它"关闭"的数量可能非常大。

感谢Asperi的回答,我实现了一个轻量级的swiftUI库来裁剪图像。这是库和演示。这里

魔术如下:

public var body: some View {
GeometryReader { proxy  in
// ...

Button(action: {
// how to crop the image according to rectangle area
if self.tempResult == nil {
self.cropTheImageWithImageViewSize(proxy.size)
}
self.resultImage = self.tempResult
})  {
Text("Crop Image")
.padding(.all, 10)
.background(Color.blue)
.foregroundColor(.white)
.shadow(color: .gray, radius: 1)
.padding(.top, 50)
}
}
}
func cropTheImageWithImageViewSize(_ size: CGSize) {
let imsize =  inputImage.size
let scale = max(inputImage.size.width / size.width,
inputImage.size.height / size.height)

let zoomScale = self.scale
let currentPositionWidth = self.dragAmount.width * scale
let currentPositionHeight = self.dragAmount.height * scale

let croppedImsize = CGSize(width: (self.cropSize.width * scale) / zoomScale, height: (self.cropSize.height * scale) / zoomScale)

let xOffset = (( imsize.width - croppedImsize.width) / 2.0) - (currentPositionWidth  / zoomScale)
let yOffset = (( imsize.height - croppedImsize.height) / 2.0) - (currentPositionHeight  / zoomScale)
let croppedImrect: CGRect = CGRect(x: xOffset, y: yOffset, width: croppedImsize.width, height: croppedImsize.height)

if let cropped = inputImage.cgImage?.cropping(to: croppedImrect) {
//uiimage here can write to data in png or jpeg
let croppedIm = UIImage(cgImage: cropped)
tempResult = croppedIm
result = Image(uiImage: croppedIm)
}
}

答案是由 juanj 通过 GitHub 存储库提供的

let imageToManipulate =  UIImage(named: "landscape")
let zoomScale = self.scale
let imsize = imageToManipulate!.size
var scale : CGFloat = self.frameSize.width / imsize.width
if imsize.height * scale < self.frameSize.height {
scale = self.frameSize.height / imsize.height
}
let currentPositionWidth = self.currentPosition.width / scale
let currentPositionHeight = self.currentPosition.height / scale
let croppedImsize = CGSize(width: (self.frameSize.width/scale) / zoomScale, height: (self.frameSize.height/scale) / zoomScale)
let xOffset = (( imsize.width - croppedImsize.width ) / 2.0) - (currentPositionWidth / zoomScale)
let yOffset = (( imsize.height - croppedImsize.height) / 2.0) - (currentPositionHeight / zoomScale)
let croppedImrect: CGRect = CGRect(x: xOffset, y: yOffset, width: croppedImsize.width, height: croppedImsize.height)
let r = UIGraphicsImageRenderer(size:croppedImsize)
let croppedIm = r.image { _ in
imageToManipulate!.draw(at: CGPoint(x:-croppedImrect.origin.x, y:-croppedImrect.origin.y))
}
self.croppedImage = croppedIm
self.photoIsFinished = true

可以在存储库中查看演示如何允许用户在 SwiftUI 视图中缩放和平移框架内的图像,然后将结果裁剪为新图像的完整代码。

最新更新