CATiledLayer、CGContextDrawImage 和 CGContextTranslateCTM

发布于 2024-12-26 02:55:22 字数 1484 浏览 1 评论 0原文

我有一个很大的 UIScrollView ,其中包含一个 CATiledLayer ,我用它来在 drawRect: 中绘制更大的图块,如下所示

- (void)drawRect:(CGRect)rect {
    int firstCol = floorf(CGRectGetMinX(rect) / tileSize);
    int lastCol = floorf((CGRectGetMaxX(rect)-1) / tileSize);
    int firstRow = floorf(CGRectGetMinY(rect) / tileSize);
    int lastRow = floorf((CGRectGetMaxY(rect)-1) / tileSize);

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    CGContextTranslateCTM(context, 0, tileSize);
CGContextScaleCTM(context, 1.0, -1.0);

    for( int row = firstRow; row <= lastRow; row++ ) {
    for( int col = firstCol; col <= lastCol; col++ ) {
            UIImage = [self getTileWithRow:row column:col];

            CGRect tileRect = CGRectMake((col * tileSize), 
                                         row * tileSize),
                                         tileSize, tileSize);

            CGContextTranslateCTM(context, 0, tileRect.size.height);
            CGContextScaleCTM(context, 1.0, -1.0);
            CGContextDrawImage(context, tileRect, tile.CGImage);
        }
    }

    CGContextRestoreGState(context);
}

:当我注释掉 CGContextSaveGStateCGContextSaveGStateCGContextScaleCTMCGContextRestoreGState 调用但图像向上时 向下。调用到位后,根本不会绘制图像。我可以使用 [tile drawInRect:] 但这会反向绘制行,从而搞乱了较大的图像。

我的翻译做错了什么?

编辑:按照建议将保存/恢复和转换移出循环,但它仍然没有绘制任何内容。

I have a large UIScrollView which contains a CATiledLayer which I'm using to draw tiles of a much larger in drawRect: like this:

- (void)drawRect:(CGRect)rect {
    int firstCol = floorf(CGRectGetMinX(rect) / tileSize);
    int lastCol = floorf((CGRectGetMaxX(rect)-1) / tileSize);
    int firstRow = floorf(CGRectGetMinY(rect) / tileSize);
    int lastRow = floorf((CGRectGetMaxY(rect)-1) / tileSize);

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    CGContextTranslateCTM(context, 0, tileSize);
CGContextScaleCTM(context, 1.0, -1.0);

    for( int row = firstRow; row <= lastRow; row++ ) {
    for( int col = firstCol; col <= lastCol; col++ ) {
            UIImage = [self getTileWithRow:row column:col];

            CGRect tileRect = CGRectMake((col * tileSize), 
                                         row * tileSize),
                                         tileSize, tileSize);

            CGContextTranslateCTM(context, 0, tileRect.size.height);
            CGContextScaleCTM(context, 1.0, -1.0);
            CGContextDrawImage(context, tileRect, tile.CGImage);
        }
    }

    CGContextRestoreGState(context);
}

This works when I comment out the CGContextSaveGState, CGContextSaveGState, CGContextScaleCTM and CGContextRestoreGState calls but the images are upside down. With the calls in place the image is not drawn at all. I could use [tile drawInRect:] but that draws the rows in reverse which screws up the larger image.

What am I doing wrong with the translation?

EDIT: Moved save/restore and transform out of the loop as suggested but it's still not drawing anything.

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

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

发布评论

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

评论(2

橘虞初梦 2025-01-02 02:55:22

设置正确的转换来垂直翻转内容是出了名的困难。看不到任何东西的可能原因是变换将图像移到了矩形之外。我以前曾经成功过,但不记得我是怎么做到的。现在我在 CATiledLayer 上设置“geometryFlipped = YES”,它为我执行翻转。

顺便说一句,为什么不将 CATiledLayer 的“tileSize”设置为图块的大小,那么您就不需要这个 for 循环图块映射内容了。每个图块都会调用一次drawRect,因此您可以简单地执行以下操作:

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

    int col = floorf(CGRectGetMinX(rect) / tileSize);
    int row = floorf(CGRectGetMinY(rect) / tileSize);

    UIImage tile = [self getTileWithRow:row column:col];

    CGContextDrawImage(context, rect, tile.CGImage);
}

Setting the right transformations to flip the content vertically is notoriously hard. The likely cause of not seeing anything, is because the transformations move the image outside of the rect. I have made it work before, but don't remember how I did it. Now I set "geometryFlipped = YES" on the CATiledLayer instead, which does the flipping for me.

By the way, why don't you set the "tileSize" of the CATiledLayer to the size of your tiles, then you don't need this for-loop tile mapping stuff. The drawRect is called once for each of your tiles, so you can then do simply:

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

    int col = floorf(CGRectGetMinX(rect) / tileSize);
    int row = floorf(CGRectGetMinY(rect) / tileSize);

    UIImage tile = [self getTileWithRow:row column:col];

    CGContextDrawImage(context, rect, tile.CGImage);
}
享受孤独 2025-01-02 02:55:22

首先,将所有 CGContextSaveGState / CGContextRestoreGState 移出这些循环,因为这些循环会增加实现所需的工作量。

其次,添加 CGContextRef context = UIGraphicsGetCurrentContext(); 作为该 drawRect 方法的第一行。

所以你的实现应该看起来更好,如下所示:

- (void)drawRect:(CGRect)rect 
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    CGContextTranslateCTM(context, 0, rect.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

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

    for( int row = firstRow; row <= lastRow; row++ ) 
    {
        for( int col = firstCol; col <= lastCol; col++ ) 
        {
            UIImage = [self getTileWithRow:row column:col];

            CGRect tileRect = CGRectMake((col * tileSize), 
                                         row * tileSize),
                                         tileSize, tileSize);

            CGContextDrawImage(context, tileRect, tile.CGImage);
        }
    }
    CGContextRestoreGState(context);
}

First of all, move all of that CGContextSaveGState / CGContextRestoreGState out of those loops as those would add more workload than needed onto your implementation.

Second, add CGContextRef context = UIGraphicsGetCurrentContext(); as the first line of that drawRect method.

So your implementation should look better like this:

- (void)drawRect:(CGRect)rect 
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    CGContextTranslateCTM(context, 0, rect.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

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

    for( int row = firstRow; row <= lastRow; row++ ) 
    {
        for( int col = firstCol; col <= lastCol; col++ ) 
        {
            UIImage = [self getTileWithRow:row column:col];

            CGRect tileRect = CGRectMake((col * tileSize), 
                                         row * tileSize),
                                         tileSize, tileSize);

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