UIView 中的 UIimage:高于屏幕分辨率?

发布于 2024-10-25 05:47:24 字数 391 浏览 2 评论 0原文

我有一个 UIView,我通过典型的 UIGraphicsBeginImageContextWithOptions 方法将其渲染为 UIImage,使用比例为 2.0,因此图像输出将始终是屏幕上显示的“视网膜显示”版本,无论用户的实际情况如何屏幕分辨率。

我正在渲染的 UIView 包含图像和文本(UIImages 和 UILabels)。该图像以其全分辨率出现在渲染的 UIImage 中,看起来很棒。但 UILabels 似乎已按 1.0 比例进行光栅化,然后放大到 2.0,导致文本模糊。

我做错了什么,或者有什么方法可以让文本在更高的比例级别上呈现漂亮和清晰的效果?或者除了使用 UIGraphicsBeginImageContextWithOptions 的缩放参数之外还有其他方法可以达到更好的结果吗?  谢谢!

I've got a UIView which I'm rendering to a UIImage via the typical UIGraphicsBeginImageContextWithOptions method, using a scale of 2.0 so the image output will always be the "retina display" version of what would show up onscreen, regardless of the user's actual screen resolution.

The UIView I'm rendering contains both images and text (UIImages and UILabels).  The image is appearing in the rendered UIImage at its full resolution, and looks great.  But the UILabels appear to have been rasterized at a 1.0 scale and then upscaled to 2.0, resulting in blurry text.

Is there something I'm doing wrong, or is there some way to get the text to render nice and crisp at the higher scale level?  Or is there some way to do this other than using the scaling parameter of UIGraphicsBeginImageContextWithOptions that would have better results?   Thanks!

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

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

发布评论

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

评论(3

相守太难 2024-11-01 05:47:24

解决方案是在绘制之前将标签的 contentScale 更改为 2,然后立即将其设置回来。我刚刚编写了一个项目来验证它,它可以很好地在普通的视网膜手机(模拟器)中制作 2x 图像。 [如果您有公共场所,我可以告诉我。]

编辑:扩展代码遍历子视图和任何容器 UIView 来设置/取消设置比例

- (IBAction)snapShot:(id)sender
{
    [self changeScaleforView:snapView scale:2];

    UIGraphicsBeginImageContextWithOptions(snapView.bounds.size, snapView.opaque, 2);
    [snapView.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    imageDisplay.image = img; // contentsScale
    imageDisplay.contentMode = UIViewContentModeScaleAspectFit;

    [self changeScaleforView:snapView scale:1];
}

- (void)changeScaleforView:(UIView *)aView scale:(CGFloat)scale
{
    [aView.subviews enumerateObjectsUsingBlock:^void(UIView *v, NSUInteger idx, BOOL *stop)
        {
            if([v isKindOfClass:[UILabel class]]) {
                v.layer.contentsScale = scale;
            } else
            if([v isKindOfClass:[UIImageView class]]) {
                // labels and images
                // v.layer.contentsScale = scale; won't work

                // if the image is not "@2x", you could subclass UIImageView and set the name of the @2x
                // on it as a property, then here you would set this imageNamed as the image, then undo it later
            } else
            if([v isMemberOfClass:[UIView class]]) {
                // container view
                [self changeScaleforView:v scale:scale];
            }       
        } ];
}

The solution is to change the labels's contentsScale to 2 before you draw it, then set it back immediately thereafter. I just coded up a project to verify it, and its working just fine making a 2x image in a normal retina phone (simulator). [If you have a public place I can put it let me know.]

EDIT: the extended code walks the subviews and any container UIViews to set/unset the scale

- (IBAction)snapShot:(id)sender
{
    [self changeScaleforView:snapView scale:2];

    UIGraphicsBeginImageContextWithOptions(snapView.bounds.size, snapView.opaque, 2);
    [snapView.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    imageDisplay.image = img; // contentsScale
    imageDisplay.contentMode = UIViewContentModeScaleAspectFit;

    [self changeScaleforView:snapView scale:1];
}

- (void)changeScaleforView:(UIView *)aView scale:(CGFloat)scale
{
    [aView.subviews enumerateObjectsUsingBlock:^void(UIView *v, NSUInteger idx, BOOL *stop)
        {
            if([v isKindOfClass:[UILabel class]]) {
                v.layer.contentsScale = scale;
            } else
            if([v isKindOfClass:[UIImageView class]]) {
                // labels and images
                // v.layer.contentsScale = scale; won't work

                // if the image is not "@2x", you could subclass UIImageView and set the name of the @2x
                // on it as a property, then here you would set this imageNamed as the image, then undo it later
            } else
            if([v isMemberOfClass:[UIView class]]) {
                // container view
                [self changeScaleforView:v scale:scale];
            }       
        } ];
}
坦然微笑 2024-11-01 05:47:24

尝试渲染为双倍尺寸的图像,然后创建缩放图像:

UIGraphicsBeginImageContextWithOptions(size, NO, 1.0);
// Do stuff
UImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

newImage=[UIImage imageWithCGImage:[newImage CGImage] scale:2.0 orientation:UIImageOrientationUp];

其中:
大小 = 实际大小 * 比例;

Try rendering to an image with double size, and then create the scaled image:

UIGraphicsBeginImageContextWithOptions(size, NO, 1.0);
// Do stuff
UImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

newImage=[UIImage imageWithCGImage:[newImage CGImage] scale:2.0 orientation:UIImageOrientationUp];

Where:
size = realSize * scale;

ぃ双果 2024-11-01 05:47:24

在文本视图到 PDF 渲染的上下文中,我一直在努力解决同样的奇怪问题。我发现构成视图的 CALayer 对象上有一些记录的属性。也许设置相关(子)图层的 rasterizationScale 有帮助。

I have been struggling with much the same oddities in the context of textview to PDF rendering. I found out that there are some documented properties on the CALayer objects which make up the view. Maybe setting the rasterizationScale of the relevant (sub)layer(s) helps.

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