首页 » iOS编程(第4版) » iOS编程(第4版)全文在线阅读

《iOS编程(第4版)》19.2 处理图片

关灯直达底部

现在为BNRItemCell中的UIImageView对象设置图片。要在BNRItemCell中显示BNRItem对象的图片,可以先根据BNRItem对象从BNRImageStore中获取相应的图片,然后直接赋给UIImageView对象。但是因为图片的尺寸很大,所以这样做需要读取大量的数据,还要由UIImageView负责调整图片的大小,这些额外的工作都会影响应用的性能。另一种更合理的解决方案是创建并使用图片的缩略图(thumbnail)。

iOS SDK提供了多种创建缩略图的途径,其中之一是根据原图在屏外上下文(offscreen context)中画出按比率缩小后的版本,然后从上下文取出新创建的图片。下面通过这种途径为BNRItem对象的图片创建缩略图。首先要为BNRItem添加一个UIImage属性,指向缩略图;然后要将这些缩略图保存起来,以便在应用再次启动时重新载入。

第11章通过BNRImageStore对象存取全尺寸的图片,每张图片都有自己的独立文件;相反,缩略图的文件体积很小,可以直接将其和BNRItem对象的其他属性一起固化。

打开BNRItem.h,为BNRItem对象的缩略图声明一个新属性,此外还要声明一个新方法,根据全尺寸图片设置缩略图,代码如下:

@property (nonatomic, copy) NSString *imageKey;

@property (nonatomic, strong) UIImage *thumbnail;

- (void)setThumbnailFromImage:(UIImage *)image;

@end

当用户为某个BNRItem对象拍摄或选取了图片后,BNRItem对象会获得相应的全尺寸图片。然后,BNRItem对象要为全尺寸图片生成缩略图,并赋给thumbnail属性。

完成上述过程的方法是setThumbnailFromImage:。它根据传入的全尺寸图片,在屏外上下文中创建图片的小尺寸版本,并将其赋给thumbnail。

为了能够创建屏外上下文,并通过上下文创建图片,iOS特别提供了一套函数。UIGraphicsBeginImageContext函数可以创建屏外图形上下文(offscreen image context)。需要传入该函数的实参有:图形上下文的宽和高(CGSize结构)、缩放倍数(scaling factor)和图片是否透明(布尔值)。调用该函数后,新创建的CGContext结构将成为当前图形上下文。

要在上下文中绘图,需要使用Core Graphics。具体做法和实现UIView子类的drawRect:类似。调用UIGraphicsGetImageFromCurrentImageContext函数可以从上下文得到一个UIImage对象,即绘制的图片。

通过图形上下文得到UIImage对象后,必须调用UIGraphicsEndImageContext函数,清理相应的上下文。

在BNRItem.m中实现以下方法,通过屏外上下文创建缩略图。

- (void)setThumbnailFromImage:(UIImage *)image

{

CGSize origImageSize = image.size;

// 缩略图的大小

CGRect newRect = CGRectMake(0, 0, 40, 40);

// 确定缩放倍数并保持宽高比不变

float ratio = MAX(newRect.size.width / origImageSize.width,

newRect.size.height / origImageSize.height);

// 根据当前设备的屏幕scaling factor创建透明的位图上下文

UIGraphicsBeginImageContextWithOptions(newRect.size, NO, 0.0);

// 创建表示圆角矩形的UIBezierPath对象

UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:newRect

cornerRadius:5.0];

// 根据UIBezierPath对象裁剪图形上下文

[path addClip];

// 让图片在缩略图绘制范围内居中

CGRect projectRect;

projectRect.size.width = ratio * origImageSize.width;

projectRect.size.height = ratio * origImageSize.height;

projectRect.origin.x = (newRect.size.width - projectRect.size.width) / 2.0;

projectRect.origin.y = (newRect.size.height - projectRect.size.height) / 2.0;

// 在上下文中绘制图片

[image drawInRect:projectRect];

// 通过图形上下文得到UIImage对象,并将其赋给thumbnail属性

UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();

self.thumbnail = smallImage;

// 清理图形上下文

UIGraphicsEndImageContext();

}

修改BNRDetailViewController.m中的imagePickerController:didFinishPicking- MediaWithInfo:,加入以下代码,在获取全尺寸图片后创建缩略图。

- (void)imagePickerController:(UIImagePickerController *)picker

didFinishPickingMediaWithInfo:(NSDictionary *)info

{

UIImage *image = info [UIImagePickerControllerOriginalImage];

[self.item setThumbnailFromImage:image];

为BNRItem添加thumbnail属性后,就可以在BNRItemsViewController中使用该属性。更新BNRItemsViewController.m中的tableView:cellForRowAtIndexPath:,代码如下:

cell.valueLabel.text =

[NSString stringWithFormat:@“$%d”, item.valueInDollars];

cell.thumbnailView.image = item.thumbnail;

return cell;

}

构建并运行应用。为某个BNRItem对象拍摄照片,当UITableView对象再次出现时,应该会显示该对象的缩略图、名称和价值(对已经存在的BNRItem对象需要重新拍摄照片)。

最后还要将缩略图固化到文件。在BNRItem.m的initWithCoder:中加入以下代码:

- (id)initWithCoder:(NSCoder *)aDecoder

{

self = [super init];

if (self) {

_itemName = [aDecoder decodeObjectForKey:@“itemName”];

_serialNumber = [aDecoder decodeObjectForKey:@“serialNumber”];

_dateCreated = [aDecoder decodeObjectForKey:@“dateCreated”];

_itemKey = [aDecoder decodeObjectForKey:@“itemKey”];

_thumbnail = [aDecoder decodeObjectForKey:@“thumbnail”];

_valueInDollars = [aDecoder decodeIntForKey:@“valueInDollars”]

}

return self;

}

- (void)encodeWithCoder:(NSCoder *)aCoder

{

[aCoder encodeObject:self.itemName forKey:@“itemName”];

[aCoder encodeObject:self.serialNumber forKey:@“serialNumber”];

[aCoder encodeObject:self.dateCreated forKey:@“dateCreated”];

[aCoder encodeObject:self.itemKey forKey:@“itemKey”];

[aCoder encodeObject:self.thumbnail forKey:@“thumbnail”];

[aCoder encodeInt:self.valueInDollars forKey:@“valueInDollars”];

}

构建并运行应用。为若干BNRItem对象拍摄照片,然后终止应用并重新启动,应该能看到之前拍摄的照片的缩略图。