【问题标题】:iOS - CATiledLayer renderInContext: results in distorted imageiOS - CATiledLayer renderInContext:导致图像失真
【发布时间】:2013-07-10 20:16:33
【问题描述】:

我有一个支持 CATiledLayer 的 UIScrollView,它显示了一个非常大的图像。 我想要实现的是将此视图捕获到 UIImage 中(将其用作进度条视图的背景)。 有几个问题:

  • 在“100%”缩放时(整个图片可见)似乎没问题
  • 如果我放大滚动视图,一些图块会变形(比例和/或偏移量不好)
  • 尝试使用 Apple 的 PhotoScroller 示例对其进行复制,该示例几乎可以正常工作,只是捕获的图像有时会像素化
  • 我没有写代码,所以我不知道如何修复它

检查了有关此的其他 stackoverflow 条目,但它们并没有太大帮助...

图像采集代码:

CGRect rect = [view bounds];
UIImage* img = nil;

if ([view isKindOfClass:[UIScrollView class]])
{
    UIScrollView* scrollview = (UIScrollView*)view;
    CGPoint contentOffset = scrollview.contentOffset;

    UIGraphicsBeginImageContextWithOptions(rect.size, view.opaque, 0.0);
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    CGContextTranslateCTM(ctx, -contentOffset.x, -contentOffset.y);
    [view.layer renderInContext:ctx];

    img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}

以及平铺视图的drawRect:方法的代码:

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();

    if (self.clipContent)
    {
        CGContextSaveGState(context);
        CGFloat color[4] = {1.0, 1.0f, 1.0f, 1.0f};
        CGContextSetFillColor(context, color);
        CGContextFillRect(context, self.bounds);

        CGRect clips[] = {
            CGRectMake(self.bounds.size.width / 2.0, 0,
                       self.bounds.size.height / 2.0 , self.bounds.size.width / 2.0)
        };

        CGContextClipToRects(context, clips, sizeof(clips) / sizeof(clips[0]));
    }

    CGFloat scale = CGContextGetCTM(context).a;
    CGSize tileSize = [_dataSource tileSize];

    double width = (double)tileSize.width / (double)scale;//pow(2.0, (int)log2(scale));
    double height = (double)tileSize.height / (double)scale;//pow(2.0, (int)log2(scale));

    int firstCol = floorf(CGRectGetMinX(rect) / width);
    int lastCol = floorf((CGRectGetMaxX(rect) - 1) / width);
    int firstRow = floorf(CGRectGetMinY(rect) / height);
    int lastRow = floorf((CGRectGetMaxY(rect) - 1) / height);

    for (int row = firstRow; row <= lastRow; row++) {
        for (int col = firstCol; col <= lastCol; col++) {
            UIImage* tileImage = [_dataSource tileForScale:scale row:row col:col];

            CGRect tileRect = CGRectMake(width * col, height * row, width, height);
            tileRect = CGRectIntersection(rect, tileRect);

            [tileImage drawInRect:tileRect];
        }
    }

    if (self.clipContent)
        CGContextRestoreGState(context);
}

有什么想法吗?

【问题讨论】:

    标签: ios catiledlayer


    【解决方案1】:

    经过大量的尝试和错误,结果发现Cocoa实现本身是不完整的,所以问题无法解决。

    随着 iOS 7 的发布,有一种新方法:

    [view drawViewHierarchyInRect:rect afterScreenUpdates:YES];
    

    (而不是 renderInContext),并且它可以工作(图像有些模糊,但这是可以接受的副作用)。

    【讨论】:

    • 对此我感激不尽。在我找到这篇文章之前,我已经为不正确渲染的快照苦苦挣扎了好几个小时。
    • 但是这样一来,图像就变形了!它的形状根本不正确。 @庇护
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-13
    • 1970-01-01
    相关资源
    最近更新 更多