有些时候你可能需要绘制一个很大的图片,常见的例子就是一个高像素的照片或者是地球表面的详细地图。iOS应用通畅运行在内存受限的设备上,所以读取整个图片到内存中是不明智的。载入大图可能会相当地慢,那些对你看上去比较方便的做法(在主线程调用UIImage-imageNamed:方法或者-imageWithContentsOfFile:方法)将会阻塞你的用户界面,至少会引起动画卡顿现象。

能高效绘制在iOS上的图片也有一个大小限制。所有显示在屏幕上的图片最终都会被转化为OpenGL纹理,同时OpenGL有一个最大的纹理尺寸(通常是20482048,或40964096,这个取决于设备型号)。如果你想在单个纹理中显示一个比这大的图,即便图片已经存在于内存中了,你仍然会遇到很大的性能问题,因为Core Animation强制用CPU处理图片而不是更快的GPU(见第12章『速度的曲调』,和第13章『高效绘图』,它更加详细地解释了软件绘制和硬件绘制)。

CATiledLayer为载入大图造成的性能问题提供了一个解决方案:将大图分解成小片然后将他们单独按需载入。让我们用实验来证明一下。

小片裁剪

这个示例中,我们将会从一个2048*2048分辨率的雪人图片入手。为了能够从CATiledLayer中获益,我们需要把这个图片裁切成许多小一些的图片。你可以通过代码来完成这件事情,但是如果你在运行时读入整个图片并裁切,那CATiledLayer这些所有的性能优点就损失殆尽了。理想情况下来说,最好能够逐个步骤来实现。

清单6.11 演示了一个简单的Mac OS命令行程序,它用CATiledLayer将一个图片裁剪成小图并存储到不同的文件中。

清单6.11 裁剪图片成小图的终端程序

 

 1 #import 
 2 
 3 int main(int argc, const char * argv[])
 4 {
 5     @autoreleasepool{
 6//handle incorrect arguments
 7         if (argc < 2) {
 8             NSLog(@"TileCutter arguments: inputfile");
 9             return 0;
10         }
11 
12         //input file
13         NSString *inputFile = [NSString stringWithCString:argv[1] encoding:NSUTF8StringEncoding];
14 
15         //tile size
16         CGFloat tileSize = 256; //output path
17         NSString *outputPath = [inputFile stringByDeletingPathExtension];
18 
19         //load image
20         NSImage *image = [[NSImage alloc] initWithContentsOfFile:inputFile];
21         NSSize size = [image size];
22         NSArray *representations = [image representations];
23         if ([representations count]){
24             NSBitmapImageRep *representation = representations[0];
25             size.width = [representation pixelsWide];
26             size.height = [representation pixelsHigh];
27         }
28         NSRect rect = NSMakeRect(0.0, 0.0, size.width, size.height);
29         CGImageRef imageRef = [image CGImageForProposedRect:&rect context:NULL hints:nil];
30 
31         //calculate rows and columns
32         NSInteger rows = ceil(size.height / tileSize);
33         NSInteger cols = ceil(size.width / tileSize);
34 
35         //generate tiles
36         for (int y = 0; y < rows; ++y) {
37             for (int x = 0; x < cols; ++x) {
38             //extract tile image
39             CGRect tileRect = CGRectMake(x*tileSize, y*tileSize, tileSize, tileSize);
40             CGImageRef tileImage = CGImageCreateWithImageInRect(imageRef, tileRect);
41 
42             //convert to jpeg data
43             NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:tileImage];
44             NSData *data = [imageRep representationUsingType: NSJPEGFileType properties:nil];
45             CGImageRelease(tileImage);
46 
47             //save file
48             NSString *path = [outputPath stringByAppendingFormat: @"_%02i_%02i.jpg", x, y];
49             [data writeToFile:path atomically:NO];
50             }
51         }
52     }
53     return 0;
54 }
View Code

相关文章:

猜你喜欢
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案