【问题标题】:Using CATiledLayer to display a large image that has been programmatically split into tiles使用 CATiledLayer 显示已以编程方式分割成图块的大图像
【发布时间】:2013-01-18 05:18:08
【问题描述】:

我在使用 CATiledLayer 时遇到了问题...我有一张大图,即 4726 x 2701 的地图。基本上我需要将此图像分解为图块并能够放大查看很多细节,还可以一直放大看整个地图。使用我当前的实现,如果滚动视图的缩放级别设置为 1.0(最大缩放比例),它可以完美地工作,但是如果你缩小瓷砖被错误地替换。

这里的缩放级别设置为 1.0。地图看起来很完美。

但是,如果缩放级别完全超出(我相信是 0.2),那么地图就会一团糟。我应该看到整个地图,而不仅仅是两个图块。

这是我从大图像中获取图块的方法:

- (UIImage *)tileForScale:(CGFloat)scale row:(int)row col:(int)col {
     float tileSize = 256.0f;
     CGRect subRect = CGRectMake(col*tileSize, row * tileSize, tileSize, tileSize);
     CGImageRef tiledImage = CGImageCreateWithImageInRect([mapImage CGImage], subRect);
     UIImage *tileImage = [UIImage imageWithCGImage: tiledImage];
     return tileImage;
}

我正在像 Apple 在 PhotoScroller 应用程序中一样显示图块。

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGFloat scale = CGContextGetCTM(context).a;

    CATiledLayer *tiledLayer = (CATiledLayer *)[self layer];
    CGSize tileSize = tiledLayer.tileSize;
    tileSize.width /= scale;
    tileSize.height /= scale;

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

    for (int row = firstRow; row <= lastRow; row++) {
        for (int col = firstCol; col <= lastCol; col++) {
            UIImage *tile = [self tileForScale:scale row:row col:col];
            CGRect tileRect = CGRectMake(tileSize.width * col, tileSize.height * row,
                                     tileSize.width, tileSize.height);
            tileRect = CGRectIntersection(self.bounds, tileRect);

            [tile drawInRect:tileRect];
        }
    }
}

另外,这里是我设置细节级别的代码,它为我的图像返回 4:

- (id)initWithImageName:(NSString *)name andImage:(UIImage*)image size:(CGSize)size {
    self = [super initWithFrame:CGRectMake(0, 0, size.width, size.height)];
    if (self) {
        _imageName = [name retain];
        mapImage = [image retain];

        CATiledLayer *tiledLayer = (CATiledLayer *)[self layer];
        tiledLayer.levelsOfDetail = [self zoomLevelsForSize:mapImage.size];
    }
    return self;
}
- (NSUInteger)zoomLevelsForSize:(CGSize)imageSize {
    int zLevels = 1;
    while(YES) {
        imageSize.width /= 2.0f;
        imageSize.height /= 2.0f;
        if(imageSize.height < 256.0 || imageSize.width < 256.0) break;
        ++zLevels;
    }
    return zLevels;
}

我假设它与图块大小和缩放比例有关,但我真的不知道如何解决这个问题。我似乎无法在 Google 上找到任何解决我的问题的方法。任何帮助都会很棒! :)

【问题讨论】:

  • 平铺层的levelsOfDetail 属性的值是多少?您对所有比例都使用相同的源图像,因此 levelsOfDetail 应设置为 1
  • 我更新了问题以反映详细程度。
  • 据我了解,您需要为每个级别的详细信息提供不同的图像,而您目前对所有级别都使用相同的图像。
  • 我会手动拆分图像,然后像 Apple 那样使用预渲染的图块,但我没有这个选项。我必须在运行时使用代码将大图像文件拆分为较小的图像。你知道我应该如何正确地做到这一点吗?
  • 我应该停止说话并尝试您所说的。将levelsOfDetail 设置为1 效果很好! :)

标签: iphone ios draw tile catiledlayer


【解决方案1】:

你有一个泄漏 - (UIImage *)tileForScale:(CGFloat)scale row:(int)row col:(int)col.

CGImageRef tiledImage = CGImageCreateWithImageInRect([mapImage CGImage], subRect);

不要忘记释放 CGImageRef:CGImageRelease(tiledImage);

【讨论】:

    【解决方案2】:

    我认为示例代码中的比例设置错误。 我有以下内容:

    CGFloat scale = CGContextGetCTM(context).a;
    scale = 1.0f / roundf(1.0f / scale);
    if (scale == INFINITY) {
        scale = 1.0f;
    }
    

    【讨论】:

      猜你喜欢
      • 2017-02-14
      • 1970-01-01
      • 2013-12-05
      • 1970-01-01
      • 2015-04-28
      • 1970-01-01
      • 1970-01-01
      • 2018-07-11
      • 1970-01-01
      相关资源
      最近更新 更多