对于旋转的 UIImageView 有什么快速而肮脏的抗锯齿技术吗?

发布于 2024-07-26 17:08:47 字数 144 浏览 6 评论 0原文

我有一个 UIImageView(全框和矩形),我正在用 CGAffineTransform 旋转它。 UIImageView 的 UIImage 填充整个框架。 当旋转和绘制图像时,边缘会出现明显的锯齿状。 我能做些什么让它看起来更好吗? 显然它没有与背景抗锯齿。

I've got a UIImageView (full frame and rectangular) that i'm rotating with a CGAffineTransform. The UIImage of the UIImageView fills the entire frame. When the image is rotated and drawn the edges appear noticeably jagged. Is there anything I can do to make it look better? It's clearly not being anti-aliased with the background.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

知足的幸福 2024-08-02 17:08:48

新 API – iOS 6/7

也适用于 iOS 6,正如 @Chris 所指出的,但直到 iOS 7 才公开。

自 iOS 7 以来,CALayer 有了一个新属性 allowsEdgeAntialiasing 在这种情况下完全可以满足您的需求,而不会产生为应用程序中的所有视图启用它的开销! 这是 CALayer 的一个属性,因此要为 UIView 启用此属性,请使用 myView.layer.allowsEdgeAntialiasing = YES 。

New API – iOS 6/7

Also works for iOS 6, as noted by @Chris, but wasn't made public until iOS 7.

Since iOS 7, CALayer has a new property allowsEdgeAntialiasing which does exactly what you want in this case, without incurring the overhead of enabling it for all views in your application! This is a property of CALayer, so to enable this for a UIView you use myView.layer.allowsEdgeAntialiasing = YES.

[浮城] 2024-08-02 17:08:48

只需在图像中添加 1px 透明边框即可

CGRect imageRect = CGRectMake(0, 0, image.size.width, image.size.height);
UIGraphicsBeginImageContextWithOptions(imageRect.size, NO, 0.0);
[image drawInRect:CGRectMake(1,1,image.size.width-2,image.size.height-2)];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

just add 1px transparent border to your image

CGRect imageRect = CGRectMake(0, 0, image.size.width, image.size.height);
UIGraphicsBeginImageContextWithOptions(imageRect.size, NO, 0.0);
[image drawInRect:CGRectMake(1,1,image.size.width-2,image.size.height-2)];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
壹場煙雨 2024-08-02 17:08:48

请记住设置适当的抗锯齿选项:

CGContextSetAllowsAntialiasing(theContext, true);
CGContextSetShouldAntialias(theContext, true);

Remember to set the appropriate anti-alias options:

CGContextSetAllowsAntialiasing(theContext, true);
CGContextSetShouldAntialias(theContext, true);
(り薆情海 2024-08-02 17:08:48

只需在 plist 中添加“使用边缘抗锯齿渲染”和 YES 即可。

just add "Renders with edge antialiasing" with YES in plist and it will work.

安静被遗忘 2024-08-02 17:08:48

我完全推荐以下库。

http://vocaro.com/ trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/

它包含许多有用的 UIImage 扩展,可以解决这个问题,还包括用于生成缩略图等的代码。

享受吧!

I would totally recommend the following library.

http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/

It contains lots of useful extensions to UIImage that solve this problem and also include code for generating thumbnails etc.

Enjoy!

乱了心跳 2024-08-02 17:08:48

我发现拥有平滑边缘和清晰图像的最佳方法是这样做:

CGRect imageRect = CGRectMake(0, 0, self.photo.image.size.width, self.photo.image.size.height);
UIGraphicsBeginImageContextWithOptions(imageRect.size, NO, 0.0);
[self.photo.image drawInRect:CGRectMake(1, 1, self.photo.image.size.width - 2, self.photo.image.size.height - 2)];
self.photo.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

像一些人描述的那样添加 Info.plist 键对性能有很大影响,如果你使用它,那么你基本上将它应用到所有东西而不仅仅是您需要它的一个地方。

另外,不要只使用 UIGraphicsBeginImageContext(imageRect.size); 否则图层会模糊。 您必须像我所展示的那样使用 UIGraphicsBeginImageContextWithOptions

The best way I've found to have smooth edges and a sharp image is to do this:

CGRect imageRect = CGRectMake(0, 0, self.photo.image.size.width, self.photo.image.size.height);
UIGraphicsBeginImageContextWithOptions(imageRect.size, NO, 0.0);
[self.photo.image drawInRect:CGRectMake(1, 1, self.photo.image.size.width - 2, self.photo.image.size.height - 2)];
self.photo.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Adding the Info.plist key like some people describe has a big hit on performance and if you use that then you're basically applying it to everything instead of just the one place you need it.

Also, don't just use UIGraphicsBeginImageContext(imageRect.size); otherwise the layer will be blurry. You have to use UIGraphicsBeginImageContextWithOptions like I've shown.

装纯掩盖桑 2024-08-02 17:08:48

我从这里找到了这个解决方案,它很完美

+ (UIImage *)renderImageFromView:(UIView *)view withRect:(CGRect)frame transparentInsets:(UIEdgeInsets)insets {
    CGSize imageSizeWithBorder = CGSizeMake(frame.size.width + insets.left + insets.right, frame.size.height + insets.top + insets.bottom);
    // Create a new context of the desired size to render the image
    UIGraphicsBeginImageContextWithOptions(imageSizeWithBorder, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();

    // Clip the context to the portion of the view we will draw
    CGContextClipToRect(context, (CGRect){{insets.left, insets.top}, frame.size});
    // Translate it, to the desired position
    CGContextTranslateCTM(context, -frame.origin.x + insets.left, -frame.origin.y + insets.top);

    // Render the view as image
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];

    // Fetch the image
    UIImage *renderedImage = UIGraphicsGetImageFromCurrentImageContext();

    // Cleanup
    UIGraphicsEndImageContext();

    return renderedImage;
}

: :

UIImage *image = [UIImage renderImageFromView:view withRect:view.bounds transparentInsets:UIEdgeInsetsZero];

I found this solution from here, and it's perfect:

+ (UIImage *)renderImageFromView:(UIView *)view withRect:(CGRect)frame transparentInsets:(UIEdgeInsets)insets {
    CGSize imageSizeWithBorder = CGSizeMake(frame.size.width + insets.left + insets.right, frame.size.height + insets.top + insets.bottom);
    // Create a new context of the desired size to render the image
    UIGraphicsBeginImageContextWithOptions(imageSizeWithBorder, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();

    // Clip the context to the portion of the view we will draw
    CGContextClipToRect(context, (CGRect){{insets.left, insets.top}, frame.size});
    // Translate it, to the desired position
    CGContextTranslateCTM(context, -frame.origin.x + insets.left, -frame.origin.y + insets.top);

    // Render the view as image
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];

    // Fetch the image
    UIImage *renderedImage = UIGraphicsGetImageFromCurrentImageContext();

    // Cleanup
    UIGraphicsEndImageContext();

    return renderedImage;
}

usage:

UIImage *image = [UIImage renderImageFromView:view withRect:view.bounds transparentInsets:UIEdgeInsetsZero];
掩耳倾听 2024-08-02 17:08:47

默认情况下,iOS 上 CoreAnimation 图层的边缘不会进行抗锯齿处理。 但是,您可以在 Info.plist 中设置一个键来启用边缘抗锯齿功能:UIViewEdgeAntialiasing。

https://developer.apple.com/ library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html

如果您不希望启用此选项带来性能开销,解决方法是 在图像边缘添加 1 像素透明边框。 这意味着图像的“边缘”不再在边缘,因此不需要特殊处理!

The edges of CoreAnimation layers aren't antialiased by default on iOS. However, there is a key that you can set in Info.plist that enables antialiasing of the edges: UIViewEdgeAntialiasing.

https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html

If you don't want the performance overhead of enabling this option, a work-around is to add a 1px transparent border around the edge of the image. This means that the 'edges' of the image are no longer on the edge, so don't need special treatment!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文