- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我有一个应用程序,其中有一个显示主图像的 UIImageView
和另一个用作 mask 的 UIImageView
,它显示一个透明的圆圈,外面是不透明的,这个圆圈可以使用 UIPanGestureRecognizer
移动,我想知道如何将圆圈内的图像裁剪成新图像。这是附加的代码和屏幕截图
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// create pan gesture
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self
action:@selector(handlePan:)];
[self.view addGestureRecognizer:pan];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = [[self makeCircleAtLocation:self.view.center radius:100.0] CGPath];
shapeLayer.strokeColor = [[UIColor clearColor] CGColor];
shapeLayer.fillColor = nil;
shapeLayer.lineWidth = 3.0;
// Add CAShapeLayer to our view
[self.view.layer addSublayer:shapeLayer];
// Save this shape layer in a class property for future reference,
// namely so we can remove it later if we tap elsewhere on the screen.
self.circleLayer = shapeLayer;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// Create a UIBezierPath which is a circle at a certain location of a certain radius.
// This also saves the circle's center and radius to class properties for future reference.
- (UIBezierPath *)makeCircleAtLocation:(CGPoint)location radius:(CGFloat)radius
{
self.circleCenter = location;
self.circleRadius = radius;
UIBezierPath *path = [UIBezierPath bezierPath];
[path addArcWithCenter:self.circleCenter
radius:self.circleRadius
startAngle:0.0
endAngle:M_PI * 2.0
clockwise:YES];
return path;
}
- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
static CGPoint oldCenter;
if (gesture.state == UIGestureRecognizerStateBegan)
{
// If we're starting a pan, make sure we're inside the circle.
// So, calculate the distance between the circle's center and
// the gesture start location and we'll compare that to the
// radius of the circle.
CGPoint location = [gesture locationInView:gesture.view];
CGPoint translation = [gesture translationInView:gesture.view];
location.x -= translation.x;
location.y -= translation.y;
CGFloat x = location.x - self.circleCenter.x;
CGFloat y = location.y - self.circleCenter.y;
CGFloat distance = sqrtf(x*x + y*y);
// If we're outside the circle, cancel the gesture.
// If we're inside it, keep track of where the circle was.
oldCenter = self.circleCenter;
}
else if (gesture.state == UIGestureRecognizerStateChanged)
{
// Let's calculate the new center of the circle by adding the
// the translationInView to the old circle center.
CGPoint translation = [gesture translationInView:gesture.view];
CGPoint newCenter = CGPointMake(oldCenter.x + translation.x, oldCenter.y + translation.y);
// CGPoint newCenter = [gesture locationInView:self.view];
if (newCenter.x < 160) {
newCenter.x = 160;
}
else if (newCenter.x > self.view.frame.size.width - 160) {
newCenter.x = self.view.frame.size.width - 160;
}
if (newCenter.y < 242) {
newCenter.y = 242;
}
else if (newCenter.y > self.view.frame.size.height - imageMain.center.y) {
newCenter.y = self.view.frame.size.height - imageMain.center.y;
}
// Update the path for our CAShapeLayer
// self.circleLayer.path = [[self makeCircleAtLocation:newCenter radius:self.circleRadius] CGPath];
imageCircle.center = newCenter;
}
}
@end
结果是
最佳答案
要保存蒙版图像,可以使用 drawHierarchy(in:afterScreenUpdates:)
.您可能还想使用 cropping(to:)
裁剪图像.请参阅下面我的 handleTap
示例。
但我注意到您显然是通过叠加图像来进行遮蔽。我可能建议使用 UIBezierPath
作为 ImageView 图层蒙版的基础,以及用于绘制圆的 CAShapeLayer
(假设您想要绘制圆圈时的边框。如果您的蒙版是规则形状(例如圆圈),则可能更灵活地使其成为带有 UIBezierPath
的 CAShapeLayer
(而不是而不是图像),因为这样你不仅可以用平移手势四处移动它,还可以用捏合手势缩放它:
这是一个示例实现:
// ViewController.swift
// CircleMaskDemo
//
// Created by Robert Ryan on 4/18/18.
// Copyright © 2018-2022 Robert Ryan. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var pinch: UIPinchGestureRecognizer!
@IBOutlet weak var pan: UIPanGestureRecognizer!
private let maskLayer = CAShapeLayer()
private lazy var radius: CGFloat = min(view.bounds.width, view.bounds.height) * 0.3
private lazy var center: CGPoint = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
private let pathLayer: CAShapeLayer = {
let _pathLayer = CAShapeLayer()
_pathLayer.fillColor = UIColor.clear.cgColor
_pathLayer.strokeColor = UIColor.black.cgColor
_pathLayer.lineWidth = 3
return _pathLayer
}()
override func viewDidLoad() {
super.viewDidLoad()
imageView.layer.addSublayer(pathLayer)
imageView.layer.mask = maskLayer
imageView.isUserInteractionEnabled = true
imageView.addGestureRecognizer(pinch)
imageView.addGestureRecognizer(pan)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
updateCirclePath(at: center, radius: radius)
}
private var oldCenter: CGPoint!
private var oldRadius: CGFloat!
}
// MARK: - Actions
extension ViewController {
@IBAction func handlePinch(_ gesture: UIPinchGestureRecognizer) {
let scale = gesture.scale
if gesture.state == .began { oldRadius = radius }
updateCirclePath(at: center, radius: oldRadius * scale)
}
@IBAction func handlePan(_ gesture: UIPanGestureRecognizer) {
let translation = gesture.translation(in: gesture.view)
if gesture.state == .began { oldCenter = center }
let newCenter = CGPoint(x: oldCenter.x + translation.x, y: oldCenter.y + translation.y)
updateCirclePath(at: newCenter, radius: radius)
}
@IBAction func handleTap(_ gesture: UITapGestureRecognizer) {
let fileURL = try! FileManager.default
.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
.appendingPathComponent("image.png")
let scale = imageView.window!.screen.scale
let radius = self.radius * scale
let center = CGPoint(x: self.center.x * scale, y: self.center.y * scale)
let frame = CGRect(x: center.x - radius,
y: center.y - radius,
width: radius * 2.0,
height: radius * 2.0)
// temporarily remove the circleLayer
let saveLayer = pathLayer
saveLayer.removeFromSuperlayer()
// render the clipped image
let image = UIGraphicsImageRenderer(size: imageView.frame.size).image { _ in
imageView.drawHierarchy(in: imageView.bounds, afterScreenUpdates: true)
}
// add the circleLayer back
imageView.layer.addSublayer(saveLayer)
// crop the image
guard
let imageRef = image.cgImage?.cropping(to: frame),
let data = UIImage(cgImage: imageRef).pngData()
else {
return
}
// save the image
try? data.write(to: fileURL)
// tell the user we're done
let alert = UIAlertController(title: nil, message: "Saved", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
present(alert, animated: true)
}
}
// MARK: - Private utility methods
private extension ViewController {
func updateCirclePath(at center: CGPoint, radius: CGFloat) {
self.center = center
self.radius = radius
let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: 0, endAngle: 2 * .pi, clockwise: true)
maskLayer.path = path.cgPath
pathLayer.path = path.cgPath
}
}
// MARK: - UIGestureRecognizerDelegate
extension ViewController: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
let tuple = (gestureRecognizer, otherGestureRecognizer)
return tuple == (pan, pinch) || tuple == (pinch, pan)
}
}
如果您不想在圆周围绘制边框,那就更简单了,因为您可以拉取与 circleLayer
相关的任何内容。
如果您对 Objective-C 示例感兴趣,请参阅 previous revision of this answer .
关于ios - 如何在 iOS 的 UIImageView 中裁剪圆圈内的图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20165906/
是否有可能(在 cmd 批处理 ffmpeg 中)拍摄宽度已知(1920px)但高度未知的图像,如果超过,则将高度裁剪为特定的值?基本上是最大高度裁剪。 我玩过缩放和裁剪,但我无法得到我需要的结果。任
我有两个 SpatialPolygonsDataFrame文件:dat1、dat2 extent(dat1) class : Extent xmin : -180 xmax
我在 TensorFlow 上实现了全卷积网络。它使用编码器-解码器结构。训练时,我始终使用相同的图像大小(224x224,使用随机裁剪)并且一切正常。 在干扰阶段,我想一次预测一张图像,因为我想使用
我在 TensorFlow 上实现了全卷积网络。它使用编码器-解码器结构。训练时,我始终使用相同的图像大小(224x224,使用随机裁剪)并且一切正常。 在干扰阶段,我想一次预测一张图像,因为我想使用
我有一个需要裁剪的 View 。我有 4 个 View 显示在主视图上查看的视频 subview 。由于视频比例,我需要裁剪使视频成为正方形而不是矩形的 View 。这是我的代码: - (void)v
我正在构建一个使用 Parse 作为我的后端的网络应用程序。 部分注册过程涉及用户上传和裁剪图片,然后我将其传递到我的数据库(图片是用户个人资料的一部分,类似于您在 Twitter 上所做的)。 我已
我正在制作一个基于立方体的游戏(一切都是立方体),目前正在尝试通过不在视野之外绘制东西来优化它。 以下内容仅适用于 x 和 y 平面,稍后我会担心 z ......所以现在只进行侧面裁剪。 我知道我自
我正在尝试在 iOS 上实现单指图像缩放/裁剪。类似于柯比·特纳的单指旋转。我正在寻找现有的库,或者如果您可以帮助我处理代码本身,那就太好了。 最佳答案 我不太清楚你所说的一指裁剪是什么意思,但我为
从这里: http://www.kylejlarson.com/blog/2011/how-to-create-pie-charts-with-css3/ .pieContainer
我已经设置了一个 SKScene 用作 SKReferenceNode。雪橇是一个 SKSpriteNode,在引用节点场景中定义了一个自定义类,所有的狗都是雪橇 Sprite 的 child 。自定
我有一个库,其中包含一些图像处理算法,包括感兴趣区域(裁剪)算法。使用 GCC 编译时,自动矢量化器会加速很多代码,但会降低 Crop 算法的性能。是否有标记某个循环以被矢量化器忽略的方法,或者是否有
代码位于 http://jsfiddle.net/rSSXu/ Child #parent { margin-left:auto; margin-right:auto;
我搜索了很多以删除不需要的空间,但找不到。我只找到可用于删除黑白背景空间的链接。但我的背景图片可以是任何东西。所以,如果我有这些图片, 我如何提取我需要的图像部分。例如, 最佳答案 这是我对你的问题的
我正在尝试将 CMSampleBufferRef 中的图像裁剪为特定大小。我正在执行 5 个步骤 - 1. 从 SampleBuffer 获取 PixelBuffer 2. 将 PixelBuffer
我读到它是自动的,但在我的案例中似乎没有发生。使用 UIImagePickerController 并将 allowsEditing 设置为 YES 我得到了带有裁剪方形叠加层的编辑 View ,但是
我正在寻找一种高效的方法来裁剪二维数组。考虑这个例子: 我有一个构成 100x100 网格的二维数组。我只想返回其中的一部分,60x60。这是一个“a”方法的示例,但我正在寻找指向执行此操作的最高性能
我有一个接受 UIImage 的类,用它初始化一个 CIImage,如下所示: workingImage = CIImage.init(image: baseImage!) 然后使用图像以 3x3 的
我正在尝试显示来自 mysql 数据库的图像。有些图像显示正确,但有些图像在底部显示为剪切/裁剪,裁剪部分仅显示为空白,当它成为图像的一部分时,您真的无法摆脱。 CSS 无法解决这个问题,使用 ima
我有个问题。我有什么理由不应该使用这个 Intent: Intent intent = new Intent("com.android.camera.action.CROP"); 为了裁剪我刚刚拍摄的
我有一些代码可以调整图像大小,因此我可以获得图像中心的缩放 block - 我使用它来获取 UIImage 并返回一个小的方形表示图片,类似于在照片应用程序的相册 View 中看到的内容。 (我知道我
我是一名优秀的程序员,十分优秀!